В некоторых архитектурах (например, x86_64), где можно ссылаться на данные (например, mov) и код (jmp, call), используя режим относительной адресации ПК (RIP), действительно ли существует техническая причина, оправдывающая необходимость таких структур (получил, плт)?
Я имею в виду, если я хочу переместить глобальные данные (например) в регистр, я мог бы сделать следующую инструкцию (стандартный PIE):
mov rax, QWORD PTR [rip + 0x2009db]
mov eax, DWORD PTR [rax]
(где 0x2009db - смещение между rip и правой записью в блоке, содержащем адрес символа)
И почему мы не можем сделать что-то подобное:
mov rax, rip + 0xYYYYYY
mov eax, DWORD PTR [rax]
(0xYYYYYYY - прямая дельта между значением RIP и символом (например, глобальной переменной))
Я не привык делать ASM, поэтому мой пример, возможно, неверен. Но моя идея такова: почему бы просто не вычислить абсолютный адрес символа на основе RIP, поместить его в EAX и затем получить доступ к его содержимому. Если набор инструкций позволяет делать что угодно с относительной адресацией, зачем использовать такие структуры (got, plt)?
Тот же вопрос будет применяться для инструкций call / jmp.
Это потому, что набор инструкций этого не позволяет?
Это потому, что значение смещения не может охватить все адресное пространство? Но .. это важно? Поскольку структура раздела поддерживается, он отображается в виртуальном адресном пространстве процесса (например, раздел .dat, за которым следует .got или что-то подобное). Я имею в виду, почему смещение было бы больше при обращении непосредственно к адресу символа вместо адреса входа в полученном?
Другая причина?
Спасибо!