如何为已安装的软件包安装调试符号?

如何为已安装的软件包安装调试符号?

我尝试通过“Qt Creator”调试器运行程序来观察程序的运行情况。为了更好地定位,我还想在调用堆栈窗口中完整地查看系统(核心)实用程序,因为我习惯使用 MS Visual Studio 6.0,而不仅仅是查看它们的汇编代码。对于实用程序,“Qt Creator”调试器仅显示它们的调试符号不可用。(有时,系统会为其开发人员生成错误报告;错误报告对话框要求仅为特定程序安装此类符号。)如何获取核心调试符号?(无需翻译整个 Ubuntu 版本。我使用“更新管理器”定期安装更新。我的

/sys/内核/调试/x86
目录中只有一个空文件。我在“Ubuntu 软件中心”中没有找到它,也没有看到目录中的一些软件包http://packages.ubuntu.com/precise/x11/是我所寻求的。)谢谢!

答案1

Ubuntu 中的软件包将其调试符号存储在单独的存储库中。要下载这些调试符号,请运行(复制并粘贴):

printf "deb http://ddebs.ubuntu.com %s main restricted universe multiverse\n" $(lsb_release -cs){,-updates,-security,-proposed} | \
 sudo tee -a /etc/apt/sources.list.d/ddebs.list

将 repo 链接添加到其中/etc/apt/sources.list.d/ddebs.list(这可以更轻松地删除 repo)。或者,您也可以将每个链接复制deb到软件源中,然后从那里添加它们(请注意,您可能需要用$(lsb_release -cs)您正在运行的 Ubuntu 版本替换它们)。

然后,对于 Ubuntu 18.04 或更高版本,您需要执行密钥环安装命令:

sudo apt install ubuntu-dbgsym-keyring

然后,对于任何 Ubuntu,运行:

sudo apt update

要下载 的调试符号package,您只需安装package-dbgsym或者,在某些情况下,package-dbg。请注意,来自 PPA 的软件包没有来自存储库的调试符号,并且维护者有责任提供包含调试符号的软件包,通常在名为 的软件包中package-dbg

调试符号安装在 中/usr/lib/debug,但gdb如果可用,它会自动读取调试符号,您无需手动指定查找位置。根据软件包的 Debhelper 兼容性版本,调试符号可能位于以构建 ID 名称命名的文件夹中.build-id>= 9),也可能位于可执行文件安装位置的相对位置(< 9)。例如,如果您正在寻找 的调试符号的位置/usr/bin/zip,并且版本低于 9,它将位于 中/usr/lib/debug/usr/bin/zip

要删除所有调试符号和 repo,请运行sudo apt-get remove \.*-dbgsym删除所有-dbgsym包,然后sudo rm /etc/apt/sources.list.d/ddebs.list删除调试符号 repo。

答案2

补充 Evans 的回答:在 Ubuntu 18.04 及更高版本上,您可以使用命令

sudo apt install ubuntu-dbgsym-keyring

安装 GPG 密钥。(根据https://wiki.ubuntu.com/Debug%20Symbol%20Packages

答案3

补充 saircot859 的回答。您还必须按照此处所述安装存储库的 GPG 密钥:https://wiki.ubuntu.com/Debug%20Symbol%20Packages

sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 428D7C01 C8CAB6595FDFF622

答案4

还可以获得正确的源代码apt source

除了符号之外,您还可以获取apt source如下来源:

然后使用 GDB 指向它们,substitute-path如下所述:https://stackoverflow.com/questions/23868252/gdb-source-path

Ubuntu 22.04 上的一些完全可用的命令,例如lscoreutils后面进行调试。

首先我们获取调试符号:

printf "deb http://ddebs.ubuntu.com %s main restricted universe multiverse\n" $(lsb_release -cs){,-updates,-security,-proposed} | \
 sudo tee -a /etc/apt/sources.list.d/ddebs.list
sudo apt install ubuntu-dbgsym-keyring
sudo apt update
sudo apt install coreutils-dbgsym

接下来我们获取源代码如下:错误::您必须在 sources.list 中放入一些“源”URI

sudo cp /etc/apt/sources.list /etc/apt/sources.list~
sudo sed -Ei 's/^# deb-src /deb-src /' /etc/apt/sources.list
sudo apt update
apt source coreutils

生成一个目录coreutils-8.32

最后,我们运行lsGDB 并指向下载的源代码。在 Ubuntu 22.04 上:

gdb -ex 'set substitute-path . coreutils-8.32' ls

在 Ubuntu 23.10 上我需要:

gdb -ex "set substitute-path /usr/src/coreutils-9.1-1ubuntu2 coreutils-9.1" ls

现在我正确地看到了来源如下:

(gdb) start
Temporary breakpoint 1 at 0x4d20: file src/ls.c, line 1622.
Starting program: /usr/bin/ls 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Temporary breakpoint 1, main (argc=1, argv=0x7fffffffce08) at src/ls.c:1622
warning: Source file is more recent than executable.
1622    {
(gdb) l
1617      signal_setup (false);
1618    }
1619
1620    int
1621    main (int argc, char **argv)
1622    {
1623      int i;
1624      struct pending *thispend;
1625      int n_files;
1626

选择set substitute-path .是因为如果没有substitute-path它会失败:

1622    src/ls.c: No such file or directory.

.因此我们通过将其转换为coreutils-8.32/所在位置来帮助 GDB 找到源src/。而在 Ubuntu 23.10 上,错误改为:

Cannot display "/usr/src/coreutils-9.1-1ubuntu2/src/ls.c" ([Errno 2] No such file or directory: '/usr/src/coreutils-9.1-1ubuntu2/src/ls.c')

所以现在我们想/usr/src/coreutils-9.1-1ubuntu2用 来代替coreutils-9.1

实际上,Ubuntu 23.10 的路径/usr/src非常好,明智的做法是将所有源都转储到那里,这样我们就可以一直避免这种情况substitute-path。但是,即使我cd/usr/src首先这样做,由于-1ubuntu2后缀的原因,它仍然无法正常工作。但我们可以手动:

sudo cp -rv coreutils-9.1/ /usr/src/coreutils-9.1-1ubuntu2

这使我们能够简单地:

gdb ls

不幸的是,并非所有软件包都遵循该/usr/src约定,例如在 Ubuntu 23.10 上libx11-6-dbgsym有前缀/build/libx11-9By7Fr/libx11-1.8.6/build/src/../../src/XlibInt.c。总有一天我们会到达那里。

GDB 单步调试进入 glibc

共享库也适用完全相同的过程。例如,按照以下要求使用 GDB step debug glibc:

在这种情况下,调试符号似乎已经预先安装好了,否则我们需要:

sudo apt install libc6-dbg

然后获取源代码:

apt source libc6

生成目录:glibc-2.35

然后我们创建一个 C hello world 来测试:

主程序

#include <stdio.h>

int main(void) {
    puts("hello");
}

如果我们尝试编译,GDB并进入glibc

gcc -ggdb3 -O0 -std=c99 -Wall -Wextra -pedantic -o main.out main.c
gdb main.out

作为:

(gdb) start
Temporary breakpoint 1 at 0x1151: file main.c, line 4.
Starting program: /home/ciro/tmp/main.out 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Temporary breakpoint 1, main () at main.c:4
4           puts("hello");
(gdb) s
__GI__IO_puts (str=0x555555556004 "hello") at ./libio/ioputs.c:33
33      ./libio/ioputs.c: No such file or directory.
(gdb)

我们看到该库还搜索下的文件./,因此我们再次:

set substitute-path . glibc-2.35

现在我们可以看到源代码:

(gdb) l
28      #include <string.h>
29      #include <limits.h>
30
31      int
32      _IO_puts (const char *str)
33      {
34        int result = EOF;
35        size_t len = strlen (str);
36        _IO_acquire_lock (stdout);
37

Ubuntu 的某些其他版本在绝对位置有源,例如:

/tmp/build138741687/

在这种情况下,您可能想要:

set substitute-path /tmp/build138741687/ glibc-2.35

相关内容