我正在尝试调试在具有 MIPS cpu 的板上远程运行的程序,使用 musl 作为其 libc。如果我在板上启动 gdbserver,设置 sysroot viaset sysroot /path/to/sysroot
并从 gdb 实时连接,我会得到一个有意义的堆栈跟踪(由于 musl 在 MIPS 上缺少 CFI 指令而我不得不添加它们,这需要数小时的努力,但这是一个单独的问题),我可以看到 gdblibc.so
从 sysroot 加载符号。
另一方面,如果我让该程序崩溃并生成一个核心转储(我曾经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 0xdeadbeef
0xdeadbeef实际上是加载库的地址,通过readelf获得。在最后一种情况下,gdb 最终加载了符号,但显然有些地方不对劲,可能我传递的地址不正确。问题是,我不应该这样做,gdb 应该在核心转储中找到这些信息并加载库!我如何让它做到这一点,为什么它一开始不这样做呢?