菜单

kaoqi
kaoqi
发布于 2026-09-03 / 10 阅读
0
0

仿EDK2的轻量编译工具链

总结的工具链

gcc命令参数参考:

/usr/bin/aarch64-linux-gnu-gcc
-g
-Os
-fshort-wchar
-fno-builtin
-fno-strict-aliasing
-Wall
-Werror
-Wno-array-bounds
-include
AutoGen.h
-fno-common
-ffunction-sections
-fdata-sections
-DSTRING_ARRAY_NAME=ShellStrings
-mlittle-endian
-fno-short-enums
-fverbose-asm
-funsigned-char
-Wno-address
-fno-asynchronous-unwind-tables
-fno-unwind-tables
-fno-pic
-fno-pie
-ffixed-x18
-mcmodel=small
-flto
-Wno-unused-but-set-variable
-Wno-unused-const-variable
-c
-o /Shell.obj
/edk2/ShellPkg/Application/Shell/Shell.c

链接命令参考:

aarch64-linux-gnu-gcc -o Shell.dll \
-nostdlib \
-Wl,--gc-sections \
-u _ModuleEntryPoint \
-Wl,-e,_ModuleEntryPoint,-Map,/Shell.map
-z common-page-size=0x1000 \
-Os \
-flto \
-Wno-lto-type-mismatch \
-g \
-fshort-wchar \
-fno-builtin \
-Wall \
-Wno-array-bounds \
-include AutoGen.h \
-fno-common \
-ffunction-sections \
-fdata-sections \
-mlittle-endian \
-fno-short-enums \
-fverbose-asm \
-funsigned-char \
-Wno-address \
-fno-asynchronous-unwind-tables \
-fno-unwind-tables \
-fno-pic \
-fno-pie \
-ffixed-x18 \
-mcmodel=small \
-Wno-unused-but-set-variable \
-Wno-unused-const-variable \
-Wl,--script=/edk2/BaseTools/Scripts/GccBase.lds \
-Wl,--defsym=PECOFF_HEADER_SIZE=0x228 \
-Wno-error \
Shell.obj

GenFw命令参考:

GenFw -e UEFI_APPLICATION -o /Shell.efi /Shell.dll

详尽的工具链

GCC过程:

"$(DLINK)" -o Shell.dll $(DLINK_FLAGS) -Wl,--start-group,@$(STATIC_LIBRARY_FILES_LIST),--end-group $(CC_FLAGS) $(DLINK2_FLAGS)
"$(OBJCOPY)" $(OBJCOPY_FLAGS) Shell.dll

翻译出来就是:

aarch64-linux-gnu-gcc -o Shell.dll -Wl,--emit-relocs -nostdlib -Wl,--gc-sections -u _ModuleEntryPoint -Wl,-e,_ModuleEntryPoint,-Map,/edk2/Build/Shell/RELEASE_GCC5/AARCH64/ShellPkg/Application/Shell/Shell/DEBUG/Shell.map -z common-page-size=0x20 -z common-page-size=0x1000 -flto -Os -L/edk2/ArmPkg/Library/GccLto -llto-aarch64 -Wl,-plugin-opt=-pass-through=-llto-aarch64 -Wno-lto-type-mismatch -Wl,--start-group,@/edk2/Build/Shell/RELEASE_GCC5/AARCH64/ShellPkg/Application/Shell/Shell/OUTPUT/static_library_files.lst,--end-group   -g -Os -fshort-wchar -fno-builtin -fno-strict-aliasing -Wall -Werror -Wno-array-bounds -include AutoGen.h -fno-common -ffunction-sections -fdata-sections -DSTRING_ARRAY_NAME=ShellStrings -g -Os -fshort-wchar -fno-builtin -fno-strict-aliasing -Wall -Werror -Wno-array-bounds -include AutoGen.h -fno-common -mlittle-endian -fno-short-enums -fverbose-asm -funsigned-char -ffunction-sections -fdata-sections -Wno-address -fno-asynchronous-unwind-tables -fno-unwind-tables -fno-pic -fno-pie -ffixed-x18 -mcmodel=small -flto -Wno-unused-but-set-variable -Wno-unused-const-variable -D DISABLE_NEW_DEPRECATED_INTERFACES -Wl,--script=/edk2/BaseTools/Scripts/GccBase.lds -Wl,--defsym=PECOFF_HEADER_SIZE=0x228 -Wno-error

"echo" objcopy not needed for /edk2/Build/Shell/RELEASE_GCC5/AARCH64/ShellPkg/Application/Shell/Shell/DEBUG/Shell.dll

objcopy not needed for /edk2/Build/Shell/RELEASE_GCC5/AARCH64/ShellPkg/Application/Shell/Shell/DEBUG/Shell.dll

这里需要补充做一个逐参数的解析,以确定一下哪些是真正必要的东西:

参数

含义

-Wl,--emit-relocs

GCC编译器传递给链接器的一个指令,在最终生成的可执行文件或共享库中,保留完整的重定位信息

-nostdlib

GCC选项,在链接阶段,不链接系统的标准启动文件和标准库文件

-Wl,--gc-sections

在链接阶段启用“段垃圾回收”,自动剔除最终二进制文件中未被引用的代码段和数据段

-u _ModuleEntryPoint

强制将符合_ModuleEntryPoint标记为“未定义但需要解析”,从而确保该符号及其依赖的代码被包含在最终生成的二进制文件中,即使链接器认为它没有被直接引用。用于防止链接器优化掉入口点函数。

入口函数会根据AARCH64这样的架构指定一个具体的汇编文件,在汇编中会指定入口函数的内容。

在此,入口文件被认为是/edk2/ArmPkg/Library/CompilerIntrinsicsLib/AArch64/Atomics.S中定义的内容,总之这个头留着别删。

-Wl,-e,_ModuleEntryPoint,-Map,Shell.map

这一段是告知链接器入口函数位置,并且要求链接器将段的分布情况打印在Shell.map文件中。

-z common-page-size=0x1000

将链接器用于优化重定位和段对齐的“公共页面大小”设置为4096字节(即,4KB)

-Os

指示编译器在生成机器码时,优先追求最小的可执行文件大小

-flto

启用链接时优化Inter-Procedural Optimization

-L/GccLto

指定链接器搜索库文件的目录路径

-llto-aarch64

链接名为liblto-aarch64的库文件

-Wl,-plugin-opt=-pass-through=-llto-aarch64

意思是一定要带上这个优化工具箱

-Wno-lto-type-mismatch

忽略LTO过程中版本不匹配的报错

-Wl,--start-group,@/static_library_files.lst,--end-group

传递给链接器,用于处理静态库之间的循环依赖,使用start-group让链接器可以反复循环扫描

-g

指示表一起生成目标文件中携带标准的调试信息

-fshort-wchar

这是一个十分重要的参数,在windows和UEFI环境中wchar定义为16位,但在Linux中wchar通常是32位,所以这里要指定wchar类型位2字节。

-fno-builtin

禁用内置函数优化

-Wall

启用大多数常用警告

-Wno-array-bounds

禁用数组越界警告

-include AutoGen.h

在编译任何源文件之前,预先包含AutoGen.h头文件

-fno-common

禁止将未初始化的全局变量放入"common"段

-ffunction-sections

将每个函数放置在独立的段中

-fdata-sections

将每个全局/静态数据变量放置在独立的段中

-mlittle-endian

指定生成的代码针对小端字节序架构的处理器

-fno-short-enums

禁用“短枚举”类型,使用标准的int大小

-fverbose-asm

在生成的汇编代码中添加详细的注释信息

-funsigned-char

将默认的char类型视为无符号字符

-Wno-address

禁用关于”地址比较“的警告

-fno-asynchronous-unwind-tables

禁止生成异步展开表

-fno-unwind-tables

完全禁止生成任何堆栈展开表

-fno-pic

禁止生成位置无关代码

-fno-pie

禁止生成位置无关可执行文件

-ffixed-x18

保留寄存器x18

-mcmodel=small

使用小内存模型(所有代码和全局数据都位于低2GB)

-Wno-unused-but-set-variable

忽略被赋值但从未被读取的警告

-Wno-unused-const-variable

忽略未使用的常量变量的警告

-Wl,--script=/edk2/BaseTools/Scripts/GccBase.lds

指定链接器对应的链接脚本

-Wl,--defsym=PECOFF_HEADER_SIZE=0x228

在链接阶段定义符合并赋值未0x228

-Wno-error

禁止将警告视为错误

efi过程:

$(CP) Shell.dll $(DEBUG_DIR)/$(MODULE_NAME).debug
$(OBJCOPY) $(OBJCOPY_STRIPFLAG) Shell.dll
$(OBJCOPY) $(OBJCOPY_ADDDEBUGFLAG) Shell.dll
-$(CP) $(DEBUG_DIR)/$(MODULE_NAME).debug $(BIN_DIR)/$(MODULE_NAME_GUID).debug
"$(GENFW)" -e $(MODULE_TYPE) -o Shell.efi Shell.dll $(GENFW_FLAGS)
$(CP) Shell.efi $(DEBUG_DIR)
$(CP) Shell.efi $(BIN_DIR)/$(MODULE_NAME_GUID).efi
-$(CP) $(DEBUG_DIR)/*.map $(OUTPUT_DIR)

翻译出来就是:

cp -f /edk2/Build/Shell/RELEASE_GCC5/AARCH64/ShellPkg/Application/Shell/Shell/DEBUG/Shell.dll /edk2/Build/Shell/RELEASE_GCC5/AARCH64/ShellPkg/Application/Shell/Shell/DEBUG/Shell.debug

echo --strip-unneeded -R .eh_frame /edk2/Build/Shell/RELEASE_GCC5/AARCH64/ShellPkg/Application/Shell/Shell/DEBUG/Shell.dll

echo  /edk2/Build/Shell/RELEASE_GCC5/AARCH64/ShellPkg/Application/Shell/Shell/DEBUG/Shell.dll

cp -f /edk2/Build/Shell/RELEASE_GCC5/AARCH64/ShellPkg/Application/Shell/Shell/DEBUG/Shell.debug /edk2/Build/Shell/RELEASE_GCC5/AARCH64/Shell_7C04A583-9E3E-4f1c-AD65-E05268D0B4D1.debug

"GenFw" -e UEFI_APPLICATION -o /edk2/Build/Shell/RELEASE_GCC5/AARCH64/ShellPkg/Application/Shell/Shell/OUTPUT/Shell.efi /edk2/Build/Shell/RELEASE_GCC5/AARCH64/ShellPkg/Application/Shell/Shell/DEBUG/Shell.dll

cp -f /edk2/Build/Shell/RELEASE_GCC5/AARCH64/ShellPkg/Application/Shell/Shell/OUTPUT/Shell.efi /edk2/Build/Shell/RELEASE_GCC5/AARCH64/ShellPkg/Application/Shell/Shell/DEBUG

cp -f /edk2/Build/Shell/RELEASE_GCC5/AARCH64/ShellPkg/Application/Shell/Shell/OUTPUT/Shell.efi /edk2/Build/Shell/RELEASE_GCC5/AARCH64/Shell_7C04A583-9E3E-4f1c-AD65-E05268D0B4D1.efi

cp -f /edk2/Build/Shell/RELEASE_GCC5/AARCH64/ShellPkg/Application/Shell/Shell/DEBUG/*.map /edk2/Build/Shell/RELEASE_GCC5/AARCH64/ShellPkg/Application/Shell/Shell/OUTPUT

其参数整理为:

GenFw -e UEFI_APPLICATION -o /Shell.efi /Shell.dll

对于GenFw来说,似乎没有什么多余的东西需要做。


评论