第 20 章 调试正在运行的应用程序
本章介绍了用于调试应用(可根据需要多次)在开发人员直接访问的机器上执行的技术。
20.1. 使用调试信息启用调试
要调试应用和库,需要调试信息。以下小节描述了如何获取此信息。
20.1.1. 调试信息
在调试任何可执行代码时,两种信息可以允许工具,并扩展程序员以理解二进制代码:
- 源代码文本
- 有关源代码文本与二进制代码的关系的描述
这称为调试信息。
Red Hat Enterprise Linux 对可执行二进制文件、共享库或调试信息文件使用 ELF 格式。在这些 ELF 文件中,DWARF 格式用于保存调试信息。
DWARF 符号由 readelf -w file
命令读取。
UNIX 偶尔会使用 STABS。STABS 是一种较旧、更少的格式。红帽不鼓励其使用。GCC 和 GDB 只支持 STABS 生产与消费。Valgrind 和 elfutils 等其他工具根本不支持 STABS。
其它资源
20.1.2. 使用 GCC 启用 C 和 C++ 应用程序
由于调试信息较大,因此默认情况下,不会包含在可执行文件中。要为您的 C 和 C++ 应用程序进行调试,您必须明确指示编译器创建调试信息。
使用 GCC 启用调试信息
要在编译和链接代码时使用 GCC 创建调试信息,请使用 -g
选项:
$ gcc ... -g ...
-
由编译器和链接器执行的优化可能会导致可执行代码难以与原始源代码相关:变量可以被优化,取消滚动,将操作合并到周围的代码中。这会影响调试。要改进调试体验,请考虑使用
-Og
选项设置优化。但是,更改优化级别会更改可执行代码,并可能会更改实际行为,以便删除一些程序错误。 -
f
compare-debug
GCC 选项测试 GCC 使用调试信息编译的代码,无需调试信息。如果生成的两个二进制文件相同,则测试将通过。此测试可确保可执行代码不受任何调试选项的影响,进一步确保调试代码中没有隐藏的错误。请注意,使用-fcompare-debug
选项可显著增加编译时间。有关这个选项的详情,请查看 GCC 手册页。
其它资源
- 第 20.1 节 “使用调试信息启用调试”
- 使用 GNU Compiler Collection(GCC)- 3.10 选项用于调试您的程序
- 使用 GDB 进行调试 — 18.3 Debugging Information in Separate Files
GCC 手册页:
$ man gcc
20.1.3. debuginfo Packages
debuginfo 软件包包含程序和库的调试信息和调试源代码。
先决条件
debuginfo Packages
对于从 Red Hat Enterprise Linux 软件仓库安装的软件包中安装的应用程序和库,您可以获得调试信息和调试源代码作为单独的通过另一个频道提供的调试信息软件包。debuginfo 软件包包含
.debug
文件,其中包含 DWARF debuginfo 和用于编译二进制软件包的源文件。debuginfo 软件包内容安装到 /usr/lib/debug
目录中。
debuginfo 软件包仅对具有相同名称、版本、发行版本和架构的二进制软件包提供调试信息有效:
-
二进制
软件包:packagename-version-release.architecture.rpm
-
debuginfo package:
packagename-debuginfo-version-release.architecture.rpm
20.1.4. 使用 GDB 获取应用程序或库的调试信息软件包
GNU Debugger(GDB)会自动识别缺少的调试信息并解决软件包名称。
先决条件
- 您要调试的应用程序或库安装在系统中
- GDB 已安装在系统中
-
debuginfo-install
工具安装在系统中
步骤
启动连接到要调试的应用程序或库的 GDB。GDB 自动识别缺少的调试信息,并建议要运行的命令。
$ gdb -q /bin/ls Reading symbols from /usr/bin/ls...Reading symbols from /usr/bin/ls...(no debugging symbols found)...done. (no debugging symbols found)...done. Missing separate debuginfos, use: debuginfo-install coreutils-8.22-21.el7.x86_64 (gdb)
退出 GDB,但不继续操作:键入 q 和 Enter。
(gdb) q
运行 GDB 建议的命令来安装所需的 debuginfo 软件包:
# debuginfo-install coreutils-8.22-21.el7.x86_64
为应用程序或库安装 debuginfo 软件包会为所有依赖项安装 debuginfo 软件包。
-
如果 GDB 无法推荐 debuginfo 软件包,请按照 第 20.1.5 节 “手动
获取
应用程序或库的调试信息软件包” 中的步骤操作。
其它资源
- Red Hat Developer Toolset 用户指南 - 安装调试信息
- 红帽知识库解决方案 - 如何为 RHEL 系统下载或安装 debuginfo 软件包?
20.1.5. 手动 获取
应用程序或库的调试信息软件包
要手动选择(安装) debuginfo
软件包(用于安装),请找到可执行文件 并查找该软件包来安装该软件包。
使用 GDB 确定安装的软件包更好。只有在 GDB 无法建议安装软件包时,才使用此手动步骤。
先决条件
- 应用程序或库必须安装在系统中
-
debuginfo
-install 工具必须在系统中可用
步骤
查找应用程序或库的可执行文件。
使用
哪个命令
查找应用文件。$ which nautilus /usr/bin/nautilus
使用
locate
命令查找库文件。$ locate libz | grep so /usr/lib64/libz.so /usr/lib64/libz.so.1 /usr/lib64/libz.so.1.2.7
如果调试包含的错误消息的原始原因,请在其文件名中选择库具有相同额外数字的结果。若有疑问,请尝试遵循库文件名不包含其他数字的结果。
注意locate
命令由 mlocate 软件包提供。安装它并启用其使用:# yum install mlocate # updatedb
使用文件路径,搜索提供该文件的软件包。
# yum provides /usr/lib64/libz.so.1.2.7 Loaded plugins: product-id, search-disabled-repos, subscription-manager zlib-1.2.7-17.el7.x86_64 : The compression and decompression library Repo : @anaconda/7.4 Matched from: Filename : /usr/lib64/libz.so.1.2.7
输出以格式
名称提供软件包列表 -版本。分发。架构
。在这一步中,只有 软件包名称 很重要,因为yum
输出中显示的版本可能不是实际安装的版本。重要如果此步骤没有生成任何结果,则无法决定哪个软件包提供二进制文件,这个过程会失败。
使用
rpm
低级别软件包管理工具查找系统上安装哪个软件包版本。使用软件包名称作为参数:$ rpm -q zlib zlib-1.2.7-17.el7.x86_64
输出提供以格式
名称(版本 )的已安装软件包的详细信息。分发.架构
。使用
debuginfo
-install 实用程序安装 debuginfo
软件包。在命令中,使用软件包名称以及您在上一步中确定的其他详情:# debuginfo-install zlib-1.2.7-17.el7.x86_64
为应用程序或库安装
debuginfo
软件包会为所有依赖项安装debuginfo
软件包。
其它资源
- Red Hat Developer Toolset 用户指南 - 安装调试信息
- 知识库文章 - 如何下载或安装 RHEL 系统的 debuginfo 软件包?