Различие в позиционно-независимом коде: x86 по сравнению с x86-64

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

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

Это перестало работать со следующей ошибкой:

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

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

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

24
задан Alex B 2 August 2010 в 03:38
поделиться

3 ответа

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

  1. x86-64 использует IP-относительное смещение для загрузки глобальных данных, x86-32 не может, поэтому он разыменовывает глобальное смещение.
  2. IP-относительное смещение не работает для разделяемых библиотек, потому что глобальные символы могут быть переопределены, поэтому x86-64 ломается, если не собран с PIC.
  3. Если x86-64 собран с PIC, то разыменование IP-относительного смещения теперь дает указатель на запись GOT, которая затем разыменовывается.
  4. x86-32, однако, уже использует разыменование глобального смещения, поэтому оно превращается в GOT entry напрямую.
17
ответ дан 29 November 2019 в 00:19
поделиться

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

0
ответ дан 29 November 2019 в 00:19
поделиться

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

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

4
ответ дан 29 November 2019 в 00:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: