Android中Crash Debug技巧

工作中经常会遇到Android中Crash的情况,之前没有一个很清晰的思路,现在总结一下:

一般情况下,Android中发生了Crash,会以"beginning of crash"为开头,记录crash发生的相关信息,比如是哪个进程(pid)发生的crash,如下所示

复制代码
--------- beginning of crash
08-02 17:11:45.761 10549 10655 F libc    : Fatal signal -1447396355 (?), code -1862269955 (? from pid -1459396616, uid -145) in tid 10655 (Runner: gl_5_hi), pid 10549 (50005.corporate)
08-02 17:11:45.761   938   983 I libPowerHal: [perfLockRel] hdl:60244, idx:4
08-02 17:11:45.761   938   983 I libPowerHal: [PD] fpsgo update cmd:1408300 param:0

因此,从adb logcat的角度判断是否发生了crash,在log中搜索"beginning of crash"则可以,如果搜索到了,就证明该进程发生了crash。

那么如何debug呢?需要看log中的crash这部分的log有没有记录下backtrace

1.crash记录了backtrace

直接搜"backtrace",会看到类似下面的log片段:

复制代码
07-08 08:33:43.062  2091  2091 F DEBUG   : Cmdline: /vendor/bin/hw/rild -l /vendor/lib64/libquectel-ril.so
07-08 08:33:43.062  2091  2091 F DEBUG   : pid: 2087, tid: 2087, name: rild  >>> /vendor/bin/hw/rild <<<
07-08 08:33:43.062  2091  2091 F DEBUG   : uid: 0
07-08 08:33:43.062  2091  2091 F DEBUG   : tagged_addr_ctrl: 0000000000000001
07-08 08:33:43.062  2091  2091 F DEBUG   : signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0
07-08 08:33:43.062  2091  2091 F DEBUG   : Cause: null pointer dereference
07-08 08:33:43.062  2091  2091 F DEBUG   :     x0  0000007038a8afa8  x1  0000007fd7cd33d8  x2  0000000000000000  x3  0000007fd7cd343a
07-08 08:33:43.062  2091  2091 F DEBUG   :     x4  0000000000000000  x5  0000000000000000  x6  726b68737473646d  x7  7f7f7f7f7f7f7f7f
07-08 08:33:43.062  2091  2091 F DEBUG   :     x8  3a07c997d0de8c07  x9  3a07c997d0de8c07  x10 0000007fd7cd2c08  x11 fffffffffffffffd
07-08 08:33:43.062  2091  2091 F DEBUG   :     x12 0000007fd7cd2d20  x13 00000000000000cb  x14 0000007fd7cd2ea8  x15 000000008aac1451
07-08 08:33:43.062  2091  2091 F DEBUG   :     x16 00000072ca56a530  x17 00000072ca6d3610  x18 00000072ce3e4000  x19 0000007fd7cd3438
07-08 08:33:43.062  2091  2091 F DEBUG   :     x20 0000007038aae000  x21 0000007038aaf010  x22 0000007038a86000  x23 0000007038aaf000
07-08 08:33:43.062  2091  2091 F DEBUG   :     x24 0000007fd7cd33d8  x25 0000000000000003  x26 0000005a616d9368  x27 0000000000000000
07-08 08:33:43.062  2091  2091 F DEBUG   :     x28 0000007038a8af40  x29 0000007fd7cd38a0
07-08 08:33:43.062  2091  2091 F DEBUG   :     lr  0000007038a5c76c  sp  0000007fd7cd3300  pc  0000000000000000  pst 0000000060001000
07-08 08:33:43.062  2091  2091 F DEBUG   : backtrace:
07-08 08:33:43.062  2091  2091 F DEBUG   :       #00 pc 0000000000000000  <unknown>
07-08 08:33:43.062  2091  2091 F DEBUG   :       #01 pc 000000000001b768  /vendor/lib64/libquectel-ril.so (RIL_Init+720)
07-08 08:33:43.062  2091  2091 F DEBUG   :       #02 pc 0000000000002378  /vendor/bin/hw/rild (main+804) (BuildId: e9dcddf3d5bf74361d31231eafbe6a08)
07-08 08:33:43.062  2091  2091 F DEBUG   :       #03 pc 00000000000488c8  /apex/com.android.runtime/lib64/bionic/libc.so (__libc_init+96) (BuildId: ba489d4985c0cf173209da67405662f9)

其中有三个地方需要注意:

  • Cmdline:指示代码是运行什么样的命令/应用时发生crash的,该处是运行"/vendor/bin/hw/rild -l /vendor/lib64/libquectel-ril.so"
  • Cause:指示发生Crash的原因是什么,该处是"Cause: null pointer dereference",即发生了空指针的解引用。
  • backtrace:指示调用的顺序

1.1如何debug:

1.1.1找到发生Crash的函数,然后手动在源代码中加log,一步步debug

backtrace中,对应的log中会提示是跑在哪个函数中。比如:

复制代码
07-08 08:33:43.062  2091  2091 F DEBUG   :       #01 pc 000000000001b768  /vendor/lib64/libquectel-ril.so (RIL_Init+720)

指示跑在libquectel-ril.so中的RIL_Init函数中。则我们可以检查这个RIL_Init这个函数中的代码并加log进行debug。

1.1.2利用addr2line这个工具,精准定位到哪个文件的哪一行

比如我们想定位发生crash的RIL_Init函数在哪个文件的哪一行,则可以先找到上述信息中的偏移地址"01 pc 000000000001b768"

复制代码
$ cd <Android_Source_Code>/out/target/product/<specific_product_name>/symbols/
$ find . -name libquectel-ril.so
$ cd <path_libquectel-ril.so>
$ addr2line -C -f -e libquectel-ril.so 000000000001b768

//上述命令找到symbol的位置,利用addr2line命令把偏移量转换为函数所在的文件与代码行,可以让我们知道crash在代码中的具体位置

可能会遇到"addr2line: DWARF error: invalid or unhandled FORM value"的错误,无法成功拿到正确的输出,则应该用Android Source Code中自带的addr2line工具就可以解决:

复制代码
prebuilts/clang/host/linux-x86/clang-r487747c/bin/llvm-addr2line

补充:我们发布xxxx.so文件的时候,可以连同xxxx.so.symbols一起发布,这样即使我们的编译环境更改了,也可以通过 xxxx.so.symbols 文件定位错误发生在哪一行,用法跟xxxx.so一样,以上面的命令为例,即:

复制代码
$ addr2line -C -f -e libquectel-ril.so.symbols 000000000001b768

脚本:

复制代码
exelist=(exe1 exe2)
addrlist=(addr1 addr2)

exe1=out/target/product/xxxx/symbols/vendor/lib64/egl/libGLES_mali.so
addr1=(
0000000001aa1990
0000000001926ab4
0000000001996188
0000000001ab2e1c
0000000001ab0fa0
0000000001ab1030
0000000001aaefd0

 )
exe2=out/target/product/mahakala/symbols/data/nativetest64/vendor/mali_tests64/mali_vulkan_integration_suite
addr2=(
 )

echo ${addr[*]}

for i in ${addr1[*]}; do
    llvm-addr2line -e ${exe1} 0x${i}
done



for i in ${addr2[*]}; do
    llvm-addr2line -e ${exe2} 0x${i}
done

2. crash未记录backtrace

没有backtrace意味着不知道是哪里发生了crash,这一般是由于对空指针进行解引用,导致不能记录backtrace。也就是说你只能在log里搜到"beginning of crash",而搜不到"backtrace"。这种情况需要去查找tombstone。Android的tombstone会帮助记录这些信息。

复制代码
$ adb shell
$ cd /data/tombstone/

tombstone中会记录的信息跟前面的情况一样,包含:Cmdline, Cause和backtrace。Debug方法同crash记录了backtrace的情景。

相关推荐
安东尼肉店7 小时前
Android compose屏幕适配终极解决方案
android
2501_916007477 小时前
HTTPS 抓包乱码怎么办?原因剖析、排查步骤与实战工具对策(HTTPS 抓包乱码、gzipbrotli、TLS 解密、iOS 抓包)
android·ios·小程序·https·uni-app·iphone·webview
feiyangqingyun8 小时前
基于Qt和FFmpeg的安卓监控模拟器/手机摄像头模拟成onvif和28181设备
android·qt·ffmpeg
用户20187928316712 小时前
ANR之RenderThread不可中断睡眠state=D
android
煤球王子12 小时前
简单学:Android14中的Bluetooth—PBAP下载
android
小趴菜822712 小时前
安卓接入Max广告源
android
齊家治國平天下12 小时前
Android 14 系统 ANR (Application Not Responding) 深度分析与解决指南
android·anr
ZHANG13HAO12 小时前
Android 13.0 Framework 实现应用通知使用权默认开启的技术指南
android
【ql君】qlexcel12 小时前
Android 安卓RIL介绍
android·安卓·ril
写点啥呢13 小时前
android12解决非CarProperty接口深色模式设置后开机无法保持
android·车机·aosp·深色模式·座舱