1.前言
链接器的默认配置允许所有有效内存的分配,你可以使用MEMORY命令来重新定义它
2.MEMORY命令
MEMORY命令描述了一个内存块的位置和大小。你可以用它来描述哪块内存区域可以被链接器使用,哪块内存区域一定要避开。
你可以将段分配到特定的内存区域内,链接器会基于此内存区域设置段地址,如果满了就会有警告,链接器是不会压缩段使之适合放到区域中
一个链接脚本最多只能拥有一个MEMORY命令,然而,你可以定义很多内存块,语法如下:
- MEMORY
- {
- name [(attr)] : ORIGIN = origin, LENGTH = len
- ...
- }
这个name定义了区域的名字。区域的名字对于脚本外部没有意义,它会存储在一个隔离的名字空间里,不会和符号名、文件名或者段名冲突。
在MEMORY命令里的每个内存区域名字不能冲突,不过,你可以给已经存在的内存区域定义别名,see REGION ALIAS (3.4.4 Assign alias names to memory regions)
这个attr字符串是可选项,它指明那些在链接脚本中没有被映射的输入段会被放到哪个特殊的内存区域。如 SECTIONS (3.6 SECTIONS Command)小节
对于没有指定输出段的那些输入段,链接器会创建一个同名的输出段。如果定义了区域属性,链接器可以使用它们为那些创建的输出段指定内存区域
这个attr字符串可以有一下字符组成:
- `R'
- Read-only section
- `W'
- Read/write section
- `X'
- Executable section
- `A'
- Allocatable section
- `I'
- Initialized section
- `L'
- Same as `I'
- `!'
- Invert the sense of any of the attributes that follow
如果一个没有映射的段符合这些属性,除了‘!’属性,它就会被放入此内存区域中。这个‘!’属性保留来给那些任何属性都不符合的那些没有映射的段
origin是一个数字表达式,表示内存区域的起始地址。这个表达式必须由常数来计算得到,不能包含任何符号。关键字ORIGIN还可以缩写为org或者o(但是不能是ORG)
len表示了内存区域的大小。和origin表达式一样,只能使用常数计算。关键字LENGTH可以缩写为len或者l
下面有个例子,我们定义两个可以有效分配的内存区域:一个是起始地址为0大小为256K,另一个的起始地址为‘0x40000000’大小为4M。
MEMORY { rom (rx) : ORIGIN = 0, LENGTH = 256K ram (!rx) : org = 0x40000000, l = 4M }
链接器会将每个没有映射的只读或者可执行的段放入‘rom’内存区域中,将其余没有映射的段放入‘ram’的内存区域
一旦你定义了一个内存区域,你可以使用‘>region’输出段属性直接给输出段指明一个内存区域。
比如,有一个‘mem’的内存区域,那么你可以在输出段中使用‘>mem’,see Output Section Region (3.6.8.6 Output Section Region)。
如果没有给这个输出段指明地址,链接器会将它放到该内存区域内下一个有效地址,如果把输入段放入内存区域中太大了,链接器就会报错
通过ORIGIN(memory)和LENGTH(memory)可以访问内存区域的其实地址和大小:
_fstack = ORIGIN(ram) + LENGTH(ram) - 4;
参考文献
[1] http://blog.csdn.net/han22647/article/details/64920623
[2] http://blog.csdn.net/huiyuyang_fish/article/details/16884593