I'm trying to print a string through semihosting on STM32F4. I define a variable:
let array: &[u8] = &[
0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20,
0x6e, 0x65, 0x77, 0x20, 0x77, 0x61, 0x79, 0x00, 0x00, 0x00,
];
This a non-mutable variable so it goes into .rodata section in the ELF file.
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 4] .rodata PROGBITS 0800077c 00277c 000014 00 A 0 0 4
Here I can see the variable is 20 bytes long and stored at 0x800077c
.
If I dump the section I can see the text:
Hex dump of section '.rodata':
0x0800077c 54686973 20697320 61206e65 77207761 This is a new wa
0x0800078c 79000000 y...
Finally, I load the program to the target and execute it. If I look at the address of the string I see this:
(gdb) x /20bx 0x0800077c
0x800077c <.Lbyte_str.0>: 0x00 0x68 0x01 0x00 0x00 0x00 0x72 0x07
0x8000784 <.Lbyte_str.0+8>: 0x00 0x68 0x01 0x00 0x00 0x00 0xff 0xff
0x800078c <.Lbyte_str.0+16>: 0xff 0xff 0xff 0xff
Here is the relevant section for the linker script:
.rodata : ALIGN(4)
{
_srodata = .;
*(.rodata)
*(.rodata.*)
_erodata = ALIGN(4);
} > FLASH
Why does the content of memory on the target and in the ELF file differ?
If I place the variable in RAM it works.
I checked with GDB and it loads the .rodata section as follows:
Loading section .rodata, size 0x14 lma 0xf0000ef6
Loading section .text, size 0x77a lma 0x8000000
Why does GDB load the .rodata section to 0xf0000ef6
instead of 0x800077c
? I'd expect it will read the ELF file and load the sections correctly.
Removing the .rodata section and placing content of .rodata directly into .text solves the issue.
Content of the linker script that causes the issue:
ENTRY(reset_handler)
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 256K
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 64K
}
PROVIDE(_stack_start = ORIGIN(RAM) + LENGTH(RAM));
SECTIONS
{
.text : {
__STACK_START = .;
LONG(_stack_start);
KEEP(*(.vector_table.reset_vector));
__reset_vector = ABSOLUTE(.);
KEEP(*(.vector_table.exceptions));
__eexceptions = ABSOLUTE(.);
KEEP(*(.vector_table.interrupts));
__einterrupts = ABSOLUTE(.);
*(.text*)
} > FLASH = 0xFF
.bss : ALIGN(4)
{
_sbss = .;
*(.bss.*);
_ebss = ALIGN(4);
} > RAM
.data : ALIGN(4)
{
_sdata = .;
*(.data*)
_edata = ALIGN(4);
} > RAM AT > FLASH = 0xFF
.rodata : ALIGN(4)
{
_srodata = .;
*(.rodata*)
*(.rodata)
_erodata = ALIGN(4);
} > FLASH
.ARM.exidx :
{
*(.ARM.exidx*)
} > RAM
_sidata = LOADADDR(.data);
}
Result in GDB output:
Reading symbols from target/thumbv7em-none-eabi/debug/cortex...done.
0x00000000 in ?? ()
Loading section .rodata, size 0x14 lma 0xf0000ef6
Loading section .text, size 0x77a lma 0x8000000
Loading section .ARM.exidx, size 0x10 lma 0x800077a
Start address 0x80004ae, load size 1950
Transfer rate: 1 KB/sec, 650 bytes/write.
readelf dump:
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS 08000000 001000 00077a 00 AX 0 0 4
[ 2] .bss NOBITS 20000000 002000 000000 00 WA 0 0 4
[ 3] .data NOBITS 20000000 002000 000000 00 WA 0 0 4
[ 4] .rodata PROGBITS 0800077c 00277c 000014 00 A 0 0 4