Page 1 of 1

Linking error

Posted: Sun Jan 28, 2007 9:28 am
by manutd
I've been following the instructions on thispage, with one change: I used the NASM version instead of the gas version. It all built fine, but when I try to link, ld gives this error:
ld -T linker.ld loader.o kernel.o
loader.o: In function 'loader':
%path_to_project%/loader.asm:(.text+0x14): undefined reference to 'main'

Any ideas? What am I doing wrong?

Posted: Sun Jan 28, 2007 11:06 am
by Brynet-Inc
There is a good chance is has to do with adding an underscore into the loader.asm file.. _main instead of main.

I think GCC on some targets likes to append an underscore to function names.

It'd be more helpful if you posted the contents of those files.

(BTW - use the new wiki.. http://www.osdev.org/wiki/)

Posted: Mon Jan 29, 2007 6:26 am
by manutd
I even changed it to kmain in both files, it still didn't work.
Contents - kernel.c:

Code: Select all

void _main (void* mbd, unsigned int magic)
{
}
Contents - loader.asm:

Code: Select all

global _loader           ; making entry point visible to linker
extern _main             ; _main is defined elsewhere

; setting up the Multiboot header - see GRUB docs for details
MODULEALIGN equ  1<<0                   ; align loaded modules on page boundaries
MEMINFO     equ  1<<1                   ; provide memory map
FLAGS       equ  MODULEALIGN | MEMINFO  ; this is the Multiboot 'flag' field
MAGIC       equ    0x1BADB002           ; 'magic number' lets bootloader find the header
CHECKSUM    equ -(MAGIC + FLAGS)        ; checksum required

section .text
align 4
MultiBootHeader:
   dd MAGIC
   dd FLAGS
   dd CHECKSUM

; reserve initial kernel stack space
STACKSIZE equ 0x4000          ; that's 16k.

_loader:
   mov esp, stack+STACKSIZE           ; set up the stack
   push eax                           ; pass Multiboot magic number
   push ebx                           ; pass Multiboot info structure

   call  _main                        ; call kernel proper
               hlt                    ; halt machine should kernel return

section .bss
align 32
stack:
   resb STACKSIZE      ; reserve 16k stack on a quadword boundary
Contents - linker.ld:

Code: Select all

ENTRY (_loader)

SECTIONS
{
    . = 0x00100000;

    .text :
    {
        *(.text)
    }

    .rodata ALIGN (0x1000) :
    {
        *(.rodata)
    }

    .data ALIGN (0x1000) :
    {
        *(.data)
    }

    .bss :
    {
        _sbss = .;
        *(COMMON)
        *(.bss)
        _ebss = .;
    }
}
That's it!

Posted: Mon Jan 29, 2007 6:47 am
by Solar
The point Brynet-Inc had been trying to make is that, depending on configuration, GCC might or might not add underscores to symbols. Your _main from kernel.c might have become __main in the compiling.

Try objdump -D on your object files to find out which part of your toolchain (GCC / NASM) is doing what, then set -fleading-underscore or -fno-leading-underscore accordingly to make your GCC and NASM follow the same convention.

Posted: Tue Jan 30, 2007 6:28 am
by manutd
Neither option works, and it also doesn't work when I rename _main to kmain.

Posted: Tue Jan 30, 2007 9:02 am
by Otter
Have you tried objdump to find the mistake ? I would suggest to use nm:

Code: Select all

$ nm kernel.o
You'll get a list of symbols including all underscores and so on. Search your main or kmain and you'll see to what gcc changes its name.

Posted: Tue Jan 30, 2007 6:17 pm
by manutd
Thank you so much, gcc was appending an extra _, making it __main. Problem solved!