Page 1 of 2
[SOLVED] Linker and undefined function references
Posted: Tue Jul 28, 2009 4:09 pm
by luiscubal
Hello, I am new to OS development and I was coding based on OSDev's wiki and Bran's Kernel Development tutorial.
Everything went fine until I reached the part of GDT.
Although my Assembly code can call C functions, calling Assembly functions from C causes a linker error. Although both gcc and nasm compile properly, ld fails.
Code: Select all
out/gdt.o: In function `gdt_install':
gdt.c:(.text+0x102): undefined reference to `gdt_flush'
However, gdt.o *does* define a function gdt_flush(The "nm" command proves this)
I've tried messing with leading underscores, but with no luck...
My assembly "gdt_flush" function:
Code: Select all
global gdt_flush ; Allows the C code to link to this
extern gp ; Says that 'gp' is in another file
gdt_flush:
lgdt [gp] ; Load the GDT with our 'gp' which is a special pointer
mov ax, 0x10 ; 0x10 is the offset in the GDT to our data segment
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
jmp 0x08:flush2 ; 0x08 is the offset to our code segment: Far jump!
flush2:
ret ; Returns back to the C code!
gdt_flush declaration in C:
Finally, here is my linker script:
Code: Select all
OUTPUT_FORMAT("binary")
ENTRY(start)
phys = 0x00100000;
SECTIONS
{
.text phys : AT(phys) {
code = .;
*(.text)
*(.rodata)
. = ALIGN(4096);
}
.data : AT(phys + (data - code))
{
data = .;
*(.data)
. = ALIGN(4096);
}
.bss : AT(phys + (bss - code))
{
bss = .;
*(.bss)
. = ALIGN(4096);
}
end = .;
}
What am I doing wrong?
(sorry if this is a duplicate. I've searched for quite some time now and I didn't find anything yet.)
EDIT: Ah, before I forget, I'm calling ld using this command:
Code: Select all
ld -Ttext 0x100000 -T src/link.ld out/*.o -o iso/$COREFOLDER/kernel.bin
the out folder includes the start.o(gdt_flush is defined in start.asm)
Re: Linker and undefined function references
Posted: Tue Jul 28, 2009 9:12 pm
by kop99
Code: Select all
global gdt_flush ; Allows the C code to link to this
extern gp ; Says that 'gp' is in another file
gdt_flush:
take place following.
Code: Select all
_global gdt_flush ; Allows the C code to link to this
extern gp ; Says that 'gp' is in another file
_gdt_flush:
Re: Linker and undefined function references
Posted: Wed Jul 29, 2009 4:02 pm
by luiscubal
I'm not calling both files gdt.
If I replace extern by extern "C", I get this:
Code: Select all
../src/gdt.c:30: error: expected identifier or ‘(’ before string constant
(I am using C, not C++)
Re: Linker and undefined function references
Posted: Wed Jul 29, 2009 5:22 pm
by pcmattman
berkus wrote:First, use extern "C" instead of just extern, this will turn off any name mangling.
extern "C" is a C++ thing, not an assembly or C thing. extern in the assembly code specifies that the symbol is available, but not within the object. The OP specified C
Code: Select all
_global gdt_flush ; Allows the C code to link to this
extern gp ; Says that 'gp' is in another file
_gdt_flush:
Code examples should be correct
. The _ belongs on gdt_flush, not global! Really though, you should be using -fno-leading-underscores (as berkus said).
Re: Linker and undefined function references
Posted: Wed Jul 29, 2009 5:46 pm
by luiscubal
Even when I add -fno_leading_underscores, nothing changes.
Re: Linker and undefined function references
Posted: Wed Jul 29, 2009 5:52 pm
by pcmattman
Are you certain that the assembly file is actually assembled and linked? Keep in mind that often the location of a file on the ld command line can directly impact the visibility of symbols (ie, make sure the assembly file is on the command line first, then the C file).
Re: Linker and undefined function references
Posted: Wed Jul 29, 2009 7:33 pm
by luiscubal
I've modified some things, but it still doesn't work...
Code: Select all
ld $LDFLAGS -T src/link.ld out/start.o out/gdt.o out/main.o out/srcn.o -o iso/$COREFOLDER/kernel.bin >>log.txt
(start is the assembly file, the remaining are written in C)
Re: Linker and undefined function references
Posted: Thu Jul 30, 2009 1:43 am
by Solar
objdump -t <objectfile>
Lists the symbols defined.
Toolchain FTW.
Re: Linker and undefined function references
Posted: Thu Jul 30, 2009 1:46 am
by pcmattman
nm <object file> can also show you the missing references (and help you name your assembly correctly, without guessing) in your compiled C object file too, IIRC.
Re: Linker and undefined function references
Posted: Thu Jul 30, 2009 2:02 am
by Solar
Heh, nice. There I was chanting "toolchain FTW" and didn't know about nm (since objdump does all I need, including full disassembly).
Re: Linker and undefined function references
Posted: Thu Jul 30, 2009 8:00 am
by luiscubal
nm start.o
00010000 a MULTIBOOT_AOUT_KLUDGE
e4514ffb a MULTIBOOT_CHECKSUM
00010003 a MULTIBOOT_HEADER_FLAGS
1badb002 a MULTIBOOT_HEADER_MAGIC
00000002 a MULTIBOOT_MEMORY_INFO
00000001 a MULTIBOOT_PAGE_ALIGN
U _entrypoint
00002000 b _sys_stack
U bss
U code
U end
U flush2
U gdt_flush
U gp
U mboot
U start
U stublet
So gdt_flush does exist. As I mentioned before, adding and removing leading underscores does not change anything.
Meanwhile, I've changed my build script a bit, so here's the whole updated sh script:
Code: Select all
#!/bin/sh
#Dependencies:
#gcc
#ld
#nasm
#qemu
SCRIPT_DIR_RELATIVE=$(dirname $0)
SCRIPT_DIR_ABSOLUTE=$(cd $SCRIPT_DIR_RELATIVE; pwd)
COREFOLDER=Core
BOOTFOLDER=boot/grub
CHARSET=ascii
NAME=Ovar
CFLAGS=$(echo -Wall -Wextra -m32 -O -fno-leading-underscore -fstrength-reduce -fomit-frame-pointer -finline-functions -nostdinc -nostdlib -nostartfiles -fno-builtin -nodefaultlibs)
LDFLAGS=$(echo -Ttext 0x100000 -melf_i386)
cd $SCRIPT_DIR_ABSOLUTE
if [ ! -d iso ]
then
mkdir iso>>log.txt
fi
if [ ! -d out ]
then
mkdir out>>log.txt
fi
if [ ! -d bin ]
then
mkdir bin>>log.txt
fi
if [ ! -d bin/x86 ]
then
mkdir bin/x86>>log.txt
fi
if [ ! -d iso/boot ]
then
mkdir iso/boot>>log.txt
fi
if [ ! -d iso/$COREFOLDER ]
then
mkdir iso/$COREFOLDER>>log.txt
fi
if [ ! -d iso/$BOOTFOLDER ]
then
mkdir iso/$BOOTFOLDER>>log.txt
fi
echo "Compilation started">log.txt
nasm -f elf -o out/start.o src/start.asm >>log.txt
echo "GCC tasks starting">>log.txt
cd ./out #Make sure output files end up in the right folder
gcc $CFLAGS -I../headers -c ../src/*.c >>../log.txt
cd ../
echo "Linker starting">>log.txt
ld $LDFLAGS -T src/link.ld out/start.o out/gdt.o out/main.o out/srcn.o -o iso/$COREFOLDER/kernel.bin >>log.txt
echo "Finished compilation">>log.txt
if [ ! -d iso/$BOOTFOLDER ]
then
mkdir iso/$BOOTFOLDER>>log.txt
fi
cp res/stage2_eltorito iso/$BOOTFOLDER>>log.txt
cp res/menu.lst iso/$BOOTFOLDER>>log.txt
if [ ! -d bin/x86 ]
then
mkdir bin/x86>>log.txt
fi
cd iso/
mkisofs -input-charset $CHARSET -R -b $BOOTFOLDER/stage2_eltorito -A $NAME -no-emul-boot -boot-load-size 4 -boot-info-table -o ../bin/x86/os.iso .>>../log.txt
cd ..
qemu-img create -f qcow2 bin/x86/disk.img 3G
log.txt has only a few entries and ld errors seem to be going directly to the command line.
Re: Linker and undefined function references
Posted: Thu Jul 30, 2009 8:51 am
by torshie
luiscubal wrote:nm start.o
00010000 a MULTIBOOT_AOUT_KLUDGE
e4514ffb a MULTIBOOT_CHECKSUM
00010003 a MULTIBOOT_HEADER_FLAGS
1badb002 a MULTIBOOT_HEADER_MAGIC
00000002 a MULTIBOOT_MEMORY_INFO
00000001 a MULTIBOOT_PAGE_ALIGN
U _entrypoint
00002000 b _sys_stack
U bss
U code
U end
U flush2
U gdt_flush
U gp
U mboot
U start
U stublet
So gdt_flush does exist. As I mentioned before, adding and removing leading underscores does not change anything.
Meanwhile, I've changed my build script a bit, so here's the whole updated sh script:
Code: Select all
#!/bin/sh
#Dependencies:
#gcc
#ld
#nasm
#qemu
SCRIPT_DIR_RELATIVE=$(dirname $0)
SCRIPT_DIR_ABSOLUTE=$(cd $SCRIPT_DIR_RELATIVE; pwd)
COREFOLDER=Core
BOOTFOLDER=boot/grub
CHARSET=ascii
NAME=Ovar
CFLAGS=$(echo -Wall -Wextra -m32 -O -fno-leading-underscore -fstrength-reduce -fomit-frame-pointer -finline-functions -nostdinc -nostdlib -nostartfiles -fno-builtin -nodefaultlibs)
LDFLAGS=$(echo -Ttext 0x100000 -melf_i386)
cd $SCRIPT_DIR_ABSOLUTE
if [ ! -d iso ]
then
mkdir iso>>log.txt
fi
if [ ! -d out ]
then
mkdir out>>log.txt
fi
if [ ! -d bin ]
then
mkdir bin>>log.txt
fi
if [ ! -d bin/x86 ]
then
mkdir bin/x86>>log.txt
fi
if [ ! -d iso/boot ]
then
mkdir iso/boot>>log.txt
fi
if [ ! -d iso/$COREFOLDER ]
then
mkdir iso/$COREFOLDER>>log.txt
fi
if [ ! -d iso/$BOOTFOLDER ]
then
mkdir iso/$BOOTFOLDER>>log.txt
fi
echo "Compilation started">log.txt
nasm -f elf -o out/start.o src/start.asm >>log.txt
echo "GCC tasks starting">>log.txt
cd ./out #Make sure output files end up in the right folder
gcc $CFLAGS -I../headers -c ../src/*.c >>../log.txt
cd ../
echo "Linker starting">>log.txt
ld $LDFLAGS -T src/link.ld out/start.o out/gdt.o out/main.o out/srcn.o -o iso/$COREFOLDER/kernel.bin >>log.txt
echo "Finished compilation">>log.txt
if [ ! -d iso/$BOOTFOLDER ]
then
mkdir iso/$BOOTFOLDER>>log.txt
fi
cp res/stage2_eltorito iso/$BOOTFOLDER>>log.txt
cp res/menu.lst iso/$BOOTFOLDER>>log.txt
if [ ! -d bin/x86 ]
then
mkdir bin/x86>>log.txt
fi
cd iso/
mkisofs -input-charset $CHARSET -R -b $BOOTFOLDER/stage2_eltorito -A $NAME -no-emul-boot -boot-load-size 4 -boot-info-table -o ../bin/x86/os.iso .>>../log.txt
cd ..
qemu-img create -f qcow2 bin/x86/disk.img 3G
log.txt has only a few entries and ld errors seem to be going directly to the command line.
It seems that you are using *nix, why don't you use makefile ?
Re: Linker and undefined function references
Posted: Thu Jul 30, 2009 9:10 am
by luiscubal
Because I prefer shell scripts(I know them better so I can use them to do much more).
If makefiles solved my linker errors, I'd gladly use them, but I just don't see that happening. Should I at least try?
Re: Linker and undefined function references
Posted: Thu Jul 30, 2009 9:35 am
by Solar
No, a Makefile won't solve a linker error, but:
luiscubal wrote:I know them better so I can use them to do much more.
"Make" is the right tool for the job. If you don't know it, learn it.
Hitting nails with a screwdriver works in a pinch, but the results will always be sub-par, so you should go and buy a hammer.
Re: Linker and undefined function references
Posted: Thu Jul 30, 2009 12:37 pm
by luiscubal
I may switch to make later, but right now I'm more concerned about getting it to link...