GNU链接器(LD):输入分区的垃圾回收及保护处理(KEEP命令)介绍

0 参考资料

GNU-LD-v2.30-中文手册.pdf
GNU linker.pdf

1 前言

一个完整的编译工具链应该包含以下4个部分:
(1)编译器
(2)汇编器
(3)链接器
(4)lib库
在GNU工具链中,对应的是:
(1)编译器:GCC(GNU Compiler Collection,GNU编译器套件)
(2)汇编器:GAS(GNU Assembler,GNU汇编器)
(3)链接器:LD(GNU Linker,GNU链接器)
(4)lib库:glibc(GNU C Library,GNU C 库)
本文介绍GNU链接器(LD)链接器脚本中输入分区的垃圾回收及保护处理(KEEP命令)。

2 GNU链接器(LD):输入分区的垃圾收集处理(KEEP命令)介绍

当我们的编译命令添加

<think>嗯,用户想详细了解ld.script的知识,包括介绍、使用方法和相关规范。从引用内容看,用户提供的参考资料主要集中在链接器脚本的内存地址配置(VMA/LMA)、汇编文件处理流程等底层细节。 用户可能是嵌入式系统开发者或操作系统学习者,需要直接控制硬件内存布局。ta特意提到&ldquo;不是真正需求”,说明引用材料只是线索,真正需要的是实用指导。上次讨论过LDScript函数定义(引用[1]),但这次焦点完全转向链接器脚本,需注意区分这两个相似缩写。 核心需求可能是:如何编写ld.script实现特定内存分配?尤其是VMA/LMA的应用场景。引用[3]提到&ldquo;复制到其他位置运行”的案例很有价值,这解释了为什么需要分离VMA/LMA。 需要结构化呈现: - 首先定义ld.script是什么(链接过程的蓝图) - 关键作用:控制内存布局(对照引用[3]的VMA/LMA) - 语法规范(入口点、内存区域定义、节区分配) - 必须包含实战案例(如把代码从FLASH复制到RAM执行) 特别注意引用[2]提到的&ldquo;.s文件直接进入汇编阶段”,这说明ld.script处理输入文件类型差异。在&ldquo;使用方法”部分需补充:如何处理汇编文件和C编译文件的不同需求。 用户可能遇到的痛点:不理解AT>语法(引用[3]的>符号实际是>的转义)。要在示例中明确展示此语法,并解释符号转义问题。 安全问题提醒很重要:错误的内存区域重叠会导致系统崩溃,这点在嵌入式领域尤为关键。 </think>以下是关于链接器脚本(`ld.script` 或 `.ld` 文件)的详细介绍,涵盖其作用、核心语法、使用方法及典型案例: --- ### **一、ld.script 概述** 1. **定义** `ld.script` 是 GNU 链接器 `ld` 的配置文件,指导链接器如何合并目标文件(`.o`)和库文件(`.a/.so`),生成最终的可执行文件或共享库[^2][^3]。 2. **核心作用** - **内存布局控制**:指定代码/数据在内存中的物理地址(VMA)和加载地址(LMA),解决硬件相关配置问题[^3]。 - **节区(Section)管理**:重定位 `.text`(代码)、`.data`(初始化数据)、`.bss`(未初始化数据)等节区的存储位置。 - **符号解析**:定义入口点、全局符号地址等。 --- ### **二、核心语法与编写规范** #### **1. 基本结构** ```ld ENTRY(_start) /* 指定程序入口点(符号名) */ MEMORY { /* 定义物理内存区域 */ ROM (rx) : ORIGIN = 0x08000000, LENGTH = 256K RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 64K } SECTIONS { /* 节区分配规则 */ .text : { *(.text*) /* 所有目标文件的代码段 */ } > ROM /* 存入ROM区域(VMA) */ } ``` #### **2. 关键指令详解** | **指令** | **作用** | |----------------|--------------------------------------------------------------------------| | `MEMORY` | 定义物理内存区域的属性(可读/写/执行)及范围 | | `SECTIONS` | 核心配置块,定义节区如何映射到内存区域 | | `> REGION` | 指定节区的运行地址(VMA),如 `> ROM` | | `AT > LMA_REGION` | 指定加载地址(LMA),如 `AT > ROM`(默认LMA=VMA)[^3] | | `KEEP(*(.section))` | 防止链接器优化删除特定节区 | #### **3. VMA与LMA分离场景** [^3] ```ld .data : { _data_start = .; *(.data*) _data_end = .; } > RAM AT > ROM /* VMA在RAM(运行地址),LMA在ROM(加载地址) */ ``` **用途**: - 初始化数据从 Flash(ROM)复制到 RAM 运行(提升性能)。 - 将配置数据定位到硬件特定地址(如外设寄存器)。 --- ### **三、典型应用场景** 1. **嵌入式系统启动** ```ld SECTIONS { .isr_vector : { *(.isr_vector) } > ROM /* 中断向量表固定到ROM首地址 */ .text : { *(.text*) } > ROM .data : { ... } > RAM AT > ROM /* 数据段需从ROM复制到RAM */ } ``` 2. **自定义内存布局** ```ld MEMORY { CUSTOM_RAM (rw) : ORIGIN = 0x40000000, LENGTH = 32K } .user_buffer : { *(.user_buffer*) } > CUSTOM_RAM ``` 3. **保留未引用符号** ```ld /DISCARD/ : { *(*) } /* 丢弃所有未指定节区 */ KEEP(*(.critical_code)) /* 强制保留关键代码 */ ``` --- ### **四、开发流程与调试** 1. **使用方法** ```bash arm-none-eabi-ld -T ld.script -o firmware.elf input.o # 指定链接脚本 ``` 2. **调试技巧** - 生成内存映射报告:`arm-none-eabi-ld -Map=map.txt -T ld.script ...` - 检查符号地址:`nm firmware.elf | grep _data_start` --- ### **五、注意事项** 1. **地址对齐**:使用 `. = ALIGN(4);` 确保4字节对齐。 2. **符号赋值**:`_stack_top = ORIGIN(RAM) + LENGTH(RAM) - 4;`(栈顶地址计算)。 3. **重叠检测**:避免不同节区的VMA/LMA范围重叠。 --- ### **六、完整示例:STM32启动脚本** ```ld ENTRY(Reset_Handler) MEMORY { FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512K SRAM (rwx) : ORIGIN = 0x20000000, LENGTH = 128K } SECTIONS { .isr_vector : { *(.isr_vector) } > FLASH .text : { *(.text*) } > FLASH .data : { _sidata = LOADADDR(.data); /* LMA地址(FLASH中的位置)*/ _sdata = .; /* VMA起始地址(RAM) */ *(.data*) _edata = .; /* VMA结束地址 */ } > SRAM AT > FLASH /* VMA在SRAM,LMA在FLASH */ .bss : { ... } > SRAM /* 未初始化数据直接放RAM */ } ``` --- ### **相关问题** 1. 如何解决链接时出现的 `section .text overlaps .data` 错误? 2. 在 RTOS 中如何为不同任务配置独立的堆栈空间? 3. 如何验证链接器脚本中 LMA 和 VMA 的实际加载效果? 4. 链接器脚本如何实现固件的分区块升级(Bootloader + App)? > 引用文献: > [^1]: LDScript语法基础(函数定义流程) > [^2]: 汇编文件(.s)链接器脚本的交互机制 > [^3]: VMA/LMA分离设计原理与应用场景
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

NW嵌入式开发

感谢您的支持,让我们一起进步!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值