Linux C符号的重定位信息?

Linux C符号的重定位信息?,第1张

当编译器生成一个目标文件后,其并不知道代码和变量最终的存储位置,也不知道定义在其他文件中的外部符号。因此编译器会生成一个重定位表目,里面存储着关于每一个符号的信息。这个表目告知链接器在合并目标文件时应该如何修改每个目标文件中对符号的引用。这种重定位表目存储在.rel.text 段中和.rel.data 段中。该表目可以理解为一个结构体,其中存储着每一个符号的重定位信息。

offset表示该符号在存储的段中的偏移值。symbol 代表该符号的名称,字符串实际存储在.strtab 段中,这里存储的是该字符串首地址的下标。type表示重定位类型,链接器只关心两种类型,一种是与PC相关的重定位引用,另一种是绝对地址引用。PC相关的重定位引用表示将当前的PC值(这个值通常是下一条指令的存储位置)加上该符号的偏移值。绝对地址引用表示将当前指令中已经指定的地址引用直接作为跳转的地址,不需要进行任何修改。有了这些信息,链接器就可以将符号在存储段中的偏移值加上该段在重定位后该段的新地址,这样就得到了一个新的引用地址,而这个引用地址就是该符号的最终地址。同样,在程序所有引用该地址的部分都要作修改,使用这个新的绝对地址代替旧的偏移地址。当新的符号地址被修改完毕之后,链接器的工作就结束了。

以write函数为例说明延迟绑定,如上图所示,当第一次调用write函数时候,程序会跳转到.plt表处

程序首先会跳转到0x601018处,我们看一下0x601018是什么

0x601018是一个地址,这个地址就是jmp命令的下一条指令的地址。因为是第一次第一次调用,此时got还没有添加write函数的实际地址。当重定位完成之后就不会执行0x400586处的指令了。

0x601010处存放的是一个地址即7ffff7dee6a0,这个地址是dl_runtime_reslove函数的地址。

所以重定位最终是调用dl_runtime_reslove函数去解析write函数的实际地址,解析成功将地址保存到.got.plt表中。以后在调用write函数流程就变为plt->got。

dl_runtime_reslove函数确定符号的过程如下:

根据rel_offset,找到重定位条目:

根据rel_entry中的符号表条目编号,得到对应的符号信息:

再找到符号信息中的符号名称:

获取符号对应的字符串仅仅是一小部分,具体的地址获取与link_map的实现息息相关,即压入堆栈的另一个参数,这一部分的原理与实现参考 此文

不管是>>还是2>>都属于追加重定向。也就说,新重定向的内容不会覆盖掉原有文件里的内容,而是另起一行。只不过>>,是只对正确的内容或者结果进行重定向;而2>>,只对错误的内容或结果进行重定向。

比如原有文件a.txt,里面有一内容this is a test。现在我执行了命令:ls -l >>a.txt, 那么这个时候,因为的ls -l这个命令是正确的,所以ls -l 这个命令的结果将会被追加到a.txt中,以行为单位,写在了this is a test这段内容下面。

相反如果我执行了命令aaaa 2>>a.txt,那么因为这个命令是错的,所以会把我执行的aaaa命令之后所提示的错误提示(比如: command not found)追加到a.txt,同样是在this is a test这段话的下面。

而>和2>却是不追加,而是覆盖掉原有内容,其他意思一样。

1、&>test 这个书上说是将所有输出重定向至test,那么&指的是1、2还是所有的输出文件描述符还是别的什么作用?

2、echo "hi" >&2 这句话中的&又是什么意思?我知道这句话是将hi重定向至stderr,那么&又是起的什么作用?


欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/yw/7315967.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-04-04
下一篇2023-04-04

发表评论

登录后才能评论

评论列表(0条)

    保存