在“重定位具有无效符号索引"期间发生什么?错误? [英] What happens during a "relocation has invalid symbol index" error?

查看:121
本文介绍了在“重定位具有无效符号索引"期间发生什么?错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下是重现该问题的测试:

Here is a test reproducing the problem:

$ echo "void whatever() {}" > prog.c
$ gcc prog.c

这会在GCC 4.8.4上产生以下错误:

This produces the following error on 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上,与此问题相关的错误消失了,而是产生了:

Note that on GCC 6.2.0 the errors related to this question disappear, and it instead produces just:

/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和其他地方对此进行了多次报道.

This has been reported a number of times by a number of users, on Stack Overflow, and elsewhere.

我想理解这个错误,而不是解决它(已经解决了).

I would like to understand this error, not solve it (it is already solved).

gcc-4.8 prog.c中没有main()函数的情况下执行gcc-4.8 prog.c时,会发生此错误.

This error happens when doing gcc-4.8 prog.c without a main() function inside prog.c.

我已经在binutils-source软件包上针对此错误进行了文本搜索.繁琐的谷歌搜索仅给了我一个有用的链接,可以帮助我更好地理解搬迁处理的概念.

I have done a text search for this error on the binutils-source package. A tedious googling gave me only one useful link helping me better understanding the concept of relocation handling.

错误的数量似乎并不取决于程序,这表明所考虑的重定位不是起源于此文件,而是由于缺少main()函数的直接结果.我假设这些索引错误的重定位中的3个可能是针对main()argcargv的,但仍有很多,这只是一个未经证实的假设.

The number of errors does not seem to depend on the program, which suggests the relocations in consideration do not originate in this file, but as a direct result of the missing main() function. I have hypothesized that 3 of these relocations with wrong indexes might be for main(), argc and argv, but many remain, and this is just an unproven hypothesis.

这是我的头等大事,我们将热情欢迎您提供任何有助于我更好地理解它的信息,或在以后版本的GCC中进行的更改.

This is quite above my head, and any information that helps me better understand it, or what changed in later versions of GCC, would be warmly welcome.

推荐答案

C程序功能(类似于Unix)

  • 每个程序都分别编译为elf格式
  • c程序可以使用外部变量/函数引用,稍后将对其进行链接
  • main不是您最初认为的程序的开始,c lib具有一个启动程序(crt1.o),该程序具有一个_start程序,该程序将调用我们的main并在main之后执行清理工作
  • 在上述结论中,我们可以知道,即使一个非常简单的程序(如OP所示)也需要链接
  • C Program Features (Unix-like)

    • every program is compiled separately into elf format
    • c program can use external variable/function reference, which is linked later
    • main is not the start of program as you originally thought, c lib has a starter program (crt1.o) which has a _start program which will invoke our main and do cleaning job after main
    • concludes above statement, we can know that even a very simple program as OP showed need to be linked
    • ELF有两个标头,如下所示:

      ELF has two headers, as following shows:

      • 节标题-用于链接多个小精灵以制作过程映像
      • 程序头-用于加载过程映像

      在这里,我们仅关注节标题结构:

      Here we only focus on section header structure:

          mapping<var_name, offset, size...>
          // and special cases
          mapping<external_var_name, offset, size...>
      

      每个程序都是单独编译的,这意味着地址分配是相似的(在linux的早期版本中,每个编译程序都以相同的虚拟地址-0x08000000开头,许多攻击都可以利用此地址,因此它更改为添加一些随机增量来解决该问题),因此可能存在一些重叠区域.这就是为什么需要地址重定位的原因.

      Every program is compiled separately, which means address allocation is similar (In the early version of linux, every compiled program start with same virtual address -- 0x08000000, and many attacks can make use of this, so it changes to adding some random delta to address to alleviate the problem), so there may exists some overlay area. This is why address relocation needed.

      重定位信息(偏移量,值等)存储在.rel.*部分:

      The relocation info (offset, value etc) is stored in .rel.* section:

          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文件中找不到符号,因此它抱怨并停止了链接过程.

      When the linker want to set the address of main in the process of relocation, it can't find a symbol in your compiled elf file, so it complains that and stop the linking process.

      此处是os实现的简化版本,

      Here is the simplified version of os implementations, start.c corresponds to crt1.o's source code:

          int entry(char *); // corresponds to main
      
          void _start(char *args) {
              entry(args);
              exit();
          }
      

      参考

      • ELF
      • 重定位
      • Ref

        • ELF
        • Relocation
        • 这篇关于在“重定位具有无效符号索引"期间发生什么?错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆