[APM笔记]CLI Windows/macOS/Linux使用Breakpad

2,761 阅读3分钟

github.com/Sunbreak/cl…

Windows

官方文档:chromium.googlesource.com/breakpad/br…

下载

不建议使用fetch breakpad:其中gclient sync会执行hooks,进而执行无参数的gyp.bat

rem Command Prompt
> git clone https://chromium.googlesource.com/external/gyp
> git clone https://chromium.googlesource.com/breakpad/breakpad

编译

  • 编译exception_handler、crash_generation_client、common

根据/MD, /MT, /LD (Use Run-Time Library),win_release_RuntimeLibrary和win_debug_RuntimeLibrary代表

/MultiThreadedMultiThreadedDll
ReleaseMT=0MD=2
DebugMTd=1MDd=3
rem Command Prompt
> %GYP%\gyp.bat --no-circular-check breakpad\src\client\windows\breakpad_client.gyp -Dwin_release_RuntimeLibrary=2 -Dwin_debug_RuntimeLibrary=3

根据refresh_binaries.bat,GYP已知最高支持VS 2015,若不设置则默认生成VS 2008格式vcproj,根据Upgrading to VS 2010采用DevEnv /Upgrade即可升级到VS 2019兼容格式

rem Developer Command Prompt
> cd %BREAKPAD%\src\client\windows
> DevEnv breakpad_client.sln /Upgrade
> DevEnv breakpad_client.sln /Build "Debug|x64" /Project exception_handler
exception_handler.vcxproj -> C:\Users\sunbr\google\breakpad\src\client\windows\Debug\lib\exception_handler.lib
> DevEnv breakpad_client.sln /Build "Debug|x64" /Project common
common.vcxproj -> C:\Users\sunbr\google\breakpad\src\client\windows\Debug\lib\common.lib
> DevEnv breakpad_client.sln /Build "Debug|x64" /Project crash_generation_client
crash_generation_client.vcxproj -> C:\Users\sunbr\google\breakpad\src\client\windows\Debug\lib\crash_generation_client.lib

确认RuntimeLibrary

rem Developer Command Prompt
> DumpBin /ALL Debug\lib\exception_handler.lib | findstr RuntimeLibrary
   /FAILIFMISMATCH:RuntimeLibrary=MDd_DynamicDebug
> DumpBin /ALL Debug\lib\crash_generation_client.lib | findstr RuntimeLibrary
   /FAILIFMISMATCH:RuntimeLibrary=MDd_DynamicDebug
> DumpBin /ALL Debug\lib\common.lib | findstr RuntimeLibrary
  00000090: 22 52 75 6E 74 69 6D 65 4C 69 62 72 61 72 79 3D  "RuntimeLibrary=
   /FAILIFMISMATCH:RuntimeLibrary=MDd_DynamicDebug
   /FAILIFMISMATCH:RuntimeLibrary=MDd_DynamicDebug
  00000090: 22 52 75 6E 74 69 6D 65 4C 69 62 72 61 72 79 3D  "RuntimeLibrary=
   /FAILIFMISMATCH:RuntimeLibrary=MDd_DynamicDebug
  • 编译dump_syms
rem Developer Command Prompt
> cd %BREAKPAD%\src\tools\windows\dump_syms
> DevEnv dump_syms.sln /Upgrade
> DevEnv dump_syms.sln /Build "Release|x64" /Project dump_syms
  • 编译minidump_stackwalk

TODO

使用

使用Breakpad工程编译出来的dump_syms解析PDB文件中的debug信息

根据 Windows build produces empty symbol zip file编译报错 CoCreateInstance CLSID_DiaSource {E6756135-1E65-4D17-8576-610761398C3C} failed (msdia*.dll unregistered?) ,dump_syms运行需要注册msdia*.dll

rem Administrator: Command Prompt
> regsvr32 "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\IDE\Remote Debugger\x64\msdia140.dll"
rem Command Prompt
> breakpad\windows\%PROCESSOR_ARCHITECTURE%\dump_syms build\Debug\cli-breakpad.pdb > cli-breakpad.sym

因为Windows版本minidump_stackwalk暂时无法编译,故使用Linux版本minidump_stackwalk

在Linux环境中,根据PDB文件名和sym文件UUID,创建symbols符号表

$ uuid=`awk 'FNR==1{print \$4}' cli-breakpad.sym`
$ mkdir -p symbols/cli-breakpad.pdb/$uuid/
$ mv ./cli-breakpad.sym symbols/cli-breakpad.pdb/$uuid/

在Linux环境中,使用Breakpad工程编译出来的minidump_stackwalk,配合symbols符号表,解析dmp崩溃日志

$ ./breakpad/linux/$(arch)/minidump_stackwalk 887a36fe-d37e-4b79-97c4-133e36a1c24e.dmp symbols > cli-breakpad.log

在Linux环境中,最终能直接得到产生崩溃的源码所在的文件main.cpp和行号51

$ head -n 20 cli-breakpad.log
Operating system: Windows NT
                  10.0.19043
CPU: amd64
     family 6 model 78 stepping 3
     4 CPUs

GPU: UNKNOWN

Crash reason:  EXCEPTION_ACCESS_VIOLATION_WRITE
Crash address: 0x0
Process uptime: 0 seconds

Thread 0 (crashed)
 0  cli-breakpad.exe!main [main.cpp : 51 + 0x8]
    rax = 0x0000000000000000   rdx = 0x00007ff6db128050
    rcx = 0x0000000000000034   rbx = 0x0000000000000000
    rsi = 0x0000000000000000   rdi = 0x000000cd8a3ff6c0
    rbp = 0x0000000000000000   rsp = 0x000000cd8a3ff4b0
     r8 = 0x00000217f75f0fc0    r9 = 0x0000000000000001
    r10 = 0x0000000000008000   r11 = 0x000000cd8a3ff1d0

macOS

官方文档:chromium.googlesource.com/breakpad/br…

其中根据Xcode Release Notes (apple.com)

Deprecations

  • The build setting Separate Strip (SEPARATE_STRIP) is no longer supported nor is it displayed in the build settings editor. Xcode always strips binaries in a separate task and no longer instructs the linker to perform the strip. (31584192)

下载

$ mkdir breakpad && cd breakpad
$ fetch breakpad

编译

  • 编译Breakpad.framework
$ cd $BREAKPAD/src/client/mac
$ xcodebuild -target Breakpad
build/Release/Breakpad.framework
  • 编译dump_syms
cd $BREAKPAD/src/tool/mac/dump_syms && xcodebuild -target dump_syms
  • 编译minidump_stackwalk
./configure && make

使用

使用dsymutil获取cli-breakpad的DWARF文件cli-breakpad.dSYM

$ dsymutil ./build/cli-breakpad -o cli-breakpad.dSYM

使用Breakpad工程编译出来的dump_syms解析ELF文件(dSYM)中的DWARF信息

$ ./breakpad/mac/dump_syms cli-breakpad.dSYM > cli-breakpad.sym

根据Mach-O文件名和sym文件UUID,创建symbols符号表

$ uuid=`awk 'FNR==1{print \$4}' cli-breakpad.sym`
$ mkdir -p symbols/cli-breakpad/$uuid/
$ mv ./cli-breakpad.sym symbols/cli-breakpad/$uuid/

使用Breakpad工程编译出来的minidump_stackwalk,配合symbols符号表,解析dmp崩溃日志

$ ./breakpad/mac/$(arch)/minidump_stackwalk 64C31053-BBE4-400C-9588-B29F63E08E71.dmp symbols > cli-breakpad.log

最终能直接得到产生崩溃的源码所在的文件main.cpp和行号37

Operating system: Mac OS X
                  11.3.1 20E241
CPU: amd64
     family 6 model 158 stepping 10
     12 CPUs

GPU: UNKNOWN

Crash reason:  EXC_BAD_INSTRUCTION / EXC_I386_INVOP
Crash address: 0x10b06c93f
Process uptime: 0 seconds

Thread 0 (crashed)
 0  cli-breakpad!main [main.cpp : 37 + 0x0]
    rax = 0x0000000000000001   rdx = 0x0000000000000000
    rcx = 0x00007fff205f728e   rbx = 0x0000000000000000
    rsi = 0x00007ffee4b966d8   rdi = 0x00007ffee4b96620
    rbp = 0x00007ffee4b967f0   rsp = 0x00007ffee4b966d0
     r8 = 0x00000000090008ff    r9 = 0x0000000000000003
    r10 = 0x0000000000000020   r11 = 0x00007fff20627d10

Linux

官方文档:chromium.googlesource.com/breakpad/br…

下载

$ mkdir breakpad && cd breakpad
$ fetch breakpad

编译

  • 编译libbreakpad_client.a/dump_syms/minidump_stackwalk
./configure && make

使用

根据如何在Linux上使用Google breakpad

使用Breakpad工程编译出来的dump_syms解析ELF文件中的DWARF信息

$ ./breakpad/linux/$(arch)/dump_syms build/cli-breakpad > cli-breakpad.sym

根据ELF文件名和sym文件UUID,创建symbols符号表

$ uuid=`awk 'FNR==1{print \$4}' cli-breakpad.sym`
$ mkdir -p symbols/cli-breakpad/$uuid/
$ mv ./cli-breakpad.sym symbols/cli-breakpad/$uuid/

使用Breakpad工程编译出来的minidump_stackwalk,配合symbols符号表,解析dmp崩溃日志

$ ./breakpad/linux/$(arch)/minidump_stackwalk 7df95962-acd7-488b-ac443ebd-933ebb6a.dmp symbols > cli-breakpad.log

最终能直接得到产生崩溃的源码所在的文件main.cpp和行号37

$ head -n 20 7df95962-acd7-488b-ac443ebd-933ebb6a.dmp
Operating system: Linux
                  0.0.0 Linux 5.11.0-37-generic #41~20.04.2-Ubuntu SMP Fri Sep 24 09:06:46 UTC 2021 aarch64
CPU: arm64
     2 CPUs

GPU: UNKNOWN

Crash reason:  SIGSEGV /SEGV_MAPERR
Crash address: 0x0
Process uptime: not available

Thread 0 (crashed)
 0  cli-breakpad!main [main.cpp : 37 + 0x4]
     x0 = 0x0000000000000000    x1 = 0x0000000000000000
     x2 = 0x0000000000000000    x3 = 0x0000000000000001
     x4 = 0x0000aaaab5efb408    x5 = 0x0000aaaab5efb418
     x6 = 0x000000000000017f    x7 = 0x0000000000000000
     x8 = 0x0000000000000010    x9 = 0x0000000000000000
    x10 = 0x0000000000000000   x11 = 0x0000000000000010
    x12 = 0x0000ffffa783a208   x13 = 0x0000000000000000

参考

TODO