Почему определенная функция помещена в таблицу перемещения - PullRequest
2 голосов
/ 21 февраля 2020

Я изучаю, как работает компоновщик в Linux. Вот мой код в качестве примера:

// main.c
int printf(const char *format, ...);

void func1(int i)
{
    printf("%d\n", i);
}

int main(void)
{
    func1(1);
    return 0;
}

Я выполняю команду gcc -c main.c и получаю файл obj с именем main.o.

Затем я выполняю команду objdump -r main.o и вот это вывод:

main.o:     file format elf64-x86-64

RELOCATION RECORDS FOR [.text]:
OFFSET           TYPE              VALUE
0000000000000011 R_X86_64_32       .rodata
000000000000001b R_X86_64_PC32     printf-0x0000000000000004
000000000000002c R_X86_64_PC32     func1-0x0000000000000004


RELOCATION RECORDS FOR [.eh_frame]:
OFFSET           TYPE              VALUE
0000000000000020 R_X86_64_PC32     .text
0000000000000040 R_X86_64_PC32     .text+0x0000000000000022

Если я прав, objdump -r покажет нам все таблицы перемещений в файле obj. В этом случае printf и func1 все помещаются в таблицу перемещения.

printf не определено в этом файле C, поэтому его необходимо переместить, но почему может func1 быть найденным в таблице перемещения тоже? Насколько я понимаю, func1 должен быть четко определен и может быть найден в разделе .text, его не нужно перемещать, верно?

1 Ответ

1 голос
/ 21 февраля 2020

Записи перемещения - это местоположения, которые необходимо корректировать при определении адресов секций. Во многих архитектурах, включая x86, можно писать независимый от позиции код, который ссылается на объекты или функции с помощью смещений из одного места в разделе (и поэтому смещения не изменяются при перемещении всего раздела) и может ссылаться на объекты или функции смещениями по сечениям с некоторой дополнительной помощью компоновщика (и поэтому смещения не изменяются после связывания, и все объединенное изображение может быть смещено в памяти).

Однако тот факт, что это возможно, делает не означает, что ваши инструменты сборки используют независимый от позиции код. В macOS компоновщику по умолчанию разрешено удалять «мертвые подсекции» из кода, что может изменять смещения между вещами в секциях. Это может препятствовать использованию позиционно-независимого кода.

По какой-то причине кажется, что используемые вами инструменты с переключателями, которые вы используете, не генерируют позиционно-независимый код. Таким образом, когда есть ссылка на printf или func1, генерируется перемещаемая ссылка на нее, что приводит к записи перемещения, которая должна быть откорректирована компоновщиком или загрузчиком.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...