Подтвердить что ты не робот

Почему fPIC абсолютно необходим на 64, а не на 32-битных платформах?

Недавно я получил:

... перемещение R_X86_64_32 против "локального символа" не может использоваться при создании общего объекта; перекомпилировать с помощью -fPIC

при попытке скомпилировать программу как общую библиотеку.

Теперь решение этого не слишком сложно (перекомпилируйте все зависимости с -fPIC), но после некоторых исследований выясняется, что эта проблема присутствует только на платформах x86-64. На 32-битной основе любой зависимый от позиции код может быть перемещен динамическим загрузчиком.

Лучший answer Я мог бы найти:

x86 поддерживает поддержку .text relocations (что происходит, когда у вас есть код зависимости от позиции). Эта поддержка стоит дорого, а именно, что каждый страница, содержащая такое перемещение, становится в основном не разделенной, даже если она сидит в общей библиотеке, тем самым нарушая саму концепцию совместного использования ЛИЭС. Поэтому мы решили запретить это на amd64 (плюс это создает проблемы, если значение требует более 32 бит, поскольку все .text-релоки имеют размер 'word32')

Но я не считаю это вполне адекватным. Если это так, что перемещение испортит концепцию общих библиотек, почему это можно сделать на 32-битных платформах? Кроме того, если бы были внесены изменения в формат ELF для поддержки 64-битных, то почему не все поля были увеличены в размерах, чтобы они могли разместиться?

Это может быть второстепенным моментом, но это мотивируется тем фактом, что: а) рассматриваемый код - это научный код, и было бы неплохо не принимать удар по производительности, и б) эта информация была невозможна найти в первую очередь!

[Изменить: "Ответ"

@awoodlands answer, вероятно, лучший "литературный ответ", @servn добавил какую-то полезную информацию.

В поиске, чтобы найти больше о различных типах перемещений, я нашел this и в конечном итоге x86_64 Ссылка ABI (см. стр. 68) ]

4b9b3361

Ответ 1

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

Эта статья имеет хороший углубленный анализ и дает следующее резюме:

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

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

Ответ 2

Но я не считаю это вполне адекватным. Если это так, что перераспределение испортило концепцию общих библиотек, почему это можно сделать на 32-битных платформах?

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

Также стоит упомянуть, что -fPIC обычно не представляет значительную стоимость, особенно если вы используете -fvisibility = hidden или эквивалент.

почему не все поля увеличены в размерах для размещения?

"Поле", о котором идет речь, является непосредственным полем режимов адресации x86-64, который не находится под контролем разработчиков ELF.