$echo "void whatever() {}" > prog.c $gcc prog.c
这会在GCC 4.8.4上产生以下错误:
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 0 has invalid symbol index 11 /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 1 has invalid symbol index 12 /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 2 has invalid symbol index 2 /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 3 has invalid symbol index 2 ... etc ... /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 18 has invalid symbol index 13 /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 19 has invalid symbol index 21 /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_line): relocation 0 has invalid symbol index 2 /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crt1.o: In function `_start': (.text+0x20): undefined reference to `main' collect2: error: ld returned 1 exit status
请注意,在GCC 6.2.0中,与此问题相关的错误消失,而只是产生:
/usr/lib/x86_64-linux-gnu/crt1.o: In function `_start': (.text+0x20): undefined reference to `main' collect2: error: ld returned 1 exit status
这已经被一些用户多次报道,在Stack Overflow和其他地方.
当在gcc-4.8 prog.c中没有main()函数prog.c.时,会发生此错误.
我在binutils-source包上做了这个错误的文本搜索.一个乏味的谷歌搜索让我只有one useful link helping me better understanding the concept of relocation handling.
错误的数量似乎不取决于程序,这表明考虑的重定位不是源于此文件,而是由于缺少main()函数的直接结果.我假设有3个错误索引的迁移可能是main(),argc和argv,但很多仍然存在,这只是一个未经证实的假设.
这是非常高于我的头脑,任何有助于我更好地了解它的信息,或者在后来的GCC版本中会发生什么变化,都将受到热烈的欢迎.
解决方法
>每个程序分别编译成elf格式
> c程序可以使用外部变量/函数引用,这是后来链接的
>主要不是您最初想到的程序的开始,c lib有一个启动程序(crt1.o),它有一个_start程序,它会调用main和main后执行清理任务
>上面的结论,我们可以知道,即使是一个非常简单的程序,OP显示需要链接
ELF格式
ELF有两个标题,如下所示:
> section header – 用于链接多个elf来制作流程图像
>程序头 – 用于加载过程映像
这里我们只关注节头结构:
mapping<var_name,offset,size...> // and special cases mapping<external_var_name,size...>
每个程序分别编译,这意味着地址分配是相似的(在linux的早期版本中,每个编译的程序都以相同的虚拟地址开始 – 0x08000000,许多攻击可以利用这一点,所以它改变为添加一些随机的delta地址来缓解问题),所以可能存在一些覆盖区域.这就是为什么需要重定位地址.
搬迁
重定位信息(偏移量,值等)存储在.rel.*部分中:
Relocation section '.rel.text' at offset 0x7a4 contains 2 entries: Offset Info Type Sym.Value Sym. Name 0000000d 00000e02 R_386_PC32 00000000 main 00000015 00000f02 R_386_PC32 00000000 exit Relocation section '.rel.debug_info' at offset 0x7b4 contains 43 entries: Offset Info Type Sym.Value Sym. Name 00000006 00000601 R_386_32 00000000 .debug_abbrev 0000000c 00000901 R_386_32 00000000 .debug_str
当链接器想要在重定位的过程中设置main的地址时,它在您编译的elf文件中找不到符号,所以它抱怨并停止链接过程.
例
Here是os实现的简化版本,start.c对应于crt1.o的源代码:
int entry(char *); // corresponds to main void _start(char *args) { entry(args); exit(); }
参考
> ELF
> Relocation