Strange padding in the .data section of the .elf file
I'm currently writing a program on STM32F411 that uses a simple bootloader and two sub-applications. The sub-applications are located in the flash memory and the bootloader loads one of them (both code and data) into the RAM memory and then starts executing it (from RAM). The copying is done simply by iterating over the addresses in flash and copying data from these addresses to RAM.
Recently I've encountered some strange bug. I was trying to read some data from a globally defined array. I was getting back wrong values, e.g. when I tried to read array[0] I was getting back the value of array[1].
I did some debugging and disassembly of the .elf and .hex files and I think I've found the cause of this bug. It turned out that there is an empty space between the .ARM section of the .elf file of this project.
Surprisingly, this empty space is not present in the .hex file (which I use for flashing the STM32 board).
This is what I am talking about:
- .elf file:
2000ee70: 469e mov lr, r3
2000ee72: 4770 bx lr
Disassembly of section .ARM:
2000ee74 <__exidx_start>:
2000ee74: 7fff267c svcvc 0x00ff267c
2000ee78: 00000001 andeq r0, r0, r1
Disassembly of section .data:
2000ee80 <evnames.5255>:
2000ee80: 00000000 andeq r0, r0, r0
2000ee84: 08030104 stmdaeq r3, {r2, r8}- .hex file
802de70: 4770469e
802de74: 7fff267c svcvc 0x00ff267c
802de78: 00000001 andeq r0, r0, r1
802de7c: 00000000 andeq r0, r0, r0
802de80: 08030104 stmdaeq r3, {r2, r8}Obviously, the addresses are different because the addresses in the .elf file are VMA and the addresses in the .hex file are LMA.
What I've noticed here is that in the .elf file, after the .ARM section, the next memory address should be 2000ee7C but from unknown reasons, the .data section begins at 2000ee80. So there is one mysterious, empty machine word between them (maybe some padding). But this empty word is not present in the .hex file. The 00000001 is immediately followed by 00000000.
So basically, I think the disassembly of the .hex file should output the following result:
802de70: 4770469e
802de74: 7fff267c svcvc 0x00ff267c
802de78: 00000001 andeq r0, r0, r1
802de7c: <something here>
802de80: 00000000 andeq r0, r0, r0
802de84: 08030104 stmdaeq r3, {r2, r8}Because of this empty memory space, which disappears in the .hex file, when my bootloader loads the data to RAM, the array[0] which LMA is 2000eec8 ends up being at the address 2000eec4.
What I've also noticed recently is that sometimes the data is aligned correctly in the .elf file (the first address of the .data section is the address that immediately follows the end of the .ARM section). It depends on the address where the .ARM section happens to end. I can manipulate that by adding some extra function invocations in the code (resulting in the larger .text area), for example:
2000ee84: 469e mov lr, r3
2000ee86: 4770 bx lr
Disassembly of section .ARM:
2000ee88 <__exidx_start>:
2000ee88: 7fff2668 svcvc 0x00ff2668
2000ee8c: 00000001 andeq r0, r0, r1
Disassembly of section .data:
2000ee90 <evnames.5255>:
2000ee90: 00000000 andeq r0, r0, r0
2000ee94: 2001111c andcs r1, r1, ip, lsl r1This way, I've estabilished that:
- when the .ARM section ends at address 0x*******0 the .data section incorrectly starts at 0x*******8 (should be 0x*******4)
- when the .ARM section ends at address 0x*******8 the .data section incorrectly starts at 0x*******0 (should be 0x*******C)
- when the .ARM section ends at address 0x*******4 the .data section CORRECTLY starts at 0x*******8
- when the .ARM section ends at address 0x*******C the .data section CORRECTLY starts at 0x*******0
This is probably the troubling snippet of the linker script that I use:
/* ARM specific sections, they also go to FLASH and are copied to RAM */
.ARM.extab : {
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > RAMAPP AT> FLASH_APP
.ARM : {
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
} > RAMAPP AT> FLASH_APP
/* Initialized data sections - variables etc. */
.data :
{
. = ALIGN(4);
*(.data) /* .data sections */
*(.data*) /* .data* sections */
. = ALIGN(4);
} >RAMAPP AT> FLASH_APP /* Data section is placed in FLASH_APP but its Virtual Memory Address is in RAM_APP */I use the following command to link the .o files into one .elf file:
arm-none-eabi-gcc -Wl,--gc-sections -mthumb -mthumb-interwork -mcpu=cortex-m4 --specs=nosys.specs -L[path_to_library_files] -T[path_to_ld_file] [long_list_of_object_files] -o [output_elf_file]
I use the following command to convert the .elf file into the .hex file:
arm-none-eabi-objcopy -O ihex [elf_file] [output_hex_file]
I've tried to experiment with the parameters I give to the arm-none-eabi-objcopy and arm-none-eabi-gcc to get rid of this unexplained padding, for example --file-alignment or --gap-fill but to no success so far.
I've also tried the following
- using the older/newer versions of arm-none-eabi-gcc and arm-none-eabi-objcopy in my toolchain,
- ALIGN(4) of the .ARM section,
- not copying the .ARM section to RAM.
- using diffeerent alignments for the .data section
Unfortunately, none of these solutions fixed this problem.
Does anyone have an idea about where does this empty space come from and how to get rid of it (or make it present in the .hex file as well)?