Почему "символ @GOT" не разрешен в двоичном виде?
Вот пример файла сборки, test.s
.global main
main:
mov __progname@GOT, %eax // failed to compile
mov __progname@GOT(%ebx), %eax //succeed to compile
Я попытался скомпилировать его с -pie
флаг, но не удалось.
$ gcc -pie -o test test.s
osboxes@osboxes:/mnt/hgfs/VM_Shared/Reassemblabla/src$ gcc -pie -o test test.s
/usr/bin/ld: /tmp/ccPGMLlH.o: direct GOT relocation R_386_GOT32X against `__progname' without base register can not be used when making a shared object
/usr/bin/ld: failed to set dynamic section sizes: File format not recognized
collect2: error: ld returned 1 exit status
Ошибка сказала, В круговой двоичный доступ к GOT
запись доступна только через базовый регистр.
Вопрос.
Я не знаю, почему компилятор жалуется, как указано выше.
Более конкретно, почему __progname@GOT
не разрешена адресация на круговом бинарном коде?
Мое мнение.
Грузчик знает адрес __progname@GOT
во время загрузки пирога бинарный.
Таким образом, загрузчик может просто написать этот адрес по адресу __progname@GOT
во время загрузки.
Вот что может сделать загрузчик.
Поэтому я не могу понять, почему компилятор настаивает на доступе к регистру, какmov __progname@GOT(%ebx), %eax
,
1 ответ
PIE должен использовать относительную к ПК адресацию; ia32 это дерьмо, поэтому вам нужно сделать что-то вроде:
call thunk
add $_GLOBAL_OFFSET_TABLE__, %eax
mov __progname@GOT(%eax), %eax
ret
thunk:
mov (%esp), %eax
ret
Смещение уведомления от этого программного адреса к _GLOBAL_OFFSET_TABLE__ вычисляется для ссылки GOT. Таким образом, программа может быть загружена (в отличие от связанной или расположенной) по любому адресу и найдет GOT и все переменные, поскольку относительное смещение одинаково. Для справки, приведенная выше версия amd64 выглядит примерно так:
mov __progname(%rip), %rax
ret
Обратите внимание, что оба они сохраняют текст "чистым"....