【问题标题】:relocation and symbol table value重定位和符号表值
【发布时间】:2017-11-29 00:16:57
【问题描述】:

我有 main.c 文件,其中包含对外部函数 fun() 的调用

int main()
{
 fun();
}

readelf -r 的结果如下

偏移 0x298 处的重定位节 '.rela.text' 包含 3 个条目: 偏移信息类型 Sym。价值符号。姓名+加号 00000000000a 000b00000002 R_X86_64_PC32 0000000000000000 乐趣 - 4

我只想知道 info 字段(即符号表条目)是如何与符号 fun 映射的,为什么 sym.value 是 0000??

【问题讨论】:

  • 您是否在目标文件上调用readelf?当符号fun 还没有被链接器解析?
  • 是的,我在目标文件上调用了 readelf,目标文件不是由链接器创建的。链接器只是链接该目标文件,因此我们可以创建上述代码的目标文件,它会给出 readelf 的结果,如图所示我的问题
  • 目标文件不完整,它们基本上代表一个translation unit。在别处定义的符号根本无法解析,因此这些函数的值为零。
  • 感谢您的澄清,但什么是信息字段以及它如何映射到符号输入项??
  • 这个问题实际上与 C 几乎没有关系。您几乎可以在任何其他语言中拥有类似的测试用例,并且输出因系统而异。不幸的是,没有 other 标签。因此,我认为最好添加新标签(并删除C标签)关闭此问题,因为就目前而言,它不太可能是由正在寻找它的未来访问者发现,因此不太可能对这些未来访问者有用。我不知道任何更合适的标签,所以我投票结束这个问题。

标签: c


【解决方案1】:

请记住,C 标准实际上并没有具体说明它是如何工作的,下面的描述是一种非常常见的实现方法。


使用单个翻译单元保存代码:

int main() { fun(); }

从已编译(尚未链接)的目标文件中获得的信息基本上是:

symbol  status   value
------  ------   -----
main    defined  pointer to main within object
fun     needed   zero

这是因为它知道main 在哪里,但没有关于fun 的信息 - 稍后需要找到它。所以读取目标文件自然会返回fun的未知值。

当然,您还需要一些代码来定义fun,例如在另一个翻译单元中:

void fun(void) { puts("Hello, world."); }

编译this会产生以下信息:

symbol  status   value
------  ------   -----
fun     defined  pointer to fun within object
puts    needed   zero

正是 link 阶段将这些联系在一起。它采用both 对象文件(以及任何其他依赖项的对象/库文件,例如包含puts 的 C 运行时库)并将它们绑定在一起,对所有使用的代码进行调整未定义的符号。

所以你最终会得到一个可执行文件格式,其中所有符号都已知并且所有引用都已解析。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-12-09
    • 2014-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-21
    • 2018-03-21
    相关资源
    最近更新 更多