上一篇
链接命令文件用于配置程序的内存布局和段分配,通常包含MEMORY(定义存储区域)和SECTIONS(指定代码/数据存放位置)两大核心部分,通过语法规则描述地址范围、段映射关系及符号定义,需结合硬件手册和编译器特性分析逻辑结构。
在嵌入式开发、操作系统编程或底层系统优化中,链接命令文件(Linker Script)是控制程序内存布局的核心工具,但对许多开发者来说,这种文件的结构和语法可能如同一本“天书”,本文将从实用角度出发,手把手教你理解并掌握链接命令文件的精髓。
链接命令文件的作用与价值
链接命令文件(扩展名通常为.ld或.lds)是编译工具链中链接器(如GNU LD)的“地图导航”,它决定了:
- 代码和数据在内存中的物理分配位置
- 如何将多个目标文件(
.o)组合成最终可执行文件 - 特殊符号的定义(如堆栈起始地址)
- 内存区域的保护机制(如禁止代码写入ROM)
没有它,程序可能无法在特定硬件上运行——在STM32单片机中必须通过链接脚本指定Flash和RAM的分区。

解剖链接命令文件的层级结构
MEMORY命令:定义硬件内存蓝图
MEMORY {
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 256K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 64K
}
(rx)表示访问权限(r=读,w=写,x=执行)ORIGIN是内存起始地址(必须16进制)LENGTH决定可用空间大小
SECTION命令:程序段的精确定位
SECTIONS {
.text : {
*(.text*) /* 所有代码段 */
KEEP(*(.vectors))/* 保留中断向量表 */
} > FLASH
.data : {
_sdata = .; /* 记录数据段起始 */
*(.data*)
_edata = .; /* 记录数据段结束 */
} > RAM AT> FLASH /* 装载到FLASH,运行时复制到RAM */
}
- 点号表示当前内存地址计数器
AT>指定物理存储位置与运行时位置的分离
符号赋值与表达式
_estack = ORIGIN(RAM) + LENGTH(RAM); /* 堆栈顶部=RAM末尾 */ __etext = LOADADDR(.data); /* 获取.data段的存储地址 */
实战案例解析:STM32的典型配置
ENTRY(Reset_Handler) /* 指定程序入口点 */
MEMORY {
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 128K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 32K
}
SECTIONS {
.isr_vector : { /* 中断向量表必须放在FLASH起始 */
KEEP(*(.isr_vector))
} >FLASH
.text : {
*(.text*)
*(.rodata*)
_etext = .; /* 代码段结束标志 */
} >FLASH
.data : {
_sdata = .;
*(.data*)
_edata = .;
} >RAM AT> FLASH
.bss : {
_sbss = .;
*(.bss*)
*(COMMON)
_ebss = .;
} >RAM
}
.bss段自动初始化为0COMMON块处理未初始化的全局变量
调试技巧与常见陷阱
▶ 内存溢出检测
arm-none-eabi-size -Ax firmware.elf
检查输出中各段大小是否超过MEMORY定义的长度。
▶ 地址对齐问题
使用ALIGN(4)保证数据对齐:

.data : {
. = ALIGN(4);
_sdata = .;
...
}
▶ 固件烧录失败的排查步骤
- 检查
ENTRY指定的函数是否存在 - 确认
MEMORY的地址与芯片手册一致 - 使用
nm工具查看符号地址:arm-none-eabi-nm -n firmware.elf
进阶技巧:动态内存管理
通过链接脚本实现自定义内存池:
__heap_start = .;
.heap : {
. = . + 0x1000; /* 保留4KB堆空间 */
} >RAM
__heap_end = .;
在C代码中可直接引用这些符号:

extern char __heap_start[]; extern char __heap_end[];
安全编码规范
- 关键段保护:对.bootloader区域添加
(NOLOAD)属性 - 版本标识:
.version 0x2000 : { KEEP(*(.version_info)) } >FLASH - CRC校验:在文件末尾插入校验段
.crc : { QUAD(0) /* 占位符 */ } >FLASH
引用说明
本文技术细节参考自:
- GNU Linker官方文档(https://sourceware.org/binutils/docs/ld/ )
- ARM® Compiler v6.13链接器指南
- 《Embedded Systems with ARM Cortex-M Microcontrollers in Assembly Language and C》第14章
