Почему не все позиции скомпилированного кода независимы?

StackOverflow https://stackoverflow.com/questions/813980

  •  03-07-2019
  •  | 
  •  

Вопрос

При компиляции разделяемых библиотек в gcc опция -fPIC компилирует код как независимый от позиции. Есть ли какая-либо причина (производительность или нет), почему бы вам не компилировать весь код независимо от позиции?

Это было полезно?

Решение

Это добавляет косвенность. С позиционно-независимым кодом вы должны загрузить адрес своей функции, а затем перейти к нему. Обычно адрес функции уже присутствует в потоке команд.

Другие советы

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

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

http://en.wikipedia.org/wiki/Position_independent_code

Эта статья объясняет, как работает PIC, и сравнивает его с альтернативой - перемещение времени загрузки . Я думаю, что это актуально для вашего вопроса.

В дополнение к принятому ответу. Одной вещью, которая сильно ухудшает производительность кода PIC, является отсутствие «относительной IP-адресации». на х86. С «относительной 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 родственник» режим, который делает вещи много проще.

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

Это может быть приемлемым компромиссом для получения многопроцессорной обработки без системы виртуальной памяти, где вы доверяете процессам, чтобы они не вторгались в память друг друга, и может потребоваться загрузить определенное приложение по любому базовому адресу.

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

Кроме того, аппаратное обеспечение виртуальной памяти в большинстве современных процессоров (используемых большинством современных ОС) означает, что большое количество кода (все приложения пользовательского пространства, исключая необычное использование mmap и т. п.) не обязательно должны быть независимыми от позиции. Каждая программа получает свое собственное адресное пространство, которое, как она считает, начинается с нуля.

позиционно-независимый код в большинстве архитектур снижает производительность, поскольку требует дополнительного регистра.

Итак, это для повышения производительности.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top