在“重定位有无效的符号索引”错误时会发生什么?

前端之家收集整理的这篇文章主要介绍了在“重定位有无效的符号索引”错误时会发生什么?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
这是一个复制问题的测试:
$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版本中会发生什么变化,都将受到热烈的欢迎.

解决方法

C程序特性(类Unix)

>每个程序分别编译成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

猜你在找的C&C++相关文章