android使用ndk-stack调试JNI部分的C/C++代码

原创 2013年05月06日 11:50:18

法一:使用ndk-stack输出调用堆栈

我这里的ndk-stack位置为:/home/hwh/Android_Project/Environment/android-ndk-r8e

'ndk-stack' 是一个工具,可以将.so文件的地址映射到相应的编译此.so文件的.h/.cpp的具体地址.

举例:

我这里有2个文件SampleJNIBinder.h和SampleJNIBinder.cpp,编译后生成libSampleJNIBinder.so这个动态库。

调用此.so文件的时候,出现了如下的错误。

F/libc    ( 1783): Fatal signal 11 (SIGSEGV) at 0x00000000 (code=1)
I/DEBUG   (  115): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
I/DEBUG   (  115): Build fingerprint: 'intel/mfld_dv10/mfld_dv10:4.0.4/IMM76D/release.20130301:eng/dev-keys'
I/DEBUG   (  115): pid: 1783, tid: 1783  >>> com.example.apis <<<
I/DEBUG   (  115): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 00000000
I/DEBUG   (  115):  eax bfb0eb4e  ebx 5e35753c  ecx 00000000  edx 5f200019
I/DEBUG   (  115):  esi bfb0eb48  edi 08b20db0
I/DEBUG   (  115):  xcs 00000073  xds 0000007b  xes 0000007b  xfs 00000000 xss 0000007b
I/DEBUG   (  115):  eip 5e35464a  ebp bfb0eb98  esp bfb0eb30  flags 00010206
I/DEBUG   (  115):     #00  eip: 0000264a  /data/data/com.example.apis/lib/libSampleJNIBinder.so
I/DEBUG   (  115):     #01  eip: 0007a959  /system/lib/libdvm.so (_Z16dvmCallJNIMethodPKjP6JValuePK6MethodP6Thread+0x1e9)

红色部分的代码是错误的位置,对于eip这个寄存器里面的值:0000264a,我们找不到任何线索。

但是可以通过'adb logcat > foo.txt' 将错误信息导出到当前目录的foo.txt文件中。

然后通过:'./ndk-stack -sym /home/<user-name>/workspace_android/HHDemos/obj/local/x86 -dump foo.txt'这个命令可以解析

这样返回的结果为:

huanghao@Mtn:~/Projects/AndroidNDK$ ./ndk-stack -sym /home/huanghao/workspace_android/HHDemos/obj/local/x86 -dump foo.txt
********** Crash dump: **********
Build fingerprint: 'intel/mfld_dv10/mfld_dv10:4.0.4/IMM76D/release.20130301:eng/dev-keys'
pid: 2319, tid: 2319  >>> com.example.apis <<<
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 00000000
Stack frame #00  eip: 0000264a  /data/data/com.example.apis/lib/libSampleJNIBinder.so: 
Routine Java_com_example_apis_JNI_SampleJNIBinder_JTCGetStringFromJNI 
in /home/huanghao/workspace_android/HHDemos/jni/SampleJNIBinder/SampleJNIBinder.cpp:35
Stack frame #01  eip: 0007a959  /system/lib/libdvm.so (_Z16dvmCallJNIMethodPKjP6JValuePK6MethodP6Thread+0x1e9)
Stack frame #02  eip: 00063ba1  /system/lib/libdvm.so (_Z21dvmCheckCallJNIMethodPKjP6JValuePK6MethodP6Thread+0x41)
Stack frame #03  eip: 00085d2d  /system/lib/libdvm.so (_Z22dvmResolveNativeMethodPKjP6JValuePK6MethodP6Thread+0x13d)
Stack frame #04  eip: 00125d34  /system/lib/libdvm.so
Stack frame #05  eip: 0003f466  /system/lib/libdvm.so (_Z11dvmMterpStdP6Thread+0x46)
Stack frame #06  eip: 0003bb06  /system/lib/libdvm.so (_Z12dvmInterpretP6ThreadPK6MethodP6JValue+0xd6)
Stack frame #07  eip: 000a81fa  /system/lib/libdvm.so (_Z15dvmInvokeMethodP6ObjectPK6MethodP11ArrayObjectS5_P11ClassObjectb+0x51a)

这里我们很容易看出SampleJNIBinder.cpp:35有错误,那么我们找到那部分的代码:

如下

JNIEXPORT jstring JNICALL
Java_com_example_apis_JNI_SampleJNIBinder_JTCGetStringFromJNI(JNIEnv *env, jobject thiz) {
	int * p = NULL;
	*p = 100; //这里是35行

	int n1 = true;
	int n2 = false;
	LogPrintf("jni-hh", "n1: %d, n2: %d", n1, n2);
这里是一个给空指针赋值的错误,很简单吧。



好了,需要总结一下。


使用'ndk-stack'查看backstack信息的步骤如下:


1. 进入Android-NDK的路径

我这里为:/home/<user-name>/Projects/AndroidNDK

$ cd /home/<user-name>/Projects/AndroidNDK

2.导出logcat信息到foo.txt中

$ adb logcat > foo.txt

3.通过GPF的地址和.so文件 获取实际在.cpp文件错误的地址

例子:<user-name>@Mtn:~/Projects/AndroidNDK$ ./ndk-stack -sym <.so文件目录> -dump foo.txt

我的用法:<user-name>@Mtn:~/Projects/AndroidNDK$ ./ndk-stack -sym /home/<user-name>/workspace_android/HHDemos/obj/local/x86 -dump foo.txt


当然,我们也可以将上面2句合并成一句:

如下:

$ adb logcat | $NDK_HOME/ndk-stack -sym /home/hwh/Android_Project/Code/HHDemos/obj/local/x86


注意:

1. 此时我们的操作路径是AndroidSDK目录, foo.txt也在该目录。

2.上面的x86是你平板的CPU决定了,如果你的平板是ARM的CPU那么应该改为:armeabi了。


但是我公司同事的机子adb logcat好像自动就将错误的地址转换为.cpp文件中的地址,可能需要具体配置。

暂时不清楚,我弄好了的话就在这里添加。。。。。;



法二:使用i686-linux-android-addr2line输出调试信息

下面是该文件的路径

/home/hwh/Android_Project/Environment/android-ndk-r8e/toolchains/x86-4.6/prebuilt/linux-x86/bin

其中android-ndk-r8e是我在ndk官网下载的android-ndk-r8e-linux-x86.tar.bz2解压缩后的文件夹。

用法:

$ ./i686-linux-android-addr2line -f -e /home/hwh/Android_Project/Code/HHDemos/obj/local/x86/libSampleJNIBinder.so 0000415C

总结一下就是:

$ ./i686-linux-android-addr2line -f -e <.so文件的pathName> <出错的地址>


输出结果为:

hwh@Mountain:~/Android_Project/Environment/android-ndk-r8e/toolchains/x86-4.6/prebuilt/linux-x86/bin$ ./i686-linux-android-addr2line -f -e 
/home/hwh/Android_Project/Code/HHDemos/obj/local/x86/libSampleJNIBinder.so 0000415C
Java_com_example_apis_JNI_SampleJNIBinder_JTCGetStringFromJNI
/home/hwh/Android_Project/Code/HHDemos/jni/SampleJNIBinder/SampleJNIBinder.cpp:35

i686-linux-android-addr2line
返回的信息为:

1. 出错的函数

2. 出错地点在该.cpp文件的行数




/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Android ndk-stack tool
----------------------

Introduction:
-------------

This document describes the 'ndk-stack' tool that is distributed withthe Android NDK, since release r6.

Overview:
---------

'ndk-stack' is a simple tool that allows you to filter stack traces as theyappear in the output of 'adb logcat' and replace any address inside a shared
library with the corresponding : values.

In a nutshell, it will translate something like:

    I/DEBUG   (   31): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
    I/DEBUG   (   31): Build fingerprint: 'generic/google_sdk/generic/:2.2/FRF91/43546:eng/test-keys'
    I/DEBUG   (   31): pid: 351, tid: 351  %gt;%gt;%gt; /data/local/ndk-tests/crasher <<<
    I/DEBUG   (   31): signal 11 (SIGSEGV), fault addr 0d9f00d8
    I/DEBUG   (   31):  r0 0000af88  r1 0000a008  r2 baadf00d  r3 0d9f00d8
    I/DEBUG   (   31):  r4 00000004  r5 0000a008  r6 0000af88  r7 00013c44
    I/DEBUG   (   31):  r8 00000000  r9 00000000  10 00000000  fp 00000000
    I/DEBUG   (   31):  ip 0000959c  sp be956cc8  lr 00008403  pc 0000841e  cpsr 60000030
    I/DEBUG   (   31):          #00  pc 0000841e  /data/local/ndk-tests/crasher
    I/DEBUG   (   31):          #01  pc 000083fe  /data/local/ndk-tests/crasher
    I/DEBUG   (   31):          #02  pc 000083f6  /data/local/ndk-tests/crasher
    I/DEBUG   

版权声明:本文为博主原创文章,未经博主允许不得转载。

Android NDK开发Crash错误定位

在Android开发中,程序Crash分三种情况:未捕获的异常、ANR(Application Not Responding)和闪退(NDK引发错误)。其中未捕获的异常根据logcat打印的堆栈信息很...
  • xyang81
  • xyang81
  • 2015年01月01日 19:50
  • 25136

ndk-stack的使用

问题及解决方法 jni开发过程中native崩溃log样式如下 F/libc (12115): Fatal signal 11 (SIGSEGV) at 0x37413144 (code=1),...

ndk-stack的使用

这是对ndk-stack使用文档的翻译,文档所在的路径是:\android-ndk-r9d\docs\NDK-STACK.html 介绍: 这篇文档描述的是ndk-stack工具,从R6版本起...

使用 ndk-stack 寻找Android程序Crash的原因

开篇废话很久不研究cocos2d-x了,也不知道如今发展如何了。先前写游戏时会分几块。 主要功能代码都是用C++编写,编辑器用vs android平台相关功能使用 Java 编写,编辑器用 Eclip...

分析安卓ANR tombstone使用ndk-stack addr2line

转自https://my.oschina.net/u/2424583/blog/535296 刷机过程中会碰到很多crash问题,此时安卓会在/data/tombstones目录下保存9个s...

ndk-stack定位不出崩溃代码行的问题

NDK开发包中自带的NDK-STACK工具可以

【玩转cocos2d-x之三十八】如何使用NDK-STACK tool来恢复Cocos2d-x安卓错误堆栈信息

很多童鞋在纠结在Cocos2d-x中安卓项目如何调试JNI部分的C++代码,在吃完2个茶叶蛋后我决定放大招。。。 本文翻译自:http://www.cocos2d-x.org/forums/6/to...

ndk-stack 学习使用

最近在mac上编译android 版本,各种崩溃让人蛋疼,网上学习了下ndk-stack使用方法。...

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

ndk-stack使用

1. so库要改成debug模式,在application.apk下加入APP_OPTIM := debug,然后重新编译so库 2 cmd下进入ndk的安装目录,必须进入 3. 执行命令 ad...
  • jdksym
  • jdksym
  • 2016年04月05日 21:45
  • 557
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:android使用ndk-stack调试JNI部分的C/C++代码
举报原因:
原因补充:

(最多只允许输入30个字)