Таким образом, большая часть двоичного файла состоит из таблицы перемещений? - PullRequest
2 голосов
/ 14 мая 2011

Я только что использовал objdump -x ... для проверки разделов PE-файла.

Существует около 90 000 строк записей о перемещениях:

reloc   92 offset  bc0 [524bc0] HIGHLOW
reloc   93 offset  bc4 [524bc4] HIGHLOW
    ....

Верно ли, что пространство большинствабольшинство файлов PE состоят из записей перемещений, как указано выше?

Для чего нужны эти записи?

ОБНОВЛЕНИЕ

Любой может объяснить, как записи переносаработать как выше?

1 Ответ

10 голосов
/ 23 мая 2011

Перемещения необходимы, когда в памяти есть базовый конфликт. Если динамически подключаемая библиотека хочет загрузить свой раздел кода в определенном пространстве памяти, но когда она уже была загружена другим модулем, она должна быть загружена в другом месте. Однако, загружая его в другое адресное пространство, он портит всю абсолютную ссылку, на которую ссылалась библиотека. Например, предположим, что исполняемый файл имеет глобальную переменную с именем int dummy;, а переменная находится в 0x602315. Всякий раз, когда к этой переменной обращаются / пишут, программа выполняет следующий код операции (при условии, что код находится в 0x524BBE, так же как и запись, которую вы упомянули):

0x524BBE: MOV EAX, DWORD PTR DS:[0x602315];//move dummy to eax register to do stuff

Когда библиотека загружается в другое пространство, 0x602315 не будет указывать на переменную, поскольку адресное пространство 0x602315 уже занято другим модулем. Поэтому, чтобы обойти эту проблему, вы должны указать загрузчику PE добавить / вычесть смещение (|new base address-expected base address|) к этому значению (0x602315). Для этого каждый PE содержит таблицу, называемую таблицей перемещения, и эта таблица содержит все смещения в вашем коде, относящиеся к этой переменной.

Итак, скажем, вместо 0x524000 (ожидаемое базовое смещение) библиотека была загружена в 0x700000. Затем загрузчик PE будет искать записи в таблице и добавлять смещение (0x700000-0x524000 = 0x1DC000) к смещению (0x602315), так что загруженный код будет выглядеть следующим образом:

0x700BBE: MOV EAX, DWORD PTR DS:[0x7DE315];//move dummy to eax register to do stuff

, который будет работать нормально, поскольку он указывает на правильное расположение переменной dummy.

Возвращаясь к вашему вопросу, вывод objdump показывает каждую запись этой таблицы. 92, вероятно, означает индекс записи, BC0 - относительный адрес кода, к которому вы обращаетесь к переменной, [524BC0] - результат относительного адреса + ожидаемое базовое смещение. и HIGHLOW - это просто тип перемещения (это по существу зарезервировано для будущего использования. В настоящее время используется только один тип перемещения (HIGHLOW), поэтому вам не нужно беспокоиться о других типах). Когда загрузчик читает эту запись, он изменит значение 0x524BC0, чтобы отразить это изменение.

Что касается вашего вопроса о мажоритарном пространстве PE, составленном из таблицы .reloc, ответ будет , это зависит . Если ваша программа делает частый доступ к глобальным переменным и константам, у нее будет огромная таблица перемещений, потому что там так много мест, которые должен обновлять загрузчик.

...