GNU链接器映射文件给予意外的加载地址GNU链接器映射文件给予意外的加载地址(GNU Linker

2019-05-12 08:05发布

我工作的一个嵌入式程序,我有一个自定义链接脚本。 该项目工程,但我注意到,有可能是什么不对劲的连接是如何放置两节在内存中。

以下是链接描述文件的相关部分:

MEMORY {
    ROM (rx)    : ORIGIN = 0x00100000, LENGTH = 16k
    RAM (rwx)   : ORIGIN = 0x00200000, LENGTH = 4k
}

SECTIONS {
    /* Other sections go here. */
    .data : {
...
    } >RAM AT>ROM

    .bss : {
...
    } >RAM

    .stack : {
...
    } >RAM
...
}

这里是映射文件的相关部分:

.data           0x00200040        0x0 load address 0x001003d4
                0x001003d4                __data_load = LOADADDR (.data)
                0x00200040                __data_start = .
 *(.data)
 *(.data*)
                0x00200040                . = ALIGN (0x4)
                0x00200040                _edata = .

.igot.plt       0x00200040        0x0 load address 0x001003d4
 .igot.plt      0x00000000        0x0 ./debug/sam7s_startup.o

.bss            0x00200040        0x0 load address 0x001003d4
                0x00200040                __bss_start__ = .
 *(.bss)
 *(.bss*)
 *(COMMON)
                0x00200040                . = ALIGN (0x4)
                0x00200040                _ebss = .
                0x00200040                __bss_end__ = .
                0x00200040                PROVIDE (end, _ebss)
                0x00200040                PROVIDE (_end, _ebss)
                0x00200040                PROVIDE (__end__, _ebss)

.stack          0x00200040      0x200 load address 0x001003d4
                0x00200040                __stack_start__ = .

因此,从地图文件,它看起来对我来说,存在.bss和.STACK段在ROM中得到的加载地址。 我想,这是因为这两条线:

.bss 0x00200040 0x0 load address 0x001003d4
.stack 0x00200040 0x200 load address 0x001003d4

这是不好的,因为有一个在他们占用了空间,ROM是没有意义的。 .bss段,虽然空的现在,将包含将在代码中设置为零未初始化的全局变量。 堆栈也只是一个将在代码初始化RAM的一部分。 所以,没有必要为这两种部分被占用的空间在ROM中。

所以我的问题是,什么是正确的方法来阻止的.bss和被加载到ROM .STACK? 我一定要改变的.bss和.STACK节结束>RAM>RAM AT>RAM ? 这似乎有点多余。

测试了一些事情后,我发现以下情况:

(1)使用(NOLOAD)属性(例如,通过替换.stack :.stack (NOLOAD) :仍然导致示出了用于.STACK和.bss段的ROM加载地址的映射文件。

(2)指定RAM AT>RAM ,如上所述,确实从示出了用于.STACK和.bss段ROM加载地址停止地图输出。

(3)当映射文件显示存在.bss和.STACK部分加载地址,但似乎并没有实际占用空间在ROM中。 该.STACK部分,虽然在0x200字节长,似乎并不实际占用的ROM那个空间,即使我指定填充值,并将其放置一段后,在链接脚本。 它后面的链接脚本本节没有得到移动与周围不同的堆栈大小。

因此,或许映射文件输出并不意味着什么,我想它的意思,和.STACK和.bss节实际上不是被赋予在ROM加载地址都没有。 尝试了一些东西后,它肯定会出现这样。 它仍然会是有趣的,知道为什么地图输出使它看起来好像部分给出ROM加载地址虽然,特别是当(NOLOAD)时使用。 难道这只是在LD如何生成的地图输出文件中的错误?

另请参见: 了解GNU链接脚本的位置计数器

Answer 1:

您正在寻找NOLOAD 。 见的Gnu LD输出部类型 。 我现在看你的整个后,我看你推测约NOLOAD 。 随着NOLOAD ,所有的地址都被定义。 如果你的“C”代码中使用它们,它们将加载来自该地址。 你必须提供一些启动代码,通常在汇编器清除BSS区域。 通常情况下,你不要指望你的筹码被初始化。

NOLOAD部就像一个编译/链接时间malloc() 你得到的内存来使用,只是不要指望任何那里。 对于BSS定义__bss_start____bss_end__在你的链接脚本,写一个短的初始化程序清除使用这些变量/地址此内存。

注:一切都在映射文件中显示出来。 它不会在生成的二进制显示或在ELF有数据。 就在部分元信息将在ELF举行。

编辑:在地图文件的加载地址就像是一个装载位置计数器。 负载地址是哪里ld设置为把东西。 ld是不是真的把事情出现了,如果他们采取零大小。 地图输出不是语言UN-ambiguious; 我可以看到它是混乱的,但ld正确地做事创建输出二进制文件。 BSS通常被标记NOLOAD通过在目标文件GCC,所以在仅举例堆叠部分将需要NOLOAD 。 对于像 ,是不是真的需要一个部分,只是一组符号的声明会工作。



文章来源: GNU Linker Map File Giving Unexpected Load Addresses
标签: linker arm gnu