Reprint Please specify Source:http://blog.csdn.net/xyang81/article/details/42319789
in Android development, the program crash in three scenarios: ANR (application not responding uncaught exception The stack information printed based on Logcat is easy to locate the error. anr error Check, Android rules, when the app interacts with the user, if there is no response to the user's actions within 5 seconds, a ANR error is raised, And a system prompt pops up to let the user choose to wait or close the program immediately. A traces.txt file is generated in the/DATA/ANR directory, which records the stack and thread information that the system generates the ANR exception. If it is flashback , This is a difficult question to check, The NDK is usually used in a project to cause a certain kind of fatal error to result in a flashback. Because the NDK is developed using C/s + +, programmers familiar with C + + know that pointers and memory management are the most important and the most prone to problems, with a slight careless encounter such as memory address access errors, using wild , memory leaks, stack overflows, initialization errors, type conversion errors, and numbers in addition to common problems such as 0, result in the same result: program crashes. Does not pop up the "XXX program is unresponsive, closes immediately" prompt box like when the Java layer produces an exception. When the NDK error occurs, the logcat print out of the heap of logs according to not understand, but also do not want to locate the source of the error from the log, let me often a bit crazy, furious, drink how much jdb do not work. When I tried to print the logs in each JNI function to track the problem, it was too inefficient and could not locate the problem. Good heavens have eyes, let me find the NDK provides several debugging tools to pinpoint the source of the error.
Three debugging tools are available in the NDK installation package: Addr2line, Objdump, and Ndk-stack, where Ndk-stack is placed in the $ndk_home directory, with the Ndk-build sibling directory. Addr2line and Objdump in the NDK cross compiler Toolchain directory, below is the directory structure of my native ndk cross compiler toolchain:
As you can see from the directory structure, the NDK implements multiple sets of identical tools for different CPU architectures. So when choosing the addr2line and Objdump tools, choose based on the CPU architecture of your target machine. If it is an ARM architecture, select arm-linux-androidabi-4.6/4.8 (high version is generally selected). x86 architecture, select x86-4.6/4.8. Mipsel architecture, select mipsel-linux-android-4.6/4.8. If you do not know the CPU structure of the target machine, connect the phone to the computer and use the ADB shell Cat/proc/cpuinfo to view the CPU information of the phone. It's my native ARM architecture toolchain directory structure:
Here's a sample Hello-jni project to illustrate how to pinpoint errors with the NDK's own example
#include <string.h> #include <jni.h>//hell-jni.c#ifdef __cplusplusextern "C" {#endifvoid Willcrash () {int I = 10;int y = i/0;} Jniexport jint jnicall jni_onload (javavm* vm, void* reserved) {Willcrash (); return jni_version_1_4;} Jstringjava_com_example_hellojni_hellojni_stringfromjni (jnienv* env, jobject thiz) {//Omit implementation logic here ... } #ifdef __cplusplus} #endif
Line 7th defines a Willcrash function that has an illegal operation in addition to 0, which causes the program to crash. The 13th line of the Jni_onload function calls Willcrash, which is called back after Java loads the. So file, which means the program starts crashing. Here is the log that is printed after running the program:
01-01 17:59:38.246:D/DALVIKVM (20794): late-enabling checkjni01-01 17:59:38.246:i/activitymanager (1185): Start proc Com.example.hellojni for Activity com.example.hellojni/. hellojni:pid=20794 uid=10351 gids={50351, 1028, 1015}01-01 17:59:38.296:I/DALVIKVM (20794): Enabling JNI app Bug Workarou NDS for Target SDK version 3...01-01 17:59:38.366:D/DALVIKVM (20794): Trying to load LIB/DATA/APP-LIB/COM.EXAMPLE.HELLOJN i-1/libhello-jni.so 0x422a4f5801-01 17:59:38.366:D/DALVIKVM (20794): Added gkfx lib/data/app-lib/ com.example.hellojni-1/libhello-jni.so 0x422a4f5801-01 17:59:38.366:a/libc (20794): Fatal signal 8 (SIGFPE) at 0X0000513A (code=-6), Thread 20794 (xample.hellojni) 01-01 17:59:38.476:i/debug (253): pid:20794, tid:20794, name:xample . Hellojni >>> Com.example.hellojni <<<01-01 17:59:38.476:i/debug (253): Signal 8 (SIGFPE), code-6 (si_ Tkill), fault addr 0000513a01-01 17:59:38.586:i/debug (253): R0 00000000 R1 0000513a R2 00000008 R3 0000000001-01 1 7:59:38.586:i/debug (253): R4 00000008 R5 0000000d R6 0000513a R7 0000010c01-01 17:59:38.586:i/debug (253): R8 75226d R9 00000000 SL 417c5c38 FP bedbf13401-01 17:59:38.586:i/debug (253): IP 41705910 sp bedbf0f0 lr 4012e169 pc 4 013D10C CPSR 000f0010//omitted partial log ... 01-01 17:59:38.596:i/debug (253): backtrace:01-01 17:59:38.596:i/debug (253): #00 pc 0002210c/system/lib/libc.so (t GKILL+12) 01-01 17:59:38.596:i/debug (253): #01 pc 00013165/system/lib/libc.so (pthread_kill+48) 01-01 17:59:38.596: I/debug (253): #02 pc 00013379/system/lib/libc.so (raise+10) 01-01 17:59:38.596:i/debug (253): #03 pc 00000e80 /data/app-lib/com.example.hellojni-1/libhello-jni.so (__aeabi_idiv0+8) 01-01 17:59:38.596:i/debug (253): #04 pc 00000 Cf4/data/app-lib/com.example.hellojni-1/libhello-jni.so (willcrash+32) 01-01 17:59:38.596:i/debug (253): #05 pc 0000 0d1c/data/app-lib/com.example.hellojni-1/libhello-jni.so (jni_onload+20) 01-01 17:59:38.596:i/debug (253): #06 pc 00052eb1/system/lib/libdvm.so (Dvmloadnativecode (char const*, object*, char**) +468) 01-01 17:59:38.596:i/debu G (253): #07 pc 0006a62d/system/lib/libdvm.so01-01 17:59:38.596:i/debug (253)://Omit partial log ... 01-01 17:59:38.596:i/debug (253): stack:01-01 17:59:38.596:i/debug (253): bedbf0b0 71b17034/system/lib/libsech ook.so01-01 17:59:38.596:i/debug (253): bedbf0b4 7521ce28 01-01 17:59:38.596:i/debug (253): Bedbf0b8 71b17030/system/lib/libsechook.so01-01 17:59:38.596:i/debug (253): BEDBF0BC 4012c3cf/system/lib/libc.so (DLF REE+50) 01-01 17:59:38.596:i/debug (253): bedbf0c0 40165000/system/lib/libc.so01-01 17:59:38.596:i/debug (253): Omit partial log ... 01-01 17:59:38.736:w/activitymanager (1185): Force finishing Activity com.example.hellojni/. Hellojni
Log Analysis:
Line 3rd starts the app, line 5th tries to load the so in the application Data directory, and line 6th generates a fatal error when loading the so file, and the 7th line fatal signal 8 hints that this is a fatal error, the signal is issued by Linux, Signal 8 means that the floating-point arithmetic is abnormal, it should be done in the Willcrash function in addition to the 0 operation produced. The following focuses on the 15th row of backtrace logs, backtrace logs can be considered as the stack information of the JNI call, the "#两位数字 PC" begins with the BackTrace log. Note that line 20th and line 21 are our own compiled so file and defined two functions, where an exception is thrown, causing the program to crash .
01-01 17:59:38.596:i/debug (253): #04 pc 00000CF4 /data/app-lib/com.example.hellojni-1/ Libhello-jni.so (willcrash+32) 01-01 17:59:38.596:i/debug (253): #05 pc 00000d1c /data/app-lib/ Com.example.hellojni-1/libhello-jni.so (JNI_ONLOAD+20)
began to have some clues, but the specific collapse in the position of the two functions, we are not sure, if the function code is less good check, if more complex words, look up also laborious. This is the time to rely on the NDK to provide us with the tools toprecise positioning. Before that, let's take a note of the assembly instruction address that let the program crash,Willcrash: 00000cf4,jni_onload:00000d1c
Method 1: Use Arm-linux-androideabi-addr2line to locate the error location
Take the ARM architecture CPU as an example and execute the following command:
/users/yangxin/documents/devtoos/java/android-ndk-r9d/toolchains/arm-linux-androideabi-4.8/prebuilt/darwin-x86 _64/bin/arm-linux-androideabi-addr2line-e/users/yangxin/documents/devtoos/java/android-ndk-r9d/samples/ hello-jni/obj/local/armeabi-v7a/libhello-jni.so 00000CF4 00000d1c
-e: Specify the so file path
0000CF4 0000d1c: Assembly instruction Address of error
The results are as follows:
is not pleasantly surprised to see the results we want, respectively, in the HELLO-JNI.C 10 and 15 row of the wrong, and then go back to see the source of HELLO-JNI.C,15 lines of jni_onload function within the call Willcrash functions, Line 10th does the crash caused by an operation other than 0.
Method 2: Use Arm-linux-androideabi-objdump to locate faulty function information
In the first way, through Addr2lin has gotten to the location of the code error, but do not know the function of the context information, it seems a little less "perfect" for me to pursue the ultimate, this is obviously not enough, let's look at how to locate the function information.
First, use the following command to export the function table information for so:
/users/yangxin/documents/devtoos/java/android-ndk-r9d/toolchains/arm-linux-androideabi-4.8/prebuilt/darwin-x86 _64/bin/arm-linux-androideabi-objdump-s-d/users/yangxin/documents/devtoos/java/android-ndk-r9d/samples/ hello-jni/obj/local/armeabi-v7a/libhello-jni.so > Users/yangxin/desktop/dump.log
In the generated ASM file, locate the two wrong assembly instruction addresses that we started to locate (search for CF4 in the file or Willcrash can be found), as shown in:
In this way, you can also find out which function the two wrong pointer addresses are in.
Way 3:ndk-stack
If you feel that the above method is too cumbersome, ndk-stack can help you reduce the number of steps, directly to the location of the code error.
Real-time Analytics logs:
Use ADB to get the log of the Logcat and pass the pipeline output to the Ndk-stack analysis and specify the so file location that contains the symbol table. If your program contains multiple CPU architectures, you need to choose a different CPU architecture directory based on the CPU type of your phone. Take the ARMV7 architecture as an example and execute the following command:
ADB Logcat | ndk-stack-sym/users/yangxin/documents/devtoos/java/android-ndk-r9d/samples/hello-jni/obj/local/armeabi-v7a
when the program occurs crash, the following information is output:
pid:22654, tid:22654, Name:xample.hellojni >>> com.example.hellojni <<<signal 8 (SIGFPE), code-6 (S I_tkill), fault addr 0000587eStack frame #00 pc 0002210c/system/lib/libc.so (tgkill+12) Stack frame #01 pc 00013165/s Ystem/lib/libc.so (pthread_kill+48) stack frame #02 pc 00013379/system/lib/libc.so (raise+10) stack frame #03 pc 00000e8 0/data/app-lib/com.example.hellojni-1/libhello-jni.so (__aeabi_idiv0+8): Routine __aeabi_idiv0 at/s/ndk-toolchain/ src/build/. /gcc/gcc-4.6/libgcc/. /gcc/config/arm/lib1funcs.asm:1270stack frame #04 pc 00000cf4/data/app-lib/com.example.hellojni-1/libhello-jni.so ( WILLCRASH+32): Routine willcrash at/users/yangxin/documents/devtoos/java/android-ndk-r9d/samples/hello-jni/jni/ Hello-jni.c:10stack frame #05 pc 00000d1c/data/app-lib/com.example.hellojni-1/libhello-jni.so (JNI_OnLoad+20): Routine Jni_onload AT/USERS/YANGXIN/DOCUMENTS/DEVTOOS/JAVA/ANDROID-NDK-R9D/SAMPLES/HELLO-JNI/JNI/HELLO-JNI.C : 15Stack frame #06 pc 00052eb1/system/lib/libdvm.so (Dvmloadnativecode (char const*, object*, char**) +468) Stack frame #07 pc 0006a62d/system/lib/li Bdvm.so
Lines 7th and 8th print out the error location in the source file, just as the addr2line results.
Get log re-analysis first:
This approach is similar to the one above, except that the source of the log is not the same. For apps or games to test the test department, the tester discovers crash, saves the log file with ADB Logcat, and sends it to the programmer for analysis through the Ndk-stack command. The operation flow is as follows:
ADB logcat > Crash.logadb logcat | NDK-STACK-SYM/USERS/YANGXIN/DOCUMENTS/DEVTOOS/JAVA/ANDROID-NDK-R9D/SAMPLES/HELLO-JNI/OBJ/LOCAL/ARMEABI-V7A- Dump Crash.log
The result is the same as the above method.
Android NDK development Crash error targeting