cancel
Showing results for 
Search instead for 
Did you mean: 

Appending CRCs for STL flash test leads to broken ELF file

se-nje
Associate

Steps to reproduce

You can find the output files (ELF and bin) attached to this post. The steps to create them are as follows:

  • Download and extract X-CUBE-CLASSB library for STM32H5, version 4.0.0
  • Open the contained example project in STM32CubeIDE (we'll use the TrustZone one)
  • Modify the secure application linker script to include a gap at the beginning (e.g. for MCUboot)
--- STM32CubeIDE/Secure/STM32H563ZITX_FLASH.ld.bak 2025-05-20 10:05:08.623676118 +0200 +++ STM32CubeIDE/Secure/STM32H563ZITX_FLASH.ld 2025-05-20 10:05:13.813692793 +0200 @@ -46,7 +46,7 @@ MEMORY { RAM (xrw) : ORIGIN = 0x30000000, LENGTH = 320K /* SRAM1 + SRAM2 */ - FLASH (rx) : ORIGIN = 0x0C000000, LENGTH = 1016K + FLASH (rx) : ORIGIN = 0x0C008400, LENGTH = 983K FLASH_NSC (rx) : ORIGIN = 0x0C0FE000, LENGTH = 8K }
  • Change the post-build step to (STL_Single_Tests_Nucleo_H563ZI_Secure -> Properties -> C/C++ Build -> Setting -> Build Steps) make a backup copy and correctly call the programmer with the new address. Example below is for a Linux environment, change accordingly for Windows. Alternatively, remove the post-build step and run the commands manually from a terminal.
cp "${BuildArtifactFileBaseName}.elf" "${BuildArtifactFileBaseName}-nocrc.elf" && arm-none-eabi-size "${BuildArtifactFileName}" && STM32_Programmer_CLI -sl \"${CWD}/${BuildArtifactFileName}\" 0x0C008400 0x0C100000 0x400 && arm-none-eabi-objcopy -O binary "${BuildArtifactFileBaseName}.elf" "{BuildArtifactFileBaseName}.bin" && arm-none-eabi-objcopy -O binary "${BuildArtifactFileBaseName}-nocrc.elf" "{BuildArtifactFileBaseName}-nocrc.bin"

Expected behavior

Output ELF file is modified with new CRC section and is otherwise unmodified. Output bin file contains the new additional CRC section and is otherwise the same.

Actual behavior

New CRC section is present, but all offsets in the ELF are shifted which leads to objcopy not correctly producing the binary files. Especially the .data section gets prominently moved. The STM32CubeProgrammer seems to start all sections directly after the ELF header, even though a gap is required in this case. Probably the easiest way to compare the ELF files is to compare the output of "readelf --wide -e -l <elf file>".

If you compare the resulting bin files with and without CRCs, e.g. using a hex editor, you can clearly see the .data section not being at the expected 0x3ff8 offset, but at offset 0x43c4 (0x3cc bytes offset, which is exactly the shift that happened in the ELF file).

Running objcopy plainly on the new ELF file with CRCs (arm-none-eabi-objcopy STL_Single_Tests_Nucleo_H563ZI_Secure.elf STL_Single_Tests_Nucleo_H563ZI_Secure-new.elf) adjusts a lot of broken load addresses, but sadly not all of them, especially not .data.

arm-none-eabi-objcopy: STM32CubeIDE/Secure/Debug/STL_Single_Tests_Nucleo_H563ZI_Secure-new.elf: section .isr_vector lma 0xc008034 adjusted to 0xc008400 arm-none-eabi-objcopy: STM32CubeIDE/Secure/Debug/STL_Single_Tests_Nucleo_H563ZI_Secure-new.elf: section .text lma 0xc008284 adjusted to 0xc008650 arm-none-eabi-objcopy: STM32CubeIDE/Secure/Debug/STL_Single_Tests_Nucleo_H563ZI_Secure-new.elf: section .rodata lma 0xc00bab8 adjusted to 0xc00be84 arm-none-eabi-objcopy: STM32CubeIDE/Secure/Debug/STL_Single_Tests_Nucleo_H563ZI_Secure-new.elf: section mydata lma 0xc00c018 adjusted to 0xc00c3e4 arm-none-eabi-objcopy: STM32CubeIDE/Secure/Debug/STL_Single_Tests_Nucleo_H563ZI_Secure-new.elf: section .preinit_array lma 0xc00c024 adjusted to 0xc00c3f0 arm-none-eabi-objcopy: STM32CubeIDE/Secure/Debug/STL_Single_Tests_Nucleo_H563ZI_Secure-new.elf: section .init_array lma 0xc00c024 adjusted to 0xc00c3f0 arm-none-eabi-objcopy: STM32CubeIDE/Secure/Debug/STL_Single_Tests_Nucleo_H563ZI_Secure-new.elf: section .fini_array lma 0xc00c028 adjusted to 0xc00c3f4

Concerning objcopy, this is how the LMA gets calculated (see _bfd_elf_make_section_from_shdr function in bfd/elf.c in binutils-gdb):

newsect->lma = (phdr->p_paddr + hdr->sh_offset - phdr->p_offset) / opb;

Crucially, it uses the section header offset (offset of binary data in the ELF file itself) to calculate the LMA which is then used to place the section in the output bin file. It expects the sections to be placed in the ELF file in relation to the physical address stored in the program header.

 

Due to this issue, using the STM32CubeProgrammer to generate CRCs for the STL in ELF files is currently not viable in more complex environments.

1 REPLY 1
InsignificantBit
ST Employee

Hello, thank you for your very detailed description and thorough analysis. This problem is currently known and is being worked on (ST internal bug tracker no. 205095).