我面临一个奇怪的问题,有点类似于this。我有一个Windows Phone 8原生DLL项目,主要是C ++,但其中有一个ARM程序集源代码。源处于ARM模式(即不是Thumb)。 C ++编译为Thumb。
当C ++尝试调用汇编例程时,应用程序崩溃。反汇编中的call命令是BLX,具有立即偏移量 - 它应该无条件地将模式切换回ARM,但不知何故它不会。
我有异常的详细信息。异常代码为0xc000001d(无效操作),崩溃上下文结构中的PC值为0x696d5985。这在任何一种模式下都是不可能的 - 它是未对齐的,零位是1。 BLX指令转到1b f0 0c eb
- 如果你破译,那就是一个两部分的Thumb式BLX,它有一个4对齐的位移。崩溃上下文中的T标志为SET(CPSR = 0x60000010)。
我没有设备,但来自beta测试人员的崩溃日志非常确定。我在调用汇编之前有一个调试日志记录。然后是崩溃。
编辑:related。但是,他们声称汇编程序本身(armasm
)将ARM转换为Thumb。对我来说情况并非如此 - 至少不是静态的。 DLL包含正确的ARM代码,如汇编源(CODE32
)中所指定的那样。
编辑:尝试稍微不同的跳转序列:
ldr r12, target
and r12, r12, #0xfffffffe ; To be sure
bx r12 ;BX to a register with a cleared 0th bit. Doesn't get any more explicit than that.
结果相同。看起来有一些奇怪的代码变形发生在Store的某个地方,或者操作系统本身捕获模式开关并阻止它们。
可以通过将部分可执行文件与其他崩溃数据一起转储到崩溃日志中来检测代码变形。但是,如果不将整个代码库转换为Thumb,我可以用OS干扰做什么呢?它不只是重新编译。
编辑dwelch:编译后的C代码中的调用顺序如下:
.text:1000A35E MOV R2, #g_Host ;Three parameters
.text:1000A366 MOV R1, R5
.text:1000A368 MOV R0, R6
.text:1000A36A BLX Func ; Code bytes 1B F0 0C EB
BLX到立即地址HAS切换模式。这不是有条件的,比如bx register
。呼叫目标是一个thunk:
.text:10025984 B Func_Impl
崩溃地址是这个thunk加上一个:5985。
这是已编译DLL的反汇编,但我无法保证这正是在设备上执行的内容。链接的MSDN线程中的用户声称他们查看了调试器中的反汇编 ,并看到了ARM应该在哪里。 Microsoft,IIRC拥有从发布者到设备修改应用程序代码途中的专利;这可能是原因。
答案 0 :(得分:2)
一位名叫Michael Schnell的绅士suggested elsewhere,Windows Phone 8中的中断处理程序不会恢复Thumb标志,而是将其硬编码为1.测试似乎证实了这一理论。以下代码段:
THUMB
ASMTest
mov r12, lr
blx a
mov lr, r12
bx lr
ALIGN 4
ARM
a
bx lr
在调试器下一直崩溃,但在无调试器时运行正常(即在ARM模式下没有中断)。当我在ARM模式下插入一个带有0x10000次迭代的空循环时,它会尝试几次,然后崩溃。
答案 1 :(得分:2)
我对此有第一手资料;我是反向工程师,他在Windows RT的内核中找出了原因。具体来说,Windows NT内核中的KeContextFromKframes
(ntoskrnl.exe
)在冻结线程的任务切换状态时设置T
位。这意味着是的,在中断后恢复时,你会崩溃。
这使我们对RT / WinPhone的jailbreakers感到恼火,因为我们无法直接移植Chrome的JITter而不会破坏微软的PatchGuard。我们可以加载一个内核驱动程序来修补KeContextFromKframes
,但随后PatchGuard会导致崩溃。
答案 2 :(得分:0)
从拇指到手臂使用BLX时,你无法得到一个未对齐的手臂地址。低两位由第二条指令给出。阅读arm文档,你基本上有两个指令,第一个是:
0xF01B
if H == 10 then
LR = PC + (SignExtend(offset_11) << 12)
基本上第一条指令导致修改lr,其中pc是地址,如果该指令加4(前面两条指令)。
LR = PC + 0x1B000
第二个是
0xEB0C
if H == 01 then
PC = (LR + (offset_11 << 1)) AND 0xFFFFFFFC
LR = (address of next instruction) | 1
CPSR T bit = 0
最终结果是
PC = (address of next instruction + 0x1B000 + 0x318) AND 0xFFFFFFFC
PC = (address of next instruction + 0x1B318) AND 0xFFFFFFFC
LR = address of next instruction | 1
CPSR T bit = 0, arm mode.
我认为你的崩溃是在其他地方。
您应该发布有问题的代码的反汇编,指令的地址等。
就你的BX尝试而言,你正在走一条滑坡......
ARM/Thumb state transfers
If Rm[1:0] == 0b10, the result is UNPREDICTABLE, as branches to non word-aligned
addresses are impossible in ARM state.
通过1110和你正在清除lsbit,但也可能允许一个未对齐的地址。如果你没有在r12中正确计算目标地址,如果这不是arm代码,那么它就不会工作。请发布反汇编以及清楚显示正在发生的事情,并发布第一条指令或少数目的地地址。
看起来您的异常代码告诉您,您的异常是在拇指地址的拇指模式下。请在反汇编处发布该地址/周围的代码。