Компиляция GAS-кода не обнаруживает -fPIC-опцию

Я пытаюсь скомпилировать некоторый код 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


Есть идеи?

10000