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
NOLOAD
made no difference to the map file. I usedNOLOAD
by simply replacing.bss :
with.bss (NOLOAD) :
and.stack :
with.stack (NOLOAD) :
in the linker script. - You were correct about placing a section after the stack. I moved the .text section there, and the stack did not take up any load space. - Yes, the whole question is about the map output. It suggests to me that the linker is trying to give .bss and .stack a load address in ROM (although we just found this doesn't actually happen). – Adam Goodwin