场景
目前面对移动端的sdk大多以native C++的方式进行开发,这就涉及对sdk的调试,尤其是面对crash问题的调试。掌握有效的工具定位crash位置十分必要。
问题描述
一般见到的crash示例如下:
23189 23189 F DEBUG : signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x18
23189 23189 F DEBUG : Cause: null pointer dereference
23189 23189 F DEBUG : r0 00000000 r1 00000000 r2 00000001 r3 ea875be0
23189 23189 F DEBUG : r4 00000040 r5 ffffffbf r6 ea875b78 r7 fffff87f
23189 23189 F DEBUG : r8 ea875c20 r9 ea876422 r10 00000000 r11 ea877478
23189 23189 F DEBUG : ip 00000000 sp ea875ad8 lr 00000000 pc ef41ed94
23189 23189 F DEBUG :
23189 23189 F DEBUG : backtrace:
23189 23189 F DEBUG : #00 pc 00083d94 /vendor/lib/mysdk.so (BuildId: ---)
23189 23189 F DEBUG : #01 pc 001291b9 /vendor/lib/mysdk.so (BuildId: ---)
23189 23189 F DEBUG : #02 pc 00129013 /vendor/lib/mysdk.so (BuildId: ---)
我们解释一下上面的信息。 Cause: null pointer dereference :表示空指针错误。 backtrace :显示调用堆栈,其中有明确的pc 指针(00083d94 等)以及对应的动态库mysdk.so 。
理论上讲,上面的信息告诉了我们以下信息: crash的原因:空指针 crash的文件:mysdk.so crash的位置:pc 00083d94、pc 001291b9、pc 00129013 这样就可以定位问题了。
那么问题来了:我怎么看懂pc指针呢?
工具
显然pc指针不是直接给人看的,我们想看到代码出bug的位置。 ndk中有以下两个工具可以将上面的错误信息翻译为出错的函数位置、代码行数等信息。
1. addr2line 2. ndk-stack
接下来以ndk17c介绍两个工具的使用。
addr2line
addr2line在ndk17c中的文件位置:
android-ndk-r17c\toolchains\aarch64-linux-android-4.9\prebuilt\windows-x86_64\bin\aarch64-linux-android-addr2line.exe
使用说明如下:
Usage: android-ndk-r17c\toolchains\aarch64-linux-android-4.9\prebuilt\windows-x86_64\bin\aarch64-linux-android-addr2line.exe [option(s)] [addr(s)]
Convert addresses into line number/file name pairs.
If no addresses are specified on the command line, they will be read from stdin
The options are:
@<file> Read options from <file>
-a --addresses Show addresses
-b --target=<bfdname> Set the binary file format
-e --exe=<executable> Set the input file name (default is a.out)
-i --inlines Unwind inlined functions
-j --section=<name> Read section-relative offsets instead of addresses
-p --pretty-print Make the output easier to read for humans
-s --basenames Strip directory names
-f --functions Show function names
-C --demangle[=style] Demangle function names
-h --help Display this information
-v --version Display the program's version
一般性使用示例:
aarch64-linux-android-addr2line.exe -C -f -e build\Android\libs\armeabi-v7a\mysdk.so 00083d94 001291b9
其中,-C-f 输出错误代码所在的函数,-e 输出错误所在的代码行号, mysdk.so 为sdk库文件,00083d94 001291b9 是需要转换的堆栈错误信息地址,多个pc之间使用空格。 其中代码行号在一些不带调试信息的so中将会输出??:? ,这是由于调试信息确实导致的,需要修改编译方式。
ndk-stack
ndk-stack在ndk17c中的文件位置:
android-ndk-r17c\ndk-stack
使用说明如下:
Usage: ndk-stack -sym PATH [-dump PATH]
Symbolizes the stack trace from an Android native crash.
-sym PATH sets the root directory for symbols
-dump PATH sets the file containing the crash dump (default stdin)
See <https://developer.android.com/ndk/guides/ndk-stack.html>.
一般性使用示例:
android-ndk-r17c\ndk-stack -sym build\Android\obj\local\armeabi-v7a -dump .\crash.log
其中build\Android\obj\local\armeabi-v7a 为带有符号的动态库目录,crash.log 为crash的信息。
篇幅关系,就不列举执行结果了。
总结
希望以上内容可以帮到面对crash而不知所措的同学。
|