我尝试通过“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 上的一些完全可用的命令,例如ls
从coreutils
后面进行调试。
首先我们获取调试符号:
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
。
最后,我们运行ls
GDB 并指向下载的源代码。在 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:
- https://stackoverflow.com/questions/48476571/get-source-code-for-libc-for-debugging-in-gdb
- https://unix.stackexchange.com/questions/678163/how-can-i-get-glibc-libstdc-sources-and-set-them-up-for-gdb-to-find
在这种情况下,调试符号似乎已经预先安装好了,否则我们需要:
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