1

I have been trying to implement position independent code in my firmware for a bootloader + dual slot application firmware fota strategy on a stm32 microcontroller.

The firmware is correctly launched by thew bootloader even if I upload it at a different address from where it is supposed to go by linker script, provided that the bootloader correctly rempas the irq table and loads the correct .got section offset.

However, when the firmware tries to access local static variables living the .bss section, it loads them at the wrong address, I have discovered that these variables are not accessed via .got table which I think is the main issue.

All global variables contained in the .got section are properly accessed, but the addresses of static variables declared inside functions are not present in the global offset table at all, and instead are accessed by adding an offset to the program counter ( which breaks position independency of the firmware).

These local static variables would belong to the .bss section, global variables living in .bss are loaded fine.

  • Is there a way to ensure that the .got section is used to map all local static variable just like global data, enforcing code position independency?

I am using Gcc, with

  • -fpic for position independence
  • -msingle-pic-base
  • -fno-jump-tables

I have tried to add -mpic-data-is-text-relative as suggested in another question (see below) but it did not solve the issue.

All compiler flags here

-mcpu=cortex-m33 -std=gnu11 -g3 -DDEBUG -DUSE_FULL_LL_DRIVER -DUSE_HAL_DRIVER -DSTM32H563xx -c -I../Core/Inc -I../Drivers/STM32H5xx_HAL_Driver/Inc -I../Drivers/STM32H5xx_HAL_Driver/Inc/Legacy -I../Drivers/CMSIS/Device/ST/STM32H5xx/Include -I../Drivers/CMSIS/Include -I"C:\Repos\bootloader_test\BootloaderTest\Core\Shared" -O0 -ffunction-sections -fdata-sections -Wall -fno-jump-tables -fpic -msingle-pic-base -fstack-usage -fcyclomatic-complexity --specs=nano.specs -mfpu=fpv5-sp-d16 -mfloat-abi=hard -mthumb

In the firmware linker the .got table is created as a section

  .got (APP_GOT_START):
  {
    . = ALIGN(4);
    GOT_START = .;
    KEEP(*(.got)) 
    GOT_END = .;
    . = ALIGN(4);
  } >APP_GOT AT> APP_B_GOT

and in the same linker the .bss section is declared as

  .bss (APP_RAM_START):
  {
    . = ALIGN(4);
    /* This is used by the startup in order to initialize the .bss section */
    _sbss = . ;         /* define a global symbol at bss start */
    __bss_start__ = _sbss ;
    *(.bss)
    *(.bss*)
    *(COMMON)

    . = ALIGN(4);
    _ebss = .;         /* define a global symbol at bss end */
    __bss_end__ = _ebss;
  } >RAM

These questions are more or less treating the same issue,

  1. unanswered, comments redirect to #2
  2. explains the problem but does not provide the solution, redirects to #3
  3. answered but adding -mpic-data-is-text-relative does not seem to work for me
  • "*I have been trying to implement position independent code in my firmware for a bootloader + dual slot application firmware fota strategy on a stm32 microcontroller.*" -- why? What advantage do you think PIC would provide in that context? – John Bollinger Aug 21 '23 at 14:03
  • Are you sure your static local variables are in fact assigned storage in the .bss section? If they were in the same section as their host functions' code (probably .text), then PC-relative addressing would serve position independency just fine. – John Bollinger Aug 21 '23 at 14:16
  • @JohnBollinger 1)Since the application firmware can be loaded in one of two possible memory location in a device, which one unknown at compile time, the code must be completely position independent. Countless posts (including an application note by ST) state that fpic or fpie must be used for such purpose. 2) Yes I have verified that the location of such variables is indeed within the .bss section boundaries, but they are not included in the global offset table and the program fails to fetch their correct address – Matteo Vittorio Ricciutelli Aug 21 '23 at 14:41
  • I presume your firmware is an executable, not a shared library. Are you linking with `-pie`? (Not to be confused with `-fpie`.) – John Bollinger Aug 21 '23 at 14:50
  • @JohnBollinger yes, it is a whole stm32 arm m33 executable, I am using -fpic not, -pie neither -fpie, should I? – Matteo Vittorio Ricciutelli Aug 21 '23 at 15:05
  • You should be able to use `-fpic` when compiling, though `-fpie` would be more technically correct. Either way, to get a position-independent executable, you should use `-pie` when you link. I am not positive that this will resolve your issue, but it's the right thing to do in any case. – John Bollinger Aug 21 '23 at 15:33

1 Answers1

0

Found the solution!

It turns out the trick for me is to add -mno-pic-data-is-text-relative so it enforces the compiler to disable the option pic-data-is-text-relative which is by default enabled even when not specified (!).

This is exactly the opposite of the solutions posted in the cited questions which suggested to force enable said option.

Now the local static variables are added to the global offset table and are properly accessed.

Source: [https://gcc.gnu.org/legacy-ml/gcc-patches/2016-05/msg00630.html]