打印

开新贴,翻译RVDS的scatter文档

[复制链接]
楼主: xinzha
手机看帖
扫描二维码
随时随地手机跟帖
21
xinzha|  楼主 | 2010-1-1 23:09 | 只看该作者 |只看大图 回帖奖励 |倒序浏览
本帖最后由 xinzha 于 2010-1-2 22:47 编辑

5.2.3 加载区域描述

一个加载区域包含如下内容:
1、名字(链接器用来区分不同的加载区域)
2、基地址(加载时使用的代码以及数据的起始地址)
3、属性(可选)
4、最大尺寸(可选)
5、执行区域列表(执行时区分各个模块的类别和地址)

BNF语法如下:
load_region_description ::=
    load_region_name (base_address |("+" offset)) [attribute_list] [max_size]
        "{"
              execution_region_description+
        "}"

  链接器会为每个执行区域生成一个符号 Load$$exec_region_name$$base,这个符号记录了执行区域的加载地址(参见《执行区域描述》)。而load_region_name只是用来区分各个加载区域,也就是说不会生成类似Load$$region_name的符号。
  为调试器生成的镜像文件要求每个区域有一个独一无二的基地址,因为调试器要把每个区域加载到他们的加载地址上。在调试器中使用叠加加载技术会导致镜像的部分文件被覆盖。而一个完善的加载程序或者操作系统是可以正确加载重叠的位置无关区域,此时一个或者多个位置无关区域自动地被移动到不同的地址上。

base_address:  指定区域中的目标文件被链接的地址,这个地址必须是字对齐。

+offset: 将当前加载区域的基地址描述为上一个加载区域结束地址的偏移量,offset必须能够被4整除。如果这是第一个加载区域,那么就意味着是相对于0的offset偏移。

attrbute list:声明加载区域内容的属性
1、ABSOLUTE  绝对地址
2、PI               位置无关
3、RELOC        可重新分配
4、OVERLAY    叠加
5、NOCOMPRESS  不可被压缩
前四种模式不能并存,只可指定其中一种。默认的加载区域属性是ABSOLUTE。
如果几个加载区域属性是PI,RELOC或者OVERLAY中的一种,那么这些区域可以有重叠的地址范围。对于ABSOLUTE属性的区域,链接器不允许有重叠地址。
OVERLAY关键字允许你在一个地址上放多个执行区域。ARM在RVCT中不提供overlay机制。换句话说就是如果你想使用这项功能,就得你自己提供overlay管理功能。
默认状态下,RW数据压缩功能是使能的。NOCOMPRESS关键字允许你指定一个加载区域在最终的镜像中不被压缩。

max_size  指定加载区域的最大尺寸。如果指定这一数值,armlink会在这个区域大小超出max_size时报错。

execution_region_description:指定执行区域的名字,地址和内容。参见《执行区域描述》

使用特权

评论回复
22
xinzha|  楼主 | 2010-1-2 22:39 | 只看该作者
5.2.4 执行区域描述
一个执行区域包含如下内容:
1、名字
2、基地址(绝对或者相对)
3、最大尺寸(可选)
4、执行区域属性
5、一个或多个输入段描述(放入这个执行区域的模块)

BNF语法如下:
  execution_region_description ::=
      execution_region_name(base_address|"+"offset)[attribute_list][max_size|"-"length]
          "{"
                input_section_description*
          "}"
execution_region_name:执行区域名称

base_address:指定区域内的目标文件链接的地址,此地址必须是字对齐。

+offset:将此区域的基地址描述为相对于上个区域结束地址的偏移量,这个值必须被4整除。如果这个执行区域之前没有其他执行区域(当前加载区域内的第一个执行区域),那么这个offset就代表此执行区域的基地址是相对于加载区域基地址的offset偏移。如果使用+offset语法,并且外层的加载区域包含了RELOC属性,那么执行区域也将继承RELOC属性。而如果使用一个固定的base_address,那么后续即使有+offset,这个offset也不会继承RELOC属性。   

attribute_list:指定执行区域内容的属性
  ABSOLUTE: 绝对地址,指定了执行区域的执行地址。
  PI:位置无关
  OVERLAY:叠加区域
  FIXED:固定地址。此区域的加载和执行地址都是指定的固定地址(这个区域是根区域)。参见《生成根执行区域》。根描述符必须有一个绝对基地址,或者是offset +0。
  EMPTY:在执行区域中预留一块指定长度的空内存区,主要应用于堆和栈。参见《预留一块空区域》
  PADVALUE:定义填充值。如果你指定了PADVALUE,同时你也给出一个数值,例如:
    EXEC 0x10000 PADVALUE 0xffffffff EMPTY ZEROPAD 0x2000 这将生成一块长度为0x2000的所有内容填充为0xffffffff的区域
   ZEROPAD:在elf文件中生成一块全零的区域,这样的话就不必运行时再对内存进行清零。在某些情况下,这一属性可以节约运行时的初始化时间。
  NOCOMPRESS:不允许被压缩。
  UNINIT:不能被初始化为全零。

max_size:可选项,当区域大小超过这个范围时,链接器会产生一个错误。

-length:如果长度是一个负值,那么base_address就会被认为是此区域的末尾。通常和EMPTY属性共同使用来说明一个向低地址生长的栈空间。

input_section_description:指定输入段的内容,参见《输入段描述》。

以下为注意事项:
1、你只能指定PI,OVERLAY,FIXED,ABSOLUTE这些属性中的一个,如果未指定,那么ABSOLUTE作为执行区域的默认属性。

2、具有+offset描述的执行区域要么继承前一个执行区域的属性(如果是加载区域内第一个执行区域,则继承加载区域属性),要么具有ABSOLUTE属性。

3、只有根加载区域可以使用ZEROPAD属性来进行全零初始化,如果在非根加载区域使用ZEROPAD将会产生一个警告,并且ZEROPAD属性无效。

4、不能显式指定执行区域的RELOC属性,这一属性只能从加载区域处继承。

5、使用+offset表达方式的区域不能拥有它自己的属性(除非是ABSOLUTE属性覆盖了继承属性)。使用 +0 ABSOLUTE这样的组合指定一个区域具有ABSOLUTE属性同时并不改变它的起始地址。

6、具有PI或者OVERLAY(或者继承了RELOC)属性的区域允许拥有重叠的地址范围,链接器不允许ABSOLUTE和FIXED执行区域有重叠地址范围。

7、RW数据默认被压缩。UNCOMPRESS关键字允许你指定一个执行区域在最终镜像中不被压缩。

8、UNINIT指定执行区域中的任何ZI输出段不能被零填充。使用这一特性来生成一个包含未定义数据或者存储器映射I/O的执行区域。

使用特权

评论回复
23
zp2000| | 2010-1-3 09:48 | 只看该作者
已经下载了,IAR没用过,我基本上都是用KEIL了,原来用的ADS,IAR都说好,可就是没尝试过

使用特权

评论回复
24
xinzha|  楼主 | 2010-1-3 20:00 | 只看该作者
5.2.5 输入段描述
  
  输入段描述是一种用来用以下内容区分不同输入段的模板:
  1、模块名(目标文件名,库成员名,或者库名)。这个模块名可以使用通配符。
  2、输入段名,或者输入段属性,类似于READ-ONLY或者CODE。
  3、符号名。
  
  比如说在一个输入段描述中:program.o(+RO)模块名就是program.o,输入段属性是RO。
  
  输入段的BNF语法如下:
  input_section_description ::=
          module_select_pattern
                  ["("
                          ("+" input_section_attr | input_section_pattern | input_symbol_pattern)
                          ("," "+" input_section_attr | "," input_section_pattern | "," input_symbol_pattern)*
                  ")"]
                 
  
  各个符号的含义如下:
  module_select_pattern:
          一个模板由字母组成,通配符*可以替代0个以上的字符,?替代任意单个字符。
          匹配不区分大小写,即使是在区分大小写的主机环境中。使用*.o匹配所有对象。使用*匹配所有目标文件和库。
          当module_select_pattern匹配如下几个条件中的一个,那么一个输入段就和一个模块选择模板匹配。
          1、目标文件的名字包括这个段。
          2、库成员的名字(不考虑路径)。
          3、包含这个段的库的全名(包括路径名)。如果名字中包含空格,使用通配符来简化搜索。例如用*libname.lib来匹配C:\lib dir\libname.lib。
  特殊模块选择模板.ANY允许你在不考虑输入段的父模块的情况下将其指定给执行区域。使用.ANY可以随意地填充执行区域。多数情况中,使用一个.ANY就和使用*模块选择符等效。
  注意事项:
  1、只有输入段同时匹配了module_select_pattern和至少一个input_section_attr或者input_section_pattern,才回被包含在执行区域中。如果你漏掉了(+input_section_attr)和(input_section_pattern),
     则默认为+RO。
  2、不要相信编译器产生的输入段名,或者ARM库代码使用的名字。这些可能在编译中产生变化,比如说使用了不同的编译选项。
     另外编译器使用的段名字习惯在各个版本中不保证不会产生变化。
     
  input_section_attr:
          属性选择符根据输入段属性来做匹配。每个input_section_attr都要在前面加+,同样如果你使用一个模板来匹配输入段名,那么这个名字前也必须有+,+前面紧邻的逗号可以去掉。
          属性选择符不区分大小写。下面的选择符能够被识别:
          1、RO-CODE
          2、RO-DATA
          3、RO,选择RO-DATA和RO-CODE
          4、RW-DATA
          5、RW-CODE
          6、RW,选择RW-CODE和RW-DATA
          7、ZI
          8、ENTRY,说明一个输入模块包含了ENTRY点。
          如下同义词也可以被识别:
          1、CODE,代表RO-CODE
          2、CONST,代表RO-DATA
          3、TEXT,代表RO
          4、DATA,代表RW
          5、BSS代表ZI
          如下的虚属性也被识别:
          1、FIRST
          2、LAST
          如果放置顺序很重要,FIRST和LAST可以被用来指定一个执行区域中的第一个和最后一个输入段(例如此区域中的一个输入段必须为第一个,而另一个因为包含了校验值必须是最后一个)。
          FIRST或者LAST必须是属性列表中的最后一项。
          不可以在一个分散加载描述文件中使用两个*模块选择符。不过你可以换种形式,例如使用*A和*B,而且也可以同时使用.ANY和*模块选择符。*模块选择拥有比.ANY更高的优先级,去掉文件中包含*选择符的部分,.ANY才生效。
          包含.ANY模块选择符模板的输入段描述,要在所有不包含.ANY的输入段描述符处理后才能被处理。所有没有被匹配到一个执行区域的段被指定到一个.ANY区域。
          如果有多个.ANY模板出现,链接器会选择将没被指定区域的最大尺寸输入段放置在拥有足够空间的.ANY执行区域。当armlink做出这个选择的时候,.ANY(.text)比.ANY(+RO)拥有更高优先级。
          如果几个执行区域优先级相等,那么久指定到有最多剩余空间的执行区域。
          举例来说:
          1、如果有两个同等优先级的执行区域,一个大小限制为0x2000而另一个没有限制,那么所有的段将会被指定给第二个没有边界的.ANY区域。
          2、如果两个同等优先级的执行区域,第一个大小为0x2000,第二个为0x3000,那么将先把输入段分配给第二个区域直到它小于0x2000.也就是说在选择输入段分配给谁时,依据是此时哪个区域剩余空间更大。
         
  input_section_pattern
          模板根据输入段名匹配,不区分大小写。由字母构成,*和?通配符有效。
          注意事项:如果你使用多个input_section_pattern,确保各个执行区域中没有重复的模板,以避免发生混淆。
         
  input_symbol_pattern
          你可以通过一个段定义的全局符号来选择一个输入段。这样就允许你选择分块链接的多个目标文件中的同名的不同输入段。
          :gdef:前缀区分全局符号模板和段模板。例如,使用:gdef:mysym来选择定义了mysym的段。下面的例子展示了一个描述文件,执行区域Execreg1中包含了定义了全局符号mysym1和mysym2的段:
          LoadRegion 0x8000
          {
                  ExecReg1 +0
                  {
                          *(:gdef:mysym1)
                          *(:gdef:mysym2)
                  }
                  .
                  .
          }
          注意事项:如果使用了多个input_symbol_pattern,确保在多个执行区域中没有重复的模板,以避免产生混淆。

使用特权

评论回复
25
xinzha|  楼主 | 2010-1-3 20:02 | 只看该作者
今天真是不爽,下午踢球不但受伤,而且出现了低血糖症状,看来真得考虑日常锻炼了,下周就去办个健身卡。
同学的公司也出现了问题,不但生意上有问题,而且同学关系也受到了影响,认识他们15年了啊,真不希望看到一个不愉快的结果。

使用特权

评论回复
26
xinzha|  楼主 | 2010-1-4 20:59 | 只看该作者
本帖最后由 xinzha 于 2011-1-6 21:14 编辑

5.2.6 解决多重匹配
  
          如果一个输入段跟多个执行区域匹配,匹配问题就如以下所描述方式解决。然而如果不能找到一个唯一的匹配,链接器就会认为分散加载描述失效。每个输入段通过module_select_pattern和input_section_selector来选择。
          module_select_pattern定义如下:
          1、*匹配任意模块或者库
          2、*.o匹配任意目标模块
          3、math.o匹配math.o模块
          4、*armlib*匹配所有ARM提供的库
          5、*math.lib匹配任意路径下的文件末尾是math.lib的库(例如C:\apps\lib\math\satmath.lib)。
          input_section_selector定义如下:
          1、+RO是匹配所有RO代码和RO数据的输入模块属性
          2、+RW,+ZI是匹配所有RW代码和RW数据以及ZI数据的输入模块属性。
          3、BLOCK_42是匹配所有汇编文件内定义为BLOCK_42域的输入段模板
          注意事项:编译器会生成能够被输入模块模板识别的域,比如.text,.data,.constdata和.bss。这些名字在将来也许会被改变,所以要避免使用它们。
                    如果你想从一个C或C++匹配一个特定的函数或者外部数据,需要如下操作:
                    1、将此函数或数据在一个独立的模块中编译并匹配这个模块目标文件名
                    2、使用#pragma arm section或者__attribute__来指定你那个包含你想要的函数或者数据的输入段。参见《RealView Compilation Tools v3.0》中描述ARM编译器的章节。
          下面的变量用来描述多重匹配:
          1、m1和m2表示5模块选择模板
          2、s1和s2表示输入模块选择符
          在多重匹配的情况下,链接器根据module_select_pattern和input_section_selector对的优先级来决定将输入段分配给哪个执行区域。
          例如输入段A匹配执行区域R1的m1和s1,同时也匹配执行区域R2的m2和s2,链接器判断如下:
          1、如果m1,s1优先级高,就将A分配给R1
          2、如果m2,s2优先级高,就将A分配给R2
          3、若优先级相同,链接器认为分散加载描述非法。
          armlink判断module_select_pattern,input_section_selector对的优先级顺序如下:
          1、对于模块选择模板:
                  如果m1匹配m2,但是m2不能匹配m1,那么m1的优先级高于m2。
          2、对于输入段选择符:
                  一、如果s1和s2都是匹配输入段名字的模板,那么就使用类似于模块选择符的方式决定。
                  二、如果s1和s2中的一个匹配输入段名字,另外一个匹配输入段属性,认为描述失效。
                  三、如果s1和s2都匹配输入段属性,判断谁优先级更高的原则如下:
                          I、ENTRY比RO-DATA,RO-CODE,RW-DATA,RW-CODE优先级更高。
                          II、RO-DATA,RO-CODE的优先级高于RO。
                          III、RW-CODE和RW-DATA的优先级高于RW。
          3、对于module_select_pattern,input_section_selector对来说,如果一下任意条件为真,则m1,s1的优先级高于m2,s2:
                  1、s1是字母形式的输入段名(不包含模板符号),s2是匹配除+ENTRY之外的输入段属性。
                  2、m1优先级高于m2
                  3、s1优先级高于s2
          匹配策略有如下顺序:
          1、并不依赖于它们在文件中书写的次序。
          2、通常来说,目标文件描述符优先级高,那么它所包含的输入段优先级也高。
          3、除非发生如下情况,否则不检查input_section_selectors:
           一、目标文件选择是非决定性的。
           二、一个选择符是输入段全名,而其他的是通过属性选择。这种情况下,全名的优先级高于属性(除非是ENTRY),将从一个目标文件中选择相对应的输入段。即使输入段名选择符相应的目标文件选择符优先级低于属性相应的目标文件选择符,也要按照这种规则操作。

使用特权

评论回复
27
xinzha|  楼主 | 2010-1-5 21:40 | 只看该作者
本帖最后由 xinzha 于 2010-1-20 21:07 编辑

5.3 指定区域和段地址的范例

这一节描述了如何使用分散加载文件实现以下功能:
1、生成根执行区域
2、在固定地址放置区域
3、使用叠加技术放置输入段,将输入段指定给根区域
4、放置ARM提供的库代码
5、使用预处理指令

想要获得更多在固定地址访问数据和函数的范例,请参阅《Realview Compilation Tools v3.0 Developer Guide》中描述如何开发嵌入式软件的部分。

使用特权

评论回复
28
古道热肠| | 2010-1-5 23:32 | 只看该作者
楼主最后整理个PDF文档吧,便于大家查阅.

使用特权

评论回复
29
xinzha|  楼主 | 2010-1-8 11:21 | 只看该作者
汗一个,这几天犯懒了没写。
我想先贴出来,让用到的人看看有没有什么错误的地方,好改正一下。

使用特权

评论回复
30
xinzha|  楼主 | 2010-1-20 21:36 | 只看该作者
本帖最后由 xinzha 于 2011-1-6 21:33 编辑

如今天天累得头皮发麻,到家看看小说就睡了,今天总算有点精神,继续翻译。
5.3.1 在分散加载描述中选择中间输入节

  中间输入节被用来进行ARM/THUMB间切换或者执行一个超过一条指令所能表达的长跳转(请参阅Veneer  generation)。可以使用分散加载描述文件来放置链接器生成的中间代码输入节。甚至在分散加载描述文件中的一个执行区域可以包含*(Veneer$$Code)节选择器。
  如果足够安全,链接器会把中间输入节放到有*(Veneer$$Code)节选择器标记的区域中,由于地址范围或者执行区域大小问题,一个中间输入节可能不能被指定到这个区域。如果中间输入节不能被放到特定区域内,那么它将会被指定到包含生成这个中间代码的输入节的执行区域中。

注意:在早期分散加载描述文件版本中的*(IWV$$Code)将会被自动转译为*(Veneer$$Code),请在新的描述中使用*(Veneer$$Code)。

使用特权

评论回复
31
xinzha|  楼主 | 2010-1-20 21:38 | 只看该作者
靠,终于找到中文的arm手册了,有时间的话把链接器这部分的中文手册通读一遍然后整理出来发一下。

使用特权

评论回复
32
huangqi412| | 2010-1-20 22:10 | 只看该作者
MARK,LZ可以出PDF啊.

使用特权

评论回复
33
xinzha|  楼主 | 2011-1-6 22:19 | 只看该作者
本帖最后由 xinzha 于 2011-1-8 08:54 编辑

终于有时间有心情补全文档了,过去一年了,对这些东西的理解跟过去又有了不同,继续努力。
5.3.2 生成根执行域
  如果你指定了一个镜像的初始入口点,或者链接器因为你只使用了一个ENTRY指令而生成了一个初始入口点,那么你就必须保证这个入口点位于根域,所谓根域就是加载域同执行域为同一地址的区域。如果初始入口点不在根域内,链接失败并给出如下错误信息:
    Entry point(0x00000000) lies within non-root region ER_ROM
  你可以在分散加载描述文件中利用如下方法指定一个根域:
1. 指定执行域的ABSOLUTE属性,可以显式或者用默认方式,将第一个执行域的地址同它相应加载域的地址指定为相同地址。可以通过如下方法实现执行域同加载域拥有相同地址:
   ---- 显式指定执行域和加载域的根地址指示符为相同的数值
   ----指定加载域中的第一个执行域的偏移量为+0。如果这个加载域中的所有后续执行域都被指定了+0属性,那么它们就都是根域。请参考示例 5-2。

2. 执行域使用FIXED属性来保证特定区域的加载域和执行域的地址一致,请参考示例5-3和图5-9。

你可以使用FIXED属性来把任意执行域放置在ROM中的特定位置。具体信息请参考《将域放置在固定地址》一节。

示例5-2.png (18.6 KB )

示例5-2.png

5-3.png (46.57 KB )

5-3.png

使用特权

评论回复
34
xinzha|  楼主 | 2011-1-7 22:04 | 只看该作者
图过两天补上。
5.3.3 在固定地址放置域
  可以在分散加载文件中使用FIXED属性,以生成在固定地址加载和执行的根域。
  FIXED属性也被用来实现在一个简单的加载域(通常是ROM)中生成多个根域。你可以利用这一特性,将一个函数或者数据块(比如常量表或者一个校验和)放置在ROM中的固定地址,这样就可以方便地通过指针去访问了。
  如果你指定一些初始化代码放在ROM的起始而一个校验和放在ROM的末尾,那么有些存储器的空间就没有被利用到,此时就可以用*或者.ANY模块选择符来填充位于初始化模块末尾和数据模块起始之间的空白。

注意:
  为了保证代码的可维护性和调试方便,要尽量少地在分散加载忠使用固定地址方式,应该由链接器来决定数据和函数放在哪里。
  你不能指定只经过部分链接的目标文件中的组件的地址。举例来说,如果你将obj1.o,obj2.o和obj3.o,部分链接生成了obj_all.o,在最终生成的目标文件中将丢弃中间目标文件的信息,就是说你不能再找到obj1.o,只能找到obj_all.o。

使用特权

评论回复
35
xinzha|  楼主 | 2011-1-7 22:26 | 只看该作者
将数据和函数放置在特定地址
  通常地,编译器会针对每个源文件生成其相应的RO,RW和ZI段,包含了源文件中所有的代码和数据。为了达到降单一函数或者数据放在固定地址的目的,你必须使链接器能够将此函数或者数据同输入文件的其他部分单独处理,可以通过如下途径达到此目的:
1.将函数或者数据单独放在一个文件中。
2.使用--split_section编译选项,为每个函数生成一个目标文件。这一选项可能会导致某些函数变大,因为这种方式减少了函数间数据,地址和字符串的共享。不过这种方式可以通过命令链接器挪走无用函数来减小最终镜像的大小,需要指定armlink --remove。
3.在c或者c++源文件中使用#pragma arm section来生成多个命名的段。
4.在汇编语言中使用AREA命名。在汇编代码中,最小可放置单位就是一个AREA。

使用特权

评论回复
36
xinzha|  楼主 | 2011-1-7 23:04 | 只看该作者
本帖最后由 xinzha 于 2011-1-8 08:56 编辑

放置单个目标文件的内容
  例5-4中的分散加载文件有如下功能:
1.将初始化代码放在0x0(包含所有其他RO代码和除data.o外所有目标文件中的RO数据)
2.所有全局RW变量在RAM域,地址在0x400000
3.data.o中的RO-DATA放置在固定地址0x1FF00

注意:
  有些情况下不推荐使用FIXED属性结合单一加载域。指定固定地址的其他手段如下:
1.如果你的加载器能够处理多个加载域,那么就将RO代码或者数据放置在它们各自的加载域。
2.如果你不要求数据或者函数放置在ROM中的固定地址,那么就使用ABSOLUTE属性取代FIXED属性。加载器就会将数据从加载域拷贝到RAM中的特定地址。
3.如果想将数据结构放置在内存映射的I/O地址,使用两个加载域并指定为UNINIT(此属性确保此内存位置不会被清零)。

5-4.png (30.63 KB )

5-4.png

使用特权

评论回复
37
xinzha|  楼主 | 2011-1-7 23:13 | 只看该作者
本帖最后由 xinzha 于 2011-1-8 08:57 编辑

使用arm section pragma
  将代码或者数据目标放置在它自己的源文件中,然后使用标准编码技术放置此目标文件段。另外你可以使用一个pragma和分散加载文件去放置命名段。生成一个模块(例如adder.c),并在其中显式地命名一个段,如例5-5所示。
  
  使用分散加载文件指定命名段的放置位置(如例5-6所示)。如果代码和数据段使用同样的名字,那么代码段放置在靠前的位置。

5-5.png (24.57 KB )

5-5.png

5-6.png (22.27 KB )

5-6.png

使用特权

评论回复
38
xinzha|  楼主 | 2011-1-8 09:12 | 只看该作者
5.3.4 使用重叠方式放置段
  可以在分散加载文件中使用OVERLAY关键字来实现在同一地址定位多个执行域的功能。例5-7展示了一个静态段之后紧跟几个重叠段的用法。当然,在同一时刻这些段中只有一个被例化(也就是只能n选1,这个功能在RAM空间不足的时候会非常有用)。
  例中如果静态区域的长度是未知的,最好使用+0方式来指定重叠区域的起始地址,这样就能把重叠区域紧跟在静态区域的末尾放置。例如:OVERLAY_A_RAM +0 OVERLAY。
  在这种情况下,后续使用相同+offset的重叠区域将会被定位到同样的地址,就是加载域起始或者前面的静态执行域之后的offset个字节的偏移处。这样就防止了RAM空间的浪费或者重叠域覆盖前面的静态域。

5-7.png (23.06 KB )

5-7.png

使用特权

评论回复
39
xinzha|  楼主 | 2011-1-8 09:28 | 只看该作者
5.3.5 为根域指定段
  在RVCT2.1和跟早版本中,唯一需要包含的库函数段是__main和域信息表。此后随着RW数据压缩功能的提供,更多的段就要被包含进根域。链接器能够自动将这些段包含在InRoot$$Sectons中。
  使用分散加载文件来指定一个根段同指定命名段的方式类似。例5-8展示了通过使用段选择符InRoot$$Sections将所有需要放在根域的段放置在一个称为ER_ROOT的域中。

5-8.png (15.94 KB )

5-8.png

使用特权

评论回复
40
xinzha|  楼主 | 2011-1-8 09:50 | 只看该作者
本帖最后由 xinzha 于 2011-1-8 09:52 编辑

5.3.6 保留一个空白域
  在分散加载描述可以使用EMPTY属性来为栈预留一块空白内存块。
  这个内存块并不是加载域的组成部分,但是会在执行时用到。它被初始化为空闲的ZI区域,链接器用如下标号来操作这些域:
1. Image$$region_name$$ZI$$Base
2. Image$$region_name$$ZI$$Limit
3. Image$$region_name$$ZI$$Length。
  如果长度被指定为负数,那么区域的地址会被认为是区域的末端地址,而且此地址需要是绝对地址而非相对地址。在例5-9中,一个域被定义为STACK 0x800000 EMPTY -0x10000,就声明了一个名为STACK的域从0x7F0000起始,至0x800000结束。

注意:这个空闲ZI域只是为EMPTY执行域生成,并没有在运行时清零。
如果此域的地址是相对地址(+n)格式,而长度是负数,那么链接器将会生成一个错误。
在本例中,链接器生成如下符号:
Image$$STACK$$ZI$$Base   = 0x7f0000
Image$$STACK$$ZI$$Limit    = 0x800000
Image$$STACK$$ZI$$Lenght = 0x10000   
Image$$HEAP$$ZI$$Base     = 0x800000
Image$$HEAP$$ZI$$Limit    = 0x810000
Image$$HEAP$$ZI$$Lenght = 0x10000

注意:EMPTY属性只能应用于执行域,如若一个加载域的定义中有EMPTY属性,链接器会产生一个警告并将EMPTY忽略。链接器对EMPTY域的地址解释方式不适用于其他执行域。

5-9.png (32.44 KB )

5-9.png

5-10.png (10.67 KB )

5-10.png

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则