NDK-LLDB使用及Crash定位(addr2line,objdump, ndk-stack)

LLDB简介

官网地址:http://lldb.llvm.org/index.html。LLDB是下一代,高性能的调节器。是Mac OS X上Xcode默认的调节器,支持在电脑 ,IOS设备,模拟器上调试C,Objective-C 和C++。

LLDB简单使用

在AndroidStudio使用前确保已安装LLDB,Settings->Appearance&Behavior->System Settings->Android SDK->SDK Tools。在自己编写的JNI代码上打上端点,以debugger模式运行。

  • help

在LLDB窗口下输入help 可以看到所有的调试命令。

NDK-LLDB使用及Crash定位(addr2line,objdump, ndk-stack)_第1张图片

用于打印值,可以打印函数值,$*是LLDB的命名方式,$1指向结果。

NDK-LLDB使用及Crash定位(addr2line,objdump, ndk-stack)_第2张图片

  • expression

用于给对象或变量赋值。

  int[] arry = {3, 1, 5, 2};
        testDebugger(arry);
        for (int i = 0; i < arry.length; i++) {
            Log.e("TAG",arry[i]+"");
        }

在命令行中输入 expression arrays[0]=100 ,日志输出 1 , 2 , 5 , 100。

在开发中我们通常使用po 代替expression 和 print 效果一样。

  •  frame info

返回当前栈帧的详细信息。

(lldb) frame info

frame #0: 0xa4cb9092 //1 栈帧的结构地址
libnative-lib.so`::  //2 所引用的so库
Java_com_example_com_jnitest_MainActivity_testDebugger  //3调用的方法
(env=0xabea1230, instance=0xbf92889c, arr=0xbf9288a0)   //4方法各参数地址

at native-lib.cpp:178  //5 当前在类文件的行数
  • bt

打印当前虚拟机栈的信息,第一行是线程信息,frame是栈帧。

* thread #1, name = 'ple.com.jnitest', stop reason = instruction step over
  * frame #0: 0xab7d445b libart.so`art_quick_generic_jni_trampoline + 75
    frame #1: 0xab7ce3e3 libart.so`art_quick_invoke_stub + 339
   
  • image lookup --address +内存地址

通过栈帧的地址,输出栈帧的信息  

(lldb) image lookup --address 0xab7ce3e3
      Address: libart.so[0x001083e3] (libart.so..text + 80355)
      Summary: libart.so`art_quick_invoke_stub + 339
  • finish

跳过dan当前断点到方法结束 或 下一个端点。但当前antive方法后java代码不会执行。

  • Thread Return

立即返回,方法后面的代码不在执行。

  • watchpoint

监听地址内容变化

 

Crash定位

我在代码里制造一个异常

NDK-LLDB使用及Crash定位(addr2line,objdump, ndk-stack)_第3张图片

运行后在logcat中可以看到错误日志jarray为空

NDK-LLDB使用及Crash定位(addr2line,objdump, ndk-stack)_第4张图片

然而通常我们在使用第三方so库时往往很难错误定位,下面我将介绍ndkgong工具进行定位。

  • ndk-stack

1.在命令行中通过adb logcat > error.log 抓取日志。

2.运行程序。

3.Android\Sdk\ndk-bundle设置为环境变量,我将使用ndk-stack.cmd处理抓取的日志

C:\Users\i7-1>ndk-stack   
Usage: ndk-stack -sym PATH [-dump PATH]  //使用方法
Symbolizes the stack trace from an Android native crash.

//Cmake编译出的so库全地址 build/intermediatescmake\debug\obj下对应CPU的so库
  -sym PATH   sets the root directory for symbols  
//日志地址
  -dump PATH  sets the file containing the crash dump (default stdin)

See .

4.执行ndk-stack

NDK-LLDB使用及Crash定位(addr2line,objdump, ndk-stack)_第5张图片

5.寻找.cpp结尾的

Stack frame 08-22 10:58:42.743 6026-6026/? A/DEBUG:   
  #16 pc 0000806b  /data/app/com.example.com.jnitest-1/lib/x86/libnative-lib.so 
(Java_com_example_com_jnitest_MainActivity_testDebugger+91): 
Routine Java_com_example_com_jnitest_MainActivity_testDebugger 
at D:\YSHDemo\JNITest\app\src\main\cpp/native-lib.cpp:178

错误发生在native-lib.cpp的178行。

 

  • addr2line

我使用X86 模拟器。在ndk-bundleti提供了一些列工具给我们使用,比如错误定位的addr2line  , objdump.

NDK-LLDB使用及Crash定位(addr2line,objdump, ndk-stack)_第6张图片

使用方法

// -f 输出函数名
// -e 输出错误代码行数和文件路径
// xxx.so 对应出错的so文件, 在android工程obj目录下
// addr 是具体的地址
arm-linux-androideabi-addr2line -f -e xxx.so addr

输出 ?? ??:0 并不知道为啥很多时候- e -f 没有输出有用的信息。0056dde是栈帧的内存地址。

NDK-LLDB使用及Crash定位(addr2line,objdump, ndk-stack)_第7张图片

  • objdump 

反汇编动态链接库文件,objdump -S -D libc.so > my.txt

生成文件my.txt。查询位偏移地址144c的信息

NDK-LLDB使用及Crash定位(addr2line,objdump, ndk-stack)_第8张图片

你可能感兴趣的:(android,java)