GCC Posistion independent code: Variables are not loaded correctly

0

The Program works fine as a stand alone on CC2650 (M3). But it shall be used also as a firmware which is loaded over the radio channel. For this purpose the position independent code is needed. The problem is, all of the variables defined as described below are not set.

uint32_t u32Timer_g = 2000;

static DeviceInterfaceStructure_t suInterfaceStructure_g = 
{
  .timeOut = 0,                        
  .state = STATE_IDLE,                                                  
  .lastState = STATE_IDLE,              
  .Config.reconnect = 0,          
  .Config.lVersion = 0x01,        
};

The Program is compiled with GCC (gcc-arm-none-eabi-7-2018-q2-update) using the following flags:

--asm
-fPIE
-pie
-fno-strict-aliasing
-fdata-sections
-ffunction-sections
-fno-exceptions

and using the following linker script

ENTRY( ResetISR )

    MEMORY
{
    CRC (RX)        : ORIGIN = 0x00001000, LENGTH = 0x00000004
    OHD (RX)        : ORIGIN = 0x00001004, LENGTH = 0x0000000C
    INT_VEC (RX)    : ORIGIN = 0x00001010, LENGTH = 0x000000C8
    FWU_DESCR (RX)  : ORIGIN = 0x000010D8, LENGTH = 0x00000040
    APP_DESCR (RX)  : ORIGIN = 0x00001118, LENGTH = 0x00000040
    FLASH (RX)      : ORIGIN = 0x00001158, LENGTH = 0x0000AF2F
    SRAM (RWX)      : ORIGIN = 0x20000000, LENGTH = 0x00005000
    /* Application can use GPRAM region as RAM if cache is disabled in the CCFG
    (DEFAULT_CCFG_SIZE_AND_DIS_FLAGS.SET_CCFG_SIZE_AND_DIS_FLAGS_DIS_GPRAM = 0) */
    GPRAM (RWX)     : ORIGIN = 0x11000000, LENGTH = 0x2000
}

/*. Generate a link error if heap and stack don’t fit into RAM .*/
_Min_Heap_Size = 0x800;
_Min_Stack_Size = 0x800;

/*. Highest address of the stack. Used in startup file .*/
_estack = ORIGIN(SRAM) + LENGTH(SRAM); /*end of SRAM .*/

REGION_ALIAS("REGION_TEXT", FLASH);
REGION_ALIAS("REGION_BSS", SRAM);
REGION_ALIAS("REGION_DATA", SRAM);
REGION_ALIAS("REGION_STACK", SRAM);
REGION_ALIAS("REGION_HEAP", SRAM);
REGION_ALIAS("REGION_ARM_EXIDX", FLASH);
REGION_ALIAS("REGION_ARM_EXTAB", FLASH);


/* Section allocation in memory */

SECTIONS
{
    .SHADOW_CRC :
    {
        KEEP(*(.SHADOW_CRC))
    } > CRC = 0xFF

    .IMAGE_HEADER :
    {
        KEEP(*(.IMAGE_HEADER))
    } > OHD = 0xFF

    .intvec :
    {
        KEEP(*(.vectors))
    } > INT_VEC = 0xFF

    .firmwareDescr :
    {
        KEEP(*(.firmwareDescr))
    } >  FWU_DESCR = 0xFF

    .applicationDescr :
    {
        KEEP(*(.applicationDescr))
    } >  APP_DESCR = 0xFF

    .text :
    {
        _text = .;
        *(.text*)
        *(.rodata)
        *(.rodata*)
        *(.init)
        *(.fini*)
        *(.eh_frame*)
        _etext = .;
    } > FLASH = 0xFF

   .ARM.exidx :
    {
        __exidx_start = .;
        *(.ARM.exidx* .gnu.linkonce.armexidx.*)
        __exidx_end = .;
    } > FLASH

    .ARM.extab :
    {
        *(.ARM.extab* .gnu.linkonce.armextab.*)
    } > FLASH

    .data :
    {
        _data = .;
        *(vtable)
        *(.data)
        *(.data*)
        _edata = .;
        *(.got)
        *(.got*)
        *(.igot*)
    } > SRAM AT > FLASH
    _ldata = LOADADDR(.data);

    .bss :
    {
        __bss_start__ = .;
        _bss = .;
        *(.bss*)
        *(COMMON)
        _ebss = .;
        __bss_end__ = .;
    } > SRAM


    /* User_heap_stack section, used to check that there is enough SRAM left */

    ._user_heap_stack :
    {
        __heap_start__ = .;
        end = __heap_start__;
        _end = end;
        __end = end;
        KEEP(*(.heap))
        __heap_end__ = .;
        __HeapLimit = __heap_end__;
        . = . + _Min_Stack_Size;
    } > SRAM

    .gpram :
    {
    } > GPRAM

}

The question is: What I'm doing wrong???

Update The initialisation and realocation:

//*****************************************************************************
void
ResetISR(void)
{
    uint32_t *pui32Src, *pui32Dest;

    //
    // CC26xx PG1 workaround: Check backdoor when coming from POR
    //
    EnableAndCheckBackdoor();

    //
    // Final trim of device
    //
    trimDevice();
    
    //
    // Copy the data segment initializers from flash to SRAM.
    //
    pui32Src = &_etext;
    for(pui32Dest = &_data; pui32Dest < &_edata; )
    {
        *pui32Dest++ = *pui32Src++;
    }

    //
    // Zero fill the bss segment.
    //
    __asm("    ldr     r0, =_bss\n"
          "    ldr     r1, =_ebss\n"
          "    mov     r2, #0\n"
          "    .thumb_func\n"
          "zero_loop:\n"
          "        cmp     r0, r1\n"
          "        it      lt\n"
          "        strlt   r2, [r0], #4\n"
          "        blt     zero_loop");

   //
   // Call the application's entry point.
   //
   main();

    //
    // If we ever return signal Error
    //
    FaultISR();
}
c
gcc
position-independent-code
asked on Stack Overflow Jul 9, 2020 by Semiory • edited Jul 9, 2020 by Useless

1 Answer

0

Even though you compiled your code position independent, your linker script makes it not-that-way. Your data relocation loop uses flash addresses to do the data copy:

pui32Src = &_etext;

You need to modify that to handle the OTA case and copy the initialized data over from wherever it is in RAM.

answered on Stack Overflow Jul 9, 2020 by Carl Norum

User contributions licensed under CC BY-SA 3.0