1

我面临一个奇怪的问题,有点类似于this。我有一个 Windows Phone 8 本机 DLL 项目,主要是 C++,但其中包含 ARM 程序集源。源处于 ARM 模式(即不是 Thumb)。C++ 编译为 Thumb。

当 C++ 尝试调用汇编例程时,应用程序崩溃。反汇编中的调用命令是带有立即偏移量的 BLX - 它应该无条件地将模式切换回 ARM,但不知何故它没有。

我有异常的详细信息。异常代码为0xc000001d(无效操作),crash context struct中PC的值为0x696d5985。这在任何一种模式下都是不可能的——它没有对齐,零位是一。BLX 指令运行1b f0 0c eb- 如果您破译,那是一个由两部分组成的 Thumb 式 BLX 好吧,具有 4 对齐位移。崩溃上下文中的 T 标志为 SET (CPSR=0x60000010)。

我没有设备,但来自 beta 测试人员的崩溃日志非常有说服力。在调用程序集之前我有一个调试日志记录。然后是崩溃。

编辑:相关。然而,他们声称汇编程序本身 ( 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.

结果相同。看起来商店中某处发生了一些奇怪的代码变形,或者操作系统本身捕获了模式切换并阻止了它们。

代码变形可以通过将可执行文件的一部分连同其余的崩溃数据一起转储到崩溃日志中来检测。但是,除了将整个代码库转换为 Thumb 之外,我还能如何处理操作系统干扰?它不只是重新编译。

为 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 到立即地址有切换模式。这不是有条件的,例如bx register. 调用目标是一个 thunk:

.text:10025984                 B               Func_Impl

崩溃地址是这个 thunk 加一:5985。

这是已编译 DLL 的反汇编,但我不能保证这正是设备上正在执行的内容。链接的 MSDN 线程中的用户声称他们查看了调试器中的反汇编并看到了 ARM 应该在的地方。微软, IIRC,拥有修改从发布者到设备的应用程序代码的专利;这可能是原因。

4

3 回答 3

3

一位名叫 Michael Schnell 的绅士在其他地方建议,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 次迭代的空循环时,它运行了几次,然后崩溃了。

于 2014-03-13T14:31:37.617 回答
3

我对此有第一手的了解;我是在 Windows RT 内核中找出原因的逆向工程师。具体来说,KeContextFromKframes在 Windows NT 内核中 ( ) 是在冻结线程状态以进行任务切换时ntoskrnl.exe设置该位。T这意味着是的,在中断后恢复时,您将崩溃。

这惹恼了我们的 RT/WinPhone 越狱者,因为我们无法在不破坏 Microsoft 的 PatchGuard 的情况下直接移植 Chrome 的 JITter。我们可以加载一个内核驱动程序来修补它KeContextFromKframes,但是 PatchGuard 稍后会导致崩溃。

于 2015-10-30T00:53:55.747 回答
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 代码,那么它将无法工作。请张贴这个以及那个的反汇编,将清楚地显示发生了什么,还张贴第一条指令或几个目标地址。

看起来您的异常代码告诉您您的异常在拇指地址处处于拇指模式。请在该地址/附近发布代码的反汇编。

于 2013-08-21T04:45:51.287 回答