如何在Ubuntu上使用调试库

11

我目前的问题与libwebkitgtk-3.0-0有关,但我想这个问题是通用的。

我的应用程序在WebKit代码中崩溃。 我的假设是我们正在做一些愚蠢的事情,想找出原因。最简单的方法是设置断点或使用库的调试版本。

  1. 如何获取构建该库的确切源代码? 在它转储核心后,我得到堆栈跟踪,但gdb所说的行号与我在代码中看到的行号不匹配。 换句话说,如果我安装libwebkitgtk-3.0-0,我想获得准确的源代码。

  2. 我已经安装了webkit库的调试版本。 这些调试版本是否具有与使用--enable-debug标志编译webkit相同的功能? Webkit的调试版本基于WEBKIT_DEBUG环境变量启用日志记录,但即使使用库的调试版本,我也无法获得相同的日志记录。

  3. 如何使用我成功编译的调试版本? 我已经在我的机器上编译了webkit,并尝试了各种负载路径等操作。 无论我做什么,应用程序都不会拾取新的共享库 - 我可以根据用户代理签名来确定。 在某个时候,我设法捡起了库,但是然后SSL停止工作。 同样的SSL问题也会在GtkLauncher中出现。 所以我做错了什么。

谢谢指教。

4个回答

31

TL;DR: 安装 libwebkitgtk-3.0-0-dbg Install libwebkitgtk-3.0-0-dbg,然后您就拥有必要的调试符号。

##对于调试符号,通常不必从源代码安装。

如您所知,为了获取自己构建的软件的调试符号,可以使用带有-g选项的GCC。

对于通过操作系统包管理器(包括此处的libwebkitgtk-3.0-0)安装的软件,至少对于官方包来说,通常也提供提供调试符号的包

实际上,您不需要具有程序或库的调试版本即可在gdb中获取符号堆栈跟踪。 gdb还支持在/usr/lib/debug中提供“附加”调试符号的文件。

您根据问题的标签使用Ubuntu。在Ubuntu上,调试符号包有两种类型:-dbg-dbgsym。位于/路径的程序或库将在/usr/lib/debug/路径处获取调试符号。
## -dbg软件包
这些软件包的名称通常与提供实际可执行文件或库文件的相应软件包不同。它们的名称通常类似于提供头文件的-dev软件包和-doc软件包。一个-dbg软件包有时在名称中具有比实际库软件包更少的库版本编号,有时覆盖在多个其他软件包中提供的二进制文件。
例如,libgtkmm-3.0-1的相应-dbg软件包是libgtkmm-3.0-dbg

另一方面,有时候一个-dbg包的名称与其提供符号的包相同(除了-dbg后缀)。例如,libwebkitgtk-3.0-0的对应-dbg包是libwebkitgtk-3.0-0-dbg那就是你想要的。

你可以在软件中心安装它,或者运行以下命令:

sudo apt-get update && sudo apt-get install libwebkitgtk-3.0-0-dbg

现在,当您调试链接到由libwebkitgtk-3.0-0提供的库的程序时,gdb将自动从libwebkitgtk-3.0-0-dbg提供的文件中加载符号。

##-dbgsym软件包

有时官方软件包提供的二进制可执行文件没有任何-dbg软件包提供的符号。当出现这种情况时,通常可以安装-dbgsym软件包。

-dbg软件包不同,-dbgsym软件包:

  • 几乎总是以简单(和可预测)的方式命名为X-dbgsym,其中X是提供程序或库本身的软件包。
  • 由特殊的软件源(存储库)提供,而不是提供相应程序/库软件包和-dbg软件包的相同软件源。

由于-dbgsym软件包位于单独的存储库中,因此必须启用这些存储库。它们的DEB行是:

deb http://ddebs.ubuntu.com <strong>YOUR_RELEASE</strong> main restricted universe multiverse
deb http://ddebs.ubuntu.com <strong>YOUR_RELEASE</strong>-updates main restricted universe multiverse
deb http://ddebs.ubuntu.com <strong>YOUR_RELEASE</strong>-security main restricted universe multiverse
deb http://ddebs.ubuntu.com <strong>YOUR_RELEASE</strong>-proposed main restricted universe multiverse

为了启用它们,您可以运行以下命令(改编自DebuggingProgramCrash,由Ubuntu文档维基的贡献者第2节):
echo "deb http://ddebs.ubuntu.com $(lsb_release -cs) main restricted universe multiverse
<em>deb http://ddebs.ubuntu.com $(lsb_release -cs)-updates main restricted universe multiverse
deb http://ddebs.ubuntu.com $(lsb_release -cs)-security main restricted universe multiverse
deb http://ddebs.ubuntu.com $(lsb_release -cs)-proposed main restricted universe multiverse</em>
" | sudo tee -a /etc/apt/sources.list.d/ddebs.list
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 428D7C01
sudo apt-get update

留下斜体字行(如果您使用开发版本(alpha或beta),请不要留下斜体字行)。但是,如果您继续使用稳定版本,则确保添加它们。

这些命令执行三个操作:

  1. 创建文件/etc/apt/sources.list.d/ddebs.list(其中包含DEB行)。
  2. 导入这些存储库的签名密钥。
  3. 更新系统有关从哪里安装哪些软件包和版本的信息。

因此,如果您想要使用提供的符号-dbgsym而不是提供的符号-dbg,则与上述简单命名约定相符的libwebkitgtk-3.0-0-dbgsym软件包是libwebkitgtk-3.0-0-dbgsym

您可以在同一系统上安装-dbg-dbgsym软件包,但如果它们提供相同文件的符号,则不行。因此,libwebkitgtk-3.0-0-dbglibwebkitgtk-3.0-0-dbgsym会互相冲突;它们不能同时安装。

##使用符号

在大多数类Unix操作系统中,调试器会自动查找已安装的符号。Ubuntu也不例外——在Ubuntu中,gdb会自动在/usr/lib/debug中查找它们。因此,您无需进行任何特殊操作。

但是,如果您需要告诉gdb加载特定的调试符号文件,则应使用-s file标志。有关详细信息,请参见GNU手册gdb(1)


这很有趣,但它如何帮助?如果你没有安装源代码,你仍然无法准确地看到导致问题的原因——除非你能从调用栈中的函数名猜测出来。 - Brent Bradburn
1
不幸的是,这并不总是奏效。例如,libarchive13既没有-dbg也没有-dbgsym.... - socketpair
我认为经过一段时间的尝试,这是不可能的,而且Ubuntu也不在意。如果我们想要对第三方库(如Webkit或GTK)进行源代码单步调试,难道我们都必须去安装Gentoo吗? - Lothar
我的脚本替换了一个损坏的链接,但我不确定这个包现在位于哪里。请考虑改进修复或回滚 :) - Glorfindel

5

1) 当我需要调用通过包安装的库时,我会首先从源代码进行安装。我的意思是配置/make/make install。我通常将源代码放在/usr/local/src下,并将其安装在/usr/local中。在我看来,这是运行您拥有源代码的确切代码最可靠的方法。

2) 典型情况下是这样的。但这取决于库的编写方式以及Ubuntu打包者决定采取的措施。

3)

我如何使用我编译的调试版本?

这听起来就像我上面所描述的。您需要做的是确保您的软件正在使用托管编译的启用调试的库的包含和链接目录。这意味着要确保设置-I/usr/local/include和-L /usr/local/lib标志,并且它们排在/usr/include和/usr/lib之前。

您甚至可以通过从Ubuntu安装中删除库的二进制版本来更加确定,确保您构建和安装的版本是硬盘上唯一存在的版本。这样,您就可以确定您能够配置应用程序使用该库,否则它将失败,而不是您不断想知道它是否使用了新库还是旧库。

这样一来,您就可以更好地理解问题的根源。祝你好运!


4

@Eliah的回答介绍了一种便捷获取符号的方法。

问题在于,“如何获得准确的源代码?”

通常我会使用apt-get source <pkgname>,这很好,但是之后我必须手动告诉gdb:dir <path-to-wherever-I-put-the-source>。如果是像eglibc这样的包,就必须确定路径引用来自nss子目录,而不是根目录。

在RHEL上只需执行例如yum install --enable-repo rhel-debuginfo libX11-debuginfo(在CentOS 7上仅为yum install libX11-debuginfo),即可立即获得完整的符号和源代码,无需额外的麻烦。我还在寻找Ubuntu上的相应便利方法。


以下是在kdbg中的操作步骤:设置->此程序->调试器: gdb --fullname --nx --directory(库源码的相对路径)--参见此处 - Brent Bradburn

1
为了针对动态库进行调试,您可以按建议添加带有符号和源分发包的调试齿轮。然后需要检查调试符号表的编译目录是否与已安装源的路径匹配,如果不是,则应在gdb中映射路径。按照以下命令启用glibc的调试。
$ objdump -g /usr/lib/debug/lib/x86_64-linux-gnu/libc-2.27.so | sed -n '/<.*>\s\+DW_AT_comp_dir/ {s/\s\+<.*>\s\+//; p;}' | sort | uniq
DW_AT_comp_dir : (indirect string, offset: 0x1127a): /build/glibc-OTsEL5/glibc-2.27/malloc
...
DW_AT_comp_dir : (indirect string, offset: 0xd139): /build/glibc-OTsEL5/glibc-2.27/stdio-common
DW_AT_comp_dir : (indirect string, offset: 0xef40): /build/glibc-OTsEL5/glibc-2.27/libio
$ ls -ld glibc-2.27/{stdio-common,libio}
drwxrwxr-x 3 fusillator fusillator 12288 feb 1 2018 glibc-2.27/libio
drwxrwxr-x 3 fusillator fusillator 4096 feb 1 2018 glibc-2.27/stdio-common
$ gdb ./hello
Reading symbols from ./hello...done.
(gdb) set substitute-path /build/glibc-OTsEL5/glibc-2.27 glibc-2.27
(gdb) b main
Breakpoint 1 at 0x63e: file hello.c, line 10.
(gdb) run
Starting program: hello
Breakpoint 1, main () at hello.c:10
10 printf("hello world\n");
(gdb) s
_IO_puts (str=0x5555555546e4 "hello world") at ioputs.c:33
33 {
(gdb) backtrace
#0 _IO_puts (str=0x5555555546e4 "hello world") at ioputs.c:33
#1 0x000055555555464a in main () at hello.c:10

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