android native crash日志解析
版权申明:未经允许请勿转载。转载前请先联系作者(hello@yeshen.org)
背景是上一篇博客遇到了问题。crashlytics的解析符号没解析出来,./gradlew crashlyticsUploadSymbolsRelease
执行了也没起什么作用。
嗯,这个问题先从 so
库的一些背景知识说起。
什么是 so
http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html
so 就是share-library。先看怎么build出so吧。
Makefile
all : test.o main.o out libtest oouttest.o: test.cc test.h g++ -c test.ccmain.o : main.cc test.h g++ -c main.cclibtest : test.o g++ -shared -o libtest.so test.oout: main.o libtest.so g++ -o out main.o libtest.soclean: rm -f *.o *.so out oout
main.cc
#include #include "test.h"int main(int argc, const char *argv[]){ test t(22); t.increase(); printf("Received: %i", t.getFlag());}
test.cc
#include #include "test.h"test::test(unsigned int flag) : _flag(flag){}test::~test(){}unsigned int test::getFlag() const{ return _flag;}void test::increase(){ _flag += 1;}
test.h
#ifndef TEST_H#define TEST_H#include class test{private: unsigned int _flag;public: test(unsigned int flag); ~test(); void increase(); unsigned int getFlag() const;};#endif
关键的代码编译代码就只有一行
g++ -shared -o libtest.so test.o
也就是它把多个o文件合并成一个。
什么是 symbols
crash日志中,最重要的是符号,是代码的行数和对应的记录。
可以怎么看呢?
make nm -C out
执行之后,就可以看到具体的函数信息了。
0000000100000f68 s GCC_except_table0 U __Unwind_Resume0000000100000f00 T test::increase()0000000100000e90 T test::test(unsigned int)0000000100000e70 T test::test(unsigned int)0000000100000ed0 T test::~test()0000000100000ec0 T test::~test()0000000100000ef0 T test::getFlag() const U std::terminate()0000000100000e60 t ___clang_call_terminate U ___cxa_begin_catch U ___gxx_personality_v00000000100000000 T __mh_execute_header0000000100000db0 T _main U _printf U dyld_stub_binder
当然我们对外的时候,不能把symbols都打进包里,所以这个时候,会
strip out
在看一下
U __Unwind_Resume U std::terminate() U ___cxa_begin_catch U ___gxx_personality_v00000000100000000 T __mh_execute_header U _printf U dyld_stub_binder
可以看到,很多信息都被strip
掉了。
在android平台上,不是直接用上面的 g++、strip。因为具体手机平台和PC的平台的环境是不同的,要用交叉编译。也就是用对应平台的gcc去编译。android的话,在 android/sdk/ndk-bundle/toolchains
下面。
adb logcat 日志的解析方法
参考: https://developer.android.com/ndk/guides/ndk-stack?hl=zh-CN
借助 ndk-stack
工具,您可以使用符号来表示来自 adb logcat
的堆栈轨迹或 /data/tombstones/
中的 tombstone
。该工具会将共享库内的任何地址替换为源代码中对应的
,从而简化调试流程。
例如,它可将下面的代码:
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 >>> /data/local/ndk-tests/crasher <<
转换为更具可读性的代码:
********** Crash dump: **********Build fingerprint: 'generic/google_sdk/generic/:2.2/FRF91/43546:eng/test-keys'pid: 351, tid: 351 >>> /data/local/ndk-tests/crasher <<
用法
要使用 ndk-stack,您首先要有一个包含未剥离版应用共享库的目录。如果您使用 ndk-build,则可在 $PROJECT_PATH/obj/local/ 中找到这些未剥离版共享库,其中 是您设备的 ABI。
使用此工具的方式有两种。您可以将 logcat 文本作为直接输入馈送到程序。例如:
adb logcat | $NDK/ndk-stack -sym $PROJECT_PATH/obj/local/armeabi-v7a
您也可以使用 -dump 选项将 logcat 指定为输入文件。例如:
adb logcat > /tmp/foo.txt$NDK/ndk-stack -sym $PROJECT_PATH/obj/local/armeabi-v7a -dump foo.txt
该工具会在开始解析 logcat 输出时查找第一行星号。例如:
*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
更多相关文章
- SpringBoot 2.0 中 HikariCP 数据库连接池原理解析
- tcping测试服务器TCP端口
- Android(安卓)Fragment 基本了解
- Android(安卓)设置全屏和无标题模式
- Android关机和重启的调用代码
- Android(安卓)自定义弹性ListView控件实例代码(三种方法)
- [Android1.5]DigitalClock自定义日期输出格式
- 使用AIDL实现进程间的通信
- Android(安卓)Device Monitor官方替代工具