如何在GNU ld手册中了解关于链接描述文件的这样的示例?

时间:2016-07-11 02:03:36

标签: gnu ld binutils

我正在学习GNU链接器ld脚本sample about memory region alias

我看到以下ld脚本片段:

SECTIONS
{
    .text :
    {
        *(.text)
    } > REGION_TEXT

    .rodata :
    {
        *(.rodata)
        rodata_end = .;
    } > REGION_RODATA  <=========== PLACE 1

    .data : AT (rodata_end) <=========== PLACE 2
    {
        data_start = .;
        *(.data)
    } > REGION_DATA <=========== PLACE 3

    data_size = SIZEOF(.data);
    data_load_start = LOADADDR(.data);

    .bss :
    {
        *(.bss)
    } > REGION_BSS
}

样本中给出的一个可能的系统内存区域布局是这样的(该示例中的 C ):

MEMORY
    {
        ROM : ORIGIN = 0, LENGTH = 2M            /*0M ~ 2M*/
        ROM2 : ORIGIN = 0x10000000, LENGTH = 1M  /*256M ~ 257M*/
        RAM : ORIGIN = 0x20000000, LENGTH = 1M   /*512M ~ 513M*/
    }

REGION_ALIAS("REGION_TEXT", ROM);     /*0M ~ 2M*/
REGION_ALIAS("REGION_RODATA", ROM2);  /*256M ~ 257M*/
REGION_ALIAS("REGION_DATA", RAM);     /*512M ~ 513M*/
REGION_ALIAS("REGION_BSS", RAM);      /*512M ~ 513M*/

所以,

PLACE 1.rodata必须进入REGION_RODATA,即256M~257M

PLACE 2表示.data部分必须在.rodata部分之后立即 。因此,.data部分必须从 最多 257M开始。

但是PLACE 3.data部分必须进入REGION_DATA区域。因此.data部分必须从 至少 512M开始。

那怎么可能呢?

1 个答案:

答案 0 :(得分:2)

理解此示例的关键概念是虚拟内存地址(VMA)加载内存地址(LMA)

The GNU Linker官方文档将这两个术语定义如下。

  

每个可加载或可分配的输出部分都有两个地址。该   首先是 VMA ,或虚拟内存地址。这是地址了   部分将在输出文件运行时生成。第二个是 LMA ,   或加载内存地址。这是该部分的地址   加载。

在该示例中,对于除.data之外的所有输出节,VMA和LMA地址是相同的。对于.data部分,LMA由AT (rodata_end)指定,而VMA地址是REGION_DATA内存区域的第一个可用地址。

考虑到这一点,我们可以再次阅读该示例,并看到它导致下面所示的情况。

ROM (alias REGION_TEXT)
+---------+------------------------------+
|  .text  |                              |
+---------+------------------------------+

ROM2 (alias REGION_RODATA)
+-----------+---------+--------+
|  .rodata  |  .data  |        |
+-----------+---------+--------+

RAM (alias REGION_DATA)
+---------+--------+-----------+
|  .data  |  .bss  |           |
+---------+--------+-----------+

.data部分出现两次:一次在ROM2,一次在RAM。加载时将其置于加载地址(LMA);随后在运行程序之前将其移动到其虚拟地址。 顺便说一句,这就是为什么,在你提到的文档后面几行,我们可以读到

  

可以编写一个通用的系统初始化例程进行复制   如有必要,将ROM或ROM2中的.data部分放入RAM中。