【发布时间】:2011-12-07 19:15:49
【问题描述】:
我最近在使用 Assembly 编程时遇到了 ARM Cortex-A8 的奇怪行为。每当我 MOV 任何东西进入 R4 时,我的程序都会崩溃(下面的堆栈转储)
10-14 09:48:43.117: INFO/DEBUG(3048): Build fingerprint: 'google/soju/crespo:2.3.6/GRK39F/189904:user/release-keys'
10-14 09:48:43.121: INFO/DEBUG(3048): pid: 7082, tid: 7082 >>> neontests <<<
10-14 09:48:43.121: INFO/DEBUG(3048): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 00000001
10-14 09:48:43.125: INFO/DEBUG(3048): r0 00000001 r1 afa025b6 r2 00000000 r3 bec77051
10-14 09:48:43.128: INFO/DEBUG(3048): r4 00000001 r5 bec7704c r6 00000001 r7 00000004
10-14 09:48:43.128: INFO/DEBUG(3048): r8 00000005 r9 00000000 10 4214cca4 fp 800a5368
10-14 09:48:43.128: INFO/DEBUG(3048): ip afa03110 sp bec77010 lr afa0133b pc afd37b42 cpsr 60000030
10-14 09:48:43.132: INFO/DEBUG(3048): d0 0000000200000053 d1 0000000400000074
10-14 09:48:43.132: INFO/DEBUG(3048): d2 000000060000006f d3 0000000800000070
10-14 09:48:43.132: INFO/DEBUG(3048): d4 006f0065006e002e d5 007300650074006e
10-14 09:48:43.136: INFO/DEBUG(3048): d6 0000000c00000005 d7 0000002000000015
10-14 09:48:43.136: INFO/DEBUG(3048): d8 0000000c00000005 d9 0000002000000015
10-14 09:48:43.140: INFO/DEBUG(3048): d10 0000000000000000 d11 0000000000000000
10-14 09:48:43.140: INFO/DEBUG(3048): d12 0000000000000000 d13 0000000000000000
10-14 09:48:43.140: INFO/DEBUG(3048): d14 0000000000000000 d15 0000000000000000
10-14 09:48:43.144: INFO/DEBUG(3048): d16 800220e8401644a8 d17 bff0000000000000
10-14 09:48:43.144: INFO/DEBUG(3048): d18 3ff0000000000000 d19 0000000000000000
10-14 09:48:43.148: INFO/DEBUG(3048): d20 0000000000000000 d21 0000000000000000
10-14 09:48:43.148: INFO/DEBUG(3048): d22 3ff0000000000000 d23 0000000000000000
10-14 09:48:43.148: INFO/DEBUG(3048): d24 3ff0000000000000 d25 0000000000000000
10-14 09:48:43.148: INFO/DEBUG(3048): d26 0000000000000000 d27 0000000000000000
10-14 09:48:43.148: INFO/DEBUG(3048): d28 0000000000000000 d29 0000000000000000
10-14 09:48:43.148: INFO/DEBUG(3048): d30 0000000000000000 d31 0000000000000000
10-14 09:48:43.148: INFO/DEBUG(3048): scr 20000012
10-14 09:48:43.195: INFO/DEBUG(3048): #00 pc 00037b42 /system/lib/libc.so
10-14 09:48:43.195: INFO/DEBUG(3048): #01 pc 00001338 /system/lib/liblog.so
10-14 09:48:43.199: INFO/DEBUG(3048): #02 pc 00001482 /system/lib/liblog.so
10-14 09:48:43.199: INFO/DEBUG(3048): #03 pc 00000c54 /data/data/neontests/lib/libneon_tests.so
10-14 09:48:43.199: INFO/DEBUG(3048): #04 pc 00017e34 /system/lib/libdvm.so
10-14 09:48:43.199: INFO/DEBUG(3048): #05 pc 0004968c /system/lib/libdvm.so
10-14 09:48:43.199: INFO/DEBUG(3048): #06 pc 0004ee62 /system/lib/libdvm.so
10-14 09:48:43.199: INFO/DEBUG(3048): #07 pc 0001d034 /system/lib/libdvm.so
10-14 09:48:43.199: INFO/DEBUG(3048): #08 pc 000220e4 /system/lib/libdvm.so
10-14 09:48:43.199: INFO/DEBUG(3048): #09 pc 00020fdc /system/lib/libdvm.so
10-14 09:48:43.199: INFO/DEBUG(3048): #10 pc 0005fdde /system/lib/libdvm.so
10-14 09:48:43.203: INFO/DEBUG(3048): #11 pc 00067b52 /system/lib/libdvm.so
10-14 09:48:43.203: INFO/DEBUG(3048): #12 pc 0001d034 /system/lib/libdvm.so
10-14 09:48:43.203: INFO/DEBUG(3048): #13 pc 000220e4 /system/lib/libdvm.so
10-14 09:48:43.203: INFO/DEBUG(3048): #14 pc 00020fdc /system/lib/libdvm.so
10-14 09:48:43.203: INFO/DEBUG(3048): #15 pc 0005fc40 /system/lib/libdvm.so
10-14 09:48:43.203: INFO/DEBUG(3048): #16 pc 0004c126 /system/lib/libdvm.so
10-14 09:48:43.203: INFO/DEBUG(3048): #17 pc 00032572 /system/lib/libandroid_runtime.so
10-14 09:48:43.203: INFO/DEBUG(3048): #18 pc 0003341e /system/lib/libandroid_runtime.so
10-14 09:48:43.203: INFO/DEBUG(3048): #19 pc 00008cca /system/bin/app_process
10-14 09:48:43.207: INFO/DEBUG(3048): #20 pc 00014b52 /system/lib/libc.so
10-14 09:48:43.207: INFO/DEBUG(3048): code around pc:
10-14 09:48:43.207: INFO/DEBUG(3048): afd37b20 18801889 c003f810 c003f801 d2f93b01
10-14 09:48:43.207: INFO/DEBUG(3048): afd37b30 bf00bdf0 2200b510 3201e003 4618b90b
10-14 09:48:43.207: INFO/DEBUG(3048): afd37b40 5c83e004 42a35c8c 1b18d0f7 bf00bd10
10-14 09:48:43.207: INFO/DEBUG(3048): afd37b50 b152b530 5cc42300 42ac5ccd 1b60d001
10-14 09:48:43.207: INFO/DEBUG(3048): afd37b60 b114e004 429a3301 2000d1f5 bf00bd30
10-14 09:48:43.207: INFO/DEBUG(3048): code around lr:
10-14 09:48:43.207: INFO/DEBUG(3048): afa01318 fffffff4 00001e20 b088b570 4615460c
10-14 09:48:43.207: INFO/DEBUG(3048): afa01328 b9099001 447c4c28 46204928 f7ff4479
10-14 09:48:43.207: INFO/DEBUG(3048): afa01338 2800edc4 4926d02e 22034620 f7ff4479
10-14 09:48:43.207: INFO/DEBUG(3048): afa01348 b338edc2 46204923 f7ff4479 b308edb6
10-14 09:48:43.207: INFO/DEBUG(3048): afa01358 46204921 f7ff4479 b1d8edb0 4620491f
10-14 09:48:43.207: INFO/DEBUG(3048): stack:
10-14 09:48:43.207: INFO/DEBUG(3048): bec76fd0 800a5368
10-14 09:48:43.207: INFO/DEBUG(3048): bec76fd4 afd1c701 /system/lib/libc.so
10-14 09:48:43.207: INFO/DEBUG(3048): bec76fd8 bec771f0
10-14 09:48:43.207: INFO/DEBUG(3048): bec76fdc bec77051
10-14 09:48:43.207: INFO/DEBUG(3048): bec76fe0 0000ce60
10-14 09:48:43.207: INFO/DEBUG(3048): bec76fe4 000003fa
10-14 09:48:43.207: INFO/DEBUG(3048): bec76fe8 ffff0208
10-14 09:48:43.207: INFO/DEBUG(3048): bec76fec bec7704c
10-14 09:48:43.207: INFO/DEBUG(3048): bec76ff0 000003ff
10-14 09:48:43.207: INFO/DEBUG(3048): bec76ff4 00000000
10-14 09:48:43.210: INFO/DEBUG(3048): bec76ff8 00000003
10-14 09:48:43.210: INFO/DEBUG(3048): bec76ffc 00000004
10-14 09:48:43.210: INFO/DEBUG(3048): bec77000 80400d90 /data/data/neontests/lib/libneon_tests.so
10-14 09:48:43.210: INFO/DEBUG(3048): bec77004 bec7704c
10-14 09:48:43.210: INFO/DEBUG(3048): bec77008 df002777
10-14 09:48:43.210: INFO/DEBUG(3048): bec7700c e3a070ad
10-14 09:48:43.210: INFO/DEBUG(3048): #00 bec77010 00000001
10-14 09:48:43.210: INFO/DEBUG(3048): bec77014 afa0133b /system/lib/liblog.so
10-14 09:48:43.210: INFO/DEBUG(3048): #01 bec77018 80400420 /data/data/neontests/lib/libneon_tests.so
10-14 09:48:43.210: INFO/DEBUG(3048): bec7701c 00000004
10-14 09:48:43.210: INFO/DEBUG(3048): bec77020 bec7701c
10-14 09:48:43.210: INFO/DEBUG(3048): bec77024 00000001
10-14 09:48:43.210: INFO/DEBUG(3048): bec77028 80400d90 /data/data/neontests/lib/libneon_tests.so
10-14 09:48:43.210: INFO/DEBUG(3048): bec7702c 00000014
10-14 09:48:43.210: INFO/DEBUG(3048): bec77030 00000000
10-14 09:48:43.210: INFO/DEBUG(3048): bec77034 00000000
10-14 09:48:43.210: INFO/DEBUG(3048): bec77038 bec7704c
10-14 09:48:43.210: INFO/DEBUG(3048): bec7703c afd4d5c8
10-14 09:48:43.210: INFO/DEBUG(3048): bec77040 00000001
10-14 09:48:43.210: INFO/DEBUG(3048): bec77044 afa01487 /system/lib/liblog.so
编辑:上面的堆栈转储是以下代码的结果(抱歉,这里的 GNU 汇编突出显示有点奇怪):
.arm
.global asm_test
asm_test:
mov r0, #4 @make sure r0 is not the same as r4
mov r4, #1 @move to r4 something different from r0
mov pc, lr @return from function
我从(本机)C 中调用它,如下所示:
#include <jni.h>
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include <arm_neon.h>
#include <android/log.h>
#include "com_something_neontests_NativeLib.h"
extern volatile int asm_test(void);
JNIEXPORT jint JNICALL Java_com_something_neontests_NativeLib_asmTry
(JNIEnv * env, jobject obj)
{
__android_log_print(ANDROID_LOG_INFO, "com.something.neontests", "Start!");
asm_test();
__android_log_print(ANDROID_LOG_INFO, "com.something.neontests", "Done!");
return 0;
}
以下是我注意到的几件事。首先,每当我为 R4 分配任何东西时,无论是 MOV R4, #2 还是 ADD R4, R0, R1,结果确实在程序崩溃之前会出现在 R4 中,但同样的结果也总是会出现在 R0 中。我还发现我可以 POP 将堆栈中的东西放入 R4。没有其他寄存器表现出相同的行为。汇编代码使用 Android NDK 编译,我相信它使用 GCC 4.4.3。我在几部 Android 手机上测试过,一切似乎都是一致的。
我知道所有寄存器都是分段的,这样 R0-R3 接受参数,R4-R12 是变量寄存器,然后是特殊寄存器等等。也许这种行为是由我从未听说过的某种 C 调用约定引起的?有没有对此的解释,是预期的吗?
干杯! = )
更新:
正如@Graham 亲切地指出的那样,r4(或者 v1)是一个应该保留的变量寄存器。但是,在他的回答中提供的link 中,ARM 文档本身利用了 v1 寄存器,首先将其结果与另一个保留寄存器的值一起保存在堆栈中:
STMDB sp!,{v1,lr}
LDR v1,[a2,#0]
然后检索它们的值。当我编译这段代码时,它的崩溃方式和我原来的一样,但是
STMDB sp!,{v1,lr}
LDR v2,[a2,#0]
没有(注意 v2 而不是 v1)。
【问题讨论】:
-
您能否展示可能崩溃的最小代码?
fault addr 00000001似乎建议您从r4中包含的地址加载。r0中出现的相同结果听起来很奇怪。 -
@user786653 好的,正在编辑我的问题。
-
我仍然觉得我们没有显示所有相关代码。您是否有展示这种行为的自包含示例?
-
@user786653 没有其他代码。我使用 Android Native 接口从 C 调用它。如果这是相关的,我也可以发布我的 C 函数。
-
是的,请执行此操作以及您用于存储和检索
v1的所有代码(原因可能是一个简单的拼写错误)。
标签: android android-ndk arm assembly cortex-a8