跳过导航链接 | |
退出打印视图 | |
![]() |
手册页第 1 部分:用户命令 Oracle Solaris 11 Information Library (简体中文) |
- 模块调试器
mdb [-fkmuwyAFKMSUW] [±o option] [-p pid] [-s distance] [-I path] [-L path] [-P prompt] [-R root] [-V dis-version] [object [core] | core | suffix]
mdb 实用程序是针对实时操作系统、操作系统故障转储、用户进程、用户进程核心转储以及对象文件执行底层调试和编辑的可扩展实用程序。 有关 mdb 功能的更为详细的说明,请参阅手册《Oracle Solaris Modular Debugger Guide》。
调试是分析软件程序的执行和状态以便消除缺陷的过程。传统的调试工具提供了用于执行控制的工具,因此,程序员可以在受控环境中重新执行程序并显示程序数据的当前状态,或者借助开发程序时使用的源语言对表达式进行求值。
不幸的是,这些技术通常不适用于以下情形:调试复杂的软件系统(例如操作系统,其中出现的错误可能无法再现,并且程序状态非常多且分布在各处)、经过高度优化的程序(这些程序的调试信息已删除,或者自身即为底层调试工具)、开发人员只能访问事后分析信息的客户情况。
mdb 提供了用于调试这些程序和方案的可完全自定义的环境,包括动态模块工具,程序员可使用该工具实现自己的调试命令,以便执行特定于程序的分析。每个 mdb 模块可用于在多种不同上下文中检查程序,包括实时和事后分析。
目标是调试器所检查的程序。mdb 当前提供了对以下类型目标的支持:用户进程、用户进程核心文件、实时操作系统(通过 /dev/kmem 和 /dev/ksyms)、操作系统故障转储、记录在操作系统故障转储内部的用户进程映像、ELF 对象文件以及原始二进制文件。每个目标导出一组标准的属性,其中包括一个或多个地址空间、一个或多个符号表、一组装入对象和一组线程,这些内容均可以使用下述调试器命令检查。
调试器命令在 mdb 术语中称为 dcmd(发音为 dee-command),是调试器中可以访问当前目标的任意属性的例程。mdb 解析标准输入中的命令,然后执行对应的 dcmd。每个 dcmd 也可以接受字符串或数字参数列表,如以下语法说明中所示。mdb 包含一组始终可供使用的内置 dcmd,如下所示。您也可以通过编写自己的 dcmd 来扩展 mdb 自身的功能,如《Oracle Solaris Modular Debugger Guide》中所述。
遍历器是一组例程,用来描述如何在特定程序数据结构的元素中进行遍历或迭代。遍历器封装 dcmd 以及 mdb 自身中的数据结构实现。您可以按交互方式使用遍历器,也可将它们用作基元来构建其他 dcmd 或遍历器。在使用 dcmd 时,您可以将自己的遍历器作为调试器模块的一部分实现,从而扩展 mdb。
调试器模块(即 dmod,发音为 dee-mod)是动态载入的库,包含一组 dcmd 和遍历器。在初始化期间,mdb 尝试装入与目标中存在的装入对象相对应的 dmod。接下来,在运行 mdb 时,您可以随时装入或卸载 dmod。 随 mdb 提供了一组标准 dmod,它们可用于调试 Solaris 内核。《Oracle Solaris Modular Debugger Guide》中包含有关开发自己的调试器模块的更多信息。
宏文件是包含一组要执行的命令的文本文件。宏文件通常用于自动执行显示简单数据结构的进程。mdb 为执行针对 adb(1) 编写的宏文件提供了完整的向后兼容性,而 Solaris 安装包括一组用于调试 Solaris 内核的宏文件,它们可以在任意一种工具中使用。
调试器处理标准输入中的命令。如果标准输入为终端,则 mdb 提供终端编辑功能。mdb 也可以处理来自宏文件以及来自 dcmd 流水线的命令,如下所述。语言语法的设计以下面的概念为中心:计算表达式的值(通常为目标中的内存地址),然后对该地址应用 dcmd。当前地址位置称为点,使用 ``.'' 来引用相关值。
元字符为以下字符之一:
[ ] | ! / \ ? = > $ : ; NEWLINE SPACE TAB
空白为制表符或空格。词是由一个或多个不括起的元字符分隔的字符序列。一些元字符仅在特定上下文中起到分界符的作用,如下文所述。标识符是字母、数字、下划线、句点或反引号组成的序列,以字母、下划线或句点开头。标识符用作符号、变量、dcmd 和遍历器的名称。使用换行或分号 (;) 来分隔各个命令。
使用以下词或元字符之一表示 dcmd:
/ \ ? = > $character :character ::identifier
使用元字符命名或者使用单个 $ 或 : 作为前缀的 dcmd 作为内置运算符提供,并且与旧的 adb(1) 实用程序的命令集实现完全兼容。dcmd 在解析之后,/、\、?、=、>、$ 和 : 字符在参数列表终止之前不再识别为元字符。
简单命令是一个 dcmd,后面跟随由零个或多个以空格分隔的词组成的序列。除非在下面的引用和算术扩展中指定,否则词将作为参数传递到调用的 dcmd。 每个 dcmd 返回一个退出状态,指示成功、失败或者在调用时使用了无效参数。
流水线是由 | 分隔的一个或多个简单命令。与 shell 不同,mdb 流水线中的 dcmd 不作为单独进程执行。对流水线进行解析之后,按照从左到右的顺序依次调用各个 dcmd。对每个 dcmd 的输出进行处理并存储,如下面的 dcmd 流水线中所述。左侧的 dcmd 完成之后,经过处理的输出将用作流水线中下一个 dcmd 的输入。如果任何 dcmd 都未返回成功的退出状态,流水线将异常中止。
表达式是一个词序列,对该序列进行求值以计算得出 64 位的无符号整数值。词使用下面的算术扩展中所述的规则求值。
命令可以是以下内容之一:
简单命令或流水线可以选择使用 ! 字符作为后缀,指示调试器应打开 pipe(2) 并将 mdb 流水线中上一个 dcmd 的标准输出发送到外部进程。该外部进程是使用以下方法创建的:执行 $SHELL -c,后面跟随通过在 ! 字符后串联词所构成的字符串。有关详细信息,请参见下面的 Shell 转义。
可以使用一个表达式作为简单命令或流水线的前缀。 在执行流水线之前,将点的值(使用 ``.'' 表示的变量)设置为表达式的值。
可以使用两个表达式作为简单命令或流水线的前缀。对第一个表达式求值,确定点的新值;对第二个表达式求值,确定流水线中第一个 dcmd 的重复计数。此 dcmd 将执行 count 次数,然后再执行流水线中的下一个 dcmd。重复计数仅应用于流水线中的第一个 dcmd。
如果省略了第一个表达式,则不修改点,但是将根据表达式的值重复流水线中的第一个 dcmd。
一个命令只能由一个算术表达式组成。对表达式求值并将点变量设置为表达式值,然后使用点的新值来执行上一个 dcmd 和参数。
一个命令只能由一个点表达式和重复计数表达式组成。将点设置为第一个表达式的值之后,上一个 dcmd 和参数将重复执行由第二个表达式的值指定的次数。
如果省略第一个表达式,则不修改点,但上一个 dcmd 和参数将重复执行由计数表达式的值指定的次数。
如果命令以 ! 字符开头,则不执行任何 dcmd,而调试器仅执行 $SHELL -c,后面跟随通过在 ! 字符后串联词所构成的字符串。
词以 // 开头时,将忽略该词以及后面直至换行之前的所有字符。
当 mdb 命令前面为表示起始地址的可选表达式时,或者为起始地址和重复计数时,将执行算术扩展。还可以执行算术扩展来计算 dcmd 的数字参数。在参数列表中可以出现算术表达式,该表达式必须以方括号括起,前面使用美元符号 ($[ expression ])。该表达式将由表达式的值取代。
表达式可以包含以下任意特殊词:
指定的整数值。整数值可以使用以下前缀:0i 或 0I 表示二进制值;0o 或 0O 表示八进制值;0t 或 0T 表示十进制值;0x 或 0X 表示十六进制值(缺省值)。
转换为 IEEE 双精度浮点值表示法的指定十进制浮点值。
通过将每个字符转换为等于 ASCII 值的字节计算得到的整数值。在字符常量中最多可以指定八个字符。字符从最低有效字节开始,按逆序(从右到左)压缩为整数。
以 identifier 命名的变量的值。
以 identifier 命名的符号的值。
expression 的值。
点的值。
最近执行 dcmd 所用的点的值。
使用当前增量递增的点的值。
使用当前增量递减的点的值。
增量为全局变量,用于存储上一个格式化 dcmd 读取的字节总数。有关增量的详细信息,请参阅下面的格式化 dcmd 中讨论的内容。
一元运算符从右向左执行运算,优先级高于二元运算符。一元运算符包括:
逻辑否定。
按位取反。
整数否定。
对象文件位置的指针大小数量的值,该位置对应于目标虚拟地址空间中的虚拟地址 expression。
对象文件位置的字符、短整型、整型或长整型大小数量的值,该位置对应于目标虚拟地址空间中的虚拟地址 expression。
对象文件位置的单字节、双字节、四个字节或八个字节数量的值,该位置对应于目标虚拟地址空间中的虚拟地址 expression。
目标虚拟地址空间中的虚拟地址 expression 处的指针大小数量的值。
目标虚拟地址空间中的虚拟地址 expression 处的字符、短整型、长整型大小数量的值。
目标虚拟地址空间中的虚拟地址 expression 处的单字节、双字节、四字节或八字节数量的值。
二元运算符从左向右执行运算,优先级低于一元运算符。二元运算符按照优先级从高到低的顺序为:
整数相乘。
整数相除。
将左侧向上取整到右侧的下一个倍数。
整数相加。
整数相减。
左移位。
右移位。
逻辑等。
逻辑不等。
按位与。
按位异或。
按位同或。
除非括起来,否则上述各个元字符(参见语法)将终止词。字符可以括起来(强制 mdb 按原义解释各个字符,而不解释为任何特殊含义),方法是使用一对单引号 (' ') 或双引号 (" ") 将这些字符括起来。单引号内部不能出现单引号。在双引号内部,mdb 可以识别 C 编程语言字符转义序列。
! 字符可用于在 mdb 命令和用户 shell 之间创建流水线。如果 $SHELL 环境变量已设置,mdb 将为 shell 转义派生并执行此程序;否则将使用 /bin/sh。使用 -c 选项,后面跟随通过在 ! 字符后串联词所构成的字符串,以此调用 shell。! 字符优先级高于除分号 (;) 和换行之外的所有其他元字符。检测到 shell 转义时,后面直到下一个分号或换行的其余字符将按原义传递到 shell。shell 命令的输出不能通过流水线输出到 mdb dcmd。由 shell 转义执行的命令将命令输出直接发送到终端,而不是发送到 mdb。
variable 是变量名称、对应的整数值以及一组属性。变量名是由字符、数字、下划线或句点组成的序列。可以使用 > dcmd 或 ::typeset dcmd 为变量赋值,变量的属性可以使用 ::typeset dcmd 来处理。每个变量的值用一个 64 位无符号整数表示。变量可以具有以下一个或多个属性:只读(不能由用户修改)、持久(不能由用户取消设置)和已标记(用户定义的指示符)。
以下变量定义为持久变量:
使用 /、\、? 或 = dcmd 列显的最近值。
用于 $< dcmd 的最近计数。
数据区的根基的虚拟地址。
数据区大小(以字节为单位)。
入口点的虚拟地址。
目标主对象文件的初始字节数(幻数),如果尚未读取对象文件,则为零。
文本区大小(以字节为单位)。
与匹配软件事件说明符匹配的次数。参见下面的事件回调。
当前代表线程的线程标识符。标识符的值取决于当前目标使用的线程模型。参见下面的线程支持。
此外,mdb 内核和进程目标将代表线程寄存器集的当前值导出为命名变量。这些变量的名称取决于目标的平台和指令集体系结构。
按照上面的语法说明中的解释,表达式上下文中存在的符号标识符的计算结果为此符号的值。该值通常表示与目标虚拟地址空间中的符号关联的存储的虚拟地址。目标可以支持多个符号表,包括但不限于针对多个装入对象中每个对象(例如用户进程中的共享库或者 Solaris 内核中的内核模块)的主可执行符号表、主动态符号表、运行时链接编辑器符号表以及标准和动态符号表。目标通常先搜索主可执行符号表,然后搜索一个或多个其他符号表。请注意,ELF 符号表只包含外部、全局和静态符号的条目;自动符号不显示在由 mdb 处理的符号表中。
此外,mdb 提供了私有的用户定义符号表,该表将在搜索任何目标符号表之前进行搜索。私有符号表最初是空的,可以使用 ::nmadd 和 ::nmdel dcmd 处理。::nm -P 选项可用于显示私有符号表的内容。用户可以使用私有符号表为原始程序中缺少的或已删除的程序函数或数据创建符号定义。然后,只要 mdb 将符号名称转换为地址,或者将地址转换为最接近的符号,就会使用这些定义。
由于目标包含多个符号表,并且每个符号表可以包含来自多个对象文件的符号,所以可以存在同名的不同符号。mdb 使用反引号 (`) 字符作为符号名称作用范围运算符,使程序员能够在这种情况下获取所需符号的值。程序员可以将用于解析符号名称的作用范围指定为以下值之一:object`name;file`name 或 object`file`name。 对象标识符指装入对象的名称。文件标识符指在指定对象的符号表中具有 STT_FILE 类型的符号的源文件的根基名称。对象标识符的解释取决于目标类型。
mdb 内核目标需要 object 来指定已装入内核模块的根基名称。例如,符号名称
specfs`_init
计算结果为 specfs 内核模块中 _init 符号的值。
mdb 进程目标需要 object 来指定可执行文件的名称或者已装入共享库的名称。可以采用以下形式之一:
完全匹配(即完整路径名):/usr/lib/libc.so.1
精确根基名称匹配:libc.so.1
初始根基名称,一直匹配到 ``.'' 后缀之前的内容:libc.so 或 libc
文本字符串 a.out 可接受作为可执行文件的别名。
进程目标也可以接受在上述四种形式中的任意一种前面添加可选的链接图 ID (lmid)。可以在初始的 "LM" 后面跟随十六进制的链接图 ID,然后再跟随一个反引号,以此指定 lmid 前缀。例如,符号名称
LM0`libc.so.1`_init
计算结果为 _init 符号的值,该符号位于在链接图 0 (LM_ID_BASE) 上装入的 libc.so.1 库中。如果相同库在多个链接图上装入,则链接图说明符对于解决符号命名冲突是必需的。有关链接图的更多信息,请参阅《链接程序和库指南》和 dlopen(3C)。在根据 showlmid 选项的设置列显符号时,将显示链接图标识符,如“选项”下的内容所述。
如果符号与十六进制整数值之间出现命名冲突,mdb 在将不确定的标记求值为整数值之前,将先尝试将该标记求值为符号。例如,标记 f 可以引用在十六进制(缺省基数)中指定的十进制整数值 15,也可以引用目标符号表中名为 f 的全局变量。如果存在具有不确定名称的符号,则可以使用显式 0x 或 0X 前缀来指定整数值。
如前面所述,每个 mdb dmod 提供了一组 dcmd 和遍历器。dcmd 和遍历器是在两个不同的全局名称空间中跟踪的。mdb 还会跟踪与每个 dmod 关联的 dcmd 和遍历器名称空间。在一个指定的 dmod 中不允许具有同名的 dcmd 或遍历器:存在此类命名冲突的 dmod 无法装入。在全局名称空间中,允许来自不同 dmod 的 dcmd 或遍历器之间的名称冲突。出现冲突时,要装入的第一个具有该特定名称的 dcmd 或遍历器将在全局名称空间中优先。备用定义按照装入顺序保存在列表中。反引号字符 (`) 可以在 dcmd 或遍历器名称中用作作用范围运算符来选择备用定义。例如,如果 dmod m1 和 m2 均提供了一个 dcmd d,并且 m1 在 m2 之前装入,则:
执行 m1 的 d 定义。
执行 m1 的 d 定义。
执行 m2 的 d 定义。
如果模块 m1 现在已卸载,则全局定义列表中的下一个 dcmd (m2`d) 将提升为具有全局可见性。使用下面所述的 ::which dcmd 可以确定 dcmd 或遍历器的当前定义。使用 ::which -v 选项可以显示全局定义列表。
使用 | 运算符可以将 dcmd 组合成为流水线。流水线的作用是从一个 dcmd 或遍历器向另一个 dcmd 或遍历器传递值列表,通常为虚拟地址。流水线阶段可用于将指针从一种类型的数据结构映射到对应数据结构的指针,以便对地址列表进行排序或者选择具有特定属性的结构地址。
mdb 按照从左到右的顺序执行流水线中的各个 dcmd。最左侧的 dcmd 使用点的当前值执行,或者使用在命令开头由显式表达式指定的值执行。遇到 | 运算符时,mdb 在左侧的 dcmd 输出与 mdb 解析器之间创建流水线(共享缓冲区),并创建空的值列表。当 dcmd 执行时,相应的标准输出将放在流水线中,然后由解析器使用和求值,等同于 mdb 从标准输入读取了此数据。每一行必须包含使用换行或分号 (;) 终止的算术表达式。表达式的值将附加到与流水线关联的值列表中。如果检测到语法错误,流水线将异常中止。
当位于 | 运算符左侧的 dcmd 完成时,将使用与流水线关联的值列表来调用位于 | 运算符右侧的 dcmd。对于列表中的每个值,点将设置为该值,并且执行右侧的 dcmd。只有流水线中最右侧的 dcmd 会将输出列显到标准输出中。如果流水线中的任何 dcmd 向标准错误生成了输出,这些消息将直接列显到标准错误,而不作为流水线的一部分进行处理。
调试器忽略 PIPE 和 QUIT 信号。INT 信号用于异常中止当前正在执行的命令。调试器拦截 ILL、TRAP、 EMT、FPE、BUS 和 SEGV 信号并提供对这些信号的特殊处理。如果异步生成了这些信号中的任意一个(即从其他使用 kill(2) 的进程传送的信号),mdb 会将信号恢复到缺省处理和转储核心。但是,如果这些信号中的任意一个由调试器进程本身同步生成,并且来自外部装入 dmod 的 dcmd 当前正在执行,并且标准输入为终端,则 mdb 提供了一个选项菜单,允许用户选择强制执行核心转储、退出而不生成核心转储、停止以便由调试器附加或者尝试恢复。恢复选项将异常中止所有活动命令并卸载出现故障时相应的 dcmd 处于活动状态的 dmod。 随后,它可由用户重新装入。恢复选项可以为错误频发的 dcmd 提供有限的保护。有关与恢复选项相关的风险的信息,请参阅下面的警告使用错误恢复机制。
从终端设备输入的最后一个 HISTSIZE(缺省值为 128)命令的文本保存在内存中。接下来介绍的内嵌编辑工具提供了用于从历史记录列表中搜索和提取元素的键映射。
如果标准输入为终端设备,则 mdb 提供了一些简单的 emacs 风格的工具,这些工具可用于编辑命令行。编辑模式下的 search、previous 和 next 命令提供了对历史记录列表的访问。在搜索时,只匹配字符串,不匹配模式。在下表中,控制字符的表示法为在插入记号 (^) 后面跟随以大写形式显示的字符。转义序列的表示法为后跟有字符的 M-。例如,M-f(发音为 meta-eff)的输入方法为:按下 ESC,然后按下 'f';在支持 Meta 键的键盘上则按下 Meta,然后按下 'f'。使用回车或换行来提交和执行命令行。编辑命令包括:
将光标向前(向右)移动一个字符。
将光标向前移动一个词。
将光标向后(向左)移动一个字符。
将光标向后移动一个词。
将光标移到行的开头。
将光标移到行的结尾。
如果当前行不为空,则删除当前字符。如果当前行为空,则 ^D 将指示 EOF,并且调试器将退出。
(Meta 退格)删除上一个词。
删除光标至行尾之间的内容。
清除屏幕并重新列显当前行。
将当前字符与下一个字符换位。
从历史记录中提取下一个命令。每次输入 ^N 时,将按时间检索下一个命令。
从历史记录中提取上一个命令。每次输入 ^P 时,将按时间检索上一个命令。
在历史记录中反向搜索包含 string 的上一个命令行。字符串应使用回车或换行终止。如果省略 string,则检索包含最近使用的字符串的上一个历史记录元素。
编辑模式还会将以下用户定义的序列解释为编辑命令。用户定义的序列可以使用 stty(1) 命令读取或修改。
用户定义的删除字符(通常为 ^H 或 ^?)。删除上一字符。
用户定义的中断字符(通常为 ^C)。异常中止当前命令并列显新的提示符。
用户定义的中止字符(通常为 ^U)。中止当前整个命令行。
用户定义的退出字符(通常为 ^\)。退出调试器。
用户定义的暂停字符(通常为 ^Z)。暂停调试器。
用户定义的词删除字符(通常为 ^W)。删除前面的词。
如果键盘支持带有方向键的小键盘,mdb 会将以下击键解释为编辑命令:
从历史记录中提取上一个命令(与 ^P 相同)。
从历史记录中提取下一个命令(与 ^N 相同)。
将光标向后移动一个字符(与 ^B 相同)。
将光标向前移动一个字符(与 ^F 相同)。
mdb 提供了内置的输出页面调度程序。如果调试器的标准输出是终端设备,将启用输出页面调度程序。每次执行命令时,mdb 在生成了满屏输出后将暂停,并显示页面调度程序提示符:
>> More [<space>, <cr>, q, n, c, a] ?
页面调度程序识别以下键序:
显示下一个满屏输出。
中止当前顶级命令并返回到提示符。
继续显示输出,不在每次满屏时停止,直至当前顶级命令完成。
显示下一行输出。
仅退出(异常中止)当前 dcmd。
/、\、? 和 = 元字符用于表示特殊输出格式的 dcmd。这些 dcmd 中的每一个可接受由一个或多个格式字符、重复计数或括起字符串组成的参数列表。格式字符是下表中显示的 ASCII 字符之一。格式字符用于从目标中读取并格式化数据。重复计数是在格式字符之前的正整数,始终按照 Base 10(十进制)来解释。重复计数也可以指定为使用方括号括起的表达式,前面带有美元符号 ($[ ])。字符串参数必须使用双引号括起来 (" ")。格式参数之间不必留有空格。
格式化 dcmd 包括:
从由点指定的虚拟地址开始,显示来自目标的虚拟地址空间的数据。
从由点指定的物理地址开始,显示来自目标的物理地址空间的数据。
从与由点指定的虚拟地址对应的对象文件位置开始,显示来自目标的主对象文件的数据。
以各个指定的数据格式显示点本身的值。因此,= dcmd 在基数之间转换和执行算术运算时非常有用。
除了点之外,mdb 还可以跟踪另一种称为增量的全局值。增量表示点与上一个格式化 dcmd 读取的所有数据后面的地址之间的距离。例如,如果执行了点等于地址 A 的格式化 dcmd,并且显示 4 个字节的整数,则在此 dcmd 完成后,点仍旧为 A,但增量设置为 4。+ 字符(在上面的算术扩展中介绍)现在的计算结果为值 A + 4,可用于将点重置为后续 dcmd 的下一个数据对象的地址。
大部分格式字符将增大增量的值,增加的大小为与数据格式大小对应的字节数,如表中所示。格式字符的表可以使用 ::formats dcmd 在 mdb 中显示。格式字符包括:
|
/、\ 和 ? 格式化 dcmd 也可用于写入目标的虚拟地址空间、物理地址空间或对象文件,方法是将以下修饰符之一指定为第一个格式字符,然后指定词列表,该词列表可以直接为值,也可以为用方括号括起的表达式,前面带有美元符号 ($[ ])。
写入修饰符包括:
将每个表达式值的最低字节写入从点所指定的位置开始的目标。
将每个表达式值的最低 2 个字节写入从点所指定的位置开始的目标。
将每个表达式值的最低 4 个字节写入从点所指定的位置开始的目标。
将每个表达式值的全部 8 个字节写入从点所指定的位置开始的目标。
/、\ 和 ? 格式化 dcmd 也可分别用于搜索目标虚拟地址空间、物理地址空间和对象文件中的特定整数值,方法是将以下修饰符之一指定为第一个格式字符,然后指定值和可选的掩码。值和掩码均可以直接指定为值,也可以指定为使用方括号括起的表达式,在前面使用美元符号。如果只指定了值,mdb 将读取合适大小的整数,并在包含匹配值的地址处停止。如果指定了值 V 和掩码 M,mdb 将读取合适大小的整数,并在包含值 X(其中 (X & M) == V)的地址处停止。dcmd 完成之后,点将更新为包含匹配项的地址。如果找不到匹配项,点将保留为最后一个读取的地址。
搜索修饰符包括:
|
请注意,对于用户和内核目标而言,地址空间通常由一组不连续的段组成。从没有对应段的地址进行读取是非法的。如果搜索到达段边界但没有找到匹配项,将在由于读取超出段边界结尾而失败时异常中止。
mdb 提供了用于控制和跟踪实时运行程序的执行的工具。目前,只有用户进程目标提供对执行控制的支持。mdb 提供了简单的执行控制模型:目标进程可以使用 ::run 从调试器内部启动,mdb 也可以使用 :A、::attach 或 -p 命令行选项附加到现有进程,如下文所述。用户可以指定跟踪的软件事件列表。每次目标进程中发生跟踪的事件时,目标中的所有线程将停止,触发事件的线程将被选定作为代表线程,同时控制权将返回给调试器。将目标程序设置为运行之后,可以通过键入用户定义的中断字符(通常为 ^C)将控制权异步返回给调试器。
软件事件是目标程序中由调试器观察的状态转换。例如,调试器可以观察程序计数器寄存器到关注值(断点)的转换或发出特殊信号。
软件事件说明符是对软件事件类的说明,由调试器用于对目标程序进行校验,以便观察这些事件。::events dcmd 用于列出软件事件说明符。每个事件说明符有一组标准属性与之关联,如下文 ::events 中所述。
调试器可以观察大量不同的软件事件,包括断点、监视点、信号、计算机故障和系统调用。可以使用 ::bp、::fltbp、::sigbp、::sysbp 或 ::wp 创建新说明符。每个说明符都具有关联的回调(要执行的 mdb 命令字符串,就像在命令提示符中键入了这些内容)和属性集合,如下文所述。可以为同一个事件创建任意数量的说明符,每个说明符可以具有不同的回调和属性。可以使用 ::events dcmd 显示跟踪事件和对应事件说明符属性的当前列表。事件说明符属性在下面的 ::events 和 ::evset dcmd 说明中定义。
执行控制内置 dcmd(在下面介绍)始终可用,但当应用于不支持执行控制的目标时,将发出一条错误消息,指示不受支持。有关执行、附加、释放及作业控制与调试器执行控制进行交互的详细信息,请参阅下面的“备注”。
使用 ::evset dcmd 和事件跟踪 dcmd 可以将事件回调(使用 -c 选项)与各个事件说明符关联。事件回调是表示 mdb 命令的字符串,在目标中出现对应事件时执行。这些命令的执行与在命令提示符中键入这些内容时相同。在执行各个回调之前,点变量设置为代表线程的程序计数器的值,而 "hits" 变量设置为此说明符匹配的次数(包括当前匹配)。
如果事件回调本身包含一个或多个继续在目标中执行的命令(例如,::cont 或 ::step),则这些命令不立即在目标中执行,而是等待再次停止。相反,在事件回调内部,继续 dcmd 将注意到继续操作当前处于暂挂状态,然后立即返回。 因此,如果一个事件回调中包含了多个 dcmd,则步骤或继续 dcmd 应为最后一个指定的命令。在执行所有事件回调之后,如果所有匹配事件回调请求了继续,目标将立即恢复执行。如果请求了冲突的继续操作,具有最高优先级的操作将确定要发生的继续操作类型。优先级的顺序从高到低依次为:单步执行,步过(下一步),步出,继续。
mdb 提供了用于检查与目标关联的各个线程的栈和寄存器的工具。持久性 "thread" 变量包含当前代表线程标识符。线程标识符的格式取决于目标。::regs 和 ::fpregs dcmd 可用于检查代表线程的寄存器集,如果其他线程的寄存器集当前可用,也可进行检查。此外,代表线程的寄存器集将导出为一组命名变量。用户可以将 > dcmd 应用于对应的命名变量,从而修改一个或多个寄存器的值。
mdb 内核目标将导出对应内部线程结构的虚拟地址,作为指定线程的标识符。《Oracle Solaris Modular Debugger Guide》提供了有关 Solaris 内核中线程调试支持的更多信息。mdb 进程目标提供了相应的支持,可以检查使用本机 lwp_* 接口、/usr/lib/libthread.so 或 /usr/lib/lwp/libthread.so 的多线程用户进程。调试实时用户进程时,mdb 将检测是单线程进程 dlopen 还是关闭 libthread,并自动即时调整线程模型的视图。根据应用程序使用的线程模型,进程目标线程标识符分别对应于代表线程的 lwpid_t、thread_t 或 pthread_t。
如果 mdb 在调试用户进程目标并且目标使用了编译器支持的线程局部存储,则 mdb 自动将引用线程局部存储的符号名称求值为与当前代表线程对应的存储的地址。::tls 内置 dcmd 可用于显示除代表线程之外的其他线程的符号值。
mdb 提供了一组已定义的内置 dcmd。其中一些 dcmd 仅适用于特定目标:如果 dcmd 不适用于当前目标,则将失败并列显消息,指示 "command is not supported by current target"。在许多情况下,mdb 为旧的 adb(1) dcmd 名称提供了等效助记符 (::identifier)。例如,提供的 ::quit 与 $q 等同。有经验的 adb(1) 程序员,或者喜欢简洁或崇尚高深莫测编程的程序员,会偏好使用内置的 $ 或 : 形式。而刚开始接触 mdb 的程序员可能会偏好使用更详细的 :: 形式。内置形式按字母顺序排列。如果 $ 或 : 形式具有等效的 ::identifier,则将在 ::identifier 形式下方显示。 内置 dcmd 包括:
将点值赋值给指定的命名变量。一些变量为只读,无法修改。如果 > 后面跟随前后带有 / / 的修饰符字符,则该值将作为赋值的一部分进行修改。修饰符字符包括:
无符号字符值(1 个字节)
无符号短整数值(2 个字节)
无符号整数值(4 个字节)
无符号长整数值(32 位系统下为 4 个字节,64 位系统下为 8 个字节)
请注意,这些运算符不执行类型转换,而是提取指定数量的低位字节(在小端字节序体系结构上)或高位字节(在大端字节序体系结构上)。提供修饰符是为了实现向后兼容性;应改为使用 mdb */modifier/ 和 %/modifier/ 语法。
从指定的宏文件读取和执行命令。可以按绝对路径或相对路径提供文件名。如果文件名是简单名称(即,其中不包含 '/'),mdb 将在宏文件头文件路径中搜索文件。如果当前在处理另一个宏文件,则此文件将关闭,并使用新文件替换。
从指定的宏文件读取和执行命令(与使用 $< 一样),但不关闭当前打开的宏文件。
如果是用户进程或核心文件,则列显进程 ID 和当前信号,然后列显代表线程的常规寄存器集。
列显 C 栈回溯,包括栈帧指针信息。如果 dcmd 前面是显式地址,将显示在此虚拟内存地址开始的回溯。否则,将显示代表线程的栈。如果将可选计数值指定为参数,则在输出中为每个栈帧显示不超过 count 个参数。
获取或设置缺省输出基数。如果 dcmd 的前面为显式表达式,则缺省输出基数将设置为指定的 base;否则当前基数将按照 Base 10(十进制)列显。缺省基数为 Base 16(十六进制)。
列显所有类型为对象或函数的已知外部(全局)符号、符号的值以及存储在目标虚拟地址空间中此位置的前 4 个(32 位 mdb)或 8 个(64 位 mdb)字节。::nm dcmd 提供了更多灵活选项来显示符号表。
将提示符设置为指定的 prompt-string。缺省提示符为 '>'。提示符也可以使用 ::set -P 或 -P 命令行选项来设置。
获取或设置与地址到符号名称转换的 distance 匹配的符号。与距离匹配的符号模式将在“选项”下随 -s 命令行选项一起介绍。与距离匹配的符号也可以使用 ::set -s 选项修改。如果未指定距离,则显示当前设置。
列显具有非零值的命名变量的列表。::vars dcmd 提供了用于列出变量的其他选项。
将输出页的 width 设置为指定值。通常,此命令并不是必需的,因为 mdb 会向终端查询其宽度并处理大小调整事件。
重新打开目标以便执行写入,等同于在命令行上使用 -w 选项执行 mdb。写入模式也可以使用 ::set -w 选项启用。
如果用户进程目标处于活动状态,则附加到指定的进程 ID 或核心文件并进行调试。核心文件路径名应以字符串参数形式指定。进程 ID 可以按字符串参数形式指定,也可以指定为 dcmd 前面的表达式的值。请记住,缺省基数为十六进制,因此将使用 pgrep(1) 或 ps(1) 获取的十进制 PID 指定为表达式时,应该在前面加上 "0t"。
在指定位置设置断点。::bp dcmd 在每个指定的地址或符号处设置断点,包括 dcmd 前某个显式表达式指定的可选位置,以及 dcmd 之后的每个字符串或即时值。该参数可以为符号名称,也可以是表示所需特定虚拟地址的直接值。 如果指定了符号名称,则它可以引用目标进程中目前无法求值的符号。 即,它可以由尚未打开的装入对象的对象名和其中的函数名组成。在这种情况下,断点将延迟,在目标中不活动,直至装入了与指定名称匹配的对象。打开装入对象时会自动启用断点。在共享库中定义的符号上的断点应始终使用符号名称设置,而不能使用地址表达式,因为地址可以引用对应的过程链接表 (PLT) 条目而非实际符号定义。如果 PLT 条目随后解析为实际符号定义,则可以使用运行时链接编辑器覆盖在 PLT 条目上设置的断点。-d、-D、-e、-s、-t、-T、-c 和 -n 选项的含义与在 ::evset dcmd 中相同,如下文所述。如果使用了 dcmd 的 :b 形式,则仅在由 dcmd 前面的表达式指定的虚拟地址上设置断点。:b dcmd 之后的参数会串联在一起形成回调字符串。如果此字符串包含元字符,必须引用该字符串。
串联并显示文件。可以按相对路径名或绝对路径名指定各个文件名。文件内容将列显到标准输出,但无法传递到输出页面调度程序。此 dcmd 旨在随 | 运算符一起使用;程序员可以使用存储在外部文件中的地址列表来启动流水线。
暂停调试器,继续执行目标程序,并等待直至出现所关注的软件事件之后终止或停止。如果由于调试器已附加到正在运行的程序并且启用了 -o nostop 选项,从而导致目标已在运行,此 dcmd 将等待目标在出现所关注事件后终止或停止。如果将可选的信号名称或编号(参见 signal.h(3HEAD))指定为参数,则该信号将在恢复执行过程中立即传输到目标。如果跟踪了 SIGINT 信号,可以键入用户定义的中断字符(通常为 ^C),将控制权异步返回给调试器。 此 SIGINT 信号将自动清除,下次继续时目标将观察不到该信号。如果当前没有目标程序在运行,::cont 将启动新的程序开始运行,如同使用 ::run 一样。
到指定进程的上下文切换。上下文切换操作仅在使用内核目标时有效。进程上下文使用它在内核虚拟地址空间中的 proc 结构的 address 来指定。使用特殊上下文地址 "0" 来表示内核本身的上下文。在检查故障转储期间,只有当转储中包含指定用户进程的物理内存页(与只有内核页相对)时,mdb 才能执行上下文切换。可以使用 dumpadm(1M) 配置内核故障转储工具,以便转储所有页或当前用户进程的页。::status dcmd 可用于显示当前故障转储的内容。
用户请求从内核目标进行上下文切换时,mdb 构建表示指定用户进程的新目标。进行切换之后,新目标在全局级别插入 dcmd:因此,/ dcmd 现在将格式化并显示来自用户进程虚拟地址空间的数据,::mappings dcmd 将显示用户进程地址空间中的映射等等。内核目标可以通过执行 0::context 来还原。
列出可用 dcmd 并列显每个 dcmd 的简要说明。
删除具有指定 ID 号的事件说明符。ID 号参数在缺省情况下按照十进制解释。如果在 dcmd 前面指定了可选的地址,将删除与指定虚拟地址关联的所有事件说明符(例如,所有影响该地址的断点或监视点)。如果指定了特殊参数 "all",将删除所有事件说明符,但标记为粘滞(T 标记)的说明符除外。::events dcmd 显示当前事件说明符列表。
在由最后一个参数指定的 address 处或周围,或者在点的当前值处开始反汇编。如果地址与已知函数的开头匹配,则将反汇编整个函数。否则,将列显指定地址前后的指令“窗口”以便提供上下文。缺省情况下,从目标的虚拟地址空间读取指令。如果存在 -f 选项,则改为从目标的对象文件读取指令。如果调试器当前未附加到实时进程、核心文件或故障转储,缺省情况下将启用 -f 选项。-w 选项可用于强制“窗口”模式,即使地址是已知函数的开头也是如此。 窗口大小的缺省值为十个指令,可以使用 -n 选项显式指定指令数量。
列出可用的反汇编程序模式。初始化目标时,mdb 尝试选择合适的反汇编程序模式。用户可以使用 ::dismode dcmd 将模式更改为列出的任意模式。
获取或设置反汇编程序模式。如果未指定参数,将列显当前反汇编程序模式。如果指定了 mode 参数,会将反汇编程序切换到指定的模式。可以使用 ::disasms dcmd 显示可用反汇编程序的列表。
列出已装入的调试器模块。如果指定了 -l 选项,将在各个 dmod 名称下列显相关联的 dcmd 和遍历器的列表。可以通过将特定 dmod 名称指定为附加参数,将输出限制为该 dmod。
对于包含由点指定的地址的内存,列显内存的 16 字节对齐区域的十六进制和 ASCII 内存转储。如果为 ::dump 指定了重复计数,这将解释为要转储的字节数而非重复次数。::dump dcmd 还可以识别以下选项:
字节存储顺序的调整。-e 选项采用 4 字节词。-g 选项可用于更改缺省词大小。
从与指定虚拟地址对应的对象文件位置读取数据,而不是从目标的虚拟地址空间读取。如果调试器当前未附加到实时进程、核心文件或故障转储,缺省情况下将启用 -f 选项。
显示 bytes 组中的字节。缺省组大小为 4 个字节。组大小必须为除以行宽的 2 的幂。
将 address 解释为目标地址空间中的物理地址位置而非虚拟地址。
不列显数据的 ASCII 解码。
相对于开始地址对行进行编号,而不是使用每一行的显式地址。此选项暗含 -u 选项。
省略重复行。
只读取并显示指定地址的内容,而不是读取和列显整行。
取消对齐输出而不是将输出在段落边界对齐。
按每行 16 字节的段落来显示段落。paragraphs 的缺省数量为 1。-w 可接受的最大值为 16。
将参数列显到标准输出,以空格分隔,并且以换行终止。用 $[ ] 括起的表达式将计算得出某个值,并按照缺省基数列显。
对指定的字符串求值并作为命令执行。如果命令包含元字符或空格,则应括在双引号或单引号中。
显示软件事件说明符的列表。每个事件说明符都分配有一个唯一的 ID 号,可用于在以后删除或修改事件说明符。调试器也可以针对自己的内部事件启用跟踪。这些事件只有在存在 -a 选项时才显示。如果存在 -v 选项,将显示包括任何说明符不活动原因在内的更为详细的内容。以下为示例输出:
> ::events ID S TA HT LM Description Action ----- - -- -- -- -------------------------------- ------ [ 1 ] - T 1 0 stop on SIGINT - [ 2 ] - T 0 0 stop on SIGQUIT - [ 3 ] - T 0 0 stop on SIGILL - ... [ 11] - T 0 0 stop on SIGXCPU - [ 12] - T 0 0 stop on SIGXFSZ - [ 13] - 2 0 stop at libc`printf ::echo printf >
下表说明了每一列的含义。使用 ::help events 可以获取有关此信息的汇总。
事件说明符标识符。如果启用了说明符,标识符将显示在方括号 [ ] 中;如果禁用了说明符,标识符将显示在圆括号 ( ) 中;如果目标程序当前已由于与指定说明符匹配的事件而停止,标识符将显示在尖括号 < > 中。
事件说明符状态。状态为以下符号之一:
事件说明符处于空闲状态。未运行任何目标程序时,所有说明符都处于空闲状态。目标程序正在运行时,如果无法对某个说明符求值,则该说明符处于空闲状态(例如,尚未装入的共享对象中的延迟断点)。
事件说明符处于活动状态。目标继续执行时,调试器将检测到此类型的事件。
事件说明符已设置。此状态表示目标当前正在运行用于该事件类型的测试设备。只有在调试器使用 -o nostop 选项附加到正在运行的程序时,此状态才可见。
由于操作系统错误,事件说明符未设置。::events -v 选项可用于显示有关测试设备失败原因的更多信息。
临时、粘滞和自动事件说明符属性。可以显示以下一个或多个符号:
事件说明符为临时,下次目标停止时将被删除(无论是否匹配)。
事件说明符为粘滞状态,不会由 ::delete all 或 :z 删除。该说明符可以通过在 ::delete 中显式指定 ID 号来删除。
命中计数等于命中限制时,将自动禁用事件说明符。
命中计数等于命中限制时,将自动删除事件说明符。
命中计数等于命中限制时,将自动停止目标。
当前命中计数。此列显示自该事件说明符创建以来,对应的软件事件在目标中出现的次数。
当前命中限制。此列显示使自动禁用、自动删除或自动停止行为生效的命中计数限制。这些行为可以使用 ::evset dcmd 配置,如下文所述。
与指定说明符匹配的软件事件类型的说明。
要在发生对应的软件事件时执行的回调字符串。此回调的执行与在命令提示符中键入该内容相同。
修改一个或多个软件事件说明符的属性。对于通过在 dcmd 前面的可选表达式以及在 dcmd 后面的可选参数列表进行标识的说明符,每个说明符都设置了属性。除非指定了显式基数,否则参数列表将解释为十进制整数列表。::evset dcmd 可以识别以下选项:
命中计数达到命中限制时,禁用事件说明符。如果指定了 -d 形式的选项,将禁用此行为。禁用某个事件说明符之后,调试器将删除任何对应的测试设备,并忽略对应的软件事件,直至随后重新启用了该说明符。如果没有 -n 选项,将立即禁用说明符。
命中计数达到命中限制时,删除事件说明符。如果指定了 -D 形式的选项,将禁用此行为。-D 选项优先级高于 -d 选项。命中限制可以使用 -n 选项配置。
启用事件说明符。如果指定了 -e 形式的选项,将禁用该说明符。
命中计数达到命中限制时,停止目标程序。如果指定了 -s 形式的选项,将禁用此行为。-s 行为可以通知调试器:其操作与每次执行说明符回调后发布 ::cont 相同,但第 N 次执行除外,N 是说明符命中限制的当前值。-s 选项优先级高于 -D 选项和 -d 选项。
将事件说明符标记为临时。临时标识符在目标下次停止时将自动删除,不论是否是由于与指定说明符对应的软件事件而造成目标停止。 如果指定了 -t 形式的选项,将删除临时标记。-t 选项优先级高于 -T 选项。
将事件说明符标记为粘滞。::delete all 或 :z 不删除粘滞说明符。将对应的说明符 ID 指定为 ::delete 的显式参数,可以删除粘滞说明符。如果指定了 -T 形式的选项,将删除粘滞属性。缺省事件说明符集在最初均标记为粘滞。
每次目标程序中发生对应的软件事件时,执行指定的 cmd 字符串。当前回调字符串可以使用 ::events 显示。
将当前的命中限制值设置为 count。如果当前未设置命中限制,并且 -n 选项没有使用 -s 或 D,则将命中限制设置为 1。
使用 ::help evset 可以获取有关此信息的汇总。
列显已知源文件的列表(类型为 STT_FILE 的符号显示在各种目标符号表中)。
跟踪指定的计算机故障。可以在 dcmd 前面使用可选的故障号来标识故障,也可以在 dcmd 后面使用故障名称或编号的列表来标识(参见 <sys/fault.h>)。-d、-D、-e、-s、-t、-T、-c 和 -n 选项具有与用于 ::evset dcmd 时的相同意义。
列显代表线程的浮点寄存器集。如果指定了线程,将显示该线程的浮点寄存器。线程表达式应为上面的线程支持中所述的线程标识符之一。
列出可用于 /、\、? 和 = 格式化 dcmd 的输出格式字符。格式及这些字符的用法在上面的格式化 dcmd 中介绍。
对指定的命令字符串求值,如果点的新值非零,将列显点的旧值。如果 command 包含空格或元字符,则必须括起来。::grep dcmd 可在流水线中用于过滤地址列表。
不带参数时,::help dcmd 将列显 mdb 中可用的帮助工具的简短说明。如果指定了 dcmd-name,mdb 将列显该 dcmd 的用法汇总。
如果目标是实时用户进程,将忽略指定的信号并允许将它透明地传送到目标。从跟踪事件列表中删除跟踪指定信号传送的所有事件说明符。缺省情况下,忽略的信号集初始化为补充的信号集合,这些信号集合在缺省情况下导致进程转储核心(参见 signal.h(3HEAD)),但在缺省情况下跟踪的 SIGINT 除外。
显示调试器忽略并由目标直接处理的信号的列表。可以使用 ::events dcmd 获取跟踪的信号的更多信息。
如果目标为实时用户进程,则强制终止目标。存在调试器时,如果目标是由调试器使用 ::run 创建的,也将强制终止该目标。
如果目标是用户进程,将列显代表线程的 LWPID。
如果目标是用户进程,将列显目标中各个 LWP 的 LWPID。
遍历链接列表数据结构中的元素,并列显列表中每个元素的地址。可以使用可选的地址指定列表中第一个元素的地址。否则,列表将采用点的当前值作为开头。 类型参数必须命名 C 结构或联合类型,并且该参数用于说明列表元素的类型,以便 mdb 可以在合适大小的对象中读取。member 参数用于命名 type 类型的 member,其中包含指向下一个列表元素的指针。::list dcmd 继续重复执行,直至遇到 NULL 指针、再次达到第一个元素(循环列表)或在读取元素时出错。如果指定了可选的 variable-name,将为指定的变量分配在 mdb 调用流水线的下一阶段时遍历的每一步骤所返回的值。::list dcmd 只能用于包含旨在用于 mdb 的符号调试信息的对象。有关详细信息,请参阅下面的“注释”中的符号调试信息。
装入指定的 dmod。可以按绝对路径或相对路径提供模块名称。如果 module-name 是简单名称(即不包含 '/'),mdb 将在模块库路径中搜索该名称。不能装入存在名称冲突的模块,必须先卸载现有模块。如果存在 -s 选项,mdb 将保持无提示运行,在找不到模块或无法装入模块时不发出任何错误消息。
启用或禁用输出记录。mdb 提供了交互式日志工具,可以将输入命令和标准输出记录到文件,同时仍与用户交互。-e 选项允许记录到指定文件,如果未指定文件名,将重新允许记录到以前的日志文件。-d 选项可以禁用日志。如果使用 $> dcmd,则在指定了文件名参数时启用日志;否则将禁用日志。如果指定的日志文件已存在,mdb 会将任意新日志输出附加到文件。
使用指定为字符串参数的 command,将点的值映射到对应值,然后列显点的新值。如果 command 包含空格或元字符,则必须括起来。::map dcmd 可在流水线中用于将地址列表转换为新的地址列表。
在目标的虚拟地址空间中列显各个映射的列表,包括各个映射的地址、大小和说明。如果 dcmd 的前面为 address,mdb 将只显示包含指定地址的映射。如果指定了字符串 name 参数,mdb 将只显示与该说明匹配的映射。
单步执行目标程序的一个指令,但步过子例程调用。如果将可选的信号名称或编号(参见 signal.h(3HEAD))指定为参数,则该信号将在恢复执行过程中立即传输到目标。如果当前没有目标程序在运行,::next 将启动新的程序开始运行,如同使用 ::run 一样,并在第一个指令处停止。
列显与当前目标关联的符号表。如果在 dcmd 前面指定了可选的地址,将只显示与 address 对应的符号的符号表条目。如果指定了 object,将只显示此装入对象的符号表。::nm dcmd 还可以识别以下选项:
列显 .dynsym(动态符号表)而非 .symtab。
列显私有符号表而非 .symtab。
以十进制列显值和大小字段。
仅列显全局符号。
隐藏标题行。
按名称对符号进行排序。
以八进制列显值和大小字段。
以一系列 ::nmadd 命令形式列显符号。此操作可以与 -P 一起使用以便生成宏文件,该文件随后可以使用 $< 读入调试器。
仅列显未定义的符号。
按值对符号进行排序。
以十六进制列显值和大小字段。
仅列显指定类型的符号。有效的 type 参数字符串为:
STT_NOTYPE
STT_OBJECT
STT_FUNC
STT_SECTION
STT_FILE
STT_COMMON
STT_TLS
STT_SPARC_REGISTER
仅列显指定符号信息。有效 format 参数字符串为:
符号表索引
符号值
大小,以字节为单位
符号类型
移动绑定
其它
区段索引
符号名称
符号的 C 类型(如果已知)
定义符号的对象
将指定的符号 name 添加到私有符号表。mdb 提供了私有的可配置符号表,可用于在目标的符号表上插入,如上面的符号名称解析中所述。::nmadd dcmd 还可以识别以下选项:
将符号的大小设置为 end - value。
将符号的类型设置为 STT_FUNC。
将符号的类型设置为 STT_OBJECT。
将符号的大小设置为 size。
从私有符号表中删除指定的符号 name。
列显目标的虚拟地址空间的映射,只显示与每个已知装入对象的主映射(通常为文本区段)相对应的那些映射。-v 选项显示各个装入对象的版本。版本信息并非对所有装入对象都可用。对于没有版本信息的装入对象,在 -v 信息的输出中,将作为 "Unknown" 版本列出。
列显指定 type 的指定 member 的偏移。type 应为 C 结构的名称。偏移按字节列显,除非 member 是位字段,在这种情况下将按位列显偏移。为了清楚起见,输出始终使用合适的单位作为后缀。类型名称可以使用反引号 (`) 作用范围运算符,如上面的符号名称解析中所述。::offsetof dcmd 只能用于包含旨在用于 mdb 的符号调试信息的对象。有关详细信息,请参阅下面的“注释”中的符号调试信息。
使用指定的 type 信息列显位于指定虚拟 address 的数据结构。type 参数可以命名 C 结构、联合、枚举、基本整数类型或者指向任意这些类型的指针。如果类型名称包含空格(例如,"struct foo"),则必须使用单引号或双引号括起来。类型名称可以使用反引号 (`) 作用范围运算符,如上面的符号名称解析中所述。如果类型为结构化类型,::print dcmd 将递归列显结构或联合的每个成员。如果不存在 type 参数,并且静态或全局 STT_OBJECT 符号与该地址匹配,::print 将自动推理合适的类型。如果指定了 type 参数,则后面可以跟随可选的 member 表达式列表,在这种情况下只显示指定 type 的成员和子成员。如果 type 包含其他结构化类型,每个成员字符串可以通过生成使用句点 ('.') 分界符分隔的成员名称列表来引用子结构元素。::print dcmd 只能用于包含旨在用于 mdb 的符号调试信息的对象。有关详细信息,请参阅下面的“注释”中的符号调试信息。显示数据结构之后,::print 会将点增加 type 的大小(以字节为单位)。
如果存在 -a 选项,将显示每个成员的地址。如果存在 -p 选项,::print 会将 address 解释为物理内存地址而非虚拟内存地址。如果存在 -t 选项,将显示每个成员的类型。如果存在 -d 或 -x 选项,将以十进制 (-d) 或十六进制 (-x) 显示所有整数。缺省情况下,使用试探式方法来确定应以十进制还是十六进制显示值。可以使用 -c 选项来限制在字符数组中读取并显示为字符串的字符数。如果存在 -C 选项,将不强制任何限制。可以使用 -l 选项来限制在标准数组中读取并显示的元素数。如果存在 -L 选项,将不强制任何限制,并且显示所有数组元素。-c 和 -l 的缺省值可以使用 ::set 或 -o 命令行选项修改,如下面的“选项”中所述。
如果指定了 -i 选项,地址值将解释为要列显的直接值。必须指定用于解释值的类型。如果类型小于 64 位,该直接值将作为类型的大小进行解释。-i 选项不能与 -p 选项一起使用。如果指定了 -a 选项,则显示的地址为从零开始的字节偏移。
退出调试器。
列显代表线程的通用寄存器集。如果指定了线程,将显示该线程的通用寄存器集合。线程表达式应为上面的线程支持中所述的线程标识符之一。
释放以前附加的进程或核心文件。如果存在 -a 选项,则将释放进程,并且该进程将保留停止状态且被放弃。然后,可以通过 prun(1)(参见 proc(1))继续执行,也可以通过应用 mdb 或其他调试器来恢复。缺省情况下,如果释放的进程是由 mdb 使用 ::run 创建的,将强制终止该进程;如果该进程是由 mdb 使用 -p 选项、使用 ::attach 或 :A dcmd 附加的,将释放该进程并设置为正在运行。
启动新的目标程序,使用指定的参数运行并附加到该程序。参数不由 shell 解释。如果调试器已在检查实时运行的程序,它会先与此程序分离,如同使用 ::release 一样。
获取或设置其他调试器属性。如果未指定任何选项,将显示当前调试器属性集合。::set dcmd 可以识别以下选项:
强制接管 ::attach 应用到的下一个用户进程,等同于在命令行上使用 -F 选项执行 mdb。
设置用于定位宏文件的缺省路径。路径参数可以包含任意特殊标记,这些标记在“选项”下针对 -I 命令行选项进行介绍。
设置用于定位调试器模块的缺省路径。路径参数可以包含任意特殊标记,这些标记在“选项”下针对 -I 命令行选项进行介绍。
启用指定的调试器选项。如果使用了 -o 形式,将禁用选项。选项字符串在“选项”下随 -o 命令行选项一起介绍。
将命令提示符设置为指定的提示字符串。
将符号匹配距离设置为指定的距离。有关详细信息,请参阅“选项”下的 -s 命令行选项的说明。
重新打开目标以便执行写入,等同于在命令行上使用 -w 选项执行 mdb。
显示硬件和软件的修订信息。未指定任何选项时,将显示一般系统信息。-v 选项显示所有装入对象的版本信息,而 -p 选项仅显示已作为修补程序的一部分安装在系统上的装入对象的版本信息。版本信息并非对所有装入对象都可用。没有版本信息的装入对象将在 -p 选项的输出中省略,而在 -v 选项的输出中作为 "Unknown" 版本列出。
跟踪指定信号的传送。可以在 dcmd 前面使用可选的信号编号来标识信号,也可以在 dcmd 后面使用信号名称或编号的列表来标识(参见 signal.h(3HEAD))。-d、-D、-e、-s、-t、-T、-c 和 -n 选项具有与用于 ::evset dcmd 时的相同意义。最初,对缺省情况下导致进程转储核心的信号集(参见 signal.h(3HEAD)) 和 SIGINT 进行跟踪。
列显指定 type 的大小(以字节为单位)。type 参数可以命名 C 结构、联合、枚举、基本整数类型或者指向任意这些类型的指针。类型名称可以使用反引号 (`) 作用范围运算符,如上面的符号名称解析中所述。::sizeof dcmd 只能用于包含旨在用于 mdb 的符号调试信息的对象。有关详细信息,请参阅下面的“注释”中的符号调试信息。
列显 C 栈回溯。如果 dcmd 前面是显式地址,将显示在此虚拟内存地址开始的回溯。否则,将显示代表线程的栈。如果将可选计数值指定为参数,则在输出中为每个栈帧显示不超过 count 个参数。
列显与当前目标相关的信息汇总。
单步执行目标程序的一个指令。如果将可选的信号名称或编号(参见 signal.h(3HEAD))指定为参数,则该信号将在恢复执行过程中立即传输到目标。如果指定了可选的 "over" 参数,::step 将步出子例程调用。::step over 参数与 ::next dcmd 相同。如果指定了可选的 "out" 参数,目标程序将继续执行,直至代表线程从当前函数返回。如果当前没有目标程序在运行,::step out 将启动新的程序开始运行,如同使用 ::run 一样,并在第一个指令处停止。:s dcmd 与 ::step 相同。:u dcmd 与 ::step out 相同。
跟踪指定系统调用的进入或退出。可以在 dcmd 前面使用可选的系统调用号来标识系统调用,也可以在 dcmd 后面使用系统调用名称或编号的列表来标识(参见 <sys/syscall.h>)。如果指定了 -i 选项(缺省值),事件说明符将在进入每个系统调用的内核时触发。如果指定了 -o 选项,事件说明符将在从内核中退出时触发。-d、-D、-e、-s、-t、-T、-c 和 -n 选项具有与用于 ::evset dcmd 时的相同意义。
列显指定线程局部存储 (TLS) 符号在指定线程上下文中的存储地址。线程表达式应为上面的线程支持中所述的线程标识符之一。符号名称可使用上面的符号名称解析中所述的任何作用范围运算符。
设置命名变量的属性。如果指定了一个或多个变量名,则定义这些变量并且将它们设置为点的值。如果存在 -t 选项,将设置与各个变量关联的用户定义标记。如果存在 -t 选项,将清除标记。如果未指定变量名,将列显变量列表及其值。
卸载指定的 dmod。可以使用 ::dmods dcmd 列显活动 dmod 的列表。不能卸载内置模块。不能卸载繁忙的模块(即 dcmd 正在执行)。
从已定义变量的列表中取消设置(删除)指定的变量。mdb 导出的一些变量已标记为持久变量,不能由用户取消设置。
列显命名变量的列表。如果存在 -n 选项,输出将限制为当前具有非零值的变量。如果存在 -p 选项,将按照适合于调试器使用 $< dcmd 重新处理的形式列显变量。此选项可用于将变量记录到宏文件中,然后在以后恢复这些值。如果存在 -t 选项,将只列显标记的变量。可以使用 ::typeset dcmd 的 -t 选项来标记变量。
列显调试器版本号。
列显指定虚拟地址的物理地址映射(如果可行)。::vtop dcmd 仅在检查内核目标时可用,或者在检查内核故障转储内部的用户进程时可用(在发出 ::context dcmd 之后)。
从内核上下文检查内核目标时,-a 选项可用于指定备用地址空间结构的地址 (as),该地址空间结构应该用于虚拟地址到物理地址的转换。缺省情况下,使用内核的地址空间进行转换。即使转储内容只包含内核页,此选项也可用于活动地址空间。
使用指定的遍历器遍历数据结构的元素。 可以使用 ::walkers dcmd 列出可用遍历器。一些遍历器在全局数据结构上操作,不需要起始地址。例如,遍历内核中的 proc 结构列表。其他遍历器对必须显式指定地址的特定数据结构进行操作。例如,在给定指向地址空间的指针的情况下,遍历区段的列表。在交互使用时,::walk dcmd 以缺省基数显示数据结构中各个元素的地址。dcmd 也可用于为流水线提供地址列表。 遍历器名称可以使用反引号 (`) 作用范围运算符,如上面的 dcmd 和遍历器名称解析中所述。如果指定了可选的 variable-name,将为指定的变量分配在 mdb 调用流水线的下一阶段时遍历的每一步骤所返回的值。
列出可用遍历器并列显每个遍历器的简要说明。
列显导出指定的 dcmd 和遍历器的 dmod。这些 dcmd 可用于确定哪个 dmod 当前正在提供指定的 dcmd 或遍历器的全局定义。有关全局名称解析的详细信息,请参阅上面的有关 dcmd 和遍历器名称解析的部分。-v 选项使 dcmd 按照优先级顺序列显各个 dcmd 和遍历器的备用定义。
在指定地址设置监视点。可通过在 dcmd 之前指定可选的重复计数来设置被监视区域的长度(以字节为单位)。如果没有显式设置长度,缺省值为一个字节。::wp dcmd 允许将监视点配置为在存在任何读取(-r 选项)、写入(-w 选项)或执行(-x 选项)访问的组合时触发。-d、-D、-e、-s、-t、-T、-c 和 -n 选项具有与用于 ::evset dcmd 时的相同意义。:a dcmd 可在指定地址处设置读取访问监视点。:p dcmd 可在指定地址处设置执行访问监视点。:w dcmd 可在指定地址处设置写入访问监视点。:a、:p 和 :w dcmd 之后的参数会串联在一起形成回调字符串。如果此字符串包含元字符,必须引用该字符串。
列出由当前目标导出的外部数据缓冲区。 外部数据缓冲区表示与无法通过标准目标工具访问的目标相关联的信息(即地址空间、符号表或寄存器集合)。这些缓冲区可以由 dcmd 使用;有关详细信息,请参阅《Oracle Solaris Modular Debugger Guide》。
从跟踪的软件事件列表中删除所有事件说明符。事件说明符也可以使用 ::delete 删除。
支持下列选项:
禁止自动装入 mdb 模块。缺省情况下,mdb 尝试装入与用户进程或核心文件中的活动共享库对应的调试器模块,或者尝试装入与实时操作系统或操作系统故障转储中的已装入内核模块对应的调试器模块。
强制原始文件调试模式。缺省情况下,mdb 尝试推断对象和核心文件操作数是引用了用户可执行文件和核心转储,还是引用了成对的操作系统故障转储文件。如果无法推断文件类型,则缺省情况下,调试器将文件作为纯二进制数据进行检查。 -f 选项强制 mdb 将参数作为一组原始文件解释以进行检查。
如果需要,强制接管指定的用户进程。 缺省情况下,mdb 拒绝附加到已处于其他调试工具(例如 truss(1))控制下的用户进程。使用 -F 选项,mdb 会强制附加到这些进程。这可能会在 mdb 和其他尝试控制进程的工具之间造成意外的交互。
设置用于定位宏文件的缺省路径。宏文件使用 $< 或 $<< dcmd 读取。路径是使用冒号 (:) 字符分界的目录名称序列。-I include 路径和 -L library 路径(参见下文)也可以包含以下任意标记:
展开到当前的指令集合体系结构 (ISA) 名称('sparc'、'sparcv9' 或 'i386')。
展开到要修改的路径的旧值。要将目录附加到现有路径之前或之后时,这非常有用。
展开到当前平台字符串(可以为 uname -i,或者为存储在进程核心文件或故障转储中的平台字符串)。
展开到根目录的路径名。可以使用 -R 选项指定备用根目录。如果不存在 -R 选项,将从指向 mdb 可执行文件自身的路径动态派生根目录。例如,如果执行 /bin/mdb,根目录将为 /。如果执行 /net/hostname/bin/mdb,根目录将派生为 /net/hostname。
展开到当前目标的名称。这可以为文本字符串 'proc'(用户进程或用户进程核心文件)、'kvm'(内核故障转储或实时操作系统)或 'raw'(原始文件)。
32 位 mdb 的缺省包含文件路径为:
%r/usr/platform/%p/lib/adb:%r/usr/lib/adb
64 位 mdb 的缺省包含文件路径为:
%r/usr/platform/%p/lib/adb/%i:%r/usr/lib/adb/%i
强制内核调试模式。缺省情况下,mdb 尝试推断对象和核心文件操作数是引用了用户可执行文件和核心转储,还是引用了成对的操作系统故障转储文件。-k 选项强制 mdb 假定这些文件为操作系统故障转储文件。如果未指定对象或核心操作数,但指定了 -k 选项,mdb 将缺省使用对象文件 /dev/ksyms 和核心文件 /dev/kmem。限制只有组 sys 可以对 /dev/kmem 执行读取访问。写入访问需要 ALL 权限。
装入 kmdb,停止实时运行的操作系统内核,并继续到 kmdb 调试器提示符。此选项只应在系统控制台上使用,因为后续的 kmdb 提示符将显示在系统控制台上。
设置用于定位调试器模块的缺省路径。模块在启动时自动装入,或者使用 ::load dcmd 装入。路径是使用冒号 (:) 字符分界的目录名称序列。-L 库路径也可以包含为上面的 -I 显示的任何标记。
禁止按需装入内核模块符号。缺省情况下,mdb 处理已装入内核模块的列表并执行每模块符号表的按需装入。如果指定了 -m 选项,mdb 将不尝试处理内核模块列表或提供每模块符号表。因此,在启动时不装入与活动内核模块对应的 mdb 模块。
预装所有内核模块符号。缺省情况下,mdb 执行内核模块符号的按需装入:当地址为该模块的文本或者引用了数据区时,将读取模块的完整符号表。使用 -M 选项时,mdb 将在启动期间装入所有内核模块的完整符号表。
启用指定的调试器选项。如果使用了 -o 形式的选项,将禁用指定的 option。除非在下面另有说明,否则缺省情况下将禁用所有选项。mdb 可以识别以下 option 参数:
启用更严格的 adb(1) 兼容性。提示符设置为空字符串,并且禁用诸如输出页面调度程序等多种 mdb 功能。
对 ::print 显示的数组成员数设置缺省限制。如果 limit 是特殊标记 none,缺省情况下将显示所有数组成员。
对 ::print 在列显字符数组时尝试作为 ASCII 字符串显示的字符数设置缺省限制。 如果 limit 是特殊标记 none,缺省情况下将整个字符数组显示为字符串。
设置调试器跟踪 exec(2) 系统调用的行为。mode 应为以下命令常量之一:
如果 stdout 是终端设备,调试器将在 exec(2) 系统调用返回后停止,然后提示用户决定跟踪 exec 还是停止。如果 stdout 不是终端设备,ask 模式将缺省为 stop。
调试器将通过自动继续执行目标进程来跟踪 exec,并根据新的可执行文件重置所有映射和符号表。follow 行为在下面的“注释”的与 Exec 交互中进行了详细介绍。
调试器将停止从 exec 系统调用返回的内容。stop 行为在下面的“注释”的与 Exec 交互中进行了详细介绍。
设置调试器跟踪 fork(2)、fork1(2) 或 vfork(2) 系统调用的行为。mode 应为以下命令常量之一:
如果 stdout 是终端设备,调试器将在 fork(2) 系统调用返回后停止,然后提示用户决定跟踪父进程还是子进程。如果 stdout 不是终端设备,ask 模式将缺省为 parent。
调试器跟踪父进程,与子进程分离并将它设置为正在运行。
调试器跟踪子进程,与父进程分离并将它设置为正在运行。
终端中输入 EOF 序列 (^D) 时,调试器不退出。必须使用 ::quit dcmd 退出。
指定了 -p 选项或者应用了 ::attach 或 :A dcmd 时,在附加到用户进程时不停止该进程。nostop 行为在下面的“注释”的进程附加和释放中进行详细介绍。
启用输出页面调度程序(缺省)。
如果在终端输入了换行作为完整命令时,mdb 将使用点的当前值重复上一个命令。-o adb 暗含此选项。
对于使用链接图而非 LM_ID_BASE 和 LM_ID_LDSO 的用户应用程序,mdb 为用户应用程序中的符号命名和标识提供了支持,如上面的符号名称解析中所述。链接图上除 LM_ID_BASE 或 LM_ID_LDSO 之外的符号显示为 LMlmid`library`symbol,其中 lmid 是以缺省输出基数 (16) 显示的链接图 ID。用户可以选择通过启用 showlmid 选项来配置 mdb,以便显示所有符号和对象的链接图 ID 范围,包括与 LM_ID_BASE 和 LM_ID_LDSO 关联的那些内容。处理对象文件名的内置 dcmd 根据上面的 showlmid 值显示链接图 ID,包括 ::nm、::mappings、$m 和 ::objects。
附加到指定的进程 ID 并停止该进程。mdb 使用 /proc/pid/object/a.out 文件作为可执行文件路径名。
设置命令提示符。缺省提示符为 '>'。
设置路径名扩展的根目录。缺省情况下,从 mdb 可执行文件自身的路径名派生根目录。根目录在路径名扩展期间替换 %r 标记。
设置地址到符号名称的转换到指定 distance 的符号匹配距离。缺省情况下,mdb 将距离设置为零,这将启用智能匹配模式。每个 ELF 符号表条目包括值 V 和大小 S,表示函数或数据对象的大小(以字节为单位)。在智能模式中,如果 A 在范围 [V, V + S) 中,mdb 会将地址 A 与指定符号匹配。如果指定了任意非零距离,将使用相同的算法,但上面的表达式中的 S 始终为指定的绝对距离,并且忽略符号大小。
抑制用户的 ~/.mdbrc 文件的处理。缺省情况下,如果由 $HOME 定义的用户起始目录中存在宏文件 .mdbrc,mdb 将读取和处理宏文件。如果存在 -S 选项,将不读取此文件。
强制用户调试模式。缺省情况下,mdb 尝试推断对象和核心文件操作数是引用了用户可执行文件和核心转储,还是引用了成对的操作系统故障转储文件。-u 选项强制 mdb 假定这些文件不是操作系统故障转储文件。
如果 kmdb 已装入,则将它卸载。如果不在使用 kmdb,则应将它卸载,以便将内核调试器所使用的内存释放回可供操作系统使用的空闲内存。
设置反汇编程序版本。缺省情况下,mdb 将尝试推断调试目标的适当反汇编程序版本。反汇编程序可以使用 -V 选项显式设置。::disasms dcmd 列出可用的反汇编程序版本。
打开指定的对象和核心文件进行写入。
允许对映射到 I/O 设备的内存地址的访问。缺省情况下,mdb 不允许此类访问,因为许多设备不会针对无效的软件处理提供硬件保护。请仅在调试设备驱动程序时谨慎使用此选项。
发送用于 tty 模式的显式终端初始化序列。某些终端(例如 cmdtool(1))需要显式初始化序列以便切换到 tty 模式。如果没有此初始化序列,诸如 standout 模式这样的终端功能将无法供 mdb 使用。
支持下列操作数:
指定要检查的 ELF 格式对象文件。mdb 提供了检查和编辑 ELF 格式可执行文件 (ET_EXEC)、ELF 动态库文件 (ET_DYN)、ELF 可重定位对象文件 (ET_REL) 和操作系统 unix.X 符号表文件的功能。
指定 ELF 进程核心文件 (ET_CORE) 或操作系统故障转储 vmcore.X 文件。如果提供的 ELF 核心文件操作数没有对应的对象文件,mdb 将尝试使用不同算法推断生成核心的可执行文件的名称。如果找不到可执行文件,mdb 仍将执行,但某些符号信息可能会不可用。
指定表示一对操作系统故障转储文件的数字后缀。例如,如果后缀为 '3',mdb 推断应检查文件 'unix.3' 和 'vmcore.3'。如果这些文件不存在,但 'vmdump.3' 存在,将列显一条消息,指示必须先运行 savecore -f vmdump.3 以便解压缩转储文件。如果当前目录中存在具有相同名称的实际文件,数字字符串将不解释为后缀。
mdb 以大文件感知方式处理所有输入文件(包括脚本、对象文件、核心文件和原始数据文件)。有关处理大于等于 2 GB(231 字节)的大文件的详细信息,请参见 largefile(5)。
将返回以下退出值:
调试器成功完成执行。
发生了致命错误。
指定的命令行选项无效。
此变量用于确定命令历史记录列表的最大长度。如果不存在此变量,缺省长度将为 128。
此变量用于确定 .mdbrc 文件可以驻留在其中的用户起始目录的路径名。如果不存在此变量,不会发生 .mdbrc 处理。
此变量用于确定用来处理通过 ! 元字符请求的 shell 转义的 shell 路径名。如果不存在此变量,将使用 /bin/sh。
用户 mdb 初始化文件。在初始化调试目标之后、但在执行模块自动装入或从标准输入中读取任何命令之前处理 .mdbrc 文件(如果存在)。
内核虚拟内存映像设备。此设备特殊文件在检查实时操作系统时用作核心文件。
内核符号表设备。此设备特殊文件在检查实时操作系统时用作对象文件。
在检查和控制用户进程时读取的进程信息文件。
使用 $< 和 $<< dcmd 读取的宏文件的缺省目录。platform-name 是平台的名称,该名称从核心文件或故障转储中的信息派生,也可从当前计算机派生,就像由 uname -i 派生一样(参见 uname(1))。
使用 ::load dcmd 装入的调试器模块的缺省目录。platform-name 是平台的名称,该名称从核心文件或故障转储中的信息派生,也可从当前计算机派生,就像由 uname -i 派生一样(参见 uname(1))。
有关下列属性的描述,请参见 attributes(5):
|
adb(1)、cmdtool(1)、gcore(1)、proc(1)、pgrep(1)、ps(1)、stty(1)、truss(1)、uname(1)、coreadm(1M)、dumpadm(1M)、largefile(5)、savecore(1M)、exec(2)、fork(2)、_lwp_self(2)、pipe(2)、vfork(2)、dlopen(3C)、elf(3ELF)、libc_db(3LIB)、libkvm(3LIB)、libthread(3LIB)、signal(3C)、signal.h(3HEAD)、thr_self(3C)、core(4)、proc(4)、attributes(5)、largefile(5)、threads(5)、ksyms(7D)、mem(7D)
《Oracle Solaris Modular Debugger Guide》
调试器及其 dmod 在相同地址空间中执行,因此有错误的 dmod 很可能会导致 mdb 转储核心或者发生错误的行为。mdb 恢复功能(如上面的信号处理中所述)为这些情况提供了有限的恢复机制。但是,mdb 不可能明确了解有问题的 dmod 是仅破坏了自身的状态,还是破坏了调试器的全局状态。因此,无法确保恢复操作安全,也无法保证调试器接下来不会出现故障。在恢复之后,最安全的操作过程是保存所有重要调试信息,然后退出并重新启动调试器。
使用调试器修改(即写入到)实时运行操作系统的地址空间中是极度危险的,在用户损坏了核心数据结构的情况下,可能会导致系统故障。
mdb 不支持检查由 Solaris 2.6 之前的 Solaris 版本生成的进程核心文件。调试由 Solaris 9 或更早版本生成的核心文件时,符号信息可能不可用。由于这些核心文件中不存在文本区段和只读数据,符号信息可能与转储核心时进程中存在的数据不匹配。在早于 Solaris 9 的发行版中,文本区段和只读数据在缺省情况下包括在核心文件中。用户可以使用 coreadm(1M) 配置用户进程,从核心文件中排除该信息。因此,mdb 为这些核心文件提供的信息无法与进程转储核心时存在的数据匹配。Solaris x86 系统中的核心文件无法在 Solaris SPARC 系统上进行检查,反之亦然。
Solaris 7 和更早发行版的故障转储只能在使用与操作系统发行版相对应的 libkvm 时才能进行检查。如果使用不同操作系统发行版的 dmod 检查某个操作系统发行版的故障转储,内核实现中的更改可能会导致某些 dcmd 或遍历器无法正常工作。mdb 在检测到这种情况时将发出警告消息。Solaris x86 系统中的故障转储无法在 Solaris SPARC 系统上进行检查,反之亦然。
mdb 支持对 32 位和 64 位程序进行调试。在检查目标并确定数据模型之后,mdb 在必要时会自动重新执行与目标具有相同数据模型的 mdb 二进制文件。这种方法简化了编写调试器模块的任务,因为装入的模块使用与主要目标相同的数据模型。只能将 64 位调试器用于调试 64 位目标程序。64 位调试器只能在运行 64 位操作环境的系统中使用。
执行 64 位进程的调试器在调试 32 位进程时,可能需要重新执行自身,反之亦然。这种情况的处理在下面的与 Exec 交互中进行详细介绍。
受控进程执行成功的 exec(2) 时,调试器的行为由 ::set -o follow_exec_mode 选项控制,如上文所述。如果调试器和被调试的进程具有相同的数据模型,"stop" 和 "follow" 模式将确定 mdb 是自动继续执行目标还是在 exec 之后返回调试器提示符。如果调试器和被调试的进程具有不同的数据模型,"follow" 行为将导致 mdb 使用合适的数据模型自动重新执行 mdb 二进制文件并重新附加到进程,仍然在从 exec 返回时停止。并非所有调试器状态在此重新执行过程中均会保留。
如果 32 位被调试进程执行了 64 位程序,"stop" 将返回到命令提示符,但调试器不再能够检查进程,因为它现在使用 64 位数据模型。要恢复调试,请执行 ::release - a dcmd,退出 mdb,然后执行 mdb -p pid 以便将 64 位调试器重新附加到进程。
如果 64 位被调试进程执行 32 位程序,"stop" 将返回到命令提示符,但调试器只提供有限的功能用于检查新进程。所有内置 dcmd 均按预期工作,但可以装入的 dcmd 并非如此,因为它们不执行数据模型结构转换。用户应按上文所述,将调试器释放并重新附加到进程,以便恢复完整的调试功能。
如果调试器附加到由作业控制停止的进程(即,为了响应 SIGTSTP、SIGTTIN 或 SIGTTOU 而停止),则在由继续 dcmd 继续执行时,进程无法重新设置为正在运行。如果被调试进程是相同会话的成员(即与 mdb 共享相同的控制终端),mdb 会尝试将关联的进程组提升到前台,并使用 SIGCONT 继续执行进程,以便将进程从作业控制停止中恢复。将 mdb 与此类进程分离时,它在退出前会将进程组还原到后台。如果被调试进程不是相同会话的成员,mdb 将无法安全地将进程组提升到前台,因此它会针对调试器继续执行进程,但进程仍由作业控制停止。mdb 在这种情况下将列显警告,用户必须从合适的 shell 发出 "fg" 命令以便恢复进程。
mdb 附加到正在运行的进程时,进程将停止并保持停止状态,直至应用了继续 dcmd 之一或者调试器退出。如果在使用 -p 将调试器附加到进程之前,或者在发出 ::attach 或 :A 命令之前,-o nostop 选项已启用,则 mdb 将附加到进程,但不停止进程。虽然进程仍在运行,它可以检测为正常(尽管带有不一致的结果),并且可能会启用断点或其他跟踪标志。如果 :c 或 ::cont dcmd 在进程运行的时候执行,调试器将等待进程停止。如果没有发生跟踪的软件事件,用户可以在 :c 或 ::cont 之后发送中断 (^C),以便强制进程停止并将控制权返回给调试器。
在执行 :R、::release、:r、::run、$q 或 ::quit dcmd 时,或者调试器由于 EOF 或信号而终止时,mdb 将释放当前正在运行的进程(如果有)。如果进程最初是由调试器使用 :r 或 ::run 创建的,则会在释放时强制终止,就如使用 SIGKILL 一样。如果在将 mdb 附加到进程之前进程已在运行,该进程在释放时将再次设置为正在运行。进程可以使用 ::release -a 选项释放、保持停止或者被放弃。
::list、::offsetof、::print 和 ::sizeof dcmd 要求一个或多个装入对象包含适用于 mdb 的压缩符号调试信息。此信息当前只能用于某些 Solaris 内核模块。
《Oracle Solaris Modular Debugger Guide》提供了有关 mdb 功能的更为详细的说明,以及面向调试器模块开发者的信息。
头文件 <sys/mdb_modapi.h> 包含 MDB 模块 API 中函数的原型,而 /source/demo/mdb-examples 软件包在目录 /usr/demo/mdb 中提供了示例模块的源代码。