core dump 问题
bt
显示 ??
gdb 版本过低
thread apply all bt
中完全无主程序的调试信息
1
2
3
| Thread 1 (LWP 2528530):
#0 0x00007f36376b7fff in ?? ()
#1 0x0000000000000000 in ?? ()
|
gdb program core
考虑 program 二进制文件与 core 文件是否一致。
thread apply all bt
中存在主程序的调试信息,明显与主程序地址段不同的显示为 ??
1
2
3
4
5
6
7
8
9
10
11
| // dl.cpp
void dlthrow() {
throw -1;
}
// main.cpp
void dlthrow();
int main(int argc, char* argv[]) {
dlthrow();
return 0;
}
|
1
2
| g++ -shared -fPIC -o libdlthrow.so dl.cpp
g++ -L./ -ldlthrow main.cpp
|
1
| gdb a.out -c core.a.out-2640879-1648111582
|
1
2
3
4
| warning: Can't open file /xxx/yyy/zzz/libdlthrow.so during file-backed mapping note processing
[New LWP 2640879]
warning: Could not load shared library symbols for /xxx/yyy/zzz/libdlthrow.so.
|
可以通过 export LD_LIBRARY_PATH=/xxx/yyy/lib:$export LD_LIBRARY_PATH
进行配置,或 gdb 控制台执行 set solib-search-path /xxx/yyy/zzz/
。
dlopen
等方式加载的库缺失
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| // dl.cpp
extern "C"
void dlthrow() {
throw -1;
}
// main.cpp
#include "dlfcn.h"
#include <iostream>
int main(int argc, char* argv[]) {
void* handler = dlopen("libdlthrow.so", RTLD_LAZY);
if (handler == nullptr) {
std::cout << "handler is null" << std::endl;
return -1;
}
(void)dlerror();
auto dlthrow = reinterpret_cast<void (*)()>(dlsym(handler, "dlthrow"));
if (dlerror() != nullptr) {
std::cout << "dlthrow is null" << std::endl;
return -1;
}
dlthrow();
return 0;
}
|
1
2
| g++ -shared -fPIC -o libdlthrow.so dl.cpp
g++ -ldl main.cpp
|
gdb 加载 core 文件时提示库缺失,栈显示如下:
1
2
3
4
5
6
7
8
9
| #0 0x00007ff7304f9fff in raise () from /lib/x86_64-linux-gnu/libc.so.6
#1 0x00007ff7304fb42a in abort () from /lib/x86_64-linux-gnu/libc.so.6
#2 0x00007ff730e120ad in __gnu_cxx::__verbose_terminate_handler() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#3 0x00007ff730e10066 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#4 0x00007ff730e100b1 in std::terminate() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#5 0x00007ff730e102c9 in __cxa_throw () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#6 0x00007ff7302c578b in ?? ()
#7 0x00007ffed5edd540 in ?? ()
#8 0x000055aa3ead8b0a in main ()
|
如 #6
/#7
与 #8
地址段明显不同。
1
2
3
4
5
6
7
8
| From To Syms Read Shared Object Library
0x00007ff731103d80 0x00007ff73110494e Yes (*) /lib/x86_64-linux-gnu/libdl.so.2
0x00007ff730e0c7e0 0x00007ff730eb4d49 Yes (*) /usr/lib/x86_64-linux-gnu/libstdc++.so.6
0x00007ff730a82680 0x00007ff730aee8da Yes (*) /lib/x86_64-linux-gnu/libm.so.6
0x00007ff730868a90 0x00007ff730878895 Yes (*) /lib/x86_64-linux-gnu/libgcc_s.so.1
0x00007ff7304e6940 0x00007ff730610613 Yes (*) /lib/x86_64-linux-gnu/libc.so.6
0x00007ff731307aa0 0x00007ff731322fb0 Yes (*) /lib64/ld-linux-x86-64.so.2
No /xxx/yyy/zzz/libdlthrow.so
|
可以看到 /xxx/yyy/zzz/libdlthrow.so (有些 hack 的场景也可能看不到)。
但通过查看 mmap 映射区,可以通过地址精确的定位缺失的库为 libdlthrow.so (#6
0x00007ff7302c578b 对应地址段 [0x7ff7302c5000, 0x7ff7302c6000) /xxx/yyy/zzz/libdlthrow.so)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
| Mapped address spaces:
Start Addr End Addr Size Offset objfile
0x55aa3ead8000 0x55aa3ead9000 0x1000 0x0 /xxx/yyy/zzz/a.out
0x55aa3ecd9000 0x55aa3ecda000 0x1000 0x1000 /xxx/yyy/zzz/a.out
0x55aa3ecda000 0x55aa3ecdb000 0x1000 0x2000 /xxx/yyy/zzz/a.out
0x7ff7302c5000 0x7ff7302c6000 0x1000 0x0 /xxx/yyy/zzz/libdlthrow.so
0x7ff7302c6000 0x7ff7304c5000 0x1ff000 0x1000 /xxx/yyy/zzz/libdlthrow.so
0x7ff7304c5000 0x7ff7304c6000 0x1000 0x0 /xxx/yyy/zzz/libdlthrow.so
0x7ff7304c6000 0x7ff7304c7000 0x1000 0x1000 /xxx/yyy/zzz/libdlthrow.so
0x7ff7304c7000 0x7ff73065c000 0x195000 0x0 /lib/x86_64-linux-gnu/libc-2.24.so
0x7ff73065c000 0x7ff73085c000 0x200000 0x195000 /lib/x86_64-linux-gnu/libc-2.24.so
0x7ff73085c000 0x7ff730860000 0x4000 0x195000 /lib/x86_64-linux-gnu/libc-2.24.so
0x7ff730860000 0x7ff730862000 0x2000 0x199000 /lib/x86_64-linux-gnu/libc-2.24.so
0x7ff730866000 0x7ff73087c000 0x16000 0x0 /lib/x86_64-linux-gnu/libgcc_s.so.1
0x7ff73087c000 0x7ff730a7b000 0x1ff000 0x16000 /lib/x86_64-linux-gnu/libgcc_s.so.1
0x7ff730a7b000 0x7ff730a7c000 0x1000 0x15000 /lib/x86_64-linux-gnu/libgcc_s.so.1
0x7ff730a7c000 0x7ff730a7d000 0x1000 0x16000 /lib/x86_64-linux-gnu/libgcc_s.so.1
0x7ff730a7d000 0x7ff730b80000 0x103000 0x0 /lib/x86_64-linux-gnu/libm-2.24.so
0x7ff730b80000 0x7ff730d7f000 0x1ff000 0x103000 /lib/x86_64-linux-gnu/libm-2.24.so
0x7ff730d7f000 0x7ff730d80000 0x1000 0x102000 /lib/x86_64-linux-gnu/libm-2.24.so
0x7ff730d80000 0x7ff730d81000 0x1000 0x103000 /lib/x86_64-linux-gnu/libm-2.24.so
0x7ff730d81000 0x7ff730ef3000 0x172000 0x0 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.22
0x7ff730ef3000 0x7ff7310f3000 0x200000 0x172000 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.22
0x7ff7310f3000 0x7ff7310fd000 0xa000 0x172000 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.22
0x7ff7310fd000 0x7ff7310ff000 0x2000 0x17c000 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.22
0x7ff731103000 0x7ff731106000 0x3000 0x0 /lib/x86_64-linux-gnu/libdl-2.24.so
0x7ff731106000 0x7ff731305000 0x1ff000 0x3000 /lib/x86_64-linux-gnu/libdl-2.24.so
0x7ff731305000 0x7ff731306000 0x1000 0x2000 /lib/x86_64-linux-gnu/libdl-2.24.so
0x7ff731306000 0x7ff731307000 0x1000 0x3000 /lib/x86_64-linux-gnu/libdl-2.24.so
0x7ff731307000 0x7ff73132a000 0x23000 0x0 /lib/x86_64-linux-gnu/ld-2.24.so
0x7ff73152a000 0x7ff73152b000 0x1000 0x23000 /lib/x86_64-linux-gnu/ld-2.24.so
0x7ff73152b000 0x7ff73152c000 0x1000 0x24000 /lib/x86_64-linux-gnu/ld-2.24.so
|
动态链接库存在部分函数名显示 ??
1
2
3
4
5
6
7
8
| #0 0x00007f320d227fff in raise () from /lib/x86_64-linux-gnu/libc.so.6
#1 0x00007f320d22942a in abort () from /lib/x86_64-linux-gnu/libc.so.6
#2 0x00007f320db400ad in __gnu_cxx::__verbose_terminate_handler() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#3 0x00007f320db3e066 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#4 0x00007f320db3e0b1 in std::terminate() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#5 0x00007f320db3e2c9 in __cxa_throw () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#6 0x0000555d9b9a47c8 in raiseException() ()
#7 0x0000555d9b9a47dc in main ()
|
#3
可能原因为栈被破坏。
干扰因素
C/C++ 语言添加编译选项 -g
-g
选项提供了行号信息,-g
选项带来的效果如下:
1
| #7 0x000055e9c75f9b0a in main (argc=1, argv=0x7ffdd4124638) at main.cpp:17
|
不包含 -g
选项时:
1
| #7 0x000055aa3ead8b0a in main ()
|
该选项对于 bt
显示 ?? 并无帮助,但可以使用诸如 list <function-name>
等 gdb 命令。
Go 语言添加编译选项 -gcflags "-N -l"
其中 -N
禁止优化,-l
禁止内联,对于 bt
显示 ?? 亦无帮助。
gdb 加载 Go 插件 runtime-gdb.py
1
| source /usr/local/go/src/runtime/runtime-gdb.py
|
runtime-gdb.py 主要提供了 $len()
、$cap()
、$dtype()
以及 goroutine 相关的查看,对于 bt
显示 ?? 同样无帮助。
参考:Debugging Go Code with GDB