本节讨论 MDB 设计的重要方面,以及此体系结构带来的益处。
目标是指调试器正在检查的程序。 目前 MDB 提供了对以下目标类型的支持:
用户进程
用户进程核心转储文件
没有内核执行控制的实时操作系统(通过 /dev/kmem 和 /dev/ksyms)
具有内核执行控制的实时操作系统(通过 kmdb(1))
操作系统崩溃转储
在操作系统崩溃转储内记录的用户进程映像
ELF 目标文件
原始数据文件
每个目标都导出标准属性集,包括一个或多个地址空间、一个或多个符号表、一组装入对象和一组线程。图 2–1 概述了 MDB 体系结构,包括两个内置目标和一对样例模块。
在 MDB 术语中,调试器命令又名 dcmd(读作 dee-command),是调试器中能够访问当前目标的任何属性的例程。 MDB 解析标准输入中的命令,然后执行对应的 dcmd。 每个 dcmd 还可以接受字符串或数值参数的列表,如语法所示。MDB 包含一组始终可用的内置 dcmd(在第 5 章,内置命令中介绍)。 通过使用 MDB 附带的编程 API 编写 dcmd,程序员还可以扩展 MDB 本身的功能。
walker 是说明如何遍历或迭代特定程序数据结构的元素的一组例程。 walker 从 dcmd 和从 MDB 本身封装数据结构的实现。 可以交互使用 walker,或者将它们用作元语以生成其他 dcmd 或 walker。 与使用 dcmd 一样,程序员可以通过将其他 walker 作为调试器模块的一部分进行实现来扩展 MDB。
调试器模块又名 dmod(读作 dee-mod),是包含一组 dcmd 和 walker 的动态装入的库。 在初始化过程中,MDB 尝试装入与目标中存在的装入对象对应的 dmod。 随后可以在运行 MDB 时随时装入或卸载 dmod。 MDB 提供了一组标准 dmod,用于调试 Solaris 内核。
宏文件是包含一组要执行的命令的文本文件。宏文件通常用于自动执行显示简单数据结构的过程。 MDB 提供了完全的向后兼容性以执行为 adb 编写的宏文件。 因此,Solaris 安装附带的一组宏文件可以与任一工具一起使用。
MDB 的模块化体系结构的优点不仅仅是能够装入包含其他调试器命令的模块。MDB 体系结构各层之间定义了清晰的接口边界(如图 2–1 所示)。宏文件执行以 MDB 或 adb 语言编写的命令。调试器模块中的 Dcmd 和 walker 是使用 MDB 模块 API 编写的,这为允许调试器及其模块独立发展的应用程序二进制接口奠定了基础。
walker 和 dcmd 的 MDB 名称空间还在调试代码(随着目标程序本身的发展,最大限度地实现代码共享并限制必须修改的代码量)之间定义第二组层。例如,Solaris 内核中的主要数据结构之一是表示系统中活动进程的 proc_t 结构的列表。::ps dcmd 必须迭代此列表才能生成其输出。但是,用于迭代该列表的代码不在 ::ps dcmd 中,而是封装在 genunix 模块的 proc walker 中。
MDB 同时提供了 ::ps 和 ::ptree dcmd,但是这两者都不知道如何在内核中访问 proc_t 结构。相反,它们以程序方式调用 proc walker,并相应地格式化返回的结构集。如果用于 proc_t 结构的数据结构发生更改,则 MDB 可以提供新的 proc walker,而且相关的 dcmd 都不需要更改。 还可以使用 ::walk dcmd 以交互方式访问 proc walker,以便在调试会话中工作时创建新的命令。
除了便于分层和代码共享外,MDB 模块 API 还提供了具有单一稳定接口的 dcmd 和 walker,以访问基础目标的各种属性。使用同一 API 函数访问用户进程或内核目标中的信息,简化了开发新调试工具的任务。
此外,可以使用自定义 MDB 模块在各种上下文中执行调试任务。例如,您也许希望为正在开发的用户程序开发一个 MDB 模块。开发模块后,当 MDB 检查执行该程序的实时进程、该程序的核心转储、甚至是在执行该程序的系统上所取得的内核崩溃转储时,就可以使用此模块。
模块 API 提供了用于访问以下目标属性的工具:
模块 API 提供了用于从目标的虚拟地址空间读取和写入数据的工具。 还为内核调试模块提供了使用物理地址读取和写入的功能。
模块 API 提供了对目标主要可执行文件的静态和动态符号表、其运行时链接编辑器和一组装入对象(用户进程中的共享库或 Solaris 内核中的可装入模块)的访问。
模块 API 提供了用于检索与目标关联的指定外部数据缓冲区集合的工具。 例如,MDB 提供了对与用户进程或用户核心转储文件目标关联的 proc(4) 结构的程序访问。
此外,可以使用内置 MDB dcmd 访问有关目标内存映射、装入对象、寄存器值的信息以及控制用户进程目标的执行。