Skip to content

Conversation

@dennisgr102
Copy link
Contributor

@dennisgr102 dennisgr102 commented Dec 4, 2025

Similar story to #100541

When using modern versions (e.g. 13.2) of the gcc-arm-none-eabi toolchain the following linker warning is emitted when building the mcumgr example:

warning: zephyr/zephyr_pre0.elf has a LOAD segment with RWX permissions
warning: zephyr/zephyr.elf has a LOAD segment with RWX permissions

This can be reproduced with the following commands:

export ZEPHYR_TOOLCHAIN_VARIANT=gnuarmemb
export GNUARMEMB_TOOLCHAIN_PATH=<path to your 13.2 gcc-arm-none-eabi toolchain>
west build -b nrf54l15dk/nrf54l15/cpuapp zephyr/samples/subsys/mgmt/mcumgr/smp_svr

Taking a quick look at the program headers I found the following:

arm-none-eabi-readelf -l build/zephyr/zephyr.elf 

Elf file type is EXEC (Executable file)
Entry point 0x12ac9
There are 5 program headers, starting at offset 52

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  EXIDX          0x00bc4c 0x0001bb6c 0x0001bb6c 0x00008 0x00008 R   0x4
  LOAD           0x0000e0 0x00010000 0x00010000 0x0dca4 0x0dca4 RWE 0x10 <---------- This one
  LOAD           0x00dd88 0x20000000 0x0001dca4 0x00338 0x00338 RW  0x8
  LOAD           0x00e0c0 0x0001dfdc 0x0001dfdc 0x00004 0x00004 RW  0x4
  LOAD           0x000000 0x20000338 0x20000338 0x00000 0x03868 RW  0x8

The linker is unhappy that our ROM region (code, rodata, etc) has the W (write) flag set when it should only be R (read) and E (execute).

Looking further to figure out why it's getting the W (write) flag:

arm-none-eabi-readelf -t build/zephyr/zephyr.elf
There are 40 section headers, starting at offset 0x21d140:

Section Headers:
  [Nr] Name
       Type            Addr     Off    Size   ES   Lk Inf Al
       Flags
  [ 0] 
       NULL            00000000 000000 000000 00   0   0  0
       [00000000]: 
  [ 1] rom_start
       PROGBITS        00010000 0000e0 000c7c 00   0   0  4
       [00000006]: ALLOC, EXEC
  [ 2] text
       PROGBITS        00010c7c 000d5c 00aef0 00   0   0  4
       [00000006]: ALLOC, EXEC
  [ 3] .ARM.exidx
       ARM_EXIDX       0001bb6c 00bc4c 000008 00   2   0  4
       [00000082]: ALLOC, LINK ORDER
  [ 4] initlevel
       PROGBITS        0001bb74 00bc54 000090 00   0   0  4
       [00000002]: ALLOC
  [ 5] device_area
       PROGBITS        0001bc04 00bce4 0000e0 00   0   0  4
       [00000002]: ALLOC
  [ 6] sw_isr_table
       PROGBITS        0001bce4 00bdc4 000878 00   0   0  4
       [00000002]: ALLOC
  [ 7] flash_driver_api_area
       PROGBITS        0001c55c 00c63c 000030 00   0   0  4
       [00000002]: ALLOC
  [ 8] gpio_driver_api_area
       PROGBITS        0001c58c 00c66c 000024 00   0   0  4
       [00000002]: ALLOC
  [ 9] spi_driver_api_area
       PROGBITS        0001c5b0 00c690 000008 00   0   0  4
       [00000002]: ALLOC
  [10] clock_control_driver_api_area
       PROGBITS        0001c5b8 00c698 00001c 00   0   0  4
       [00000002]: ALLOC
  [11] uart_driver_api_area
       PROGBITS        0001c5d4 00c6b4 00000c 00   0   0  4
       [00000002]: ALLOC
  [12] log_const_area
       PROGBITS        0001c5e0 00c6c0 0000d0 00   0   0  4
       [00000002]: ALLOC
  [13] log_backend_area
       PROGBITS        0001c6b0 00c790 000010 00   0   0  4
       [00000002]: ALLOC
  [14] mcumgr_handler_area
       PROGBITS        0001c6c0 00c7a0 00000c 00   0   0  4
       [00000003]: WRITE, ALLOC <---------- Culprit
  [15] rodata
       PROGBITS        0001c6d0 00c7b0 0015d4 00   0   0 16
       [00000002]: ALLOC
  [16] .ramfunc
       PROGBITS        20000000 00e0c4 000000 00   0   0  1
       [00000001]: WRITE
  [17] datas
       PROGBITS        20000000 00dd88 0002b8 00   0   0  8
       [00000003]: WRITE, ALLOC
  [18] device_states
       PROGBITS        200002b8 00e040 000010 00   0   0  1
       [00000003]: WRITE, ALLOC
  [19] log_mpsc_pbuf_area
       PROGBITS        200002c8 00e050 000038 00   0   0  4
       [00000003]: WRITE, ALLOC
  [20] log_msg_ptr_area
       PROGBITS        20000300 00e088 000004 00   0   0  4
       [00000003]: WRITE, ALLOC
  [21] k_sem_area
       PROGBITS        20000304 00e08c 000010 00   0   0  4
       [00000003]: WRITE, ALLOC
  [22] net_buf_pool_area
       PROGBITS        20000314 00e09c 000024 00   0   0  4
       [00000003]: WRITE, ALLOC
  [23] .comment
       PROGBITS        00000000 00e0c4 000044 01   0   0  1
       [00000030]: MERGE, STRINGS
  [24] .debug_aranges
       PROGBITS        00000000 00e108 002d30 00   0   0  8
       [00000000]: 
  [25] .debug_info
       PROGBITS        00000000 010e38 118e16 00   0   0  1
       [00000000]: 
  [26] .debug_abbrev
       PROGBITS        00000000 129c4e 0195cf 00   0   0  1
       [00000000]: 
  [27] .debug_line
       PROGBITS        00000000 14321d 04c69a 00   0   0  1
       [00000000]: 
  [28] .debug_frame
       PROGBITS        00000000 18f8b8 007384 00   0   0  4
       [00000000]: 
  [29] .debug_str
       PROGBITS        00000000 196c3c 016d5d 01   0   0  1
       [00000030]: MERGE, STRINGS
  [30] .debug_loc
       PROGBITS        00000000 1ad999 04e476 00   0   0  1
       [00000000]: 
  [31] .debug_ranges
       PROGBITS        00000000 1fbe10 00b330 00   0   0  8
       [00000000]: 
  [32] .debug_line_str
       PROGBITS        00000000 207140 0000df 01   0   0  1
       [00000030]: MERGE, STRINGS
  [33] .ARM.attributes
       ARM_ATTRIBUTES  00000000 20721f 000038 00   0   0  1
       [00000000]: 
  [34] .last_section
       PROGBITS        0001dfdc 00e0c0 000004 00   0   0  4
       [00000003]: WRITE, ALLOC
  [35] bss
       NOBITS          20000338 00e0c8 000c38 00   0   0  8
       [00000003]: WRITE, ALLOC
  [36] noinit
       NOBITS          20000f70 00e0c8 002c30 00   0   0  8
       [00000003]: WRITE, ALLOC
  [37] .symtab
       SYMTAB          00000000 207258 00ba90 10  38 1640  4
       [00000000]: 
  [38] .strtab
       STRTAB          00000000 212ce8 00a24d 00   0   0  1
       [00000000]: 
  [39] .shstrtab
       STRTAB          00000000 21cf35 00020b 00   0   0  1
       [00000000]: 

From this we see that mcumgr_handler_area has the WRITE flag. Looking further in to the zephyr.map file I found the exact variables being put in this section:

mcumgr_handler_area
                0x0001c6c0        0xc
                0x0001c6c0                        _mcumgr_handler_list_start = .
 *(SORT_BY_NAME(SORT_BY_ALIGNMENT(._mcumgr_handler.static.*)))
 ._mcumgr_handler.static.img_mgmt_
                0x0001c6c0        0x4 zephyr/subsys/mgmt/mcumgr/grp/img_mgmt/libsubsys__mgmt__mcumgr__grp__img_mgmt.a(img_mgmt.c.obj)
                0x0001c6c0                img_mgmt
 ._mcumgr_handler.static.os_mgmt_
                0x0001c6c4        0x4 zephyr/subsys/mgmt/mcumgr/grp/os_mgmt/libsubsys__mgmt__mcumgr__grp__os_mgmt.a(os_mgmt.c.obj)
                0x0001c6c4                os_mgmt
 ._mcumgr_handler.static.stat_mgmt_
                0x0001c6c8        0x4 zephyr/subsys/mgmt/mcumgr/grp/stat_mgmt/libsubsys__mgmt__mcumgr__grp__stat_mgmt.a(stat_mgmt.c.obj)
                0x0001c6c8                stat_mgmt
                0x0001c6cc                        _mcumgr_handler_list_end = .

So ultimately the issue boils down to the fact we are putting a non-const (writeable!) data in a ROM region (linker script snippet for mcumgr: https://github.com/zephyrproject-rtos/zephyr/blob/main/include/zephyr/linker/common-rom/common-rom-misc.ld#L30). With this change the warning is no longer present and the program headers look correct:

arm-none-eabi-readelf -l build/zephyr/zephyr.elf

Elf file type is EXEC (Executable file)
Entry point 0x12ac9
There are 5 program headers, starting at offset 52

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  EXIDX          0x00bc4c 0x0001bb6c 0x0001bb6c 0x00008 0x00008 R   0x4
  LOAD           0x0000e0 0x00010000 0x00010000 0x0dca4 0x0dca4 R E 0x10 <---------- Write flag is gone
  LOAD           0x00dd88 0x20000000 0x0001dca4 0x00338 0x00338 RW  0x8
  LOAD           0x00e0c0 0x0001dfdc 0x0001dfdc 0x00004 0x00004 RW  0x4
  LOAD           0x000000 0x20000338 0x20000338 0x00000 0x03868 RW  0x8

Additionally, this const keyword requirement for STRUCT_SECTION_ITERABLE in ROM is documented here: https://github.com/zephyrproject-rtos/zephyr/blob/main/include/zephyr/sys/iterable_sections.h#L213

Ensure mcumgr handler variables are consts in order to make ld happy and
not emit the "LOAD segment with RWX permissions" warning

Signed-off-by: Dennis Grijalva <[email protected]>
@zephyrbot zephyrbot added size: XS A PR changing only a single line of code area: mcumgr labels Dec 4, 2025
@sonarqubecloud
Copy link

sonarqubecloud bot commented Dec 4, 2025

@dennisgr102
Copy link
Contributor Author

Adding @keith-packard as I see he's done some similar work in:

#89577
#89574

Copy link
Contributor

@keith-packard keith-packard left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, this lets the compiler verify that the variables aren't written too. Oh, and thanks for the detailed description of how to fix these linker issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: mcumgr size: XS A PR changing only a single line of code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants