【发布时间】:2021-07-12 05:39:46
【问题描述】:
我正在尝试使用 gcc 在 64 位模式下为 UEFI 制作 UEFI 可引导的 PE32+ 文件。
首先我正在编译源代码。
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,而 objcopy 直接取消设置 0x0001、0x0004 和 0x0008,而不是事后手动设置?
编辑: 我尝试将文件与 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
--subsystem which:major.minor
指定您的程序将在哪个子系统下执行。这 其合法值为 native、windows、console、posix 和 xbox。 您也可以选择设置子系统版本。数值是 也接受了。 [此选项特定于 i386 PE 链接器的目标端口]
所以我需要一个选项“EFI”或数值为 10。此处不存在该选项。
我还尝试了 pe-x86-64 和 pei-i386 以及我发现的所有名称中带有 pe 的东西。没有子系统选项的链接会导致几乎完全为零的标题。
Objcopy 做得最好,但仍然不好(上面讨论的问题)我写了一个小实用程序,可以正确填写标题,所以最后我坚持使用我的实用程序。
【问题讨论】:
-
从 binutils 2.34 开始,您可以告诉
ld始终创建重定位表(使用-Wl,--enable-reloc-section)。 -
也许使用objcopy的
--set-section-flags? -
@ssbssa --enable-reloc-section 仅支持 i386pe 和 i386pep。不适用于 pei-x86-64 - 我如何将它与 pei-x86-64 一起使用?我在原始问题中添加了说明。谢谢!
-
@OlafDietsche 如何使用 --set-section-flags 设置 PE 标头特征标志?谢谢!
-
我现在看到
ld根本就没有被调用过,所以看起来您应该修改objcopy以完全满足您的需要。
标签: c gcc portable-executable uefi objcopy