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

北城余情 提交于 2019-12-06 07:47:55
old_timer

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.

The accepted answer achieves the desired goal, but to address the answer exactly as asked you can use the .equ directive to associate a constant vale with a symbol, that can then be used as an operand to instructions. This has the assembler synthesise the trampoline if/when necessary:

equ myFirmwareFunction, 0x12346570
.globl _start
        mov r0, #42
        b   myFirmwareFunction

Which generates the following assembly[1]

01000000 <_start>:
 1000000:   e3a0002a    mov r0, #42 ; 0x2a
 1000004:   eaffffff    b   1000008 <__*ABS*0x12346570_veneer>

01000008 <__*ABS*0x12346570_veneer>:
__*ABS*0x12346570_veneer():
 1000008:   e51ff004    ldr pc, [pc, #-4]   ; 100000c <__*ABS*0x12346570_veneer+0x4>
 100000c:   12346570    data: #0x12345670

If the immediate value is close enough to PC that the offset will fit in the immediate field, then the verneer (trampoline) is skipped and you will get a single branch instruction to the specified constant address.

[1] using the codesorcery (2009q1) toolchain with: arm-none-eabi-gcc -march=armv7-a -x assembler test.spp -o test.elf -Ttext=0x1000000 -nostdlib

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!