我需要debuggingpthreads?

我想debugging我的自定义Linux发行版上的pthreads,但我错过了一些东西。 我的主机是Ubuntu 12.04,我的目标是使用crosstool-NG交叉编译器工具集构build的i486定制embedded式Linux,其余的操作系统是使用Buildroot制作的。

我将列举事实:

例如

$./gdb -n -ex "thread apply all backtrace" ./a.out --pid 716 dlopen failed on 'libthread_db.so.1' - /lib/libthread_db.so.1: undefined symbol: ps_lgetfpregs GDB will not be able to debug pthreads. GNU gdb 6.8 

我不认为ps_lgetfpregs是因为这个问题。

  • 我的crosstool构build了libthread_db.so文件,并将其放在目标上。

  • 我的crosstool构build为我的目标创build了gdb,所以它应该与我在目标上运行的库相链接。

  • 如果我在我的主机上运行gdb,对我的testing应用程序,我得到每个运行线程的回溯。

我怀疑Breakpad的问题与GDB的问题有关,但是我不能证实这一点。 唯一的共同点是缺乏multithreadingdebugging。

我的主机和目标之间有一些关键的区别阻止了我能够debugging目标上的pthreads。

有谁知道它是什么?

编辑:

TI的Denys Dmytriyenko表示:

通常情况下,GDB不是很挑剔,你可以混合使用不同版本的gdb和gdbserver。 但是,不幸的是,如果您需要debuggingmultithreading应用程序,那么对于特定的API有一些依赖关系…

例如,如果您没有为线程支持正确构buildGDB,则可能会看到以下消息之一:

dlopen在'libthread_db.so.1'上失败 – /lib/libthread_db.so.1:undefined symbol:ps_lgetfpregs GDB将无法debuggingpthreads。

请注意,这个错误与我所得到的错误是一样的,但他没有详细介绍如何正确地构buildGDB。

GDB常见问题解答说:

(Q)除了发生崩溃的线程外,GDB没有看到任何线程。 或SIGTRAP杀死我的程序,当我设置一个断点。

(A)这经常发生在Linux上,特别是在embedded式目标上。 有两个常见原因:

  • 你正在使用glibc,并且已经剥离了libpthread.so.0

  • libpthread.so.0和libthread_db.so.1不匹配

GDB本身并不知道如何解码由glibc维护的“线程控制块”,并被认为是glibc的私有实现细节。 它使用libthread_db.so.1(glibc的一部分)来帮助它。 因此,libthread_db.so.1和libpthread.so.0必须在版本和编译标志中匹配。 另外,libthread_db.so.1要求在libpthread.so.0中存在某些非全局符号。

解决方法:使用strip –strip-debug libpthread.so.0而不是strip libpthread.so.0。

我试过一个没有剥离的libpthread.so.0,但是没有什么区别。 我将调查pthread和thread_db之间的任何不匹配。

这个:

 dlopen failed on 'libthread_db.so.1' - /lib/libthread_db.so.1: undefined symbol: ps_lgetfpregs GDB will not be able to debug pthreads. 

意味着libthread_db.so.1库无法在gdb中找到符号ps_lgetfpregs

为什么?

因为我使用Crosstoolg-NG构建了gdb,并使用“构建静态本地gdb”选项,这会将-static选项添加到gcc。

本机gdb是使用-rdynamic选项构建的,这将ELF文件中的.dynsym符号表填充为全部符号,甚至是未使用的符号。 libread_db使用此符号表从gdb中查找ps_lgetfpregs

-static从ELF文件中.dynsym表。

此时有两种选择:

  1. 如果你想调试线程,不要建立一个静态的本机gdb。
  2. 构建一个静态的gdb和一个静态的libthread_db(未经测试)

编辑:

顺便说一下,这并不能解释为什么Breakpad无法在我的目标上调试多线程应用程序。

只是一个虽然…要使用gdb调试器,你需要用-g选项编译你的代码。 例如,gcc -g -c * .c。