GNU链接映射文件给予意外的加载地址 [英] GNU Linker Map File Giving Unexpected Load Addresses

查看:393
本文介绍了GNU链接映射文件给予意外的加载地址的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

  MEMORY {
    ROM(RX):ORIGIN = 0x00100000开始,长度为16K
    RAM(RWX):ORIGIN = 0x00200000开始,长度为4K
}SECTIONS {
    / *其他部分去这里。 * /
    。数据:{
...
    }> RAM AT> ROM    .bss段:{
...
    }> RAM    .STACK:{
...
    }> RAM
...
}

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

 。数据0x00200040为0x0加载地址0x001003d4
                0x001003d4 __data_load = LOADADDR(。数据)
                0x00200040 __data_start =。
 *(。数据)
 *(。数据*)
                0x00200040。 = ALIGN(为0x4)
                0x00200040 _edata =。.igot.plt 0x00200040为0x0加载地址0x001003d4
 .igot.plt 00000000为0x0 ./debug/sam7s_startup.o.bss中0x00200040为0x0加载地址0x001003d4
                0x00200040 __bss_start__ =。
 *(BSS)
 *(BSS *)
 *(共同)
                0x00200040。 = ALIGN(为0x4)
                0x00200040 _ebss =。
                0x00200040 __bss_end__ =。
                0x00200040提供:(年底,_ebss)
                0x00200040提供:(_end,_ebss)
                0x00200040提供:(__END__,_ebss).STACK 0x00200040为0x200加载地址0x001003d4
                0x00200040 __stack_start__ =。


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

的.bss 0x00200040为0x0加载地址0x001003d4 结果
.STACK 0x00200040为0x200加载地址0x001003d4

这是不好的,因为有在其中占用空间在ROM中没有任何意义。 .bss段,虽然空现在,将包含将在code被设置为零未初始化的全局变量。该协议栈也只是一个RAM的一部分,将在code初始化。因此,没有必要对其中任何一个部分是占用空间在ROM中。

所以我的问题是,什么是正确的方法来阻止.bss中和被加载到ROM中.STACK?我一定要改变的.bss的末端,从&GT .STACK段; RAM > RAM AT> RAM ?这似乎有点多余。

测试出一些事情我已经找到了以下后:

(1)使用(NOLOAD)属性(如更换 .STACK: .STACK(NOLOAD):)仍然导致显示为.STACK和.bss部分的ROM加载地址映射文件

(2)指定 RAM AT&GT; RAM ,如上面提到的,确实展示了.STACK和.bss段ROM加载地址停止地图输出<。 / p>

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

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

另请参见:<一href=\"http://stackoverflow.com/questions/13831462/understanding-the-location-counter-of-gnu-linker-scripts\">Understanding GNU链接脚本的位置计数器


解决方案

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

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

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

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

I'm working on an embedded program where I have a custom linker script. The program works, but I have noticed that there is possibly something amiss with how the linker is placing a couple of sections in memory.

Here are the relevant parts of the linker script:

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
...
}

And here is the relevant part of the MAP file:

.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__ = .


So from the map file it looks to me like the .bss and .stack sections are getting load addresses in ROM. I think this because of these two lines:

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

This isn't good, because there's no point in them taking up space in ROM. The .bss section, although empty right now, will contain uninitialised global variables that will be set to zero in code. The stack is also just a part of RAM that will be initialised in code. So there's no need for either of these sections to be taking up space in ROM.

So my question is, what is the correct way to stop .bss and .stack from being loaded into ROM? Do I have to change the end of the .bss and .stack sections from >RAM to >RAM AT>RAM? This seems a bit redundant.

After testing out some things I have found the following:

(1) Using the (NOLOAD) attribute (e.g. by replacing .stack : with .stack (NOLOAD) :) still results in the map file showing a ROM load address for the .stack and .bss sections.

(2) Specifying RAM AT>RAM, as mentioned above, does indeed stop the map output from showing ROM load addresses for the .stack and .bss sections.

(3) When the map file shows load addresses for the .bss and .stack sections, it appears that they do not actually take up space in ROM. The .stack section, although 0x200 bytes long, does not seem to actually take up that space in ROM, even if I specify fill values for it and place a section after it in the linker script. The section that follows it in the linker script does not get moved around with different stack sizes.

So perhaps the map file output doesn't mean what I think it means, and the .stack and .bss sections aren't actually being given load addresses in ROM at all. After trying out a few things it would certainly appear this way. It would still be interesting to know why the map output makes it appear as though the sections are given ROM load addresses though, especially when (NOLOAD) is used. Could this just be a bug in how LD generates its map output files?

See Also: Understanding the Location Counter of GNU Linker Scripts

解决方案

You are looking for NOLOAD. See Gnu LD output section type. I read your whole post now and I see you postulated about NOLOAD. With NOLOAD, all of the addresses are defined. If you use them within your 'C' code, they will load from that address. You must provide some start-up code, usually in assembler that clears the BSS area. Usually, you don't expect your stack to be initialized.

A NOLOAD section is like a compile/link time malloc(). You get the memory to use, just don't expect anything there. For BSS you define __bss_start__ and __bss_end__ in your linker script and write a short initialization routine to clear this memory using those variables/addresses.

Note: everything shows up in the map file. It won't show up in a generated binary or have data in an ELF. Just the section meta information will be held in the ELF.

Edit: The load address in the map file is like a location counter for loading. The load address is where ld is set to put stuff. ld is not really putting things there if they take zero size. The map output is not linguistically un-ambiguious; I can see how it is confusing, but ld does things correctly in creating the output binary. BSS is normally marked NOLOAD by gcc in the object files, so in the example only the stack section would need NOLOAD. For a something like stack, a section is not really needed and just a set of symbols declarations would work.

这篇关于GNU链接映射文件给予意外的加载地址的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆