Android
官方文档:chromium.googlesource.com/breakpad/br…
编译
$ cd $BREAKPAD/src/android
$ cp -r google_breakpad jni
$ $NDK/ndk-build
Android NDK: APP_PLATFORM not set. Defaulting to minimum supported version android-16.
# ...
[arm64-v8a] StaticLibrary : libbreakpad_client.a
# ...
[armeabi-v7a] StaticLibrary : libbreakpad_client.a
# ...
[x86] StaticLibrary : libbreakpad_client.a
# ...
[x86_64] StaticLibrary : libbreakpad_client.a
$ find . -name libbreakpad_client.a
./obj/local/armeabi-v7a/libbreakpad_client.a
./obj/local/x86/libbreakpad_client.a
./obj/local/arm64-v8a/libbreakpad_client.a
./obj/local/x86_64/libbreakpad_client.a
使用
依赖符号表-解析dmp文件
根据如何在Android平台使用Google Breakpad
在Linux环境中,使用Breakpad工程编译出来的dump_syms解析ELF文件中的DWARF信息
$ $CLI_BREAKPAD/.../dump_syms libflutter-breakpad.so > libflutter-breakpad.so.sym
在Linux环境中,使用Breakpad工程编译出来的minidump_stackwalk,配合symbols符号表,解析dmp崩溃日志
$ $CLI_BREAKPAD/.../minidump_stackwalk libflutter-breakpad.so.dmp symbols > libflutter-breakpad.so.log
最终能直接得到产生崩溃的源码所在的文件flutter_breakpad.cpp和行号44
$ head -n 20 libflutter-breakpad.so.log
Operating system: Android
0.0.0 Linux 3.18.71-perf-g4a0ef96 #1 SMP PREEMPT Thu Nov 22 00:40:45 CST 2018 aarch64
CPU: arm64
4 CPUs
GPU: UNKNOWN
Crash reason: SIGSEGV /SEGV_MAPERR
Crash address: 0x0
Process uptime: not available
Thread 0 (crashed)
0 libflutter-breakpad.so!Java_com_example_flutter_1breakpad_Utils_crash [flutter_breakpad.cpp : 44 + 0x0]
x0 = 0x0000007618a792a0 x1 = 0x0000007fc3f6f4f4
x2 = 0x0000000000000000 x3 = 0x0000007618a0dc00
x4 = 0x0000007fc3f6f910 x5 = 0x00000075ff39203b
x6 = 0x0000000000000002 x7 = 0x0000000000000000
x8 = 0x0000000000000000 x9 = 0x0000000000000001
x10 = 0x0000000000430000 x11 = 0x0000000000000000
x12 = 0x0000000000000001 x13 = 0x0000000000000000
依赖DWARF信息-解析dmp文件
使用Android Studio内置minidump_stackwalk(不同Android Studio版本具体路径不同,请自行搜索),直接解析dmp崩溃日志
| 平台 | 路径 |
|---|---|
| Windows | %ANDRIOD_STUDIO%\bin\lldb\minidump_stackwalk.exe |
| macOS | $ANDRIOD_STUDIO/Contents/bin/lldb/bin/minidump_stackwalk |
| Linux | $ANDRIOD_STUDIO/bin/lldb/minidump_stackwalk |
$ $ANDRIOD_STUDIO/.../minidump_stackwalk libflutter-breakpad.so.dmp > libflutter-breakpad.so.log
可以看到崩溃代码偏移地址0x15fe0
$ head -n 20 libflutter-breakpad.so.log
Operating system: Android
0.0.0 Linux 3.18.71-perf-g4a0ef96 #1 SMP PREEMPT Thu Nov 22 00:40:45 CST 2018 aarch64
CPU: arm64
4 CPUs
Crash reason: SIGSEGV
Crash address: 0x0
Process uptime: not available
Thread 0 (crashed)
0 libflutter-breakpad.so + 0x15fe0
x0 = 0x0000007618a792a0 x1 = 0x0000007fc3f6f4f4
x2 = 0x0000000000000000 x3 = 0x0000007618a0dc00
x4 = 0x0000007fc3f6f910 x5 = 0x00000075ff48f03b
x6 = 0x0000000000000002 x7 = 0x0000000000000000
x8 = 0x0000000000000000 x9 = 0x0000000000000001
x10 = 0x0000000000430000 x11 = 0x0000000000000000
x12 = 0x0000000000000001 x13 = 0x0000000000000000
x14 = 0x00000000ffffffff x15 = 0x00000000000fd090
x16 = 0x000000761ba5c2c8 x17 = 0x00000075ff02afc4
使用Android NDK内置的addr2line,借助ELF文件,解析崩溃地址对应的源代码的行号
$ANDROID_SDK/ndk/21.1.6352462/toolchains/llvm/prebuilt/${PLATFORM_ARCH}/bin/${ANDROID_ARCH}-addr2line
| 平台\Android | armeabi-v7a | arm64-v8a | x86 | x86-64 |
|---|---|---|---|---|
| windows/x86-64 | windows-x86_64/bin/arm-linux-androideabi.exe | windows-x86_64/bin/aarch64-linux-android.exe | windows-x86_64/bin/i686-linux-android.exe | windows-x86_64/bin/x86_64-linux-android.exe |
| mac/x86-64 | darwin-x86_64/bin/arm-linux-androideabi | darwin-x86_64/bin/aarch64-linux-android | darwin-x86_64/bin/i686-linux-android | darwin-x86_64/bin/x86_64-linux-android |
| linux/x86-64 | linux-x86_64/bin/arm-linux-androideabi | linux-x86_64/bin/aarch64-linux-android | linux-x86_64/bin/i686-linux-android | linux-x86_64/bin/x86_64-linux-android |
$ $ANDROID_SDK/.../addr2line -f -C -e libflutter-breakpad.so 0x15fe0
/Users/sunbreak/Sunbreak/flutter-breakpad.trial/android/app/src/main/cpp/flutter_breakpad.cpp:44
最终能直接得到产生崩溃的源码所在的文件flutter_breakpad.cpp和行号44
iOS
官方文档:无
编译
$ cd $BREAKPAD/src/client/ios
$ xcodebuild -sdk iphoneos -arch arm64 && xcodebuild -sdk iphonesimulator -arch x86_64
$ lipo -create build/Release-iphoneos/libBreakpad.a build/Release-iphonesimulator/libBreakpad.a -output libBreakpad.a
使用
依赖符号表-解析dmp文件
在macOS环境中,使用dsymutil获取Runner的DWARF文件Runner.dSYM
$ dsymutil build/ios/Debug-iphonesimulator/Runner.app/Runner -o Runner.dSYM
在macOS环境中,使用Breakpad工程编译出来的dump_syms解析ELF文件(dSYM)中的DWARF信息
$ $CLI_BREAKPAD/.../dump_syms Runner.dSYM > Runner.sym
在macOS环境中,使用Breakpad工程编译出来的minidump_stackwalk,配合symbols符号表,解析dmp崩溃日志
$ $CLI_BREAKPAD/.../minidump_stackwalk Runner.dmp symbols > Runner.log
最终能直接得到产生崩溃的源码所在的文件util.m和行号5
$ head -n 20 Runner.log
Operating system: iOS
11.2.3 20D91
CPU: amd64
family 6 model 70 stepping 1
8 CPUs
GPU: UNKNOWN
Crash reason: EXC_BAD_ACCESS / KERN_INVALID_ADDRESS
Crash address: 0x0
Process uptime: 2 seconds
Thread 0 (crashed)
0 Runner!crash [util.m : 5 + 0x0]
rax = 0x0000000000000000 rdx = 0x000000010ebe52a0
rcx = 0x000000010c3e1b90 rbx = 0x0000000000000000
rsi = 0x000000010c3e1ba0 rdi = 0x0000000000000000
rbp = 0x00007ffee381d290 rsp = 0x00007ffee381d290
r8 = 0x0060000000000000 r9 = 0x0000007700000001
r10 = 0x0000000000000002 r11 = 0x0000000000000246
依赖符号表-手动解析dmp文件
在macOS环境中,使用Breakpad工程编译出来的minidump_stackwalk,直接解析dmp崩溃日志
$ $ANDRIOD_STUDIO/.../minidump_stackwalk Runner.dmp > Runner.log
可以看到崩溃代码偏移地址0x1560
$ head -n 20 Runner.log
Operating system: iOS
11.2.3 20D91
CPU: amd64
family 6 model 70 stepping 1
8 CPUs
GPU: UNKNOWN
Crash reason: EXC_BAD_ACCESS / KERN_INVALID_ADDRESS
Crash address: 0x0
Process uptime: 2 seconds
Thread 0 (crashed)
0 Runner + 0x1560
rax = 0x0000000000000000 rdx = 0x000000010ebe52a0
rcx = 0x000000010c3e1b90 rbx = 0x0000000000000000
rsi = 0x000000010c3e1ba0 rdi = 0x0000000000000000
rbp = 0x00007ffee381d290 rsp = 0x00007ffee381d290
r8 = 0x0060000000000000 r9 = 0x0000007700000001
r10 = 0x0000000000000002 r11 = 0x0000000000000246
进而搜索Runner.sym中首列为”1560“的行,即0x1560地址中,偏移量为6,源码行数为5,文件ID为15
$ grep 1560 Runner.sym
1560 6 5 15
# ...
再搜索Runner.sym中前两列为“FILE 15”的行,即源文件为util.m
$ grep "FILE 15" Runner.sym
FILE 15 /Users/sunbreak/Sunbreak/flutter-breakpad.trial/ios/Runner/util.m
依赖dSYM-手动解析dmp文件
获取程序起始地址,即vmaddr 0x0000000100000000
$ otool -l build/ios/Debug-iphonesimulator/Runner.app/Runner | grep -B 1 -A 10 "LC_SEGM" | grep -B 3 -A 8 "__TEXT"
Load command 1
cmd LC_SEGMENT_64
cmdsize 1592
segname __TEXT
vmaddr 0x0000000100000000
vmsize 0x0000000000018000
fileoff 0
filesize 98304
maxprot 0x00000005
initprot 0x00000005
nsects 19
flags 0x0
偏移量0x1560对应的地址为0x0000000100000000 + 0x1560 = 0x0000000100001560,通过dwarfdump搜索dSYM文件
$ dwarfdump --lookup 0x0000000100001560 Runner.dSYM
Runner.dSYM/Contents/Resources/DWARF/Runner: file format Mach-O 64-bit x86-64
0x000975ab: Compile Unit: length = 0x0000006f version = 0x0004 abbr_offset = 0x0000 addr_size = 0x08 (next unit at 0x0009761e)
0x000975b6: DW_TAG_compile_unit
DW_AT_producer ("Apple clang version 12.0.0 (clang-1200.0.32.27)")
DW_AT_language (DW_LANG_ObjC)
DW_AT_name ("/Users/sunbreak/Sunbreak/flutter-breakpad.trial/ios/Runner/util.m")
DW_AT_LLVM_sysroot ("/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator14.2.sdk")
DW_AT_APPLE_sdk ("iPhoneSimulator14.2.sdk")
DW_AT_stmt_list (0x00017c05)
DW_AT_comp_dir ("/Users/sunbreak/Sunbreak/flutter-breakpad.trial/ios")
DW_AT_APPLE_major_runtime_vers (0x02)
DW_AT_low_pc (0x0000000100001550)
DW_AT_high_pc (0x0000000100001568)
0x000975ed: DW_TAG_subprogram
DW_AT_low_pc (0x0000000100001550)
DW_AT_high_pc (0x0000000100001568)
DW_AT_frame_base (DW_OP_reg6 RBP)
DW_AT_name ("crash")
DW_AT_decl_file ("/Users/sunbreak/Sunbreak/flutter-breakpad.trial/ios/Runner/util.m")
DW_AT_decl_line (3)
DW_AT_external (true)
Line info: file 'util.m', line 5, column 8, start line 3
最终能直接得到产生崩溃的源码所在的文件util.m和行号5