我需要什么来调试pthreads?

Mr *_*nky 8 linux embedded cross-platform pthreads cross-compiling

我想在我的自定义Linux发行版上调试pthreads,但我遗漏了一些东西.我的主机是Ubuntu 12.04,我的目标是使用crosstool-NG交叉编译工具集构建的i486自定义嵌入式Linux,其余的操作系统是用Buildroot制作的.

我会列出事实:

  • 我可以在目标上运行多线程应用程序

  • 当我在目标上运行多线程应用程序时,Google Breakpad无法创建崩溃报告.当我在主机上运行时,具有完全相同构建的Breakpad库的完全相同的应用程序将成功.

  • GDB无法调试目标上的多线程应用程序.

例如

$./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
Run Code Online (Sandbox Code Playgroud)

我不认为ps_lgetfpregs是一个问题因为这个.

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

  • 我的crosstool构建为我的目标创建了gdb,因此它应该与我在目标上运行的相同库链接.

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

我怀疑Breakpad的问题与GDB的问题有关,但我无法证实这一点.唯一的共同点是缺少多线程调试.

我的主机和目标之间存在一些重要的区别,使我无法在目标上调试pthread.

有谁知道它是什么?

编辑:

来自TI的Denys Dmytriyenko说:

通常,GDB不是很挑剔,你可以混合和匹配不同版本的gdb和gdbserver.但是,遗憾的是,如果您需要调试多线程应用程序,那么特定API有一些依赖性......

例如,如果您没有为线程支持正确构建GDB,那么这是您可能会看到的消息之一:

dlopen在'libthread_db.so.1'上失败 - /lib/libthread_db.so.1:未定义的符号:ps_lgetfpregs GDB将无法调试pthread.

请注意,此错误与我获得的错误相同,但他没有详细介绍如何"正确"构建GDB.

GDB FAQ说:

(Q)除了发生崩溃的线程之外,GDB没有看到任何线程; 或者,当我设置断点时,SIGTRAP会终止我的程序.

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

  • 你正在使用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之间的任何不匹配.

Mr *_*nky 5

这个:

dlopen failed on 'libthread_db.so.1' - /lib/libthread_db.so.1: undefined symbol: ps_lgetfpregs
GDB will not be able to debug pthreads.
Run Code Online (Sandbox Code Playgroud)

表示该libthread_db.so.1库无法ps_lgetfpregs在gdb中找到该符号。

为什么?

因为我使用Crosstoolg-NG和“ Build a static native gdb”选项构建了gdb,这会将-static选项添加到gcc。

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

但是-static剥去.dynsym从ELF文件表。

此时有两种选择:

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

编辑:

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