【问题标题】:How to understand such sample in GNU ld manual about linker script?如何理解 GNU ld 手册中有关链接器脚本的此类示例?
【发布时间】:2016-11-12 21:12:26
【问题描述】:

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

我看到下面的ld脚本sn-p:

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 开始。

那怎么可能呢?

【问题讨论】:

  • 你能用这个脚本链接一些示例并使用 readelf/objdump 从中转储部分信息吗?

标签: gnu ld binutils


【解决方案1】:

理解此示例的关键概念是虚拟内存地址 (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。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2015-07-31
  • 2010-09-24
  • 1970-01-01
  • 1970-01-01
  • 2023-03-12
  • 1970-01-01
  • 2017-08-31
  • 1970-01-01
相关资源
最近更新 更多