GDB 在加载核心文件时不会加载共享库符号,甚至不会加载 libc.so (musl)



我正在尝试调试在带有MIPS CPU的电路板上远程运行的程序,使用musl作为其libc。 如果我在板上启动 gdbserver,通过set sysroot /path/to/sysroot设置系统根并从 gdb 实时连接,我会得到一个有意义的堆栈跟踪(由于 musl 缺乏关于 MIPS 的 CFI 指令并且我必须添加它们,这需要花费数小时的努力,但这是一个单独的问题(,我可以看到 gdb 从系统根libc.so加载符号。

另一方面,如果我让该程序崩溃并生成一个核心转储(我使用kill -6 <pid>强制一个用于测试(,gdb 将从二进制文件加载符号,但不会加载它的任何共享库,甚至不会加载libc.so。虽然其他共享库很好,但不是必需的,如果没有来自 libc.so 的调试信息,gdb 无法解析堆栈跟踪,它们看起来都像垃圾。

成功的实时 gdb 会话

$ mipsel-poky-linux-gdb -iex "set sysroot /path/to/sysroot" /path/to/testprog
GNU gdb (GDB) 8.2.1
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "--host=x86_64-pokysdk-linux --target=mipsel-poky-linux".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from /path/to/testprog...done.
(gdb) 
(gdb) target extended-remote remote-hostname:10000
Remote debugging using remote-hostname:10000
Reading symbols from /path/to/sysroot/lib/ld.so.1...done.
__cp_end () at src/thread/mips/syscall_cp.s:38
38      beq     $7, $0, 1f
(gdb) bt
#0  __cp_end () at src/thread/mips/syscall_cp.s:38
#1  0x77eff348 in __syscall_cp_c (nr=4029, u=<optimized out>, v=<optimized out>, w=<optimized out>, x=0, y=0, z=0)
at src/thread/pthread_cancel.c:33
#2  0x77f0b4b0 in pause () at src/unistd/pause.c:7
#3  0x556ecd3c in core_run (argc=1, argv=0x7f7bf4a4) at /path/to/source-file.cpp:461
#4  0x77e93d28 in libc_start_main_stage2 (main=0x556b1ac0 <main(int, char**)>, argc=1, argv=0x7f7bf4a4)
at src/env/__libc_start_main.c:94
#5  0x556eb890 in _start_c (p=<optimized out>) at crt/crt1.c:18
#6  0x556eb850 in _start () at /path/to/header-file.hpp:130
Backtrace stopped: frame did not save the PC

(注意:在上面,我用占位符替换了内部路径/文件名/等(

核心转储 gdb 会话失败

$ mipsel-poky-linux-gdb -iex "set verbose on" -iex "set sysroot /path/to/sysroot" /path/to/testprog core
GNU gdb (GDB) 8.2.1
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "--host=x86_64-pokysdk-linux --target=mipsel-poky-linux".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from /path/to/testprog...done.
Reading in symbols for /path/to/source/main.cpp...done.
[New LWP 1285]
[New LWP 1408]
[New LWP 1409]
[New LWP 1410]
[New LWP 1412]
[New LWP 1407]
[New LWP 1401]
[New LWP 1402]
[New LWP 1403]
[New LWP 1404]
Using PIE (Position Independent Executable) displacement 0x555c4000 for "/path/to/testprog".
warning: platform-specific solib_create_inferior_hook did not load initial shared libraries.
Reading symbols from system-supplied DSO at 0x7ff2b000...(no debugging symbols found)...done.
Core was generated by `/remote/path/to/testprog'.
Program terminated with signal SIGABRT, Aborted.
#0  0x77e80204 in ?? ()
[Current thread is 1 (LWP 1285)]
(gdb) bt
warning: GDB can't find the start of the function at 0x77e80204.
GDB is unable to find the start of the function at 0x77e80204
and thus can't determine the size of that function's stack frame.
This means that GDB may be unable to access that stack frame, or
the frames below it.
This problem is most likely caused by an invalid program counter or
stack pointer.
However, if you think GDB should simply search farther back
from 0x77e80204 for code which looks like the beginning of a
function, you can increase the range of the search using the `set
heuristic-fence-post' command.
#0  0x77e80204 in ?? ()
(gdb)

(注意:在上面,我用占位符替换了内部路径/文件名/等(

我尝试过的事情

我尝试了几件事,包括使用set solib-search-path而不是set sysroot,直接告诉 gdb 通过add-symbol-file /path/to/libc.so加载库,甚至add-symbol-file /path/to/libc.so 0xdeadbeef0xdeadbeef实际上是通过 readelf 获得的库加载地址。在最后一种情况下,gdb 最终加载了符号,但显然有些不对劲,可能是我传递的地址不正确。问题是,我不应该这样做,gdb 应该在核心转储中找到此信息并加载库!我如何让它做到这一点,为什么它一开始就不这样做?

/path/to/libc.sogdb它显示了什么? 它可以读取调试符号吗?$ gdb /path/to/libc.so

通常libc.so不包含调试符号本身,而是包含指向包含其调试符号的文件的链接

在 Linux 中,调试符号可以位于:

/usr/lib/debug

/usr/bin/.debug

查看gdb在哪里查找单独的调试符号文件:

(gdb) show debug-file-directory

如果需要,您可以设置为另一个(如果其中包含所需的调试符号文件(

您可以知道 .so 指向的调试符号文件的名称,如下所示:

$ readelf -x.gnu_debuglink /lib/x86_64-linux-gnu/libc.so.6

Hex dump of section '.gnu_debuglink':
0x00000000 6c696263 2d322e32 372e736f 00000000 libc-2.27.so....
0x00000010 48c02c04                            H.,.

libc-2.27.so调试符号文件的名称实际上在我的系统上/usr/lib/debug//lib/x86_64-linux-gnu/

add-symbol-file /path/to/libc.so#here您应该提供包含调试符号的文件,而不是仅具有指向调试符号文件的链接的文件,因为它不包含路径(请参阅上面的输出(,因此可以在帮助和使用debug-file-directory

相关内容

最新更新