我使用lea rax, [rel _GLOBAL_OFFSET_TABLE_]
.
我区分了readelf -a
输出。但是,来自不同地址的噪音很多。
readelf -a get_got.so | diff -u - <(readelf -a get_got_rel.so) | less
最有趣的区别是:
--- readelf -a get_got.so
+++ readelf -a get_got_rel.so
....
-Dynamic section at offset 0xe40 contains 22 entries:
+Dynamic section at offset 0xe50 contains 21 entries:
...
- 0x0000000000000016 (TEXTREL) 0x0
0x000000006ffffffe (VERNEED) 0x3b0
0x000000006fffffff (VERNEEDNUM) 1
0x000000006ffffff0 (VERSYM) 0x398
- 0x000000006ffffff9 (RELACOUNT) 4
+ 0x000000006ffffff9 (RELACOUNT) 3
所以绝对版本有一个文本重定位。我不知道 Linux / ELF 动态链接可以在映射共享库后应用修复。但显然可以。(最好不要这样做,因为它弄脏了内存页面,所以它不再只是由磁盘上的文件支持。)
但我检查了 GDB,这就是发生的事情:在其中设置一个断点get_got
并运行它:
(gdb) disas
Dump of assembler code for function get_got:
=> 0x00007f9e77b235b0 <+0>: movabs rax,0x7f9e77d24000
0x00007f9e77b235ba <+10>: ret
objdump -dRC -Mintel get_got.so
: (注意没有换行-w
):
00000000000005b0 <get_got>:
5b0: 48 b8 00 10 20 00 00 movabs rax,0x201000
5b7: 00 00 00
5b2: R_X86_64_RELATIVE *ABS*+0x201000
5ba: c3 ret
感谢@Jester 的-R
提示;我通常使用objdump -dr ...
, not -R
,并且小写的 r 不会为.so
.
上get_got.o
,-r
显示movabs rax,0x0 2: R_X86_64_64 _GLOBAL_OFFSET_TABLE_
。
gcc -nostdlib -pie
也将 64 位绝对重定位链接到 PIE 可执行文件。(PIE 可执行文件是ELF 共享对象)。
PIC / PIE 中不允许的是 32 位绝对重定位:x86-64 Linux 中不再允许使用 32 位绝对地址?. 您收到链接器错误。像这样的寻址模式array[rcx*4]
在 PIC/PIE 代码中不可用,您需要单独的指令将地址放入寄存器。
lea rdi, [rel array]
是比64 位立即绝对值更好的选择,因为它更小,对 uop 缓存更友好,并且在加载时不需要修复。