I built your code and a modified version using lea rax, [rel _GLOBAL_OFFSET_TABLE_]
.
I diffed the readelf -a
output. There's a lot of noise from different addresses, though.
readelf -a get_got.so | diff -u - <(readelf -a get_got_rel.so) | less
The most interesting difference is:
--- 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
So the absolute version has a text relocation. I didn't know Linux / ELF dynamic linking could apply fixups after mapping shared libraries. But apparently it can. (It's better not to, because it dirties the memory page so it's no longer just backed by the file on disk.)
But I checked with GDB, and that's what's going on: set a breakpoint in get_got
and run it:
(gdb) disas
Dump of assembler code for function get_got:
=> 0x00007f9e77b235b0 <+0>: movabs rax,0x7f9e77d24000
0x00007f9e77b235ba <+10>: ret
objdump -dRC -Mintel get_got.so
: (note line wrapping without -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
Thanks @Jester for the -R
tip; I normally use objdump -dr ...
, not -R
, and lower-case r doesn't print any relocations for the .so
.
On get_got.o
, -r
shows movabs rax,0x0 2: R_X86_64_64 _GLOBAL_OFFSET_TABLE_
.
gcc -nostdlib -pie
will link 64-bit absolute relocations into PIE executables as well. (A PIE executable is an ELF shared object).
What isn't allowed in PIC / PIE are 32-bit absolute relocations: 32-bit absolute addresses no longer allowed in x86-64 Linux?. You get a linker error. Addressing modes like array[rcx*4]
aren't usable in PIC/PIE code, you need a separate instruction to get the address into a register.
lea rdi, [rel array]
is a much better choice than a 64-bit immediate absolute, because it's smaller and more friendly to the uop cache, and doesn't require a fixup when loading.