great post.
I have some comments that I thought I’d publish in a previous post (Tracking Firmware Code Size | Interrupt). But I think they’re probably more relevant to the topics of this article.
The question concerns the vma and lma that can be expressed in the linker script with the keyword AT.
let’s take the following linker script:
/* Entry Point */
ENTRY(main)
/* Specify the memory areas */
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 128K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 32K
}
/* Define output sections */
SECTIONS
{
/* The program code and other data goes into FLASH */
.text :
{
. = ALIGN(4);
*(.text) /* .text sections (code) */
*(.text*) /* .text* sections (code) */
*(.glue_7) /* glue arm to thumb code */
*(.glue_7t) /* glue thumb to arm code */
*(.eh_frame)
KEEP (*(.init))
KEEP (*(.fini))
. = ALIGN(4);
_etext = .; /* define a global symbols at end of code */
} >FLASH
/* Constant data goes into FLASH */
.rodata :
{
. = ALIGN(4);
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
. = ALIGN(4);
} >FLASH
.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH
.ARM : {
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
} >FLASH
/* Initialized data sections goes into RAM, load LMA copy after code */
.data :
{
. = ALIGN(4);
*(.data*) /* .data* sections */
. = ALIGN(4);
} >RAM AT> FLASH
/* Uninitialized data section */
.bss :
{
. = ALIGN(4);
*(.bss*)
*(COMMON)
. = ALIGN(4);
} >RAM
/* Remove information from the standard libraries */
/DISCARD/ :
{
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
}
.ARM.attributes 0 : { *(.ARM.attributes) }
}
I’d like you to put the attention on the .data and .bss sections:
.data :
{
. = ALIGN(4);
*(.data*) /* .data* sections */
. = ALIGN(4);
} >RAM AT> FLASH
/* Uninitialized data section */
.bss :
{
. = ALIGN(4);
*(.bss*)
*(COMMON)
. = ALIGN(4);
} >RAM
I try to explain it in words: we are saying that .data has vma in RAM but lma in FLASH, instead .bss I expect it to have vma and lma identical and in RAM.
this is explained in 3.1 Basic Linker Script Concepts and in 3.6.8.2 Output Section LMA
I consider a very simple source file:
static int g_my_global_bss;
static int g_my_global_data = 37;
const int g_my_global_rodata = 45;
int main(void)
{
g_my_global_bss = g_my_global_data + g_my_global_rodata;
return 0;
}
I build the elf with this makefile:
all: main.elf
CFLAGS = \
-std=gnu11 \
-mcpu=cortex-m4 \
-mthumb \
-specs=nano.specs \
-O0 \
-Wall \
-ffunction-sections \
-fdata-sections \
-c \
-Werror
LDFLGS = \
-mcpu=cortex-m4 \
-mthumb \
-specs=nano.specs \
-Wl,--gc-sections \
-Wl,--print-memory-usage
LD_SCRIPT = STM32F410RBTx_FLASH.ld
CC = arm-none-eabi-gcc
main.elf: main.o
$(CC) $(LDFLGS) -T$(LD_SCRIPT) -Wl,--cref,-Map=$(@:.elf=.map) -o $@ $^
main.o: main.c
$(CC) $(CFLAGS) -o $@ $<
.PHONY: clean
clean:
rm *.o *.elf *.map
linker tells me:
Memory region Used Size Region Size %age Used
FLASH: 64 B 128 KB 0.05%
RAM: 8 B 32 KB 0.02%
and size tells me:
max@jarvis:~/Dropbox/test_mem$ arm-none-eabi-size -G main.elf
text data bss total filename
60 4 4 68 main.elf
then I extract the information of vma and lma from the elf using objdump.
max@jarvis:~/Dropbox/test_mem$ arm-none-eabi-objdump -h main.elf
main.elf: file format elf32-littlearm
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 0000003c 08000000 08000000 00010000 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .rodata 00000000 0800003c 0800003c 00020004 2**0
CONTENTS, ALLOC, LOAD, DATA
2 .data 00000004 20000000 0800003c 00020000 2**2
CONTENTS, ALLOC, LOAD, DATA
3 .bss 00000004 20000004 08000040 00020004 2**2
ALLOC
4 .ARM.attributes 0000002a 00000000 00000000 00020004 2**0
CONTENTS, READONLY
5 .comment 00000079 00000000 00000000 0002002e 2**0
CONTENTS, READONLY
again I highlight .data and .bss (and also .text for comparison)
Idx Name Size VMA LMA File off Algn
0 .text 0000003c 08000000 08000000 00010000 2**2
2 .data 00000004 20000000 0800003c 00020000 2**2
3 .bss 00000004 20000004 08000040 00020004 2**2
-
.text has vma and lma coinciding and in FLASH. I expected this
-
.data has vma in RAM and lma in FLASH. I expected this
-
.bss has vma in RAM and lma in FLASH as .data. I wasn’t expecting that.
why this unexpected behavior? What am I missing? Is this a bug?
best regards
Max