Search code examples
clinkeroperating-systemldbare-metal

ld: warning: cannot find entry symbol main; not setting start address


While reading the book "Operating Systems From 0 to 1", i'm currently trying to build a debuggable program on bare metal.

I'm compiling the following program:

void main() {}

using gcc -ffreestanding -nostdlib -gdwarf-4 -m32 -ggdb3 -c os.c -o os.o without an error. But when running ld -m elf_i386 -nmagic -T os.ld os.o -o os.o on the output, os.ld being:

ENTRY(main);

PHDRS
{
    headers PT_PHDR PHDRS;
    code PT_LOAD FILEHDR PHDRS;
}

SECTIONS
{
    .text 0x600: ALIGN(0x100) { *(.text) } :code
    .data : { *(.data) }
    .bss : { *(.bss) }
    /DISCARD/ : { *(.eh_frame) }
}

it throws the following error:

ld: warning: cannot find entry symbol main; not setting start address

Altough according to readelf os.o contains the symbol "main". output of readelf -s os.o:

Symbol table '.symtab' contains 23 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 00000000     0 FILE    LOCAL  DEFAULT  ABS os.c
     2: 00000000     0 SECTION LOCAL  DEFAULT    3
     3: 00000000     0 SECTION LOCAL  DEFAULT    5
     4: 00000000     0 SECTION LOCAL  DEFAULT    6
     5: 00000000     0 SECTION LOCAL  DEFAULT    7
     6: 00000000     0 SECTION LOCAL  DEFAULT    8
     7: 00000000     0 SECTION LOCAL  DEFAULT   10
     8: 00000000     0 SECTION LOCAL  DEFAULT   11
     9: 00000000     0 SECTION LOCAL  DEFAULT   13
    10: 00000000     0 SECTION LOCAL  DEFAULT   17
    11: 00000000     0 SECTION LOCAL  DEFAULT   19
    12: 00000000     0 SECTION LOCAL  DEFAULT   21
    13: 00000000     0 SECTION LOCAL  DEFAULT   22
    14: 00000000     0 SECTION LOCAL  DEFAULT   15
    15: 00000000     0 SECTION LOCAL  DEFAULT   23
    16: 00000000     0 NOTYPE  LOCAL  DEFAULT    2 wm4.0.5fa2ff0e40930321219
    17: 00000000     0 SECTION LOCAL  DEFAULT   20
    18: 00000000     0 SECTION LOCAL  DEFAULT    1
    19: 00000000     0 SECTION LOCAL  DEFAULT    2
    20: 00000000    20 FUNC    GLOBAL DEFAULT    3 main
    21: 00000000     0 FUNC    GLOBAL HIDDEN     7 __x86.get_pc_thunk.ax
    22: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND _GLOBAL_OFFSET_TABLE_

Any idea what the problem might be?


Solution

  • You are trashing your os.o (input same as output)

    Change:

    ld -m elf_i386 -nmagic -T os.ld os.o -o os.o
    

    Into:

    ld -m elf_i386 -nmagic -T os.ld os.o -o osx
    

    Thanks, that fixed it. I was trying to overwrite it on purpose. Can you explain why it caused that error? – Felix B.

    ld [and most such build commands] do not allow an input file to be specified as an output file.

    ld may have to read os.o several times while writing the -o osx output file.

    The simple construction is that we open a file for read and an output file for writing when the program starts.

    For what you wanted, the program would have to detect that infile and outfile are the same and create a temp copy of infile.

    Too difficult to guarantee in the general case. It's rarely used and would slow things down.

    Also, if you put the commands in a makefile:

    all: osx
    
    os.o: os.c
        gcc -ffreestanding -nostdlib -gdwarf-4 -m32 -ggdb3 -c os.c -o os.o
    
    osx: os.o os.ld
        ld -m elf_i386 -nmagic -T os.ld os.o -o osx
    

    If ld produced an error, make would remove the osx file.

    Consider that if os.o was the the output file, this would mess up the dependencies that make relies on.