GNU Linker Script(.lds文件)的学习

资料来自于:(GNU Tools for ARM Embedded Processors 6-2017-q1-update)
Version 2.27.90

一、定义和作用:
Linker script是一个连接脚本,其主要目的在于描述输入文件的sections应该怎么映射到输出文件,并且控制输出文件的存储空间布局。

二、用法:
连接器总是要用到一个连接脚本,如果自己没定义的话,连接器将用一个默认的脚本(该脚本已经被编译进了可执行的连接器)。

三、关于连接脚本的一些概念
object file相关:
1、连接器将若干个输入文件组合成一个输出文件,这个输出文件和每个输入文件都遵循同一种数据格式,即object file目标文件格式,每个文件都被称为目标文件,而输出文件也常被称为可执行的目标文件。

section相关:
2、每个目标文件都有一系列的sections,输入文件中的section称为输入section,输出文件同理。目标文件中的每个section都有一个名字和一个大小值。大多数section还有一个关联的数据块(block of data),被称为段内容。
3、一个section也许会被标记为可加载的,意思是当可执行文件运行时这个section的段内容应该被加载到存储空间中。一个没有段内容的section也许是可分配的,意思是存储空间中这块区域应该被留出,但这里不加载任何内容(有时这块区域必须被置位0)。一个即不是可加载的也不是可分配的section,通常包含某种调试信息。
4、每个可加载或者可分配的输出section都有两个地址:一个是VMA虚拟内存地址,这是可执行文件运行时,section得到的地址,即执行地址。另一个是LMA加载存储地址,section将被加载到这个地址。在大多数情况下两个地址是相同的。一个不相同的例子是:当数据section被加载进ROM,然后当程序启动时被拷贝到RAM时,在这里ROM地址就是LMA,而RAM地址就是VMA。
5、可以用objdump程序的“-h”选项查看一个目标文件中的section。

symbols相关:
6、每个目标文件也有一系列的symbols,称为符号表(symbol table)。一个符号可以是已定义或未定义。每个符号都有一个名字,每个已定义的符号都有一个地址。假如把一个C或C++程序编译成目标文件,每一个已定义的函数、全局变量、静态变量都将获得一个已定义的符号。每一个输入函数涉及到的未定义函数、全局变量都将变成一个未定义的符号。
7、可以用nm程序来查看目标文件的符号,或者通过objdump程序的“-t”选项。

四、连接脚本的格式
连接脚本是一个txt文件。连接脚本由一系列命令组成,每个命令都是一个关键字,可能紧随其后的是参数,或者赋值符号。可用“;”来分隔命令,空格通常被忽略。
1、文件名、格式名这样的字符串可以直接输入。假如文件名含有标点符号如逗号(逗号本来是用来分隔文件名的)那么需要将这个文件名用双引号括起来。所以文件名中不能出现双引号。
2、连接脚本中的注释可以用/**/,就像C语言中的注释一样。

五、简单的连接脚本示例
最简单的连接脚本只有一个命令“SECTIONS”。使用该命令来描述输出文件的存储空间布局。
该命令是一个很强大的指令,这里我们来举一个简单的例子,假设你的程序只由代码、初始化的数据、未初始化的数据构成。这些数据分别在“.text”,“.data”,“.bss”段中,再假设你的输入文件中只有这几个段。
举个例子,比如代码从0x10000地址被加载,数据从地址0x8000000地址开始,下面是连接脚本:

SECTIONS
{
. = 0x10000;
.text : { *(.text) }
. = 0x8000000;
.data : { *(.data) }
.bss : { *(.bss) }
}

这个SECTIONS是一个关键字,后面跟着的是一系列的符号赋值,大括号里面是输出段的描述。

“SECTIONS”命令内部的第一行:给符号“.”赋值为0x10000,”.”是一个位置计数器,假如你不指定某输出段的地址,那么这个输出段地址将被设为位置计数器的当前值,同时位置计数器在当前值的基础上累加了该输出段的大小。

在SECTIONS命令开始时,位置计数器的值是0。

第二行:定义了一个输出段“.text”,冒号是语法规定的可忽略,输出段名字后面的大括号里列出的是输入段的名字,表示这些输入段的内容应该被放置到输出段内。是通配符,(.text) 表示输入文件中所有的.text输入段。所以这行的意思就是:输入文件中所有的.text段的内容都放置到可执行文件的输出段.text内。当定义输出段.text时,位置计数器的当前值为0x10000,所以连接器将可执行文件中的.text段地址设为0x10000。

同理,后续几行定义了输出可执行文件中的.data和.bss段。连接器将输出段.data放置在0x8000000地址。.data : { *(.data) }语句后,位置计数器的值是0x8000000加上.data段的大小。那么.bss段在存储空间中将紧挨着.data段放置。

连接器应该保证每个输出段是对齐的,必要时可以通过增加位置计数器来实现。在这个例子里,输出段.text和.data是直接定义了地址,所以满足对齐约束,但连接器必须在.data和.bss段之间制造一小段空隙才能满足对齐约束。

六、简单的连接器脚本指令
6.1 设置入口点
在程序中被调用的第一条指令,称之为入口点。可以用ENTRY命令设置入口点,该命令的参数是一个符号名:
ENTRY(symbol)

有以下几种方法可以设置入口点:
(1)“-e”入口命令行选项;
(2)连接脚本中用ENTRY(symbol)命令;
(3)目标的特殊符号的值,对于大多数目标,这个符号是start。但PE和BeOS系统会检查一系列可能的入口符号,匹配第一个被找到的那个符号。
(4).text段的第一个字节地址位置,若存在的话;
(5)从0地址位置。

6.2 处理文件的命令

INCLUDE filename

filename是连接脚本

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值