Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linker: Moving all functions but two to a specific memory region

I am working on firmware for a PIC32MX microcontroller. The program memory should be split into three segments:

  • Section 1: interrupt service routine and main function (startup_region)
  • Section 2: 50% of remaining program memory (program1)
  • Section 3: 50% of remaining program memory (program2)

The firmware is only stored in either Section 2 or 3. The other is reserved for future updates. As such the active region can safely override the other to store the update. A config bit is flipped and the main() function of Section 0 now jumps to the other program on reboot.

As such I need the linker to put all functions except isr and main into Section 1 and everything else into Section 2. Section 3 must be left completely empty, as it may be overridden in the future.

I already tried to achieve this by modifying the default linker script, however I had no success.

linkerscript.ld:

/* [...] */
INCLUDE procdefs.gld
/* [...] */
SECTIONS
{
  /* [...] */
  .text :
  {
    /* isr() and main() should be at the very first locations in program memory */
    *(.text.isr)
    *(.text.main)
    /* [...] */
    . = ALIGN(4) ;
  } >kseg0_program_mem

  .program1 :
  {
    *(*.text)
  } >program1

  /* [...] */
}

procdefs.gld:

/* [...] */
MEMORY
{
  kseg0_program_mem     (rx)  : ORIGIN = 0x9D000000, LENGTH = 0x10000
  startup_region        (rx)  : ORIGIN = 0x9D000000, LENGTH = 0x01000
  program1              (rx)  : ORIGIN = 0x9D002000, LENGTH = 0x07000
  program2              (rx)  : ORIGIN = 0x9D009000, LENGTH = 0x07000
  kseg0_boot_mem              : ORIGIN = 0x9FC00490, LENGTH = 0x970
  /* [...] */
}
/* [...] */

This results in the following:

isr() and main() are where they are supposed to be (0x9D00000 is the KSEG0 virtual address of the beginning of the program flash)

.text           0x9d000000       0x94
 *(.text.isr)
 .text.isr      0x9d000000       0x60 build/default/production/main.o
                0x9d000000                isr
 *(.text.main)
 .text.main     0x9d000060       0x34 build/default/production/main.o
                0x9d000060                main

The program1 region is correctly placed and most object files are listed correctly (notice however, that main.o is listed again -- it was already used).

.program1       0x9d002000      0xc44
 *(*.text)
 .text          0x9d002000        0x0 /opt/microchip/xc32/v2.10/bin/bin/../../lib/gcc/pic32mx/4.8.3/../../../../pic32mx/lib/./proc/32MX330F064H/crt0_mips32r2.o
 .text          0x9d002000        0x0 /opt/microchip/xc32/v2.10/bin/bin/../../lib/gcc/pic32mx/4.8.3/../../../../pic32mx/lib/debug-exception-return.o
 .text          0x9d002000        0x0 build/default/production/main.o
 .text          0x9d002000        0x0 build/default/production/commands.o
 /* [...] */
 .text          0x9d002000        0x0 build/default/production/micro-ecc/uECC.o

However, some function are located outside of this region:

.text.uECC_verify
                0x9d000b04      0x7c0
 .text.uECC_verify
                0x9d000b04      0x7c0 build/default/production/micro-ecc/uECC.o
                0x9d000b04                uECC_verify

.text.vli_mmod_fast_secp256r1
                0x9d0012c4      0x520
 .text.vli_mmod_fast_secp256r1
                0x9d0012c4      0x520 build/default/production/micro-ecc/uECC.o

I do not understand why this happens.

My questions are:

  • How can I enforce the linker to put all functions (except main and isr) into program1.
  • How can I prohibit the linker to put anything into program2, so that it remains free.

I am compiling the software with the -ffunction-segments switch, so that each function gets its own segment.

The original linkerscript also contains this suspicious looking comment:

/* Code Sections - Note that input sections *(.text) and *(.text.*)
   are not mapped here. Starting in C32 v2.00, the best-fit allocator
   locates them, so that .text may flow around absolute sections
   as needed.
*/
like image 300
Danish Avatar asked Nov 06 '22 09:11

Danish


1 Answers

The object file main.o is not the same as the function’s memory segment .tex.main. If this object file produces some other text segments they will be placed elsewhere. This is what you see in your map file.

As @Ctx mentioned the syntax of your text segment is wrong instead of *(*.text) it should be

  .program1 :
  {
    *(.text*)
  } >program1

This way all other text segments will be properly placed in the program1 memory.

like image 140
Teivaz Avatar answered Nov 15 '22 00:11

Teivaz