从debug版程序projectD中生成符号表projectsymbol.dbg
objcopy --only-keep-debug projectD projectsymbol.dbg
调试release版程序projectR,同时加载符号表projectsymbol.dbg
gdb --symbol=projectsymbol.dbg --exec=projectR
调试release版程序生成的core文件,同时加载符号表projectsymbol.dbg
gdb --symbol=projectsymbol.dbg --exec=projectR -c core
查看core dump位置:sudo sysctl -n kernel.core_pattern
设置core dump位置:sudo sysctl -w kernel.core_pattern=/tmp
测试代码:
#include "client/linux/handler/exception_handler.h"
static bool dumpCallback(const google_breakpad::MinidumpDescriptor& descriptor,
void* context, bool succeeded) {
printf("Dump path: %s\n", descriptor.path());
return succeeded;
}
void crash() { volatile int* a = (int*)(NULL); *a = 1; }
int main(int argc, char* argv[]) {
google_breakpad::MinidumpDescriptor descriptor("/tmp");
google_breakpad::ExceptionHandler eh(descriptor, NULL, dumpCallback, NULL, true, -1);
crash();
return 0;
}
编译的时候注意要链接libbreakpad_client.a静态库
g++ breakpad.cpp -o breakpad -I breakpad/include/breakpad -L breakpad/lib/ -lbreakpad_client -lpthread
接下来运行breakpad,生成dump文件,程序打印出了dump文件路径
Dump path: /tmp/4d4c5bd1-6b58-4f64-89fad7b6-98585875.dmp
Segmentation fault
有两种方法:
方法1. minidump-2-core + gdb
a.使用minidump-2-core工具将dump文件转换为core
breakpad/bin/minidump-2-core /tmp/4d4c5bd1-6b58-4f64-89fad7b6-98585875.dmp > core
b.使用gdb调试core
gdb breakpad core
Core was generated by `./breakpad'.
Program terminated with signal SIGSEGV, Segmentation fault.
(gdb) bt
#0 0x00005586a6e93185 in crash() ()
#1 0x00005586a6e93235 in main ()
(gdb)
方法2. dump_syms + minidump_stackwalk(比较麻烦)
a.从程序导出符号文件
breakpad/bin/dump_syms ./breakpad > breakpad.sym
b按照符号文件第一行内容创建指定目录结构存放符号文件
head -n1 breakpad.sym
MODULE Linux x86_64 DA1431F4146A0A08633146C746B8E5AB0 breakpad
mkdir -p ./symbols/breakpad/DA1431F4146A0A08633146C746B8E5AB0
mv breakpad.sym ./symbols/breakpad/DA1431F4146A0A08633146C746B8E5AB0/
c.使用minidump_stackwalk解析dump文件
因为stderr会输出很多冗余无用的信息,所以将其重定向到/dev/null
breakpad/bin/minidump_stackwalk /tmp/4d4c5bd1-6b58-4f64-89fad7b6-98585875.dmp ./symbols/ 2> /dev/null
输出如下:
Operating system: Linux
0.0.0 Linux 4.15.0-29deepin-generic #31 SMP Fri Jul 27 07:12:08 UTC 2018 x86_64
CPU: amd64
family 6 model 78 stepping 3
1 CPU
GPU: UNKNOWN
Crash reason: SIGSEGV /SEGV_MAPERR
Crash address: 0x0
Process uptime: not available
Thread 0 (crashed)
0 breakpad!crash() + 0x10
rax = 0x0000000000000000 rdx = 0x00005557a6cc0880
rcx = 0x0000000000000000 rbx = 0x0000000000000000
rsi = 0x0000000000000000 rdi = 0x0000000000000000
rbp = 0x00007ffe897de7f0 rsp = 0x00007ffe897de7f0
r8 = 0x0000000000000000 r9 = 0x00007ffe897de410
r10 = 0x0000000000000135 r11 = 0x00007f988d3cc3f0
r12 = 0x00005557a6aaa030 r13 = 0x00007ffe897deab0
r14 = 0x0000000000000000 r15 = 0x0000000000000000
rip = 0x00005557a6aaa185
Found by: given as instruction pointer in context
1 breakpad!main + 0xa7
rbx = 0x0000000000000000 rbp = 0x00007ffe897de9d0
rsp = 0x00007ffe897de800 r12 = 0x00005557a6aaa030
r13 = 0x00007ffe897deab0 r14 = 0x0000000000000000
r15 = 0x0000000000000000 rip = 0x00005557a6aaa235
Found by: call frame info
2 libc-2.27.so + 0x21a87
rbx = 0x0000000000000000 rbp = 0x00005557a6aba6b0
rsp = 0x00007ffe897de9e0 r12 = 0x00005557a6aaa030
r13 = 0x00007ffe897deab0 r14 = 0x0000000000000000
r15 = 0x0000000000000000 rip = 0x00007f988c6fca87
Found by: call frame info
3 breakpad!crash() + 0x19
rsp = 0x00007ffe897dea00 rip = 0x00005557a6aaa18e
Found by: stack scanning
Loaded modules:
0x5557a6aa4000 - 0x5557a6abffff breakpad ??? (main)
0x7f988c6db000 - 0x7f988c88bfff libc-2.27.so ??? (WARNING: No symbols, libc-2.27.so, 97A2D08FBF581566673836BB20FFDF110)
0x7f988ca95000 - 0x7f988caabfff libgcc_s.so.1 ???
0x7f988ccad000 - 0x7f988ce3efff libm-2.27.so ???
0x7f988d040000 - 0x7f988d1b1fff libstdc++.so.6.0.25 ???
0x7f988d3c1000 - 0x7f988d3d9fff libpthread-2.27.so ???
0x7f988d5df000 - 0x7f988d5e1fff libdl-2.27.so ???
0x7f988d7e3000 - 0x7f988d807fff ld-2.27.so ???
0x7ffe897e4000 - 0x7ffe897e5fff linux-gate.so ???
1.这里的测试程序breakpad不含调试信息,如果含有调试信息,可以定位到具体的行号,显示更多出错信息
2.第一种方法可以配合debug版程序的符号表进行调试分析,一样可以定位到具体出错信息
3.第二种方法可以直接使用minidump_stackwalk得到dump信息,然后配合addr2line工具定位崩溃点