Как компоновщик gcc получает размер функции? - PullRequest
0 голосов
/ 04 сентября 2018

В результате изучения формата ELF я вижу, что в объектном файле есть символ, соответствующий каждой функции, и соответствующая запись в таблице символов имеет значение st_size, что означает размер функции.

Проблема в том, что исполняемый файл был успешно создан, хотя я изменил st_size конкретной функции в объектном файле и связал ее. Следующий код является тестовым кодом, который я использовал.

// In main.c,

int main(void)
{
    myprintf("TEST");
}

// In log.c

#include <stdio.h>
void myprintf(const char *str)
{
    printf(str);
}

В приведенном выше коде я изменил значение st_size функции myprintf в файле log.o и связал файлы log.o и main.o. По умолчанию значение st_size было 0x13. Я проверил это, изменив его на 0x00. Я проверил это, изменив его на 0x40. Но функция myprintf файла результатов a.out исправна. Как компоновщик определяет размер каждой функции?

1 Ответ

0 голосов
/ 17 сентября 2018

Ну, во-первых, я хотел бы начать со старой поговорки о том, что для человечества более вероятно найти теорию всего и объединить квантовую механику с общей теорией относительности, а не понять оптимизацию и дерево решений линкера.

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

Допустим, у вас есть две единицы компиляции, каждая из которых содержит три последовательных функции, зачем нужно знать размер каждой функции? Не достаточно ли фиксированного разрешенного виртуального адреса, предоставленного этой функции этим конкретным компоновщиком, для перемещения? и истинный ответ - достаточно иметь только смещение функции в объектном файле, чтобы связать различные модули компиляции в один исполняемый файл.

Однако, с учетом вышесказанного, некоторые исполняемые форматы, такие как ELF , не предлагают вам смещение для машинного кода функции в модуле компиляции, и вы должны вычислить его самостоятельно, действительно используя смещение этого раздела в файле ELF и размер каждой записи символа в разделе, указанном таблицей символов. это просто означает, что если бы у вас было , как я уже говорил ранее, два модуля компиляции с тремя функциями каждый после повреждения записи размера в таблице символов, так как компоновщик попытался бы преобразовать модули компиляции в один исполняемый файл , это просто испортило бы его, и ваш исполняемый файл быстро вызвал бы вас. Я пытался сделать это у себя дома, и вот результаты, которые я получил:

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

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

надеюсь, что это как-то ответит на ваш вопрос, я был бы более чем рад помочь, если вы хотите более глубокую демонстрацию этого

...