0

Suppose that in a bare-metal(arm-none-eabi-gcc) arm v5 environment where functions are stored at fixed locations and the underlying 'application' can only access the functions through absolute address. So, a function is defined as:

    .type name, %function; \
    .extern name; \
    .equ name,0x400099

which can be invoked from the C code like this name(args); however,due to the nature of the shared binary(compiled as -fPIE), the resulting veneer produced is the following:

00012294 <name_veneer>:
00012294 ldr        r12,[DAT_0001229c]
00012298 add        pc=>LAB_412331,pc,r12
0001229c .word 400099h

Where the linker adds the current location of PC to the final destination which is incorrect and instead something like following is preferred:

00012294 <name_veneer>:
00012294 ldr        r12,[DAT_0001229c]
00012298 mov pc,r12
0001229c .word 400099h

System information

  • The underlying application has an unknown entry point during run time, hence the need for PIE.
  • The application is loaded from network for debugging purposes.
  • The SOC containing the CPU is a proprietary design.
artless noise
  • 21,212
  • 6
  • 68
  • 105
  • it is not sortable on the C level without workarounds. – 0___________ Jan 02 '22 at 19:10
  • I have a suspicion you are missing something. See [my answer to static linked libraries](https://stackoverflow.com/questions/25172834/how-to-create-static-linked-shared-libraries/25189092#25189092). Mainly, why use PIE if it is not required to relocate a static base? Then just PIC or PC-relative code is fine. PIE requires an update of the static base. – artless noise Jan 03 '22 at 15:51
  • Yes, the runtime handler is ran on the application itself which points the R9 register to the GOT which is then fixed by the reloc tables which can only be done on a shared binary – jacktheninja Jan 04 '22 at 12:28

1 Answers1

0

You could load function address directly to register by having macro like (if I got your question right)

.equ name,0x400099

movw    r12, #:lower16:name
movt    r12, #:upper16:name  // after this instruction r12 == 0x400099
mov     pc,  r12
user3124812
  • 1,861
  • 3
  • 18
  • 39
  • thank you for the answer but unfortunately that's not what i need, the `.equ name,0x400099` part is actually in an assembly file responsible for 'exporting' the defined symbol to the linker to treat it as a function so the veneer code is generated by the linker. So what i'm really looking for is someway to modify the linker in order to get a direct jump and skip the relative branch. – jacktheninja Jan 02 '22 at 22:17
  • ARM v5 does not support `movw` and `movt`. However, you can code the veneer or just list it as a function pointer. `int *name(args) = (int(*)(args))0x400099;` in a header and use this. PIE differs from PIC in that the data section is relocated. In [this page](https://developer.arm.com/documentation/den0013/d/Application-Binary-Interfaces/Procedure-Call-Standard), it documents that R12 (IP) will be used to update the static base. So I don't think you can ignore this, unless the PIE uses no statics/globals, but then it is just PIC and why compile as PIE? – artless noise Jan 03 '22 at 15:48
  • PIE is needed since the underlying application does use global variables that can be updated during runtime by relocating the exported ELF segments when compiled as a shared binary(unless PIC can somehow export the **required** relocatable segments. ie function arrays`void*funct[] = {&func1,&func2};`) – jacktheninja Jan 04 '22 at 11:07