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,