Почему батут от PLT до GOT, а не прыгает прямо в GOT?

Я изучаю, как GOT и PLT используются в динамическом соединении. Меня смущает, почему каждый вызов динамически связанной функции, похоже, переходит на позицию в PLT, которая всегда переходит на одну и ту же позицию в GOT. Почему бы просто не перейти на эту позицию в GOT? Зачем нужен еще один слой косвенности?


Я, вероятно, в корне неправильно понимаю что-то о GOT и PLT, поэтому вот краткое описание моего концептуального понимания того, как используются PLT и GOT.

У нас есть функция FunctionX, соответствующая позиция в PLT, называемая PLT[X], и соответствующая позиция в GOT, называемая GOT[X]. Адрес PLT и GOT известен во время компиляции, а адрес FunctionX - нет.

Для вызова FunctionX:

1) Назовите (в смысле сборки) адрес PLT [X].

2) PLT [X] - это переход к значению, содержащемуся в GOT[X].

3a) Если FunctionX уже был разрешен, GOT[X] содержит адрес функции, поэтому шаг 2 - это переход к FunctionX.

3b) В противном случае GOT [X] содержит адрес кода, который разрешит адрес FunctionX во время выполнения, запишет этот адрес в GOT [X] и перейдет к FunctionX. В этом случае шаг 2 приводит к разрешению FunctionX и переходу к нему.

Какова цель шага 1?

Мое понимание этой темы схематично, поэтому, пожалуйста, укажите любые уточнения, которые могут помочь в этом вопросе.

1 ответ

Просто кое что для раздумий

Представьте себе первый вызов любого адреса в GOT[X] из некоторого клиентского кода (например, main). Как вы сказали в 3b), это вызовет код, который разрешит адрес FunctionX. Но как разрешающий код может узнать, что вы хотите разрешить FunctionX? Вы вызываете его как обычную функцию, вы не предоставляете никакой дополнительной информации для распознавателя о том, что это адрес FunctionX, который вы хотите исправить. Заглушка помещает в стек дополнительную информацию, прежде чем перейти к GOT[X].

Несколько последних абзацев этой статьи очень помогли.

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