Вопрос или проблема
Я пытаюсь связать некоторые файлы. Вот моя команда:
gcc -T linker.ld -o Stack\ Berry.bin -ffreestanding -O2 -nostlib kernel.o boot.o -fPIC -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
/usr/bin/ld: final link failed: Nonrepresentable section on output
Я включил аргумент -fPIC
, может быть, я просто поставил его не на то место? Я не смог найти ничего о синтаксисе этого флага. Спасибо!
Ваш boot.o
имеет elf секцию .multiboot
, что несовместимо с -fPIC
. Вы можете попробовать скомпилировать boot.o
с -fPIC
, но это должно завершиться неудачей.
Смотрите https://www.gnu.org/software/grub/manual/multiboot/multiboot.html#OS-image-format для заголовка.
С другой стороны, нет особого смысла создавать загрузочный объект с -fPIC
. Даже если был бы “динамический загрузчик”, во время процесса загрузки не может быть ничего, с чем можно было бы динамически связываться.
Ответ или решение
При попытке связать файлы с использованием компилятора GCC и флага -fPIC
, вы столкнулись с ошибкой, связанной с несовместимостью секций, а именно:
/usr/bin/ld: boot.o: relocation R_X86_64_32 against `.multiboot' can not be used when making a PIE object; recompile with -fPIC
/usr/bin/ld: final link failed: Nonrepresentable section on output
Понимание проблемы
Ваше сообщение об ошибке указывает на то, что объектный файл boot.o
содержит секцию .multiboot
, которая несовместима с флагом -fPIC
(Position Independent Code). -fPIC
используется для создания кода, который можно загружать в любое место в памяти, что обычно требуется для динамически связываемых библиотек. Однако хостовая система, загружающая загрузочный образ, не предоставляет такой возможности, поскольку при загрузке используется статическое связывание.
Ваша команда
Вы использовали следующую команду:
gcc -T linker.ld -o Stack\ Berry.bin -ffreestanding -O2 -nostlib kernel.o boot.o -fPIC -lgcc
Несмотря на то, что флаг -fPIC
добавлен, проблема заключается в том, что boot.o
необходимо компилировать без этого флага. Таким образом, не имеет смысла использовать -fPIC
для создания загрузочного объекта, поскольку сам процесс загрузки не поддерживает динамическую компоновку.
Решение
-
Компиляция без -fPIC: Убедитесь, что
boot.o
компилируется без флага-fPIC
. Для этого необходимо проверить команду, с которой компилируетсяboot.o
. Убедитесь, что для него не используется-fPIC
. -
Проверка флагов компиляции: Если вы контролируете процесс компиляции
boot.o
, убедитесь, что используете правильные флаги. Например, команда для компиляцииboot.o
может выглядеть так:gcc -c -ffreestanding -O2 boot.c -o boot.o
-
Объединение объектов: После компиляции обоих объектов (
kernel.o
иboot.o
) без флага-fPIC
, попробуйте выполнить линковку снова без этого флага:gcc -T linker.ld -o Stack\ Berry.bin -ffreestanding -O2 -nostlib kernel.o boot.o -lgcc
Заключение
Ваша ошибка возникла не из-за неправильного использования флага -fPIC
непосредственно в команде линковки, а из-за того, что файл boot.o
не должен компилироваться с этим флагом. В случае нагрузок, когда важна независимость расположения кода (например, создание динамических библиотек), -fPIC
является обязательным. Но когда дело касается загрузочных образов, таких как boot.o
, лучше обойтись статическим кодом. Поддержание ясности и правильности флагов компиляции — ключ к успеху в разработке низкоуровневого программного обеспечения.