undefined reference link error when adding new function call

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
owst
Posts: 6
Joined: Tue Jul 06, 2010 3:22 pm

undefined reference link error when adding new function call

Post by owst »

Hey Guys, can anyone help troubleshoot what I think is a linker problem in my attempts of Bran's OS tutorial?

I've just added the GDT setup code, but am encountering a strange linking problem after adding a call to the new function. Without the function call, my object files link correctly, however, with the new function call added, I get an undefined reference to a symbol from another object file (I've verified it is actually present using objdump).

Also strangely, with the function call present, if I link all object files first using ld -r and then using my link script, there are no undefined references, but it seems the link script is being ignored since the output binary does not have the correct entry point.

My (cross-compiler) ld version:

Code: Select all

> i586-elf-ld --version
GNU ld (GNU Binutils) 2.20.1.20100303
My attempts at proving that the 'missing' symbol is present:

Code: Select all

> i586-elf-ld -T link.ld -o kernel32.bin kernel_loader.o main.o stdio.o common.o gdt.o gdt.bin -y putch
main.o: reference to putch
stdio.o: definition of putch
main.o: In function `main':
main.c:(.text+0x1f): undefined reference to `putch'
I can see the symbol that is 'missing' in the appropriate object file:

Code: Select all

> i586-elf-objdump -ht stdio.o

stdio.o:     file format elf32-i386

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         000002f9  00000000  00000000  00000034  2**2
                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
  1 .data         0000000c  00000000  00000000  00000330  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  2 .bss          00000008  00000000  00000000  0000033c  2**2
                  ALLOC
  3 .comment      00000012  00000000  00000000  0000033c  2**0
                  CONTENTS, READONLY
SYMBOL TABLE:
00000000 l    df *ABS*  00000000 stdio.c
00000000 l    d  .text  00000000 .text
00000000 l    d  .data  00000000 .data
00000000 l    d  .bss   00000000 .bss
00000000 l    d  .comment       00000000 .comment
00000000 g     F .text  00000016 strlen
00000016 g     F .text  0000005c scroll
00000008 g     O .data  00000004 numrows
00000004 g     O .bss   00000004 ypos
00000004 g     O .data  00000004 numcols
00000004       O *COM*  00000004 screen_mem
00000000         *UND*  00000000 memcpy
00000000         *UND*  00000000 memsetw
00000072 g     F .text  0000007d newline
00000000 g     O .bss   00000004 xpos
000000ef g     F .text  0000002e writech
00000000 g     O .data  00000004 colour
0000011d g     F .text  00000061 cls
0000017e g     F .text  00000010 init_video
0000018e g     F .text  00000133 putch
000002c1 g     F .text  00000037 puts
000002f8 g     F .text  00000001 set_text_colour
And the object file with unresolved reference:

Code: Select all

> i586-elf-objdump -ht main.o

main.o:     file format elf32-i386

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         0000007f  00000000  00000000  00000034  2**2
                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
  1 .data         00000000  00000000  00000000  000000b4  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  2 .bss          00000000  00000000  00000000  000000b4  2**2
                  ALLOC
  3 .rodata.str1.1 00000024  00000000  00000000  000000b4  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  4 .comment      00000012  00000000  00000000  000000d8  2**0
                  CONTENTS, READONLY
SYMBOL TABLE:
00000000 l    df *ABS*  00000000 main.c
00000000 l    d  .text  00000000 .text
00000000 l    d  .data  00000000 .data
00000000 l    d  .bss   00000000 .bss
00000000 l    d  .rodata.str1.1 00000000 .rodata.str1.1
00000000 l    d  .comment       00000000 .comment
00000000 g     F .text  0000007f main
00000000         *UND*  00000000 init_video
00000000         *UND*  00000000 gdt_install
00000000         *UND*  00000000 putch
00000000         *UND*  00000000 puts
00000018       O *COM*  00000001 gdt
00000006       O *COM*  00000001 gdtp
My link script (not sure if it's going to be relevant):

Code: Select all

OUTPUT_FORMAT("binary")
ENTRY(start)
phys = 0x00100000;
SECTIONS
{
  .text phys : AT(phys) {
    code = .;
    *(.text)
    *(.rodata*)
    . = ALIGN(4096);
  }
  .data . : AT(data)
  {
    data = .;
    *(.data)
    . = ALIGN(4096);
  }
  .bss . : AT(bss)
  {
    bss = .;
    *(.bss)
    . = ALIGN(4096);
  }
  end = .;
}
If I comment out the call to putch in main.c, I instead get undefined references to puts... if I remove the call to gdt_install, no errors!

Has anyone encountered a problem like this, or have any ideas as to further investigation?

Thanks
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: undefined reference link error when adding new function

Post by gerryg400 »

Also strangely, with the function call present, if I link all object files first using ld -r
Ignore what '-r' does. '-r' does not produce a fully linked output and will not complain about all unresolved references.

Code: Select all

i586-elf-ld -T link.ld -o kernel32.bin kernel_loader.o main.o stdio.o common.o gdt.o gdt.bin -y putch
What is the reason for 'gdt.bin' in the command ?
If a trainstation is where trains stop, what is a workstation ?
owst
Posts: 6
Joined: Tue Jul 06, 2010 3:22 pm

Re: undefined reference link error when adding new function

Post by owst »

gerryg400 wrote:Ignore what '-r' does. '-r' does not produce a fully linked output and will not complain about all unresolved references.
Even if I were then to call ld -T link.ld -o kernel32.bin temp.o? I thought that would take the relocatable output (is this the same/similar format to .o files created by GCC?) generated by the -r step and then using the link script create a fully linked output. I'm obviously misunderstanding something!
gerryg400 wrote:What is the reason for 'gdt.bin' in the command ?
As part of the GDT installation I call out (from C) to a assembly function. gdt.bin is the nasm compiled file. I'm including it in the list of files to ld, as I want the assembly and C code to be linked together.
Gigasoft
Member
Member
Posts: 856
Joined: Sat Nov 21, 2009 5:11 pm

Re: undefined reference link error when adding new function

Post by Gigasoft »

That doesn't work. The output from NASM must be an object file.
owst
Posts: 6
Joined: Tue Jul 06, 2010 3:22 pm

Re: undefined reference link error when adding new function

Post by owst »

Gigasoft wrote:That doesn't work. The output from NASM must be an object file.
Sorry, I didn't mention that I ran the following:

Code: Select all

> nasm -f elf gdt.asm -o gdt.bin
> file gdt.bin
gdt.bin: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped
Should this work, as it is an object file?
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: undefined reference link error when adding new function

Post by gerryg400 »

if I remove the call to gdt_install, no errors!
If gdt_install is in the gdt.asm file, I would be suspicious about this.
If a trainstation is where trains stop, what is a workstation ?
owst
Posts: 6
Joined: Tue Jul 06, 2010 3:22 pm

Re: undefined reference link error when adding new function

Post by owst »

gerryg400 wrote:If gdt_install is in the gdt.asm file, I would be suspicious about this.
gdt_install is in the C file, but gdt_install calls a function which is defined in gdt.asm.

Code: Select all

void gdt_install() {
    /* ... */
    gdt_reset();
}

Code: Select all

[bits 32]
[section .text]
global gdt_reset
extern gdtp

gdt_reset:
    lgdt [gdtp]
    mov ax, 0x10      ; 0x10 offset for data segment (sizeof(struct gdt_entry) * 2)
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax
    mov ss, ax
    jmp 0x08:gdt_reset2   ; 0x08 offset for code segment (sizeof(struct gdt_entry))
gdt_reset2:
    ret              ; ret back to C
User avatar
Candy
Member
Member
Posts: 3882
Joined: Tue Oct 17, 2006 11:33 pm
Location: Eindhoven

Re: undefined reference link error when adding new function

Post by Candy »

owst wrote:Should this work, as it is an object file?
As ugly as they are, we do tend to use extensions to figure out what a file is. Naming an object file .bin is the confusing part here; please rename it to .o or .obj (I suggest .o as it's an ELF).

Yes, that should work.
owst
Posts: 6
Joined: Tue Jul 06, 2010 3:22 pm

Re: undefined reference link error when adding new function

Post by owst »

Good point, I've made the change to avoid future confusion!

I still can't quite grasp how including another function call can cause the link to fail for a separate symbol... could anyone explain that?!
owst
Posts: 6
Joined: Tue Jul 06, 2010 3:22 pm

Re: undefined reference link error when adding new function

Post by owst »

I've been playing around trying to recreate the errors. If I move the gdt_install() function call to a specific place in the source code, I don't receive any errors and everything works fine:

Code: Select all

int main() {        
    
    init_video();
    
    putch('A');

    puts("<- print a single char there...\n");
   
    gdt_install();
    puts("asdf\n\n");
    
    int i;
    
    for (i = 0; i < 15; ++i) {
        if (i % 2 == 0) {
            puts("even\n");
        } else {
            puts("odd\n");
        }
    }
    
    return 0;
}
If I move the call above the first puts() call, I receive undefined references for puts!:

Code: Select all

...
init_video();

putch('A');

gdt_install();
   
puts("<- print a single char there...\n");
  
puts("asdf\n\n");

...

Code: Select all

i586-elf-ld -T link.ld -o kernel32.bin kernel_loader.o main.o stdio.o common.o gdt.o gdt_asm.o
main.o: In function `main':
main.c:(.text+0x2b): undefined reference to `puts'
main.c:(.text+0x37): undefined reference to `puts'
main.c:(.text+0x51): undefined reference to `puts'
main.c:(.text+0x63): undefined reference to `puts'


Next, if I move the call above putch(), it causes a undefined reference to putch:

Code: Select all

...
init_video();

gdt_install();

putch('A');
 
puts("<- print a single char there...\n");
  
puts("asdf\n\n");

...

Code: Select all

main.o: In function `main':
main.c:(.text+0x1f): undefined reference to `putch'
And finally, above init_video(), causes a undefined reference to init_video:

Code: Select all

...
gdt_install();

init_video();

putch('A');
 
puts("<- print a single char there...\n");
  
puts("asdf\n\n");

...

Code: Select all

main.o: In function `main':
main.c:(.text+0x15): undefined reference to `init_video'
What on earth is causing this error? It's like the gdt_install call is somehow "corrupting" other symbols...

Any ideas/suggestions?

O
Post Reply