ATJ2157 sct语法
- 公共知识篇
- BNF 简介
- Sct脚本
- Sct的作用
- Sct的语法规则
- 1. 加载域描述(Loadd region descriptions)
- 2. 执行域描述
- 3. 输入节的描述
- ATJ2157平台使用的sct
- RO的等效写法
- ScatterAssert()函数
- LoadLength()函数
- LoadBase()函数
- ImageLimit()函数
- ATJ2157平台什么数据编译出来是.data,.constdata与.bss
- sct参考学习网站
公共知识篇
BNF 简介
巴科斯范式(BNF: Backus-Naur Form 的缩写)是由 John Backus 和 Peter Naur,首次引入一种形式化符号来描述给定语言的语法。
简称为:BNF符号。
现在,几乎每一位新编程语言书籍的作者都使用巴科斯范式来定义编程语言的语法规则巴科斯范式的内容
在双引号中的字(“word”)代表着这些字符本身。而double_quote用来代表双引号。
在双引号外的字(有可能有下划线)代表着语法部分。
尖括号( < > )内包含的为必选项。
方括号( [ ] )内包含的为可选项。
大括号( { } )内包含的为可重复0至无数次的项。
竖线( | )表示在其左右两边任选一项,相当于"OR"的意思。
::= 是“被定义为”的意思。
关于具体的例子可以上网搜索,网上资料比较齐全
Sct脚本
Sct 的全称是 Scatter File Syntax,
Sct的作用
在学习一个东西之前,首先要明白,她是干什么的?那么sct脚本文件到底是什么东西?
其实吧,sct脚本文件是描述如何把输入文件中的节(sections)映射到输出文件中,并控制输出文件的存储布局的脚本文件。并且sct的语法是遵守BNF的语法规则的。
Sct的语法规则
一个.sct文件,包括了一个或者多个加载域(load region),每个加载域也包括一个或者多个执行域(execution region)
下面是一个.sct文件的文件结构图
1. 加载域描述(Loadd region descriptions)
其实加载域就是用来描述下内存的区域,这个区域是用来存放执行域的
加载区域描述的组件允许您唯一标识加载区域,并控制ELF文件的哪些部分放置在该区域中
加载域的具体结构
一个加载域描述,应该包括哪些内容呢?
1:名字(被编译器用来识别不同的加载域)
2:一个基地址(代码或数据的开始地址)
3:属性说明
4:大小
5:一个或者多个执行域
加载域的语法详解
符合BNF的规则,对规则不了解的可以百度下
load_region_description ::= load_region_name (base_address | (“+”
offset)) [attribute_list] [max_size]
“{”
execution_region_description+
“}”
load_region_name:
加载域的名字,这个是区域中区分大小写的
base_address :
这个区域内被链接的地址,注意要满足对齐的要求
+offset:
描述一个基地址,其偏移字节超出了前一个加载区域的结尾,offset必须是4字节对齐,如果这是第一个加载区域,那么+offset意味着基址从零开始偏移字节。如果使用+offset,则加载区域可能从以前的加载区域继承某些属性
attribute_list:
待定补充
max_size:
指定加载区域的最大大小。这是在执行任何解压缩或零初始化之前加载区域的大小。如果指定了可选的max_size值,那么如果分配给armlink的区域超过max_size字节,则armlink将生成错误
execution_region_description:
指定执行区域名称、地址和内容
加载的属性问题
PI 与地址无关方式存放;
RELOC 重新部署,保留定位信息,以便重新定位该段到新的执行区;
OVERLAY 覆盖,允许多个可执行区域在同一个地址,ADS不支持;
ABSOLUTE 绝对地址(默认);
加载域的继承问题
一个加载域继承另一个加载域的属性,请使用+offset
RELOC属性的继承规则
如果显性设置了一个加载域的属性为RELOC,那么执行域只能承认,不能设置
如下:
LR1 0x8000 RELOC
{
ER1 +0 ; inherits RELOC from LR1
{
…
}
ER2 +0 ; inherits RELOC from ER1
{
…
}
ER3 +0 RELOC ; Error cannot explicitly set RELOC on an execution region
{
…
}
}
2. 执行域描述
执行区域描述的组件允许您唯一地标识每个执行区域及其在父加载区域中的位置,并控制ELF文件的哪些部分放置在该执行区域中
执行域的结构
一个执行域描述,应该包括哪些内容呢? 1:名字(被编译器用来识别不同的加载域)
2:一个基地址(代码或数据的开始地址)
3:属性说明
4:大小
5:一个或者多个输入的段
执行域的语法详解
执行域其实就是在说明输入段即代码运行时的地址
execution_region_description ::=
exec_region_name (base_address | "+" offset) [attribute_list] [max_size | length]
"{"
input_section_description*
"}"
跟加载域的描述差不多,可以参考加载域的说明
PI 与地址无关,该区域的代码可任意移动后执行;
OVERLAY 覆盖;
ABSOLUTE 绝对地址(默认);
FIXED 固定地址;
UNINIT 不用初始化该区域的ZI段;
执行域的继承问题
一个执行域使用+offset属性时,能够承认前面一个执行域的属性,还有就是第一个使用+offset的执行域会承认她所在加载域的属性
有两种情况,即使使用了+offset时也不能继承
1:显性的设置了当前执行域的属性
2:前一个执行域的属性使用了OVERLAY属性
一个执行域只能继承RELOC属性(这个属性一定是加载域的)
如下例子
LR1 0x8000 PI
{
ER1 +0 ; ER1 inherits PI from LR1
{
…
}
ER2 +0 ; ER2 inherits PI from ER1
{
…
}
ER3 0x10000 ; ER3 does not inherit because it has no relative base
address and gets the default of ABSOLUTE
{
…
}
ER4 +0 ; ER4 inherits ABSOLUTE from ER3
{
…
}
ER5 +0 PI ; ER5 does not inherit, it explicitly sets PI
{
…
}
ER6 +0 OVERLAY ; ER6 does not inherit, an OVERLAY cannot inherit
{
…
}
ER7 +0 ; ER7 cannot inherit OVERLAY, gets the default of ABSOLUTE
{
…
}
}
3. 输入节的描述
输入节的结构
输入节描述的组件允许您标识ELF文件中要放置在执行区域中的部分
可以看出输入节有两个部分
1:模块名 (个人理解实际上是.o的文件名)
2:输入节的名字,或者是输入节的属性,如READ-ONLY or CODE
这里面都可以使用通匹符
输入节的语法
input_section_description ::= module_select_pattern [ “(”
input_section_selector ( “,” input_section_selector )* “)” ]
input_section_selector ::= “+” input_section_attr
| input_section_pattern
| input_symbol_pattern
| section_properties
module_select_pattern:
就是文件名,当然实际是
1:object 文件包括的节中的名字
2:库成员的名字(.lib)
3:带有全路径的库中的名字
特别说明,关于 module_select_pattern 我们可以使用通匹符,
* 可以代替0个或者多个字符
?可以代替一个字符
input_section_attr:
属性选择器,是与输入节相匹配的。
每一个输入节的属性前必须加一个+号。属性选择器不区分大小写
RO-CODE
RO-DATA
RO, selects both RO-CODE and RO-DATA.
RW-DATA.
RW-CODE.
RW, selects both RW-CODE and RW-DATA.
XO.
ZI.
ENTRY, that is, a section containing an ENTRY point.
CODE for RO-CODE.
CONST for RO-DATA.
TEXT for RO.
DATA for RW.
BSS for ZI
FIRST.
LAST
举例说明
ATJ2157平台使用的sct
US2157平台使用的.sct
跟标准的一样,
使用分号;进行一行的注解
Sct存放在MDK目录下
最终会生成一个map文件,可以看到地址信息
使用+RO,实际上没有必要在使用.rodata了
+RO 实际上已经包含了.rodata
RO的等效写法
下面4种写法是等效的
至于原因可以参考input_section_attr的说明
ScatterAssert()函数
ScatterAssert(exp)
如果exp为false则链接器就报错
在key.sct中有这样一个例子
如果.data区与.bss区之后超过了限制的大小,链接器就会报错。如下图:
LoadLength()函数
LoadLength(region_name)
返回region_name的大小
region_name 可以是加载视图或者执行视图的名字
LoadBase()函数
LoadLength(region_name)
返回region_name的基地址
region_name 可以是加载视图或者执行视图的名字
ImageLimit()函数
ImageLimit(region_name)
返回region_name的最后地址
region_name 可以是加载视图或者执行视图的名字
ATJ2157平台什么数据编译出来是.data,.constdata与.bss
.data:
1:基本的数据类型,整型,字符型,布尔型,uinon,枚举,指针(不管有没有初始化及初始化值为多少),
2:初始化不为0的数组,struct 结构体
3:static 修饰的局部变量
.constdat:
const修饰的变量
.bss:
1:初始化为0或者没有初始化的数组,struct 结构体
sct参考学习网站
官方网站
https://www.keil.com/support/man/docs/armlink/armlink_pge1362075650322.htm
CSDN相关网站:
https://blog.csdn.net/xiaowanbiao123/category_9827056.html