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

Разница в позиционно-независимом коде: x86 vs x86-64

Недавно я создал определенную общую библиотеку (ELF) для архитектуры x86-64, например:

g++ -o binary.so -shared --no-undefined ... -lfoo -lbar

Не удалось выполнить следующую ошибку:

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

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

Но это отлично работает на x86 с точно такими же аргументами построения. Итак, вопрос в том, как перемещение на x86 отличается от x86-64 и почему мне не нужно компилировать с -fPIC в первом?

4b9b3361

Ответ 1

Я нашел приятное и подробное объяснение, которое сводится к следующему:

  • x86-64 использует относительное смещение IP для загрузки глобальных данных, x86-32 не может, поэтому он разделяет глобальное смещение.
  • Относительное смещение IP не работает для разделяемых библиотек, поскольку глобальные символы могут быть переопределены, поэтому x86-64 ломается, если не построен с помощью PIC.
  • Если x86-64, построенный с помощью PIC, относительное смещение смещения IP теперь дает указатель на запись GOT, которая затем разыменовывается.
  • x86-32, однако, уже использует разыменование глобального смещения, поэтому он напрямую переходит в запись GOT.

Ответ 2

Это проблема с моделью кода. По умолчанию статический код строится, предполагая, что вся программа останется в нижней части 2G адресного пространства памяти. Код для разделяемых библиотек должен быть скомпилирован для другой модели памяти: PIC или с -mcmodel = large, который будет компилироваться без принятия этого предположения.

Обратите внимание, что -mcmodel = large не реализован в более старой версии gcc (это в 4.4, это не в 4.2, я не знаю для 4.3). .

Ответ 3

Это чисто произвольное требование, которое люди ABI навязали нам. Нет логической причины, почему динамический компоновщик на x86_64 не мог поддерживать библиотеки, отличные от ПОС. Однако, поскольку x86_64 не находится под таким ужасным давлением регистра как x86 (и имеет лучшие функции для ПОС), я не знаю какой-либо существенной причины не использовать ПОС.