4

我正在尝试调试在具有 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 0xdeadbeef0xdeadbeef实际上是加载库的地址,通过readelf获得。在最后一种情况下,gdb 最终加载了符号,但显然有些地方不对劲,可能我传递的地址不正确。问题是,我不应该这样做,gdb 应该在核心转储中找到这些信息并加载库!我如何让它做到这一点,为什么它一开始不这样做呢?

4

1 回答 1

2

给它显示/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.,.

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

或者,

add-symbol-file /path/to/libc.so#这里你应该给出包含调试符号的文件,而不是只链接到调试符号文件的文件,因为它不包含路径(见上面的输出),调试符号文件是在帮助和使用下找到的debug-file-directory

于 2020-02-02T10:54:26.100 回答