.so 部分之间的距离是否始终保留,无论 .so 加载到内存中的哪个位置?
Are the distances between .so sections always preserved, no matter where in memory the .so gets loaded?
TLDR:.so 不知道它会被加载到哪里,但是每个段肯定知道其他段相对于它自己的位置?
我有以下 .c
文件:
int shared_variable = 3;
int shared_func()
{
return shared_variable;
}
我用PIC编译它:gcc -fpic -c -g shared.c
和objdump
它,看到正在使用的GOT(第1行),以及GOT入口的重定位(第2行),然后最后获取 shared_variable
的值(第 3 行):
8: 48 8b 05 00 00 00 00 mov rax,QWORD PTR [rip+0x0] # f <shared_func+0xf>
b: R_X86_64_REX_GOTPCRELX shared_variable-0x4
f: 8b 00 mov eax,DWORD PTR [rax]
然后我创建了一个共享库:gcc -shared -o libshared.so shared.o
,objdump
,然后看到 GOT 条目的重定位已经解决:
1101: 48 8b 05 d0 2e 00 00 mov rax,QWORD PTR [rip+0x2ed0] # 3fd8 <shared_variable-0x48>
1108: 8b 00 mov eax,DWORD PTR [rax]
因此这段代码现在假定 GOT 条目位于 .text
部分的这一部分的 0x2ed0
字节处。事实上,如果我 运行 readelf
我看到 .text
从 0x1040
开始,.got
从 0x3fd0
、0x2f90
开始离开。我还看到 .text
和 .got
在不同的段中。
.so
无法知道它将 实际上 加载到内存中的哪个位置,所以我假设地址在 readelf
部分 headers 只是建议。但是由于到 GOT 条目 (mov rax,QWORD PTR [rip+0x2ed0]
) 的距离是硬编码的,我假设 之间的距离 .so
的段将始终如程序 headers?这也感觉很明智,因为 .so
中的代码将如何找到 GOT?
The .so can't know where in memory it will actually be loaded though,
正确。
so I assume the addresses in readelfs section headers are just suggestions.
不正确。
在静态 link 之后,headers 部分的地址是固定的,并且将保持原样(相对于彼此)。但是请注意,headers 部分在运行时不是必需的,可以删除(例如,通过 strip
命令)——运行时没有任何东西关注它们。
But since the distance to the GOT entry (mov rax,QWORD PTR [rip+0x2ed0]) is hard coded, I assume the distances between the segments of the .so will always be as specified in the program headers?
正确。所有(可加载)段一起加载。也就是说,加载器计算出加载段需要多少 space all,然后执行单个 mmap(0, ...)
1。 mmap
(此 .so
的负载基础)的结果决定了此 .so
的 所有 段所在的位置。
1假设 non-prelinked .so
.
我找到了一个来源。在 John R. Levine 的链接器和加载器中,第 10.2 章:
Because the GOT is in the same loadable ELF file as the code that references it, and the relative addresses within a file don't change regardless of where the program is loaded, the code can locate the GOT with a relative address, load the address of the GOT into a register, and then load pointers from the GOT whenever it needs to address static data. [my emphasis]
因此,当链接文件时,ELF 文件内部 的相对地址确实是已知的,并且可以解决同一文件(例如 GOT)中符号的重定位那么
TLDR:.so 不知道它会被加载到哪里,但是每个段肯定知道其他段相对于它自己的位置?
我有以下 .c
文件:
int shared_variable = 3;
int shared_func()
{
return shared_variable;
}
我用PIC编译它:gcc -fpic -c -g shared.c
和objdump
它,看到正在使用的GOT(第1行),以及GOT入口的重定位(第2行),然后最后获取 shared_variable
的值(第 3 行):
8: 48 8b 05 00 00 00 00 mov rax,QWORD PTR [rip+0x0] # f <shared_func+0xf>
b: R_X86_64_REX_GOTPCRELX shared_variable-0x4
f: 8b 00 mov eax,DWORD PTR [rax]
然后我创建了一个共享库:gcc -shared -o libshared.so shared.o
,objdump
,然后看到 GOT 条目的重定位已经解决:
1101: 48 8b 05 d0 2e 00 00 mov rax,QWORD PTR [rip+0x2ed0] # 3fd8 <shared_variable-0x48>
1108: 8b 00 mov eax,DWORD PTR [rax]
因此这段代码现在假定 GOT 条目位于 .text
部分的这一部分的 0x2ed0
字节处。事实上,如果我 运行 readelf
我看到 .text
从 0x1040
开始,.got
从 0x3fd0
、0x2f90
开始离开。我还看到 .text
和 .got
在不同的段中。
.so
无法知道它将 实际上 加载到内存中的哪个位置,所以我假设地址在 readelf
部分 headers 只是建议。但是由于到 GOT 条目 (mov rax,QWORD PTR [rip+0x2ed0]
) 的距离是硬编码的,我假设 之间的距离 .so
的段将始终如程序 headers?这也感觉很明智,因为 .so
中的代码将如何找到 GOT?
The .so can't know where in memory it will actually be loaded though,
正确。
so I assume the addresses in readelfs section headers are just suggestions.
不正确。
在静态 link 之后,headers 部分的地址是固定的,并且将保持原样(相对于彼此)。但是请注意,headers 部分在运行时不是必需的,可以删除(例如,通过 strip
命令)——运行时没有任何东西关注它们。
But since the distance to the GOT entry (mov rax,QWORD PTR [rip+0x2ed0]) is hard coded, I assume the distances between the segments of the .so will always be as specified in the program headers?
正确。所有(可加载)段一起加载。也就是说,加载器计算出加载段需要多少 space all,然后执行单个 mmap(0, ...)
1。 mmap
(此 .so
的负载基础)的结果决定了此 .so
的 所有 段所在的位置。
1假设 non-prelinked .so
.
我找到了一个来源。在 John R. Levine 的链接器和加载器中,第 10.2 章:
Because the GOT is in the same loadable ELF file as the code that references it, and the relative addresses within a file don't change regardless of where the program is loaded, the code can locate the GOT with a relative address, load the address of the GOT into a register, and then load pointers from the GOT whenever it needs to address static data. [my emphasis]
因此,当链接文件时,ELF 文件内部 的相对地址确实是已知的,并且可以解决同一文件(例如 GOT)中符号的重定位那么