我正在努力理解链接是如何工作的。我有一个简单的C++代码
#include "a.h"
int Other() {
return 1;
}
int SomeFunction() {
Other();
Other();
Other();
return 0;
}
它生成以下重定位表。
$ readelf -r a.o
Relocation section '.rela.text' at offset 0x240 contains 3 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000000018 000900000004 R_X86_64_PLT32 0000000000000000 _Z5Otherv - 4
00000000001d 000900000004 R_X86_64_PLT32 0000000000000000 _Z5Otherv - 4
000000000022 000900000004 R_X86_64_PLT32 0000000000000000 _Z5Otherv - 4
Relocation section '.rela.eh_frame' at offset 0x288 contains 2 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000000020 000200000002 R_X86_64_PC32 0000000000000000 .text + 0
000000000040 000200000002 R_X86_64_PC32 0000000000000000 .text + f
看起来,其他()函数的调用站点都标记为R_X86_64_PLT32类型。当我检查R_X86_64_PLT32的定义时,它表示L+ and,其中L
表示用于符号的过程链接表条目的位置(区段偏移或地址),A
表示用于计算可重定位字段的值的加载项,P
表示要重新定位的存储单元的位置(区段偏移或地址)(使用r_offset计算)。
我不知道PLT作为符号的位置意味着什么。我的问题是
发布于 2021-10-12 16:42:02
我不是一个专家,有点晚,但据我所知,较新的GCC版本使用R_X86_64_PLT32而不是R_X86_64_PC32标记32位PC相关分支。
在x86-64上,对于32位PC相关分支,我们可以生成PLT32重定位,而不是PC32重定位,后者也可以用作32位PC相对分支的标记。如果在本地定义函数,链接器总是可以将PLT32重定位减少到PC32。本地函数应该使用PC32重新定位。(相关承诺)
因此,尽管重新定位条目的类型是R_X86_64_PLT32,链接器仍将使用R_X86_64_PC32计算(S +A)来修改重新定位目标,其中:
S
是符号的值(st_value
of Elf64_Sym
)A
是加载项(在您的例子中是-4
)P
是被重新定位的内存位置的地址( call
的地址开始到Other
)。因为Other
是一个本地函数。所以PLT在你的情况下根本不起作用。
如果您想获得关于所有节标题的概述(包括。.plt,.got,.got.plt .)您可以在EXEC/ DYN文件(编译和链接)上使用readelf -S
。或者只需使用objdump -d <file
,它也会显示不同的部分以及转储。
我希望这能解释一点。
为了完整起见,下面的例子类似于您的示例(我使用了C,但这不应该有什么区别):
我有一个文件rel.c
,它在other.c
中调用函数Other
。首先,我编译了两个文件gcc -c -o <name>.o <name>.c
。
readelf -r rel.o
Relocation section '.rela.text' at offset 0x198 contains 1 entry:
Offset Info Type Sym. Value Sym. Name + Addend
000000000015 000500000004 R_X86_64_PLT32 0000000000000000 Other - 4
如您所见,A
(加载项)是-4
,最终地址S
和P
尚不清楚。
在使用gcc -o main rel.o other.o
链接所有内容之后,我使用objdump -M intel -d main
获得二进制文件的完整转储。有趣的部分如下所示。
...
0000000000001139 <main>:
1139: 55 push rbp
113a: 48 89 e5 mov rbp,rsp
113d: 48 83 ec 10 sub rsp,0x10
1141: 89 7d fc mov DWORD PTR [rbp-0x4],edi
1144: 48 89 75 f0 mov QWORD PTR [rbp-0x10],rsi
1148: b8 00 00 00 00 mov eax,0x0
114d: e8 07 00 00 00 call 1159 <Other>
1152: b8 00 00 00 00 mov eax,0x0
1157: c9 leave
1158: c3 ret
0000000000001159 <Other>:
1159: 55 push rbp
115a: 48 89 e5 mov rbp,rsp
...
可以看到,DWORD
at 0x114e
持有偏移量0x7
,它可以与IP
一起使用以跳转到Other
子例程(0x1152 + 0x7
= 0x1159
)的地址。
这是使用S + A - P
= 0x1159 - 0x4 - 0x114e
= 7
计算的。
https://stackoverflow.com/questions/64424692
复制相似问题