ld:警告:找不到入口符号 main;没有设置起始地址

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

在阅读“从 0 到 1 的操作系统”一书时,我目前正在尝试在裸机上构建可调试程序。

我正在编译以下程序:

void main() {}

使用gcc -ffreestanding -nostdlib -gdwarf-4 -m32 -ggdb3 -c os.c -o os.o没有错误。 但是当输出 运行 ld -m elf_i386 -nmagic -T os.ld os.o -o os.o 时, os.ld 是:

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) }
}

它抛出以下错误:

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

尽管根据 readelf os.o 包含符号“main”。 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_

知道问题出在哪里吗?

你正在破坏你的 os.o(输入与输出相同)

变化:

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

进入:

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 [以及大多数此类构建命令] 不允许 允许将输入文件指定为输出文件。

ld 在写入 -o osx 输出文件时可能需要多次读取 os.o

简单的构造就是我们在程序启动时打开一个文件用于读,一个输出文件用于写。

对于您想要的,程序必须检测到 infile 和 outfile 相同并创建 infile 的临时副本。

一般情况下很难保证。它很少使用并且会减慢速度。

此外,如果您将命令放在 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

如果 ld 产生错误,make 将删除 osx 文件。

考虑一下,如果 os.o 是输出文件,这会弄乱 make 所依赖的依赖项。