Я пытаюсь создать UEFI-загрузочный файл PE32+ для UEFI в 64-битном режиме с помощью gcc.
Сначала я компилирую исходники.
cc -nostartfiles -o bootx64.o bootx64.c
Затем я выбрасываю все, кроме раздела .text и .data и переименовываю файл.
objcopy -j .text -j .data --target=pei-x86-64 --subsystem=10 --strip-unneeded bootx64.o
mv bootx64.o bootx64.efi
Это создает почти идеальный файл. За исключением того, что флаги характеристик заголовка PE установлены неправильно. (https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#characteristics)
Я получаю характеристики по:
objdump -p bootx64.efi
и вывод:
bootx64.efi: file format pei-x86-64
Characteristics 0x20f
relocations stripped
executable
line numbers stripped
symbols stripped
debugging information removed
Итак, флаг характеристик установлен на 0x020f, что означает, что установлены эти флаги:
0x0200 Отладочная информация удалена из файла образа.
0x0001 Только образ, Windows CE, Microsoft Windows NT и более поздние версии. Это указывает на то, что файл не содержит базовых перемещений и поэтому должен загружаться по предпочтительному базовому адресу. Если базовый адрес недоступен, загрузчик сообщает об ошибке. По умолчанию компоновщик удаляет базовые перемещения из исполняемых (EXE) файлов.
0x0002 Только изображение. Это указывает на то, что файл образа действителен и может быть запущен. Если этот флаг не установлен, это указывает на ошибку компоновщика.
Номера строк 0x0004 COFF были удалены. Этот флаг устарел и должен быть равен нулю.
0x0008 Записи таблицы символов COFF для локальных символов были удалены. Этот флаг устарел и должен быть равен нулю.
После установки/сброса и тестирования каждого флага я обнаружил, что UEFI не нравится флаг 0x0001, потому что это означало бы, что он должен загружать код по предпочтительному адресу. Мой код не содержит никаких перемещений, но он отлично работает, когда я просто вручную удаляю флаг 0x0001. Примечание: objcopy также устанавливает два устаревших флага (0x0004 и 0x0008), и я также хотел бы, чтобы этого не произошло.
Есть ли какой-либо способ, которым objcopy может установить флаги характеристик заголовка PE только для установки 0x0002, а 0x0001, 0x0004 и 0x0008 будут удалены objcopy напрямую, вместо того, чтобы делать это вручную после этого?
РЕДАКТИРОВАТЬ: я пытался связать файл с ld, но с этим есть некоторые проблемы.
ld --oformat pei-x86-64 --subsystem 10 -o bootx64.efi bootx64.o
приводит к
ld: unrecognized option '--subsystem'
Несмотря на документацию GNU binutils (https://sourceware.org/binutils/docs/ld/Options.html), говоря, что:
--подсистема, которая
--подсистема которая:основная
--subsystem which:major.minor
Указывает подсистему, в которой будет выполняться ваша программа. Допустимые значения для которых: native, windows, console, posix и xbox. При желании вы также можете установить версию подсистемы. Принимаются также числовые значения, для которых . [Этот параметр относится к целевому порту i386 PE компоновщика]
Поэтому мне понадобится опция EFI или 10 в числовом значении. этой опции здесь нет.
Я также пробовал pe-x86-64 и pei-i386 и все, что я нашел с pe в названии. Связывание без опции подсистемы приводит к почти полностью заполненному нулями заголовку.
Objcopy справился лучше всех, но все же не очень хорошо (проблемы обсуждались выше) Я написал маленькую утилиту, которая правильно заполняет шапку, так что в итоге я застрял на своей утилите.
ld
всегда создавать таблицу перемещений (с помощью -Wl,--enable-reloc-section). - person ssbssa   schedule 17.04.2021--set-section-flags
? - person Olaf Dietsche   schedule 17.04.2021ld
вообще никогда не вызывается, поэтому похоже, что вам нужно изменитьobjcopy
, чтобы он делал именно то, что вам здесь нужно. - person ssbssa   schedule 17.04.2021man objcopy
и нашел этот вариант. Я не пробовал и не знаю на самом деле. Я бы просто поиграл и попробовал разные комбинации, может быть--set-section-flags .text=<some flags>
. Возможно, это не подходит для вашей проблемы. - person Olaf Dietsche   schedule 17.04.2021