第二章 scatter语法(一)基本结构
先来看一下,一个scatter文件的整体结构,如下图:
接下来分别对其进行详细说明。
2.1 加载region的描述信息
加载region的描述信息指出了它的孩子——执行region——的放置情况
2.1.1 加载region的描述信息组成元素
加载region描述信息由下面组成:
- 名字——被链接器用于标记唯一的加载region
- 基址——在这个region下的数据和代码开始的地址
- 属性
- 可选的最大长度
- 一个或多个执行regoin
如下图
2.1.2 加载region的属性
ABSOLUTE:
链接之后,内容被放置在一个固定地址。除非你使用PI或者RELOC属性,否则这个属性是默认值
ALIGN aligment:
将4字节对齐,增加到aligment字节对齐。aligment必须是2的正数幂。如果加载region直接指定基址,那么基址必须对齐;如果加载region使用+offset的方式指定基址,那么链接器自动计算以保证对齐。
NOCOMPRESS:
默认情况下RW数据被压缩,该属性使得RW数据内容不被压缩。
OVERLAY:
该属性使得在同一个地址,具有多个加载region。ARM工具集不会提供overlay机制。为了在同一个位置放置多个加载region,你必须提供自己的overlay管理器。
PI:
标记该region是地址无关的。内容不会依赖于任何固定的地址。
PROTECTED:
该属性阻止:
- 加载region的重叠
- venner的共享
- 使用–merge选项共享字符串
注意:venner,指的是链接器生成的一小段代码,这段代码可能用于长距离的跳转等。
RELOC:
标记该region是可重定位的。重定位信息会被保存,使其能够被其他的工具移动到其他位置,已达到可重定位的功效
2.1.3 加载region的地址属性继承规则
加载region可以继承上一个加载region的属性。为了达到此目的,只需要使用+offset的方式设置基址即可。如下情况下无法继承属性:
- 显示的设置了加载region的属性
- 前一个加载region具有OVERLAY属性
你可以显式的使用ABSOLUTE,PI,RELOC,OVERLAY指定地址属性,当地址属性没有被指定时,下面的继承规则将会被应用:
- OVERLAY属性不会被继承
- 加载和执行region的基址默认为ABSOLUTE
- +offset会继承上一个region的地址属性,如果没有上一个region,则为ABSOLUTE属性。
例如:
LR1 0x8000 PI
{
…
}
LR2 +0 ; LR2从LR1继承PI属性
{
…
}
LR3 0x1000 ; LR3不会继承因为它没有相对基址,所以为默认属性ABSOLUTE
{
…
}
LR4 +0 ; LR4从LR3继承ABSOLUTE
{
…
}
LR5 +0 RELOC ; LR5不会继承,因为它显式设置了RELOC
{
…
}
LR6 +0 OVERLAY ; LR6不会继承,因为有OVERLAY
{
…
}
LR7 +0 ; LR7不会继承OVERLAY,因此是默认属性ABSOLUTE
{
…
}
2.1.4 RELOC地址属性的继承规则
你可以给加载region设置一个RELOC属性。但是,执行region仅可以从父加载region中继承RELOC。
注意:对于BP链接模型,如果加载region有RELOC属性,那么所有的在这个加载region内的执行region必须是+offset方式来指定基址。这个保证了执行region继承父加载region的重定位信息。
例如:
LR1 0x8000 RELOC
{
ER1 +0 ; 从LR1中继承RELOC属性
{
…
}
ER2 +0 ; 从ER1中继承RELOC属性
{
…
}
ER3 +0 RELOC ; 错误,不能在执行region中显式指定RELOC属性
{
…
}
}
2.2 执行region的描述信息
这部分指定了region在运行时处在内存的什么位置。
2.2.1 执行region的描述信息组成元素
由下面的元素组成:
- 名字——被链接器标识,用于区分不同的执行region
- 基址——不是绝对值就是相对值
- 属性
- 可选的最大长度
- 一个或多个输入section的模式字符串
如下图:
2.2.2 执行region的属性
ABSOLUTE:
链接之后,内容被放置于一个固定的地址。
ALIGN aligment:
将4字节对齐提升到aligment字节对齐。aligment必须是2的正数幂。如果执行region被设置了基址,那么他必须按照aligment字节对齐。如果执行region被设置了偏移,那么链接器自动计算地址,以达到aligment字节对齐。
ALIGNALL value:
增加执行region中各section的对齐为value字节对齐。value的值必须是2的正数幂,并且必须大于等于4
ANY_SIZE max_size:
指定,该region可以放置的未分配section(即.ANY匹配的section)的最大大小。
例如:如果一个执行region,将仅被.ANY匹配的section填充,那么2%将用于venner。剩下的98%才会用于.ANY匹配的section
使用这个关键字时,注意下面的限制:
- max_size 必须小于或者等于region大小
- 可以在没有.ANY选择器的region上使用ANY_SIZE.但是,他会被armlink忽略。
EMPYT [-]length:
在内存中保留一个给定大小的空的区域。通常被用作堆或栈区域。在带有EMPTY属性的region中,不能放置任何section。
length为正数,则基址为起始地址。length为负数,则基址为结束地址。
FILL value:
链接器创建一个region,该region填充value。如果你指定了FILL,那么就必须跟一个value。例如FILL 0xFFFFFFFF.他相当于EMPTY ZEROPAD PADVALUE
FIXED:
固定地址,链接器尝试使执行地址和加载地址相同。如果无法相同将报错。
NOCOMPRESS:
armlink默认是打开RW数据压缩的。该属性使得RW数据不被压缩。
OVERLAY:
指示该region可能会有重叠的section。
PADVALUE:
定义填充的值。PADVALUE必须跟一个值,例如:
EXEC 0x10000 PADVALUE 0xffffffff EMPTY ZEROPAD 0x2000
这将创建一个大小0x2000,填满0xffffffff的region
PADVALUE属性的值必须是字大小,且被加载region所忽略。
PI:
该region仅包含位置无关的section。
注意:该属性在包含XO section时,不支持
SORTTYPE:
指定执行region的排序算法,例如:
ER1 +0 SORTTYPE CallTree
UNINIT:
用于创建包含未初始化数据或者内存映射IO的region。
ZEROPAD:
零初始化的section被写入ELF中,因此不用在运行时填充零
该属性设置ZI输出section的长度,并保存在Image$$region_name$$ZI$$Length中。
注意:Image$$region_name$$ZI$$Length是链接器使用的一些符号。因为本系列文章的主旨是scatter文件。因此不再对链接器的符号做进一步说明。
只有root region可以使用这个属性。否则将产生一个警告,并忽略。
2.2.3 执行region的地址属性的继承规则
执行region可以继承上一个执行region的属性。
为了继承,直接使用+offset的形式来指定基址。第一个执行region继承其父加载region的属性。
执行region在下面情况下无法继承属性:
- 显式设置了执行region的属性
- 上一个执行region具有OVERLAY属性
你可以使用ABSOLUTE,PI,OVERLAY属性,显式的设置执行region。但是,执行region仅继承父加载region的RELOC属性。
当没有地址属性被设置时,下面的继承规则会发生:
- OVERLAY属性不会被继承,含有OVERLAY属性的region也不会继承
- 加载或者执行region的基址默认是ABSOLUTE
- 通过+offset设置的地址,将会继承上一个执行region的地址属性,如果没有上一个,则继承父加载region的地址属性
例如:
LR1 0x8000 PI
{
ER1 +0 ; ERI从LR1中继承PI
{
…
}
ER2 +0 ; ER2从ER1中继承PI
{
…
}
ER3 0x10000 ; ER3没有继承,因为他没有使用相对基址,因此它使用了默认属性ABSOLUTE
{
…
}
ER4 +0 ; ER4从ER3中继承ABSOLUTE
{
…
}
ER5 +0 PI ; ER5不会继承,因为他显式设置了PI
{
…
}
ER6 +0 OVERLAY ; ER6不会继承,因为他设置了OVERLAY
{
…
}
ER7 +0 ; ER7不会继承OVERLAY,因此使用默认属性ABSOLUTE
{
…
}
}
2.2.4 相对地址用在加载region上的情况
当相对地址用在加载region上时,需要注意如下情况:
- 如果使用+offset的加载region(LR2)跟在一个含有ZI数据的加载region(LR1)之后。那么LR2将覆盖ZI数据。为了修复这个,使用ImageLimit()函数来指定LR2的基址。
注意:这在下一章中有例子
- LR2继承LR1的属性,除非如下情况:
- LR1有OVERLAY属性
- LR2显式设置了属性
如果一个加载region无法继承属性,那么它将使用默认值ABSOLUTE。
- 在ROM镜像中,如果一个region含有RW数据压缩,且下一个region使用+offset设置基址,则在这两个region之间,可能存在一个空隙。这是因为链接器计算相对基址时,是相对于未压缩数据的。但是这个空隙会在运行时消失。因为运行时会解压出来。
2.2.5 相对地址用在执行region上的情况
当相对地址用在执行region上时,需要注意一下情况:
- 除非执行region被显式的设置属性,否则,第一个执行region继承父加载region的属性。
- 使用相对地址的执行region(ER2)继承执行region(ER1)的属性,除非如下情况:
- ER1有OVERLAY属性
- ER2有一个显式的属性设置
如果一个执行region无法继承属性,那么将使用默认值ABSOLUTE
- 如果父加载region有RELOC属性,那么在其内的所有的执行region必须使用相对地址。
2.3 输入section的描述信息
输入section的描述信息是一个模式字符串,用于选择section
2.3.1 输入section的描述信息组成元素
由如下部分组成:
- 名字,可以使用通配符——中间文件名,库成员名,或者库名字
- 输入sectoin名,或者输入section属性,例如READ-ONLY,或者CODE。输入section名也可以使用通配符
- 符号名
如下图:
2.3.2 模块和输入section模式字符串举例
模块匹配举例:
- * 匹配任何模块和库
- *.o 匹配任何以o结尾的模块
- math.o 匹配math.o 模块
- *armlib* 匹配所有ARM支持的C库
- “file1.o” 匹配file1.o
- *math.lib 匹配所有以math.lib结尾的库。例如:c:\apps\lib\math\satmath.lib
输入section匹配举例:
- +RO 匹配所有RO代码和RO数据
- +RW,+ZI 匹配所有的RW代码,所有的RW数据,所有ZI数据
- BLOCK_42 匹配名字叫做BLOCK_42的section。这个名字可能有多个section,但是他们的属性可能不同。
本章完,下章scatter文件中使用的表达式和函数