Search code examples
gccarmgnu-assembler

ARM/Thumb code for firmware patches...How to tell gcc assembler / linker to BL to absolute addr?


I'm trying to write a firmware mod (to existing firmware, for which i don't have source code) All Thumb code.

does anybody have any idea how to do this, in gcc as (GAS) assembler: Use BL without having to manually calculate offsets, when BL'ing to some existing function (not in my code.. but i know its address)

Currently, if i want to use BL ...i have to : -go back in my code -figure out and add all the bytes that would result from assembling all the previous instructions in the function i'm writing -add the begining address of my function to that (i specify the starting address of what i'm writing, in the linker script) -and then substract the address of the firmfunc function i want to call

All this... just to calculate the offset... to be able to write abl offset... to call an existing firmware function? And if i change any code before that BL, i have to do it all over again manually !
See.. this is why i want to learn to use BX right... instead of BL

Also, i don't quite understand the BX. If i use BX to jump to an absolute address, do i have to increase the actual address by 1, when caling Thumb code from Thumb code (to keep the lsb byte 1)... and the CPU will know it's thumb code ?


Solution

  • BIG EDIT:

    Changing the answer based on what I have learned recently and a better understanding of the question

    First off I dont know how to tell the linker to generate a bl to an address that is a hardcoded address and not actually in this code. You might try to rig up an elf file that has labels and such but dummy or no code, dont know if that will fool the linker or not. You would have to modify the linker script as well. not worth it.

    your other question that was spawned from this one:

    Arm/Thumb: using BX in Thumb code, to call a Thumb function, or to jump to a Thumb instruction in another function

    For branching this works just fine:

    LDR R6, =0x24000
    ADD R6, #1       @ (set lsb to 1)
    BX R6
    

    or save an instruction and just do this

    LDR R6, =0x24001
    BX R6
    

    if you want to branch link and you know the address and you are in thumb mode and want to get to thumb code then

      ldr r6,=0x24001
      bl thumb_trampoline
      ;@returns here
      ...
    .thumb_func
    thumb_trampoline:
      bx r6
    

    And almost the exact same if you are starting in arm mode, and want to get to thumb code at an address you already know.

      ldr r6,=0x24001
      bl arm_trampoline
      ;@returns here
      ...
    arm_trampoline:
      bx r6
    

    You have to know that you can trash r6 in this way (make sure r6 isnt saving some value being used by some code that called this code).

    Very sorry misleading you with the other answer, I could swear that mov lr,pc pulled in the lsbit as a mode, but it doesnt.