Я создал ваш код и модифицированную версию, используя 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 ...
, а не -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-битное абсолютное перемещение: 32-битные абсолютные адреса больше не разрешены в x86-64 Linux?. Вы получаете ошибку компоновщика. Режимы адресации, такие как array[rcx*4]
, не могут использоваться в коде PIC / PIE, вам нужна отдельная инструкция для ввода адреса в регистр.
lea rdi, [rel array]
- намного лучший выбор, чем 64-битный немедленный абсолют, потому что он меньше по размеру и более удобен для кэша uop и не требует исправления при загрузке.
person
Peter Cordes
schedule
18.12.2017
-pie
. Затем вы должны увидеть запись о динамическом перемещении в окончательном двоичном выводе. РЕДАКТИРОВАТЬ: о, вы сделали.so
... ну, тогда вы должны увидеть перемещение там. - person Jester   schedule 18.12.2017_GLOBAL_OFFSET_TABLE_
в 64-битном коде, вы просто используете относительную адресацию сGOTPCREL
. - person Jester   schedule 18.12.2017mov eax, [rel foo wrt ..got]
. - person Jester   schedule 18.12.2017