注意:本文章只针对,裸机开发.至于SysV,BPABI,BP的链接模型请参考《armlink_user_guide》
编译器将源文件编译成中间文件。链接器将中间文件最终生成镜像文件。
在中间文件中,逻辑最小单元称为section。链接器将所有中间文件的section收集起来,然后按照一定的规则,进行重新组织。将具有相同属性的section,组织在一起,称为输出section。相应的,中间文件的section称为输入section。然后再将不同的输出section组织在一起,起个名字叫做region。
他们之间的关系如下图
下面分别介绍输入section,输出section,region和segment
输入section:输入section来自于中间文件。它含有代码,初始化数据或者描述信息。描述信息用于表示未被初始化的段或者镜像执行之前必须设置为0的段。输入section具有RO,RW,XO,ZI这样的属性。这些属性被armlink用于组织成region或者输出section
输出section:输出section其实是具有相同属性的输入section的集合,因此输出section的属性和输入section的属性相同。这些输入section被连续的放置于内存中。
region:一个region最多包含四个不同属性的输出section。默认情况下,在region中的输出section根据属性进行排序。XO输出section总是第一个,接着是RO输出section,然后是RW输出section,最后是ZI输出section。通常一个region被映射成一个物理内存设备,例如ROM,RAM。可以使用scatter改变输出section的顺序。
segment:等同于region,之所以叫segment是因为在arm elf标准中使用了这个术语。
注意:armlink的单个segment的最大值为2GB
RO——read only
RW——read write
ZI——zero initialized
XO——execute only
在执行镜像之前,可能必须要把部分region移动到它的执行地址处,或者创建ZI输出section。例如,对于已经初始化的RW数据可能必须将其从ROM移动到RAM处。
这样就会导致一个镜像具有两种不同的内存视图:加载视图,执行视图
当region的加载地址和执行地址一样时,称为root region
下图展示了这两者的区别。
为了帮助理解上述概念,这里介绍三种简单镜像。
类型1:一个加载region,三个执行region。如下图所示:
为了指定ro的地址,可以使用命令行选项–ro_base.命令如下:
armlink --ro_base 0x8000
注意:0x8000是默认地址,因此在这个例子中,也可以不用指定
加载视图:这个唯一的加载region由RO和RW两个输出section组成。ZI输出section在加载视图中不存在,他是在执行之前创建的。
执行视图:由三个连续的执行region组成,他们分别包含RO,RW和ZI输出section。RO和RW的执行地址与加载地址一样,因此无需做任何移动。但是,ZI执行region必须在运行时创建。
使用--ro_base address指定RO region的加载和执行地址。
使用--zi_base address指定ZI region的执行地址。
包含XO的加载视图
如果一个镜像包含XO section。那么XO输出section就被放置于--ro_base指定的位置处。RO和RW则连续排在其后
包含XO的执行视图
如果一个镜像包含XO section,那么XO执行地址为--ro_base指定的地址处,RO,RW和ZI紧随其后
类型2:一个加载region,三个执行region。但是RW执行region的地址和RO的执行地址不连续。
如下图:
使用下面的命令创建这种类型的镜像:
armlink --ro_base 0x0 --rw_base 0xA000
加载视图:一个加载region,包含RO和RW输出section,且这两者连续放置。
执行视图:第一执行region包含RO输出section。第二个执行region包含RW和ZI输出section
第一个执行region和加载region地址相同,因此不需要移动。第二个执行regoin和加载region的地址不同,因此它需要进行搬运。ZI 执行region在运行时创建
使用--ro_base address指定RO输出section加载和执行地址。
使用--rw_base address指定RW输出section的执行地址。
使用--zi_base address指定ZI执行region的地址
含有XO region的加载视图
如果一个镜像含有XO section。那么XO section被放置在--ro_base指定的地址处。RO和RW则紧随其后
含有XO region的执行视图
如果一个镜像含有XO section。那么XO section的执行region放置在--ro_base指定的地址处。RO则紧随其后
如果使用了--xo_base address,那么XO 执行region被放置在这个指定的地址处
类型3:该类型类似于类型2,但是跟类型2不同的是,类型3的加载视图,被分隔成多个root region。如下图:
使用下面的命令,生成这种类型的镜像:
armlink --split --ro_base 0x8000 --rw_base 0xE000
加载视图:第一个 加载region 包含 RO输出section 。第二个 加载region 包含 RW输出section。
执行视图:第一个执行region包含RO 输出section,第二个执行region包含RW输出section。第三个执行region包含ZI输出section。
RO和RW输出section都是root region,因此不需要移动,只有ZI需要在运行时创建。
使用–split,将默认的单个加载region分隔开。
含有XO的加载视图
如果一个镜像含有XO section,则XO被放置在--ro_base 所在的地址处,RO和RW紧随其后
含有XO的执行视图
如果一个镜像含有XO section,则放置在--ro_base 所指的地址处。
如果你指定了--split选项,XO和RO被放置在第一个加载regioin中,RW和ZI执行region放在第二个加载region中
如果你指定了--xo_base,XO的执行地址则是此处指定的地址。
本章完,下章,scatter文件语法