STM32, Position independent code - function pointers not in GOT?
Asked Answered
G

1

10

I need a position independent code (PIC) working on STM32F401. But i have problem with pointers to functions used e.g. in struct.

Short example:

struct process {
  struct process *next;
  const char *name;
  PT_THREAD((* thread)(struct pt *, process_event_t, process_data_t));
  struct pt pt;
  unsigned char state, needspoll;
};

process etimer_process...

static void call_process(struct process *p, process_event_t ev, process_data_t data) {
  int ret;
  ret = p->thread(&p->pt, ev, data);
}

After diassembly:

Disassembly of section .data:
   ...
 20000768 <etimer_process>:
 20000768:  00000000    andeq   r0, r0, r0
 2000076c:  0803b134    stmdaeq r3, {r2, r4, r5, r8, ip, sp, pc}
 20000770:  08027435    stmdaeq r2, {r0, r2, r4, r5, sl, ip, sp, lr}
 20000774:  00000000    andeq   r0, r0, r0
   ...

Disassembly of section .text:
   ...
 8027da4:   68fb        ldr r3, [r7, #12]  //R3 = 0x20000768
 8027da6:   689b        ldr r3, [r3, #8]   //R3 = 0x8027435
   ...
 8027db2:   4798        blx r3  //Branch to R3
   ...

Branch address in R3 is wrong for code at offset different than 0. I don't see use of GOT here. It is a bug or missing compiler/linker option?


Things which i have probably successfully solved:

  • GOT fixup
  • Interrupt table fixup
  • Newlib compiled with appropriate cflags

Used CFLAGS:

-mlittle-endian -mthumb -mthumb-interwork -mcpu=cortex-m4 -fsingle-precision-constant -Wdouble-promotion -msoft-float -fpic -msingle-pic-base -mpic-data-is-text-relative -mpic-register=r10 -Wno-strict-aliasing -lc

and linking with

-fpic

Glycoside answered 17/10, 2017 at 8:24 Comment(4)
It seems that you expect that the branch address is modified after it is retrieved from process struct. That's not the case. It must be fixed up at the time the process struct is initialized. Why does your environment require position independent code anyway? Pretty unusual for a microcontroller.Hosea
The initialization of data section is simple, just copy values from flash to ram. But i don't know, if given value is flash address or not. Iam developing IoT device and we need OTA firmware update. In the flash of STM32 will be two or maybe three firmware at different locations. In case of any error, the bootloader run another firmware.Braziel
So when you copy the values from flash into RAM (into the process struct), you have to fix the branch address. The simplest way is to have it initialized by code: etimer_process.pt = my_func;. Then the compiler will create the necessary code to compute the correct address.Hosea
Not related to the question at all, but I think you have written -Wno-strict-aliasing when you probably wanted -fno-strict-aliasing. -fno-strict-aliasing means don't let the compiler assume variables aren't aliased. -Wno-strict-aliasing means don't print a warning when variables are aliased!Cocainize
T
0

GOT does not need to be used in this case. Instead the compiler will add a runtime relocation which will instruct dynamic linker to patch etimer_process.thread at startup (I'm assuming it's initialized at definition of etimer_process).

Tynes answered 28/12, 2021 at 9:36 Comment(5)
What dynamic linker using uCs? ElaborateLonginus
@Longinus in OP's case I believe he has his own custom runtime "linker" (mind the "GOT fixup", "Interrupt table fixup" in his question - that's exactly the runtime relocation that dynamic linker typicallu does). That's not to mention things like udynlink, etc.Tynes
@Longinus do you agree that OP has a piece of code which performs runtime relocation of his code at startup? I call it a runtime linker. You can suggest a better name but please avoid personal attacks, they are not helping anyone (yes, I did program bootloaders for uCs).Tynes
No, he does not. That is the reason he wants PICLonginus
@Longinus well, he does have a code which "fixs up" pointers at startup. In my world that's called runtime relocation ¯_(ツ)_/¯Tynes

© 2022 - 2024 — McMap. All rights reserved.