【问题标题】:Why are some relocations .text + addend instead of symbol's name + addend?为什么有些重定位是 .text + addend 而不是符号名称 + addend?
【发布时间】:2021-07-08 14:33:40
【问题描述】:

为什么 ELF 文件中有一些重定位条目是 symbol name + addend 而其他的是 section + addend?我希望消除一些困惑并更深入地了解 ELF。以下是我的调查。

我有一个非常简单的 C 文件,test.c:

#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>

static void func1(void)
{
    fprintf(stdout, "Inside func1\n");
}

// ... a couple other simple *static* functions

int main (void)
{
    func1();

    // ... call some other functions

    exit(EXIT_SUCCESS);
}

然后我将它编译成一个目标文件:

clang -O0 -Wall -g -c test.c -o test.o

如果查看readelf -r test.o 的重定位,我会看到引用我的静态函数的条目如下(这个是从.rela.debug_info 部分挑选的):

Offset            Info              Type         Symbol's Value    Symbol's Name + Addend
...
000000000000006f  0000000400000001  R_X86_64_64  0000000000000000 .text + b0
...

为什么将这些函数称为section + addend 而不是symbol name + addend?我使用readelf -s test.o 看到.symtab 中的函数条目:

Num: Value            Size Type Bind  Vis     Ndx Name
  ...
  2: 00000000000000b0 31   FUNC LOCAL DEFAULT 2   func1
  ...

此外,当我反汇编目标文件(通过objdump -d)时,我看到函数在那里并且没有优化成main 或任何东西。

如果我不将函数设为静态,然后查看重定位,当类型为 R_X86_64_64 时,我会看到与以前相同的情况,但我也会看到使用符号名称的条目加上一个类型为R_X86_64_PC32 的加数。所以例如在.rela.text:

Offset            Info              Type           Symbol's Value    Symbol's Name + Addend
...
00000000000000fe  0000001200000002  R_X86_64_PC32  0000000000000000  func1 + 1c
...

如果更多示例/readelf 输出会有所帮助,请告诉我。感谢您抽出宝贵时间阅读本文。

【问题讨论】:

    标签: c linker clang elf symbol-table


    【解决方案1】:

    为什么将这些函数称为节+加数而不是符号名+加数?

    不保证静态函数的函数名称在链接时出现。您可以使用例如删除它们objcopy --strip-unneededobjcopy --strip-symbol,结果还是会链接。

    我看到.symtab 中的函数条目使用readelf -s test.o

    我相信保留它们的唯一原因是为了帮助调试,链接器根本不使用它们。但是我没有通过查看链接器源来验证这一点,因此没有回答这个related question

    【讨论】:

      【解决方案2】:

      Eli Bendersky 的博客在 his blog post 中也提到了这一点。来自标题为“额外功劳:为什么需要呼叫重定位?”的部分:

      然而,简而言之,当 ml_util_func 是全局的时,它可能会在可执行文件或其他共享库中被覆盖,因此在链接我们的共享库时,链接器不能只假设偏移量是已知的并对其进行硬编码 [12 ]。它使所有对全局符号的引用都可重定位,以允许动态加载器决定如何解析它们。这就是为什么声明函数 static 会有所不同 - 因为它不再是全局的或导出的,链接器可以在代码中硬编码它的偏移量。

      应该阅读完整的帖子以获得完整的上下文,但我想我会在这里分享它,因为它提供了比我的问题更好的示例,并强化了 Employed Russian 提供的解决方案。

      【讨论】:

        猜你喜欢
        • 2015-12-27
        • 2014-08-20
        • 2012-04-26
        • 1970-01-01
        • 1970-01-01
        • 2017-05-29
        • 2017-03-21
        • 1970-01-01
        相关资源
        最近更新 更多