Я недавно создавал определенную общую библиотеку (ELF), бывшую нацеленную x86-64 архитектура, как это:
g++ -o binary.so -shared --no-undefined ... -lfoo -lbar
Это перестало работать со следующей ошибкой:
перемещение R_X86_64_32 против 'локального символа' не может использоваться при создании общего объекта; перекомпилируйте с-fPIC
Конечно, это означает, что я должен восстановить его как позиционно-независимый код, таким образом, это подходит для соединения в общую библиотеку.
Но это работает отлично над x86 с точно теми же аргументами сборки. Таким образом, вопрос, как находится перемещение на x86, отличающемся от x86-64 и почему я не должен компилировать с -fPIC
на первом?
Я нашел хорошее и подробное объяснение, которое сводится к следующему:
Это чисто произвольное требование, которое люди из ABI навязали нам. Нет никакой логической причины, по которой динамический компоновщик на x86_64 не мог бы поддерживать не-PIC библиотеки. Однако, поскольку x86_64 не испытывает такого ужасного давления регистров, как x86 (и имеет лучшие возможности для PIC), я не знаю ни одной существенной причины не использовать PIC.
Это проблема модели кода. По умолчанию статический код собирается в предположении, что вся программа будет находиться в нижней 2G части адресного пространства памяти. Код для разделяемых библиотек должен быть скомпилирован для другой модели памяти, либо PIC, либо с -mcmodel=large, которая будет компилироваться без этого предположения.
Обратите внимание, что -mcmodel=large не реализована в старых версиях gcc (она есть в 4.4, ее нет в 4.2, я не знаю для 4.3). .