ARM assembly, efficient jump hook help?

Started by names_are_hard, December 08, 2019, 04:38:41 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

names_are_hard

I'm trying to patch in some jump hooks for debugging.  I'm finding it hard to work out efficient ARM assembly for this (I'm an ARM noob).  In x86 I'd JMP 0x12345678 and it would be 5 bytes with no register side effects.  ARM I can't set a dword constant in one go.  I'm also in Thumb mode.  Best I have so far is this, which kind of sucks:

        PUSH {R3, R4}
        MOV R4, 0x1234
        MOV R3, 0x5678
        LSL R4, R4, #16
        ADD R4, R3
        BX R4

Which is 18 bytes, feels bad to me.  Some functions I'm interested in are the same size!  Any better way to jump to an arbitrary offset?  Maybe I'd win by swapping out of Thumb first?

Alternatively, any ideas on how to accomplish the same idea efficiently in ARM would be appreciated - patch in a transfer to my own code to do arbitrary stuff, then cleanup register & stack changes and transfer back.

names_are_hard

Aaand, of course I managed to find a good example immediately after posting that.  In theory, I can do this:

    LDR PC,[PC,-4]
    #0x12345678

It compiles in Thumb, shall try it soon.  8 bytes, not bad.  I'm not used to PC being a thing I can set directly!

srsa

Quote from: names_are_hard on December 08, 2019, 04:47:42 AM
Aaand, of course I managed to find a good example immediately after posting that.  In theory, I can do this:

    LDR PC,[PC,-4]
    #0x12345678

It compiles in Thumb, shall try it soon.
The offset used in that instruction depends on several factors. Your example is valid in ARM state. In thumb state, the offset is 0 if your LDR PC instruction is on a word aligned address, and 2 if it isn't word aligned. See the ARM literature about the value of PC. There's also this, although I don't think I've encountered problems with that.

edit:
Of course, you also need to use the the correct thumb bit in the destination address (bit0 is zero for an ARM target, 1 for Thumb target).

a1ex

Right. Here's the code I've used for overriding DebugMsg on DIGIC 6/7 (and 8, but there you'd also have to reconfigure the MMU).

names_are_hard

Thanks both, that will save me lots of debugging time!  Particularly strange to me how the PC offset is negative!  I guess to do with pipelining.