Google breakpad编译过程
1、环境
为了能够获取android下C/C++的crash log, 采用google breakpad来生成dmp文件, breakpad的下载地址:
svn co http://google-breakpad.googlecode.com/svn/trunk/ google-breakpad
操作系统使用的是Mac OS X, 将breakpad编译进cocos2d-x 3.3环境下的工程, 将在android手机设备中获取相应的dmp文件。
2、准备
因为cocos2d-x 3.3在编译android环境时需要的NDK版本必须是r9版本, 而breakpad最新版必须要求r10c, 所以方案有两种:
(1) 下载breakpad之前的版本, 不需要r10c的版本, 找到一个它svn的版本为r1216
(2) 将cocos2d-x 的NDK版本改成r10c, 解决cocos2d-x编译android的问题, 可参考: [1]
在这里选择第一个方案, 那么下载breakpad的代码:
svn co http://google-breakpad.googlecode.com/svn/trunk/ -r 1216 google-breakpad-1216
3、mac下配置linux环境
由于Google Breadpad处理Android崩溃日志时需要Linux环境, 而借助vagrant可以非常方便地在Mac使用Ubuntu环境
安装brew cask
brew install brew-cask
安装vagrant与virtualbox
brew cask install vagrant
brew cask install virtualbox
下载ubuntu的box
mkdir ubuntu //创建ubuntu目录
cd ubuntu //进入ubuntu
wget http://files.vagrantup.com/precise32.box //用wget下载box, 这里是下载的32的, 也可以下载64位的
创建与初始化ubuntu box
vagrant box add ubuntu ./precise32.box
vagrant init ubuntu
ssh登录
vagrant up //启动ubuntu
vagrant ssh //ssh
4、编译
在ubuntu中下载资源
svn co http://google-breakpad.googlecode.com/svn/trunk/ -r 1216 google-breakpad-1216
编译
cd google-breakpad-1216
./configure
make
执行完上面的命令后将会在
google-breakpad-1216/src/processor 目录下生成minidump_stackwalk 工具,用于导出crash log.
google-breakpad-1216/src/tools/linux/dump_syms 目录下生成 dump_syms工具,用于导出符号文件。
google-breakpad-1216/src/client/linux 目录下生成 libbreakpad_client.a
5、集成
集成的方式有两种, 参考breakpad目录下README.ANDROID。
(1) 编译成成.a库文件, 直接用加入.a的方式来集成
(2) 使用import-module的方式, 让ndk来编译
这里采用第(2)种方式:
(1) mac下将下载下来的breakpad源码拷贝到cocos2d-x工程proj.android目录下
(2) 在jni/Android.mk中加入代码
LOCAL_STATIC_LIBRARIES += breakpad_client
$(call import-module, google-breakpad-1216/android/google_breakpad)
(3) 在main.cpp 中加入代码
#include "client/linux/handler/exception_handler.h"
#include "client/linux/handler/minidump_descriptor.h"
//breakpad
bool DumpCallback(const google_breakpad::MinidumpDescriptor& descriptor,
void* context,
bool succeeded) {
LOGD("Dump path: %s\n", descriptor.path());
return succeeded;
}
void cocos_android_app_init (JNIEnv* env, jobject thiz) {
LOGD("cocos_android_app_init");
AppDelegate *pAppDelegate = new AppDelegate();
// 这里是定义dump文件的保存位置,保存至sd卡根目录
google_breakpad::MinidumpDescriptor descriptor("/mnt/sdcard/breakpadLog");
google_breakpad::ExceptionHandler *handler = new google_breakpad::ExceptionHandler(descriptor, NULL, DumpCallback, NULL, true, -1);
...
}
此时, 就可以编译android cocos2d-x工程了, 生成的crash文件放在 /mnt/sdcard/breakpadLog下, 文件后缀为dmp
6、解析dmp文件
从android设备中取出dmp文件, 放到一个目录下, 假设此目录为Dump, 然后拷贝proj.android/obj/local/armeabi/libxxx.so到Dump下
切换到ubuntu下, 拷贝mac上的Dump目录到ubuntu下
scp -r [email protected]:~/Dump ./ // user指mac的用户名, @后面的ip为mac的ip, :后面为mac下Dump的路径, ./指保存到ubuntu下的目录路径
scp的命令参考[3]
拷贝命令dump_syms和minidump_stackwalk到Dump目录下
cp google-breakpad-1216/src/tools/linux/dump_syms/dump_syms ./Dump
cp google-breakpad-1216/src/processor/minidump_stackwalk ./Dump
生成sym文件
cd Dump
./dump_syms libxxx.so > libxxx.so.sym
查看libxxx.so.sym文件内容, 头部会有, BB0351B14DDA42A6D36FA6EA358B49D50不一样
MODULE Linux arm EB0351B143DA42A6D55FA6EA358B49D50 libxxx.so
继续执行命令
mkdir -p symbols/libxxx.so/BB0351B14DDA42A6D36FA6EA358B49D50/
mv libxxx.so.sym symbols/libxxx.so/BB0351B14DDA42A6D36FA6EA358B49D50/
这样就导出了符号文件,接下来导出崩溃堆栈
$ ./minidump_stackwalk xxxx-xxxx-xxxxx-xxxx.dmp symbols > crashed.log
确保dmp文件和symbols目录是同级的。
查看crashed.log, 类似下面这段
Thread 12 (crashed)
0 libcocos2dcpp.so!AppDelegate::applicationDidFinishLaunching() [AppDelegate.cpp : 44 + 0x4]
r0 = 0x00000000 r1 = 0x00000001 r2 = 0x5a18a8e8 r3 = 0x5a18a6b8
r4 = 0x56ea70f0 r5 = 0x5c5c47b8 r6 = 0x00000000 r7 = 0x59f59f24
r8 = 0x5e5b6c58 r9 = 0x59f59f1c r10 = 0x5c5c47c8 r12 = 0x00000000
fp = 0x5e5b6b60 sp = 0x5e5b6b18 lr = 0x5dc2d3e4 pc = 0x5db3e37c
定位到是 AppDelegate.cpp的44行崩溃。
如果没有符号文件,比如这样导出crash log
$ ./minidump_stackwalk xxxx-xxxx-xxxxx-xxxx.dmp > crashed.log
crashed.log 中的信息就是这样了
Thread 12 (crashed)
0 libcocos2dcpp.so + 0x2ee37c
r0 = 0x00000000 r1 = 0x00000001 r2 = 0x5a18a8e8 r3 = 0x5a18a6b8
r4 = 0x56ea70f0 r5 = 0x5c5c47b8 r6 = 0x00000000 r7 = 0x59f59f24
r8 = 0x5e5b6c58 r9 = 0x59f59f1c r10 = 0x5c5c47c8 r12 = 0x00000000
fp = 0x5e5b6b60 sp = 0x5e5b6b18 lr = 0x5dc2d3e4 pc = 0x5db3e37c
这个时候我们就要使用NDK中的arm-linux-androideabi-addr2line 工具定位崩溃了
arm-linux-androideabi-addr2line 路径为
$NDK_ROOT/toolchains/arm-linux-androideabi-4.8/prebuilt/darwin-x86/bin/arm-linux-androideabi-addr2line
usage: arm-linux-androideabi-addr2line -C -f -e <库路径> <内存地址>
arm-linux-androideabi-addr2line -C -f -e project/test/obj/local/armeabi/aa.so 0003deb4
这时候就可以在终端中看到是 aa.so中的哪个文件的那一行发生异常了,接下来可以使用日志追踪有问题的代码了。
7、待解决的问题
(1) 无法在mac下查看和解析crash log
(2) breakpad使用的版本不是最新的, 需解决cocos2d-x在NDK r10c下编译出错的问题
(3) breakpad直接编译成.a的方式未成功, 虽然用ndk编译后也是生成.a, 但是clean后又需重新编译
(4) crash log上传到服务器的问题
(5) breakpad在iOS下也可以使用, 没有兼容
参考
[1] 使用NDK r10构建Cocosd-x v3.2时编译和链接错误的解决办法
[2] 在Mac下安装使用Vagrant
[3] scp命令
[4] Google Breakpad Android
[5] Android使用Google Breakpad进行崩溃日志管理
[6] use addr2line in android
欢迎您加入steemit社区。设置个人头像,有助于让大家更记住您,并且也比较美观,也显得正式。
如您还不知道如何设置,可点击此链接
https://steemit.com/cn/@kkkk/3sqepx
兄弟你很熱心,是好事。但是一直貼這條回覆,有點多了,已經開始有spam的疑慮的。建議你別再貼了。遇到新用戶,寫兩句就好了。
谢谢,已更换
谢谢分享。
Congratulations @wudb! You have received a personal award!
Click on the badge to view your own Board of Honor on SteemitBoard.
Congratulations @wudb! You received a personal award!
Click here to view your Board
Vote for @Steemitboard as a witness and get one more award and increased upvotes!
Congratulations @wudb! You received a personal award!
You can view your badges on your Steem Board and compare to others on the Steem Ranking
Do not miss the last post from @steemitboard:
Vote for @Steemitboard as a witness to get one more award and increased upvotes!