Dan*_*ele 5 linux debugging gdb mips musl
我正在尝试调试在具有 MIPS cpu 的板上远程运行的程序,使用 musl 作为其 libc。如果我在板上启动 gdbserver,设置 sysroot viaset sysroot /path/to/sysroot并从 gdb 进行实时连接,我会得到有意义的堆栈跟踪(由于 musl 缺乏 MIPS 上的 CFI 指令,而我必须添加它们,因此需要花费数小时的时间,但这是一个单独的问题),我可以看到 gdb 从libc.sosysroot 加载符号。
另一方面,如果我让该程序崩溃并生成核心转储(我曾经kill -6 <pid>强制使用一个核心转储进行测试),gdb 将从二进制文件中加载符号,但不会加载其任何共享库,甚至不会加载libc.so. 虽然其他共享库很好但不是必需的,如果没有来自 libc.so 的调试信息,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
Run Code Online (Sandbox Code Playgroud)
(注意:在上面我用占位符替换了内部路径/文件名/等)
$ 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)
Run Code Online (Sandbox Code Playgroud)
(注意:在上面我用占位符替换了内部路径/文件名/等)
我尝试了几件事,包括使用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 应该在核心转储中找到此信息并加载库!我怎样才能让它做到这一点,为什么它一开始不这样做呢?
给予/path/to/libc.so它gdb表明了什么?它可以读取调试符号吗?
$ 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.,.
Run Code Online (Sandbox Code Playgroud)
我的系统上libc-2.27.so实际存在调试符号文件的名称/usr/lib/debug//lib/x86_64-linux-gnu/
或者,
add-symbol-file /path/to/libc.so#这里你应该给出包含调试符号的文件,而不是仅具有调试符号文件链接的文件,因为它不包含路径(参见上面的输出),调试符号文件是通过帮助和使用找到的debug-file-directory