当前位置: 首页 > news >正文

链接脚本基础语法

目录

前言

ELF文件布局

链接脚本语法

段定义标准格式

地址计数器 .

地址计数器的动态特性

赋值 vs 引用

符号定义

通配符规则

COMMON块

COMMON 块的产生与处理

示例脚本


前言

由于嵌入式系统内存资源珍贵,链接脚本可指定代码段(.text )、只读数据段(.rodata) 、数据段(.data )、未初始化数据段(.bss )等在内存中的存储位置以实现内存布局管控;

链接脚本将多个目标文件(.o )中相同类型的段(如 .text 代码段、.data 已初始化数据段、.bss 未初始化数据段 )合并,构建统一可执行文件;

链接脚本可以控制程序入口地址,定义初始化数据在启动时从 Flash 到 RAM 的搬移规则

ELF文件布局

代码段(.text): 存储可执行的机器指令数据段(.data): 存储已初始化的全局变量和静态变量只读数据段(.rodata): 存储不可修改的数据,比如字符串常量 const修饰的全局变量 常量BSS 段(.bss): 记录未初始化的全局变量和静态变量,不占用文件空间

链接脚本语法

SECTIONS {// 定义各个输出段及其内存布局
}
  • SECTIONS 是链接脚本的关键字,表示开始定义各个段的内存布局;
  • 大括号 {} 内包含所有段的配置信息;

段定义标准格式

段名 [地址] : { 段内容 }
  • 段名:比如 .text.data.rodata.bss等,标识段的类型;
  • [地址]:可选参数,指定具体段的起始地址(如 0x80000000);
  • 冒号(::必须存在,用于分隔 "段名 + 地址" 和 "段内容",是语法结构的核心标识;
  • 段内容:用大括号 {} 包裹,定义哪些输入段需要合并到当前段中(如 *(.text*));
/* 示例脚本 */
SECTIONS {.text 0x08000000 : { *(.text*)}
}

以点开头的段名被定义为系统保留段,以点开头的段名由编译器和链接器 "预留",链接器会默认将以点开头的段名视为标准段,并应用特定的处理逻辑,如果省略点,可能导致链接器无法正确识别段的类型,用户自定义的段通常不以点开头(如my_section),从而避免与系统段名冲突;

my_section : { *(.my_section*) }   // 用户自定义段名

地址计数器 .

. = 0x08000000; /* 设置当前地址计数器为 0x08000000 */
.text : {*(.text*) /* 所有 .text 输入段从这里开始放置 */
}
/* 链接器自动增加 . 的值到 .text 段末尾 */

地址计数器 . 的本质为变量,其值表示下一个将要被分配的地址下一个空闲地址,而非当前已使用的地址,地址计数器 . 始终指向尚未分配的内存位置;地址计数器决定当前正在描述的输出段会被放置到哪个具体地址;

地址计数器的动态特性

地址计数器 .  的值在链接脚本执行过程中会自动变化:

  • 隐式增长: 当你将一个输入段(比如 .text, .data)放入输出段时,链接器会自动将 . 的值增加该输入段的大小,指向该段之后的下一个可用地址;

  • 显式设置: 可以通过赋值语句直接设置 . 的值(例如 . = 0x08000000;),强制将后续内容定位到特定地址;

赋值 vs 引用

. = expression; /* 赋值操作,直接设置 . 的值 */symbol = .; /* 定义符号 symbol 并将其值设置为当前 . 的值, 引用不会改变 . 本身 */

符号定义

symbol = expression; 
  • symbol自定义的全局符号名称(通常以___开头避免冲突);

  • expression基于地址计数器.、内存区域或其它符号的表达式;

@ 链接脚本文件
.data 0x80004000 : {__data_start = .;  @ 记录数据段起始地址*(.data*)          @ 合并所有.data*段( 非语句,无分号)__data_end = .;    @ 记录数据段结束地址
}

链接脚本中定义的符号为强符号(Strong Symbol),不会被其他目标文件中的同名弱符号(Weak Symbol)覆盖;

链接脚本中定义的符号(__data_start 、__data_end)具有全局属性,可在C/C++代码中用extern声明或在汇编文件中直接使用;

@ ARM汇编文件
ldr r0, =__data_start  @ 将链接脚本符号作为立即数加载
汇编器处理机制1. 符号引用: 汇编器遇到 __data_start 时,会将其视为未解析的符号;2. 生成重定位信息: 在目标文件中记录该符号需要链接器解析;3. 链接器解析: 链接阶段,链接器将 __start_start 替换为实际地址值;

链接脚本中定义的符号本身不携带类型信息,在 C/C++ 和汇编文件中,开发者可以通过选择适当的类型声明来安全地使用这些符号;

extern uint8_t __data_start; 
extern void*   __data_start;     

通配符规则

星号 *:匹配任意字符序列

  • 作用:代替 “任意长度的任意字符”,用于匹配不确定的段名前缀、后缀或中间部分。
  • 示例
    • *(.text):匹配所有输入文件中名称以 .text 开头的段(如 .text.text.init.text.fini 等子段 ),常用于合并所有代码段。
    • *.o(.data):匹配所有文件名以 .o 结尾的目标文件中的 .data 段,精准筛选特定文件的段

注意:

  • “动” 则加分号:凡是改变地址(. = ...)或定义符号(__symbol = ...)的 "动作",末尾必须加分号;
  • “静” 则无分号:单纯 “选择段”(*(.text*))或 “引用内容” 的表达式,无需分号;

COMMON块

.bss : {__bss_start = .;*(.bss*)     @ 合并目标文件中的 .bss 段(已分配空间的未初始化变量)*(COMMON)    @ 合并目标文件中的 COMMON 块(未分配空间的未初始化变量)__bss_end = .;
}

早期 C 语言编译器中,对于 未初始化的全局变量,编译器不会为其分配固定大小的内存空间,而是将其标记为一个 "未定义的符号",并记录其类型和期望的大小,此类符号在目标文件(.o文件)中会被组织成 COMMON 块

COMMON 块的产生与处理

1.  示例程序 

// file1.c
int global_var;  // 未初始化全局变量,生成 COMMON 块
// file2.c
int global_var;  // 同名未初始化全局变量,另一个 COMMON 块

    2.  编译后的目标文件

    • file1.o 和 file2.o 中各有一个 COMMON 块,只记录 global_var 为 int 类型(4 字节);
    • 每个目标文件中的 COMMON块不占用实际空间,仅记录符号信息

    3.  链接时的处理

    • 链接器遇到 *(COMMON) 时,将两个目标文件的 COMMON 块合并,为 global_var 分配 4 字节空间,放入 .bss 段;
    • 最终 .bss 段中只有一个 global_var 变量,避免重复定义错误;

    注意:

    • 如果省略 *(COMMON),可能导致未初始化变量无法被正确处理,所以链接脚本中必须写*(COMMON);
    • 为确保完整收集不同编译器生成的未初始化变量,避免因遗漏导致的链接错误或运行时内存错误,因此在链接脚本的 .bss 段中必须同时合并 .bss* 和 COMMON 块

    示例脚本

    SECTIONS {.text 0x80000000 : {*(.text*)}.rodata : {*(.rodata*)}.data 0x80004000 : {__data_start = .;*(.data*)__data_end = .;}.bss : {__bss_start = .;*(.bss*)*(COMMON)__bss_end = .;}.stack 0x80200000 : {. = . + 0x40000;  @ 分配256KB栈空间__stack_top = .;  @ 栈顶地址}
    }

    相关文章:

  1. 面试150 除自身以外数组的乘积
  2. 今日推荐:data-engineer-handbook
  3. 包教包会,ES6类class的基本入门
  4. 本地编译LibreHardwareMonitor
  5. 仕么是Transformer以及工作原理和架构
  6. 人工智能、机器人最容易取哪些体力劳动和脑力劳动
  7. MySQL学习(1)——基础库操作
  8. C++智能指针编程实例
  9. Redis-CPP 5大类型操作
  10. C#Halcon从零开发_Day14_AOI缺陷检测策略1_Bolb分析+特征分析_饼干破损检测
  11. Kotlin 中为什么没有静态变量和静态方法—不用static?
  12. 鸿蒙 Column 组件指南:垂直布局核心技术与场景化实践
  13. Pandas 数据清洗
  14. 端侧调用云数据库获取业务数据
  15. 【Datawhale组队学习202506】YOLO-Master task03 IOU总结
  16. 从iPSC到成熟细胞,纳米生物材料如何当“向导”?
  17. 【大模型微调】6.模型微调实测与格式转换导出
  18. 核心概念解析:AI、数据挖掘、机器学习与深度学习的关系
  19. Linux(3)
  20. 数学:初步了解什么是“向量”
  21. 营销网站建设网络公司/360推广和百度推广哪个好
  22. 网站做微信链接怎么做的/免费网站推广平台
  23. wordpress布置网站教程/seo优化服务商
  24. 怎样帮人做网站挣钱/给我免费播放片高清在线观看
  25. 网站建设项目标书/百度地图疫情实时动态
  26. 自适应网站一般做多大尺寸/临沂百度公司地址