gdb:线程调试不可用?

3
我正在使用gdb-7.11.1,并在嵌入式powerpc系统上收到此消息。更多背景情况是,我使用的libpthread已经剥离了所有非动态符号,包括 nptl_version,这是 libthread_db 用来确保其与 libpthread 兼容的符号。
至于我的问题,gdb说它将无法调试线程,但从下面的证据看似乎可以。难道我只是误解了“线程调试”的意思吗?(您看到的 ?? 自然是由于 libpthread 中缺少符号表引起的)
(gdb) break fn2
Breakpoint 1 at 0x1000052c: file test.c, line 7.
(gdb) run
Starting program: /tmp/test
warning: Unable to find libthread_db matching inferior's thread library, thread debugging will not be available.
[New LWP 21312]
[New LWP 21313]
[New LWP 21314]
[New LWP 21315]
[New LWP 21316]
[New LWP 21317]
[Switching to LWP 21315]

Thread 5 hit Breakpoint 1, fn2 () at test.c:7
7   test.c: No such file or directory.
(gdb) thread apply all bt

Thread 7 (LWP 21317):
#0  0x0fdcf030 in ?? () from /lib/libpthread.so.0
#1  0x0fdc892c in pthread_mutex_lock () from /lib/libpthread.so.0
#2  0x00000000 in ?? ()

Thread 6 (LWP 21316):
#0  0x0fdcf030 in ?? () from /lib/libpthread.so.0
#1  0x0fdc892c in pthread_mutex_lock () from /lib/libpthread.so.0
#2  0x00000000 in ?? ()

Thread 5 (LWP 21315):
#0  fn2 () at test.c:7
#1  0x0fdc6d8c in ?? () from /lib/libpthread.so.0
#2  0x0fd26074 in clone () from /lib/libc.so.6

Thread 4 (LWP 21314):
#0  0x0fdcf030 in ?? () from /lib/libpthread.so.0
#1  0x0fdc892c in pthread_mutex_lock () from /lib/libpthread.so.0
#2  0x00000000 in ?? ()

Thread 3 (LWP 21313):
#0  0x0fdcf030 in ?? () from /lib/libpthread.so.0
#1  0x0fdc892c in pthread_mutex_lock () from /lib/libpthread.so.0
#2  0x00000000 in ?? ()

Thread 2 (LWP 21312):
#0  0x0fdcefdc in ?? () from /lib/libpthread.so.0
#1  0x0fdc892c in pthread_mutex_lock () from /lib/libpthread.so.0
#2  0x00000000 in ?? ()

Thread 1 (LWP 21309):
#0  0x0fd26038 in clone () from /lib/libc.so.6
#1  0x0fdc5f2c in ?? () from /lib/libpthread.so.0
#2  0x0fde6150 in ?? () from /lib/libpthread.so.0
#3  0x0fdc6424 in pthread_create () from /lib/libpthread.so.0
#4  0x100006a4 in main () at test.c:23
(gdb) 

你是否在进行交叉调试?很可能你需要使用 set solib-search-pathset libthread-db-search-path 命令来让 GDB 找到正确的共享库。 - tofro
@tofro 不,我实际上是在板子上运行gdb。我可以看到gdb在/lib/中找到了libpthread和libthread_db,而这些是整个文件系统中唯一的副本。 - John Engel
2个回答

1
在Linux(至少是其他系统),线程库的一个重要部分是在内核中实现的:“内核线程”,称为LWPs(轻量级进程)。
GDB不需要libthread_db的帮助来跟踪它们,因为操作系统本身可以提供关于它们的关键信息:它们的CPU寄存器(主要是IP、SP、FP)。
我不确定libthread_db在这种情况下提供了什么。我唯一能想到的就是LWP<->Thread ID映射:
* 3    Thread 0x7ffff6d19700 (LWP 21571) "erato" primes_computer_runner2 (param=0x7fffffffca50) at erato.c:46
  1    Thread 0x7ffff7fad700 (LWP 21565) "erato" 0x00007ffff7bc568d in pthread_join () from /usr/lib/libpthread.so.0

(gdb) print/x thread_handle
$1 = 0x7ffff6d19700

看到了吗,Thread 0x7ffff7fad700 对应 LWP 21565

相比之下,没有 libthread_db 时只会给出 LWP id(在另一次运行中):

* 3    LWP 22060 "erato" primes_computer_runner2 (param=0x7fffffffca50) at erato.c:46
  1    LWP 22058 "erato" 0x00007ffff76037b1 in clone () from /usr/lib/libc.so.6

如果您想了解有关pthread_db目的的更多详细信息,以及为什么它对于用户和混合线程库是强制性的(或等效的),您可以查看我几年前撰写的这篇文章:

1
“在这种情况下,libthread_db提供了什么?” - 它提供了新线程创建的通知(以及其他功能),这样GDB可以附加新线程。如果没有它,新创建的线程可能会运行未附加状态(至少直到下一个断点),而且如果新线程崩溃,你可能会失去整个低级别程序。” - Employed Russian
我明白...但是它不能使用与fork和/或exec相同的技术吗?(我的意思是,catch forkcatch exec。)我没有看到它们之间有任何根本区别,也就是线程创建。 - Kevin

1
这个错误信息的常见原因是:
Unable to find libthread_db matching inferior's thread library, ...

在编程中,libpthread.so.0完全剥离是不可取的。请注意。

特别地,libthread_db.so需要nptl_version(本地)符号。您可以使用以下命令验证您的libpthread.so.0是否具有该符号:

nm /path/to/libpthread.so.0 | grep version

应该生成类似于以下内容的东西:
0000000000012cc6 r nptl_version

有没有办法绕过nptl_version检查?我有一个挂起的进程,它使用了剥离版本的libpthread.so。在使用gdb附加到它后,由于上述错误,我无法调试线程。有没有办法强制gdb跳过版本检查?如果有影响的话,我有一个未剥离版本的libpthread.so。 - Alex Che
只是想说我可以使用“nm”和“file”来确认我的libpthread没有被剥离,但我仍然看到错误。 - JoeManiaci
@JoeManiaci,你是否有libthread_db.so.1这个文件?它是和libpthread.so.0来自同一个软件包吗? - Employed Russian
@EmployedRussian 我收回之前的说法,我所拥有的是libpthread_db-1.0.so。将它所在的最顶层目录作为参数传递给“set libthread-db-search-path”仍然似乎没有产生任何影响。 - JoeManiaci
从 https://sourceware.org/gdb/onlinedocs/gdb/Threads.html#Threads 中可以看到,“设置libthread-db-search-path目前仅在某些平台上实现”。因此,也许ARM或我的版本是其中之一。 - JoeManiaci
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接