Почему не весь код компилируется независимо от положения?


87

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


2
Но wowest не совсем правильно. Многие вызовы функций и переходы используют относительные переходы, поэтому им даже не нужна таблица переходов после перемещения.
Неизвестный

глядя на сгенерированный код сборки, кажется, что адрес функции загружается, тогда как код, отличный от fpic, кажется, это просто переход. Я неправильно понимаю ваше заявление?
ojblass 02

@ojblass я имею в виду, что некоторые переходы похожи на "переход на 50 инструкций вперед" или "переход на 5 инструкций назад" вместо "переход на 0x400000". Так что сказать, что вам нужно каждый раз загружать адрес с -fPIC, не совсем верно.
Неизвестный

Статья в Википедии дает хорошее описание. По сути, на некоторых архитектурах нет прямого способа перейти к относительному адресу. Следовательно, использование PIC на этих архивах обходится дороже. См. Ответ @ EvanTeran для получения дополнительной информации.
Алексей Шолик

Ответы:


68

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


33

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


16
@Nick: Я не согласен. Если это поможет спрашивающему, это ответ. Указание на одну или две статьи может предоставить много информации.
Эли Бендерски

5
В этом посте нет заключения, только ссылка на статью. Даже не догадывается, что PIC не используется по умолчанию из-за проблем с производительностью.
Ник

10
Хотя эта ссылка может дать ответ на вопрос, лучше включить сюда основные части ответа и предоставить ссылку для справки. Ответы, содержащие только ссылки, могут стать недействительными, если ссылка на страницу изменится.
Роб

4
@Rob: продуктивно было бы предложить правку, а не использовать комментарии для нытья. Этому ответу 4 года. В то время у SO были менее строгие правила относительно того, как должен выглядеть ответ
Эли Бендерски

6
Этот пост появился в разделе «Просмотр» с просьбой сделать это, и я сделал это. Кто-то еще отметил это. «Нюхающий комментарий» автоматически создается SO, а не мной.
Роб

27

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

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

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


23

В дополнение к принятому ответу. Одна вещь, которая сильно ухудшает производительность кода PIC, - это отсутствие «относительной IP-адресации» на x86. С «относительной IP-адресацией» вы можете запросить данные размером X байтов от текущего указателя инструкции. Это сделает код PIC намного проще.

Переходы и вызовы обычно относятся к EIP, поэтому на самом деле это не проблема. Однако для доступа к данным потребуется небольшая хитрость. Иногда регистр будет временно зарезервирован как «базовый указатель» на данные, необходимые для кода. Например, распространенным приемом является злоупотребление принципом работы вызовов на x86:

Этот и другие методы добавляют уровень косвенности при доступе к данным. Например, GOT (глобальная таблица смещений), используемая компиляторами gcc.

x86-64 добавил режим «относительного RIP», который значительно упрощает работу.


1
IIRC MIPS также не имеет адресации относительно ПК, за исключением относительных скачков
phuclv

1
Это распространенный метод, используемый в шелл-коде для получения адреса, с которого он выполняется. Я использовал это в нескольких решениях CTF.
sherrellbc

2

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

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

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


1

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


4
Но даже при использовании PIC-кода VM-MMU необходим, чтобы одна и та же библиотека .so загружалась в память только один раз, когда она используется разными исполняемыми файлами.
мммммммм

1

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

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


0

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


-5

Вопрос датируется 2009 годом. Прошло десять лет, и теперь весь код фактически независим от позиции. Теперь это обеспечивается операционными системами и компиляторами. Нет возможности отказаться. Весь код принудительно компилируется с помощью PIE, и флаг -no-pic / -no-pie игнорируется как часть этого оправдания ASLR. Причина этого в том, чтобы замедлять работу приложений, которые раньше были быстрыми, и продавать новое оборудование под видом повышения безопасности. Это совершенно иррационально, потому что теперь большие объемы памяти позволяют нам вообще избавиться от ада динамического связывания, компилируя все приложения статически.

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

Вы не жалуетесь, потому что даже не подозреваете, что все эти обучающие колеса мешают вашему коду. Что я могу сказать? Наслаждайтесь в 2 раза более медленным программным обеспечением с их PIC прямо сейчас! Более того, с появлением LLVM скоро появится принудительный JIT (управляемый код) без доступа к встроенной сборке x86, что еще больше замедлит любой код C / C ++. «Те, кто жертвуют свободой ради безопасности, не заслуживают того же».


Это просто констатация фактов: 10 лет назад PIC был необязательным, но сегодня он является обязательным и обязательным по умолчанию. Я сомневаюсь, что код, отличный от PIE, будет поддерживаться в следующих выпусках ОС. Точно так же, как поддержка реального режима была прекращена после Windows 9x. Таким образом, вопрос о том, использовать или не использовать PIC, становится скорее темой теоретической информатики, если вы каким-то образом не разблокируете свою ОС и не включите для нее поддержку. Самое важное, что люди должны знать о PIC, это то, что он достаточно медленный, чтобы компиляторы до сих пор поддерживали статическую компиляцию, и были статические версии большинства библиотек DLL.
SmugLispWeenie

2
Ваши первые пару предложений - это просто констатация фактов. Остальное - мнение, граничащее с заговором.
Митч Линдгрен

Ну просто поговорите с людьми, спросите их мнение по этому поводу. Я лично обнаружил, что PIC vs non-PIC также стал вопросом идеологии. PIC - это программный эквивалент коммунизма, когда код производится массово, и каждый получает одну и ту же копию. Non-PIC - это программный эквивалент капитализма, где существует множество конкурирующих версий одного и того же кода. Итак, люди с более левым мышлением подсознательно поддерживают PIC, чтобы доказать, что их любимая идеология может работать, по крайней мере, в вычислительной технике. Эти же люди посоветовали бы вам не использовать лично модифицированный libpng.
SmugLispWeenie

3
Разве мы не можем иметь политические тирады на веб-сайте программирования, пожалуйста, спасибо
Райан МакКэмпбелл,
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.