链接器和链接脚本

链接器

将经过编译或者汇编的二进制文件(.o文件) 生成可执行二进制文件。
例如GNU Linker,提供一个链接命令ld,常用的链接选项如下:

选项注释
-T指定链接脚本
-Map输出一个符号表文件
-o输出最终可执行二进制文件
-b指定目标代码输入文件的格式
-e使用指定的符号作为程序的初始执行点
-l把指定的库文件添加到要链接的文件清单中
-L把指定的路径添加到搜索库的目标清单中
-S忽略来自输出文件的调试器符号信息
-s忽略来自输出文件的所有符号信息
-t在处理输入文件时显示它们的名称
-Ttext使用指定的地址作为代码段的起点
-Tdata使用指定的地址作为数据段的起点
-Tbss使用指定的地址作为未初始化的数据段的起点
-Bstatic只使用静态库
-Bdynamic只使用动态库
-defsym在输出文件中定义指定的全局符号

链接脚本

链接器的链接过程由一个链接脚本控制,该脚本使用链接器命令语言编写,主要用于规定各输入文件中的程序、数据等内容段在输出文件中的空间和地址如何分配。
如果没有通过 “-T” 参数指定链接脚本时,链接器会使用内置的链接脚本。

常用语法汇总

定位符.

定位符.表示当前地址,根据 section 的大小不断增加,不能倒退。对定位符.赋值可修改当前地址,指定其后内容的存储位置,如果没有以其它的方式指定输出节的地址,则地址值会根据定位器的当前值计算。

. = 0x1000;
.text :
{}

. = 0x2000;
.rodata :
{}

先修改起始地址为 0x1000,指定 text 段从当前位置存储;再修改当前地址为 0x2000,指定 rodata 段的存储位置。

ENTRY

ENTRY(SYMBOL) :将符号 SYMBOL 对应的地址设置成程序入口地址。常见的实例比如:ENTRY(_start),表示程序从 _start 处开始运行。设置程序入口的方法有好几种,根据优先级从高到低依次为:

  • ld 命令行的 -e 选项
  • 链接脚本的ENTRY(SYMBOL)命令
  • 在汇编程序中定义了 _start 符号,使用 _start 符号值(如.global _start)
  • 如果存在 .text section,使用 .text section 首地址的值
  • 从地址 0 开始运行
MEMORY
MEMORY 
{
    NAME1 [(ATTR)] : ORIGIN = ORIGIN1, LENGTH = LEN2
    NAME2 [(ATTR)] : ORIGIN = ORIGIN2, LENGTH = LEN2
}

MEMORY声明一个或多个内存区域,名称必须唯一,其属性指定该区域是否可以写入、读取或执行。
ATTR属性支持7种模式:

  • R 只读section
  • W 读/写section
  • X 可执行section
  • A 可分配的section
  • I 初始化了的section
  • L 同 I
  • ! 反转以上任何属性
    常见的内存设置一般有一个flash和一个sram区域:
MEMORY
{
	flash (rxa) : ORIGIN = 0x80000000, LENGTH = 128K
	sram (wxa) : ORIGIN = 0x20000000, LENGTH = 32K
}
SECTIONS
SECTIONS
{
	secname [VMA_ADDR] [(TYPE)] : [AT (LMA_ADDR)]
	{ 
		contents 
	} [>VMA_REGION] [AT>LMA_REGION] [:PHDR HDR ...] [=FILLEXP]
}
  • secname
    表示输出文件的段名,后面必须紧跟一个空格,使用冒号**:**分割
  • contents
    描述该段的内容包括哪些文件、符号
  • TYPE
    每个输出section都有一个类型,如果没有指定TYPE类型,那么连接器根据输出section引用的输入section的类型设置该输出section的类型。例如 NOLOAD,表示该section在程序运行时,不被载入内存。
  • VMA_REGION
    对应 MEMORY 定义的内存区域。
  • LMA_REGION
    对应 MEMORY 定义的内存区域。
  • VMA_ADDR
    虚地址,即输出文件VMA(运行地址)。表示将该段强制链接到的地址,会改变定位符.的值。
  • LMA_ADDR
    加载地址,即数据实际存储的地。表示该段的 LMA(加载地址),默认情况下 LMA = VMA。数据段加载时会存至 Flash 中(使用LMA地址),运行时将其搬运到 RAM(使用VMA地址)。
.text :
{
} >flash AT>flash

.bss :
{
} >flash AT>sram
ALIGN

表示字节对齐, 如. = ALIGN(4)表示从该地址开始后面的存储内容进行4字节对齐。

PROVIDE

定义一个符号,相当于定义一个全局变量的符号表,其他C文件可以通过该符号来操作对应的存储内存。程序中可以先使用该符号,虽然此时未定义,但是链接时会识别到该符号。

KEEP

当链接器使用–gc-sections进行垃圾回收时,链接器可能将某些它认为没用的 section 过滤掉,此时就有必要强制让链接器保留一些特定的 section,KEEP()可以使得被标记section的内容不被清除(即防止被优化)。

参考链接

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

怦然心动如往昔

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值