8. 编译工具链接器
链接器将一个或多个目标文件的内容与一个或多个目标库的选定部分组合起来,以生成目标程序。
链接器支持以下功能:
- 链接KungFu32内核专用指令集代码;
- 按需生成交互过渡代码,用于函数调用时在不同指令集模式之间切换;
- 按需生成范围扩展过渡代码,突破分支指令和地址访问的默认偏移限制,扩展访问范围;
- 根据待链接目标文件的构建属性(如调试 / 发布模式、浮点支持情况),自动选择适配的标准 C/C++ 库变体(针对 KungFu32 的内存占用和能效进行优化);
- 通过命令行选项或带 KungFu32 专用内存区域定义的链接脚本,将代码和数据定位到KungFu32系统内存映射的指定位置(如 Flash、SRAM、外设寄存器区域);
- 对读写(RW)数据进行压缩,并对只读(RO)数据进行去重,最大限度减少 Flash 内存占用;
- 剔除未使用的段(死代码 / 数据消除),并合并重复段,减小输出目标文件的体积;
- 控制输出文件中调试信息(如 DWARF 3/4 格式)的生成,兼容 KungFu32 调试工具;
- 控制输出目标文件中符号表的内容(如保留 / 移除局部符号),平衡可调试性和目标文件大小;
- 显示输出文件中代码(TEXT 段)、数据(DATA/RW 段)和未初始化数据(BSS 段)的详细大小,并按 KungFu32 专用内存区域进行拆分展示;
- 支持checksum。
8.1 命令行语法
该链接器命令行可接收多个输入文件,以及用于指定文件处理方式的选项。调用的命令格式为:
kf32ld [options] file
其中:
[options]
命令行选项,用于配置链接行为(如内存布局控制、优化策略、输出格式指定等)。
file
以空格分隔的目标文件、库文件或符号定义(symdefs)文件列表。
8.1.1 常用选项
表8.1 kf32ld常用选项
| 选项 | 作用描述 |
|---|---|
-T <script> | 使用链接脚本,控制内存布局与段的组织(见 8.4) |
-L <dir> | 添加库文件的搜索路径 |
-l <lib> | 链接指定的库,如 -lc -lm(见 2.8) |
-o <file> | 指定输出文件名 |
-Map=<file> | 生成映射文件,记录各段与符号的地址、大小 |
--gc-sections | 删除未被引用的段,减小输出文件体积 |
-e <symbol> | 指定程序入口符号 |
--defsym=<symbol>=<value> | 定义符号的地址或数值 |
--section-start=<section>=<address> | 指定某个输出段的起始地址 |
--orphan-handling=<mode> | 设置链接脚本未放置段的处理方式,取值 place、warn、error(见 8.4.1) |
-r | 只合并输入文件,生成可重定位目标文件,不进行最终链接 |
-s | 去除输出文件中的全部符号(等价于 --strip-all) |
--whole-archive | 强制载入其后的库文件中的全部成员,--no-whole-archive 恢复正常行为 |
--checksum1-enabled 等 | 启用并配置校验和计算,共 3 组,分别以 --checksum1-、--checksum2-、--checksum3- 为前缀,后缀为 enabled、algorithm(CRC32、CRC32MP、SUM32、CMAC)、segment、start、size、fill,值以空格分隔(如 --checksum1-size 16) |
8.1.2 链接示例
kf32clang --target=kf32r -march=kf32r -c main.c -o main.o
kf32ld main.o -T KF32AXXX.ld \
-L<安装路径>/lib/clang-runtimes/kf32r/kf32r_general/lib \
-lc -lm -Map=main.map -o main.elf
8.2 链接器的输入
链接器可接受库文件、脚本文件、对象文件。
8.3 链接器的输出
链接器输出ELF文件与map文件。后续可通过kf32objcopy提取hex文件或s19文件,通过kf32objdump获取ELF内容或反汇编。
8.4 链接器输出布局
支持通过参数-T传递脚本文件,组织文件或段名或输出顺序。可通过map文件进行观察。
8.4.1 未放置段的处理
kf32r 链接器默认采取严格策略:使用包含 SECTIONS 命令的链接脚本时,脚本没有放置的输入段(孤儿段)不会被自动放置,而是直接报错并终止链接,例如:
kf32ld: error: unplaced orphan section '.mysec' from 'main.o'
错误信息中的 unplaced orphan section 表示该段未被链接脚本放置,引号内依次为段名(.mysec)与来源文件(main.o);段来自库成员时,来源显示为库文件名加成员名,如 libfoo.a(foo.o)。自动放置可能把段放到不符合预期的地址,造成数据覆盖或运行异常,因此 kf32r 默认让链接直接失败。
如需改变默认行为,可显式指定 --orphan-handling:
表8.2 未放置段的处理方式
| 取值 | 行为 |
|---|---|
error | 报错并终止链接(kf32r 使用含 SECTIONS 的脚本时的默认值) |
warn | 打印警告,并继续自动放置 |
place | 不提示,直接自动放置 |