Solution to LOAD segment with RWX permissions warning with CMSIS
I have not seen this is described somewhere, so here is a post about it. It is naturally not specific to CMSIS but I experienced it in this way.
It seems ld
has been updated some time ago, and now it emits warning: <filename> has a LOAD segment with RWX permissions
when obviously a LOAD segment has RWX permissions. A segment should ideally either have RX (the code segment) or RW (the data segment). RWX would mean a modifiable code, which is a risk.
(ELF uses the term program headers for segments)
The problem is, CMSIS linker script gcc_arm.ld has two sections, called .copy.table
and .zero.table
. These are used for initializing data
and bss
segments (actually only data
because bss
is initialized by C runtime but both has the same concept). These sections does not contain anything other than static data created by the linker, like below:
.copy.table :
{
. = ALIGN(4);
__copy_table_start__ = .;
LONG (__etext)
LONG (__data_start__)
LONG ((__data_end__ - __data_start__) / 4)
__copy_table_end__ = .;
} > FLASH
.zero.table :
{
. = ALIGN(4);
__zero_table_start__ = .;
__zero_table_end__ = .;
} > FLASH
These sections are put into the text
segment by the linker, which makes sense because they are used before data segment is initialized. However, not sure exactly why, when linker puts them into the text
segment, it is also marked as writable. So the text
segment becomes RWX, hence the warning is emitted.
Below is readelf
output:
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x001000 0x08000000 0x08000000 0x03b7c 0x03b7c RWE 0x1000
LOAD 0x005000 0x20000000 0x08003b7c 0x000c8 0x000c8 RW 0x1000
LOAD 0x0000c8 0x200000c8 0x200000c8 0x00000 0x00174 RW 0x1000
Section to Segment mapping:
Segment Sections...
00 .text .copy.table
01 .data
02 .bss
(the .zero.table
section is discarded because it is not used)
It seems like warning does not cause a problem at least with ST’s programming tool (STM32CubeProg), however it is still not ideal.
Because it is obvious that the contents of .copy.table
and .zero.table
are read-only data, the segment does not need to be writable for sure. The solution I found is to define the segments and assign the output sections to the segments manually. When the segments are defined manually, flags can be set explicitly.
Adding the following segment (program header) descriptions to the linker script:
PHDRS
{
text PT_LOAD FLAGS(5);
data PT_LOAD FLAGS(6);
bss PT_LOAD FLAGS(6);
}
says to create these segments with these particular flags; RX (5) and RW (6).
Then, an output section can be assigned to a particular segment like this:
.text :
{
...
} >FLASH :text
When the segments are defined manually, all output sections have to be assigned to the segments manually. After this is done, the segments becomes:
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x001000 0x08000000 0x08000000 0x03b7c 0x03b7c R E 0x1000
LOAD 0x005000 0x20000000 0x08003b7c 0x000c8 0x000c8 RW 0x1000
LOAD 0x0000c8 0x200000c8 0x200000c8 0x00000 0x00174 RW 0x1000
Section to Segment mapping:
Segment Sections...
00 .text .copy.table
01 .data
02 .bss
The segments are now as they should be, and the warning is not emitted.
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.