使用gdbserver调试共享库

Set*_*eth 7 linux gdb shared-libraries gdbserver

我在目标和CodeSourcery IDE上使用gdbserver.我的硬件是带有omap3530的gumstix.

我可以在主应用程序中单步执行代码,但如果我尝试进入共享库中的函数,则会获得内存地址并且调试器会终止.

这是我的库,它被编译并复制到目标系统上的/ lib文件夹.(它有调试符号)我试图使用.gbdinit文件来设置solib-absolute-prefix/lib

以下是gdb跟踪的警告:

903,056 13-gdb-set sysroot-on-target /lib
903,065 13^done
903,065 (gdb) 
903,065 14-target-select remote 192.168.1.101:2345
903,114 =thread-group-started,id="i1",pid="42000"
903,114 =thread-created,id="1",group-id="i1"
903,115 15-list-thread-groups --available
903,120 16-list-thread-groups
903,128 &"warning: Unable to find dynamic linker breakpoint function.\nGDB will be unable to debug shared library initializers\nand track explicitly loaded dynamic code."
903,128 &"\n"
Run Code Online (Sandbox Code Playgroud)

这导致

903,395 &"Error while mapping shared library sections:\n"
903,397 &"/lib/libCoreLib.so: Invalid argument.\n"
903,399 =library-loaded,id="/lib/libCoreLib.so",target-name="/lib/libCoreLib.so",hostname="/lib/libCoreLib.so",low-address="0x0",high-address="0x0",symbols-loaded="0",thread-group="i1"
Run Code Online (Sandbox Code Playgroud)

sho*_*nex 6

您可以使用安装在主机上的库进行调试,前提是调试机器也是开发机器。在这种情况下,您可以使用 set sysroot 而不是 set sysroot-on-target。例如 :

set sysroot /home/username/.../rootfs/
Run Code Online (Sandbox Code Playgroud)

where/home/username/.../rootfs/包含目标文件系统的副本

我认为你也应该指定/而不是/lib


Cir*_*四事件 5

带有调试符号的目标

这是最简单的开始工作方法,当您开发一个特定的共享库时它特别有用。

首先将测试可执行文件和共享库复制到带有调试信息的目标:

然后就达到了目标:

gdbserver --multi :1234 ./executable_name
Run Code Online (Sandbox Code Playgroud)

主持人:

arm-linux-gnueabihf-gdb -q -nh \
  -ex "target extended-remote target-hostname-or-ip:1234" \
  -ex "file ./executable_name" \
  -ex 'tb main' \
  -ex 'c' \
  -ex 'set solib-search-path .'
Run Code Online (Sandbox Code Playgroud)

sharedlibrary libmylib.so也有效。

我遇到的问题是gdbserver在动态加载器之前停止,main并且此时动态库尚未加载,因此 GDB 还不知道符号将在内存中的位置。

GDB似乎有一些自动加载共享库符号的机制,如果我为主机编译并gdbserver在本地运行,main则不需要运行到。但在ARM目标上,这是最可靠的做法。

目标gdbserver7.12-6,主机arm-linux-gnueabihf-gdb来自 Linaro 的 7.6.1。

没有调试符号的目标库

在嵌入式目标上部署之前剥离目标库是很常见的,因为调试信息会使它们变得更大。

例如,Buildroot 默认情况下会执行此操作,但您可以使用 禁用它BR2_STRIP_none=y

您可以通过运行以下命令来识别这种情况:

info shared
Run Code Online (Sandbox Code Playgroud)

这显示了类似的内容:

From                To                  Syms Read   Shared Object Library
0x00007ffff7df7f90  0x00007ffff7dfcdd7  Yes (*)     target:/lib/ld64-uClibc.so.0
0x00007ffff7b3a9b0  0x00007ffff7bbe05d  Yes (*)     target:/lib/libc.so.0
(*): Shared library is missing debugging information.
Run Code Online (Sandbox Code Playgroud)

因此这两个库都有星号 ( *),表示缺少调试信息。

如果是这种情况,那么您必须在主机上的共享库被剥离之前告诉 GDB 使用它们。

例如,Buildroot 使这对我们来说很容易,因为它在staging删除共享库之前维护包含共享库的目录,并且其相对路径与目标中的相对路径相同:

set sysroot buildroot/output/staging/
Run Code Online (Sandbox Code Playgroud)

设置此选项后,gdb立即在主机而不是目标中搜索库,并/lib/libc.so.0在路径buildroot/output/staging/+处查找/lib/libc.so.0

Reading symbols from buildroot/output/staging/lib/ld64-uClibc.so.0...done.
Reading symbols from buildroot/output/staging/lib/libc.so.0...done.
Run Code Online (Sandbox Code Playgroud)

TODO:我认为您不能设置多个sysroot,因此所有共享库必须放置在目标图像中正确的相对路径中。

如果您检查错误的默认 sysroot,您将看到:

show sysroot
Run Code Online (Sandbox Code Playgroud)

给:

target:
Run Code Online (Sandbox Code Playgroud)

这意味着默认gdb在目标根目录上搜索共享库。/