Search code examples
assemblyarmwindows-phonethumb

ARM/Thumb interworking in assembly


I'm building a Windows Phone project with some bits of it in assembly. My assembly file is in ARM mode (CODE32), and it tries to jump to a C function that I know is compiled to Thumb. The code goes like this:

    ldr r12, [pFunc]
    mov pc, r12
pFunc
    dcd My_C_Function

Here's the weird thing. The value at pFunc in the snippet is a pointer at a function thunk plus one. That is, the 0th bit is set, as if the jump target is meant to be Thumb and the jump instruction is meant to be BX. But the thunk is clearly ARM! The thunk loads the address of the function body plus one and executes a BX to it, properly switching modes.

Trying to BX to that address would probably crash, because that would switch modes and trying to execute ARM code in Thumb mode is not a good idea. Trying to simply jump to that address (as the current code does) would probably crash too, because PC would end up unaligned.

I could, in theory, manually clean up the 0th bit and then jump, but there's gotta be some error to my thinking. The thunk is generated by the C compiler - right? The C compiler knows that the thunk is ARM code. The address under pFunc is generated by the linker, since it's a cross-module call. So the low bit is placed there by the linker; why doesn't the linker know that those thunks are ARM?

Any explanation, please?

I don't have a WP8 device now, so I can't try it in real hardware. Staring hard at the generated code is the only debugging technique that I have :(

EDIT: but what if those thunks are not ARM, but Thumb-2? Thumb-2 supports some 32-bit command IIRC. Is their encoding the same as in ARM mode? How does Thumb-2 decode commands, anyway?


Solution

  • The disassembler (IDA Demo, specifically) misled me by uniting several commands into one line. It made a single mov line out of a mov-orr-orr sequence that was meant to assign a full 32-bit constant to a register. The thunks were Thumb after all. The linker works as designed.

    IDA is otherwise great. I knew in the back of my mind about this particular behavior regarding ARM, but this time it slipped.

    My bad, thanks and upvotes to everyone who tried to help.