Почему "символ @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

Обратите внимание, что оба они сохраняют текст "чистым"....

Другие вопросы по тегам