深入探讨Linux调试器的高级话题
导读 | 我们终于来到这个系列的最后一篇文章!这一次,我将对调试中的一些更高级的概念进行高层的概述:远程调试、共享库支持、表达式计算和多线程支持。这些想法实现起来比较复杂,所以我不会详细说明如何做,但是如果你有问题的话,我很乐意回答有关这些概念的问题。 |
- 准备环境
- 断点
- 寄存器和内存
- Elves 和 dwarves
- 源码和信号
- 源码层逐步执行
- 源码层断点
- 调用栈
- 处理变量
- 高级主题
远程调试对于嵌入式系统或对不同环境进行调试非常有用。它还在高级调试器操作和与操作系统和硬件的交互之间设置了一个很好的分界线。事实上,像 GDB 和 LLDB 这样的调试器即使在调试本地程序时也可以作为远程调试器运行。一般架构是这样的:
debugarch
调试器是我们通过命令行交互的组件。也许如果你使用的是 IDE,那么在其上有另一个层可以通过机器接口与调试器进行通信。在目标机器上(可能与本机一样)有一个调试存根,理论上它是一个非常小的操作系统调试库的包装程序,它执行所有的低级调试任务,如在地址上设置断点。我说“在理论上”,因为如今调试存根变得越来越大。例如,我机器上的 LLDB 调试存根大小是 7.6MB。调试存根通过使用一些特定于操作系统的功能(在我们的例子中是 ptrace)和被调试进程以及通过远程协议的调试器通信。
最常见的远程调试协议是 GDB 远程协议。这是一种基于文本的数据包格式,用于在调试器和调试存根之间传递命令和信息。我不会详细介绍它,但你可以在这里进一步阅读。如果你启动 LLDB 并执行命令 log enable gdb-remote packets,那么你将获得通过远程协议发送的所有数据包的跟踪信息。在 GDB 上,你可以用 set remotelogfile 做同样的事情。
作为一个简单的例子,这是设置断点的数据包:
$Z0,400570,1#43
$ 标记数据包的开始。Z0 是插入内存断点的命令。400570 和 1 是参数,其中前者是设置断点的地址,后者是特定目标的断点类型说明符。最后,#43 是校验值,以确保数据没有损坏。
GDB 远程协议非常易于扩展自定义数据包,这对于实现平台或语言特定的功能非常有用。
共享库和动态加载支持调试器需要知道被调试程序加载了哪些共享库,以便它可以设置断点、获取源代码级别的信息和符号等。除查找被动态链接的库之外,调试器还必须跟踪在运行时通过 dlopen 加载的库。为了达到这个目的,动态链接器维护一个 交汇结构体。该结构体维护共享库描述符的链表,以及一个指向每当更新链表时调用的函数的指针。这个结构存储在 ELF 文件的 .dynamic 段中,在程序执行之前被初始化。
一个简单的跟踪算法:
- 追踪程序在 ELF 头中查找程序的入口(或者可以使用存储在 /proc//aux 中的辅助向量)。
- 追踪程序在程序的入口处设置一个断点,并开始执行。
- 当到达断点时,通过在 ELF 文件中查找 .dynamic 的加载地址找到交汇结构体的地址。
- 检查交汇结构体以获取当前加载的库的列表。
- 链接器更新函数上设置断点。
- 每当到达断点时,列表都会更新。
- 追踪程序无限循环,继续执行程序并等待信号,直到追踪程序信号退出。
我给这些概念写了一个小例子,你可以在这里找到。如果有人有兴趣,我可以将来写得更详细一点。
表达式计算表达式计算是程序的一项功能,允许用户在调试程序时对原始源语言中的表达式进行计算。例如,在 LLDB 或 GDB 中,可以执行 print foo() 来调用 foo 函数并打印结果。
根据表达式的复杂程度,有几种不同的计算方法。如果表达式只是一个简单的标识符,那么调试器可以查看调试信息,找到该变量并打印出该值,就像我们在本系列最后一部分中所做的那样。如果表达式有点复杂,则可能将代码编译成中间表达式 (IR) 并解释来获得结果。例如,对于某些表达式,LLDB 将使用 Clang 将表达式编译为 LLVM IR 并将其解释。如果表达式更复杂,或者需要调用某些函数,那么代码可能需要 JIT 到目标并在被调试者的地址空间中执行。这涉及到调用 mmap 来分配一些可执行内存,然后将编译的代码复制到该块并执行。LLDB 通过使用 LLVM 的 JIT 功能来实现。
如果你想更多地了解 JIT 编译,我强烈推荐 Eli Bendersky 关于这个主题的文章。
多线程调试支持本系列展示的调试器仅支持单线程应用程序,但是为了调试大多数真实程序,多线程支持是非常需要的。支持这一点的最简单的方法是跟踪线程的创建,并解析 procfs 以获取所需的信息。
Linux 线程库称为 pthreads。当调用 pthread_create 时,库会使用 clone 系统调用来创建一个新的线程,我们可以用 ptrace 跟踪这个系统调用(假设你的内核早于 2.5.46)。为此,你需要在连接到调试器之后设置一些 ptrace 选项:
ptrace(PTRACE_SETOPTIONS, m_pid, nullptr, PTRACE_O_TRACECLONE);
现在当 clone 被调用时,该进程将收到我们的老朋友 SIGTRAP 信号。对于本系列中的调试器,你可以将一个例子添加到 handle_sigtrap 来处理新线程的创建:
case (SIGTRAP | (PTRACE_EVENT_CLONE << 8)): //get the new thread ID unsigned long event_message = 0; ptrace(PTRACE_GETEVENTMSG, pid, nullptr, message); //handle creation //...
一旦收到了,你可以看看 /proc//task/ 并查看内存映射之类来获得所需的所有信息。
GDB 使用 libthread_db,它提供了一堆帮助函数,这样你就不需要自己解析和处理。设置这个库很奇怪,我不会在这展示它如何工作,但如果你想使用它,你可以去阅读这个教程。
多线程支持中最复杂的部分是调试器中线程状态的建模,特别是如果你希望支持不间断模式或当你计算中涉及不止一个 CPU 的某种异构调试。
最后!呼!这个系列花了很长时间才写完,但是我在这个过程中学到了很多东西,我希望它是有帮助的。如果你有关于调试或本系列中的任何问题,请在 Twitter @TartanLlama或评论区联系我。如果你有想看到的其他任何调试主题,让我知道我或许会再发其他的文章。
以上是深入探讨Linux调试器的高级话题的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

热门话题

CentOS 和 Ubuntu 的关键差异在于:起源(CentOS 源自 Red Hat,面向企业;Ubuntu 源自 Debian,面向个人)、包管理(CentOS 使用 yum,注重稳定;Ubuntu 使用 apt,更新频率高)、支持周期(CentOS 提供 10 年支持,Ubuntu 提供 5 年 LTS 支持)、社区支持(CentOS 侧重稳定,Ubuntu 提供广泛教程和文档)、用途(CentOS 偏向服务器,Ubuntu 适用于服务器和桌面),其他差异包括安装精简度(CentOS 精

CentOS 安装步骤:下载 ISO 映像并刻录可引导媒体;启动并选择安装源;选择语言和键盘布局;配置网络;分区硬盘;设置系统时钟;创建 root 用户;选择软件包;开始安装;安装完成后重启并从硬盘启动。

CentOS将于2024年停止维护,原因是其上游发行版RHEL 8已停止维护。该停更将影响CentOS 8系统,使其无法继续接收更新。用户应规划迁移,建议选项包括CentOS Stream、AlmaLinux和Rocky Linux,以保持系统安全和稳定。

Docker利用Linux内核特性,提供高效、隔离的应用运行环境。其工作原理如下:1. 镜像作为只读模板,包含运行应用所需的一切;2. 联合文件系统(UnionFS)层叠多个文件系统,只存储差异部分,节省空间并加快速度;3. 守护进程管理镜像和容器,客户端用于交互;4. Namespaces和cgroups实现容器隔离和资源限制;5. 多种网络模式支持容器互联。理解这些核心概念,才能更好地利用Docker。

CentOS 已停止维护,替代选择包括:1. Rocky Linux(兼容性最佳);2. AlmaLinux(与 CentOS 兼容);3. Ubuntu Server(需要配置);4. Red Hat Enterprise Linux(商业版,付费许可);5. Oracle Linux(与 CentOS 和 RHEL 兼容)。在迁移时,考虑因素有:兼容性、可用性、支持、成本和社区支持。

CentOS 停止维护后,用户可以采取以下措施应对:选择兼容发行版:如 AlmaLinux、Rocky Linux、CentOS Stream。迁移到商业发行版:如 Red Hat Enterprise Linux、Oracle Linux。升级到 CentOS 9 Stream:滚动发行版,提供最新技术。选择其他 Linux 发行版:如 Ubuntu、Debian。评估容器、虚拟机或云平台等其他选项。

如何使用 Docker Desktop?Docker Desktop 是一款工具,用于在本地机器上运行 Docker 容器。其使用步骤包括:1. 安装 Docker Desktop;2. 启动 Docker Desktop;3. 创建 Docker 镜像(使用 Dockerfile);4. 构建 Docker 镜像(使用 docker build);5. 运行 Docker 容器(使用 docker run)。

VS Code 系统要求:操作系统:Windows 10 及以上、macOS 10.12 及以上、Linux 发行版处理器:最低 1.6 GHz,推荐 2.0 GHz 及以上内存:最低 512 MB,推荐 4 GB 及以上存储空间:最低 250 MB,推荐 1 GB 及以上其他要求:稳定网络连接,Xorg/Wayland(Linux)
