Я пытаюсь скомпилировать некоторый код GAS для проекта с использованием компилятора GCC gnu. Вот как я его компилирую:
gcc -c boot.s -o boot.o -fPIC
После того, как я скомпилирую файл kernel.c с аргументом -fPIC
, я попытаюсь связать его с этой командой:
gcc -N -T linker.ld -o Slack Berry.bin -ffreestanding -nostdlib kernel.o boot.o -lgcc
Это связано с:
/usr/bin/ld: boot.o: relocation R_X86_64_32 against '.multiboot' can not be used when making a PIE object; recompile with -fPIC
Это заставляет меня думать, что это не компиляция моего GAS-кода с -fPIC
. Как я могу это исправить?
Всего 2 ответа
Прежде всего вам, скорее всего, нужно -fPIE
а не -fPIC
. -fPIE
позволяет компилятору генерировать более эффективный код, но может использоваться только для кода, который является частью основного исполняемого файла (не разделяемой библиотеки).
Теперь оба -fPIC
и -fPIE
являются флагами только для компилятора и не передаются ассемблеру. Вам нужно будет явно использовать Mnemonics PIC-специфики в вашем ассемблерном коде вместо зависящих от позиции вызовов и ветвей, например, вместо
movq $bar, %rdx
использование
movq bar@GOTPCREL(%rip), %rdx
(как правило, для получения синтаксиса, который мне нужен, я просто запускаю gcc -fPIE -S -o-
по совпадению фрагмента C).
Перекомпиляция с -fPIC
применяется только в том случае, если asm был сгенерирован компилятором, а не написан вручную. Это не влияет на то, как asm собирается в машинный код.
Проблема в том, что ваш исполняемый файл PIE не может быть связан с 32-разрядными абсолютными адресами. (Вы имели в виду сделать PIE вместо статического зависимого от позиции исполняемого файла)?
Вам не нужен полный материал разделяемой библиотеки для ссылки на символы в другой библиотеке или в главном исполняемом файле (например, ответ @ yugr показывает, как это сделать). У вашего автономного ядра может даже не быть GOT или PLT, и определенно не следует использовать их для внутренних символов.
Единственное изменение - lea bar(%rip), %rdx
, RIP-относительный LEA вместо mov $imm32, %r/m64
. (movabs будет работать, но будет больше и обычно медленнее).
Или, если вы на самом деле хотели построить с помощью -static
и создать исполняемый файл, который будет загружен по фиксированному адресу в младших 32 битных адресных пространствах, вы должны использовать mov $bar, %edx
чтобы получить 5-байтный mov $imm32, %r32
вместо 7-байтового mov $sign_extended_imm32, %r/m64
или 7-байтового LEA. См. Также Разница между movq и movabsq в x86-64