Я не понимаю, о чем ты спрашиваешь.
Если вам нужны record[0]
, record[12:15]
и record[35:39]
, ну, вот они. Иди, возьми их. Что вас останавливает?
Вам нужны эти элементы, собранные в их собственный меньший список?
Это добавляет косвенность. С позиционно-независимым кодом вы должны загрузить адрес своей функции и затем перейти к нему. Обычно адрес функции уже присутствует в потоке команд.
С позиционно-независимым кодом вы должны загрузить адрес своей функции и затем перейти к нему. Обычно адрес функции уже присутствует в потоке команд. С позиционно-независимым кодом вы должны загрузить адрес своей функции и затем перейти к нему. Обычно адрес функции уже присутствует в потоке команд.Кроме того, аппаратное обеспечение виртуальной памяти в большинстве современных процессоров (используется большинством современных ОС) означает, что большое количество кода (все приложения пользовательского пространства, исключая изворотливое использование mmap и т. П.) Не требуется быть независимым от позиции. Каждая программа получает свое собственное адресное пространство, которое, как она считает, начинается с нуля.
Да, есть причины производительности. Некоторые доступы фактически находятся под другим уровнем косвенности, чтобы получить абсолютную позицию в памяти.
Существует также GOT (Глобальная таблица смещений), в которой хранятся смещения глобальных переменных. Для меня это просто выглядит как таблица исправлений IAT, которая классифицируется как зависящая от положения википедией и несколькими другими источниками.
В дополнение к принятому ответу. Одной вещью, которая сильно ухудшает производительность кода PIC, является отсутствие «относительной IP-адресации» на x86. С помощью «относительной IP-адресации» вы можете запросить данные размером X байт из текущего указателя инструкции. Это сделало бы код PIC намного проще.
Переходы и вызовы, как правило, относительны к EIP, поэтому они не представляют проблемы. Однако доступ к данным потребует немного дополнительной хитрости. Иногда регистр будет временно зарезервирован как «базовый указатель» на данные, необходимые для кода. Например, распространенным методом является злоупотребление работой вызовов в x86:
call label_1
.dd 0xdeadbeef
.dd 0xfeedf00d
.dd 0x11223344
label_1:
pop ebp ; now ebp holds the address of the first dataword
; this works because the call pushes the **next**
; instructions address
; real code follows
mov eax, [ebp + 4] ; for example i'm accessing the '0xfeedf00d' in a PIC way
Этот и другие методы добавляют слой косвенности к доступу к данным. Например, GOT (глобальная таблица смещений), используемая компиляторами gcc.
x86-64 добавил «относительный RIP»
Поскольку реализация полностью независимого от позиции кода добавляет ограничение к генератору кода, которое может предотвратить использование более быстрых операций или добавить дополнительные шаги для сохранения это ограничение.
Это может быть приемлемым компромиссом для получения многопроцессорной обработки без системы виртуальной памяти, где вы доверяете процессам не вторгаться в память друг друга и, возможно, потребуется загрузить конкретное приложение по любому базовому адресу.
Во многих современных системах компромиссы производительности различны, а перемещение загрузчика часто обходится дешевле (это стоит любых сначала загружается временной код), чем лучшее, что может сделать оптимизатор, если у него есть свобода действий. Кроме того, наличие виртуальных адресных пространств скрывает большую часть мотивации в первую очередь для позиционной независимости.