Solaris 模块调试器指南

mdb_printf()

void mdb_printf(const char *format, ...);

使用指定的格式字符串和参数列显带格式的输出。模块编写者应该将 mdb_printf() 用于所有输出,但警告和错误消息除外。在适当的情况下,此函数会自动触发内置的输出页面调度程序。mdb_printf() 函数与 printf(3C) 类似,但有一些例外:不支持宽字符串的 %C%S%ws 说明符,不支持 %f 浮点格式,两种可能的双精度格式的 %e%E%g%G 说明符仅生成单一样式的输出,不支持 %.n 格式的精度说明。支持的说明符列表如下:

标志说明符

%#

如果在格式字符串中找到 # 符号,则这会选择给定格式的替换形式。 并不是所有的格式都具有替换形式;替换形式随格式的不同而不同。有关替换格式的详细信息,请参阅下面的格式说明。

%+

列显带符号值时,始终显示符号(即以 '+' 或 '-' 为前缀)。 如果没有 %+,则正值不带有符号前缀,而在负值前面加上 '-' 前缀。

%-

在指定的字段宽度内左对齐输出。如果输出的宽度小于指定的字段宽度,则在右侧用空白填充输出。如果没有 %-,则缺省情况下将值右对齐。

%0

如果输出是右对齐的,而且输出的宽度小于指定的字段宽度,则用零填充输出字段。如果没有 %0,则在右对齐的值前面加上空白,以填充字段。

字段宽度说明符

%n

将字段宽度设置为指定的十进制值。

%?

将字段宽度设置为十六进制指针值的最大宽度。在 ILP32 环境中为 8,在 LP64 环境中为 16。

%*

将字段宽度设置为在参数列表的当前位置指定的值。假定此值为 int。请注意,在 64 位编译环境中,可能需要将 long 值强制转换为 int

整数说明符

%h

要列显的整数值为 short

%l

要列显的整数值为 long

%ll

要列显的整数值为 long long

终端属性说明符

如果调试器的标准输出是终端,而且可以通过 terminfo 数据库获取终端属性,则可以使用以下终端转义结构:

%<n>

启用对应于 n 的终端属性。对于 %<> 的每个实例,只能启用一个属性。

%</n>

禁用对应于 n 的终端属性。请注意,在反白显示、灰显文本和粗体文本的情况下,禁用这些属性的终端代码可能是相同的。因此,相互独立地禁用这些属性也许是不可能的。

如果没有可用的终端信息,则 mdb_printf() 将忽略每个终端属性结构。有关终端属性的更多信息,请参见 terminfo(4)。可用的 terminfo 属性如下:

a

替换字符集

b

粗体文本

d

灰显文本

r

反白显示

s

最突出的功能

u

加下划线

格式说明符

%%

列显 '%' 符号。

%a

以符号形式列显地址。与 %a 关联的值的最小大小是 uintptr_t;不需要指定 %la。如果打开地址到符号的转换,则调试器会尝试将地址转换为符号名称后跟当前输出中的偏移,并列显此字符串;否则,在缺省输出基数中列显值。 如果使用 %#a,则替换格式会将 ':' 后缀添加到输出。

%A

此格式与 %a 相同,只不过无法将地址转换为符号名称以及偏移时,不列显任何内容。如果使用 %#A,则在地址转换失败时替换格式列显 '?'。

%b

以符号形式解码并列显位字段。此说明符需要两个连续参数:位字段值(对于 %bint,对于 %lblong,等等)和一个指向 mdb_bitmask_t 结构的数组的指针:

typedef struct mdb_bitmask {

		const char *bm_name;       /* String name to print */

		u_longlong_t bm_mask;      /* Mask for bits */

		u_longlong_t bm_bits;      /* Result for value & mask */

} mdb_bitmask_t;

数组应该以其 bm_name 字段设置为 NULL 的结构结尾。使用 %b 时,调试器读取值参数,然后循环检查每个 mdb_bitmask 结构以查看是否为以下情况:

(value & bitmask->bm_mask) == bitmask->bm_bits

如果此表达式为真,则列显 bm_name 字符串。列显的每个字符串由逗号分隔。以下示例说明如何使用 %b 解码 kthread_t 中的 t_flag 字段:

const mdb_bitmask_t t_flag_bits[] = {

		{ "T_INTR_THREAD", T_INTR_THREAD, T_INTR_THREAD },

		{ "T_WAKEABLE", T_WAKEABLE, T_WAKEABLE },

		{ "T_TOMASK", T_TOMASK, T_TOMASK },

		{ "T_TALLOCSTK", T_TALLOCSTK, T_TALLOCSTK },

			...

		{ NULL, 0, 0 }

};



void

thr_dump(kthread_t *t)

{

		mdb_printf("t_flag = <%hb>\n", t->t_flag, t_flag_bits);



		...

}

如果 t_flag 设置为 0x000a,则该函数将列显:

t_flag = <T_WAKEABLE,T_TALLOCSTK>

如果指定 %#b,则会将与位掩码数组中的元素不匹配的所有位的联合列显为已解码名称后面的十六进制值。

%c

将指定的整数列显为 ASCII 字符。

%d

将指定的整数列显为带符号十进制值。与 %i 相同。如果指定 %#d,则替换格式将为值添加前缀 '0t'。

%e

以浮点格式 [+/-]d.ddddddde[+/-]dd 列显指定的双精度数,其中在基数字符前有一位,精度为七位,在指数后至少有两位。

%E

使用与 %e 相同的规则列显指定的双精度数,但指数字符将是 'E' 而不是 'e'。

%g

以与 %e 相同的浮点格式列显指定的双精度数,但精度为十六位。如果指定 %llg,则参数应为 long double 类型(四精度浮点值)。

%G

使用与 %g 相同的规则列显指定的双精度数,但指数字符将是 'E' 而不是 'e'。

%i

将指定的整数列显为带符号十进制值。与 %d 相同。如果指定 %#i,则替换格式将为值添加前缀 '0t'。

%I

将指定的 32 位无符号整数列显为点分十进制格式的 Internet IPv4 地址(例如,十六进制值 0xffffffff 将列显为 255.255.255.255)。

%m

列显由空格组成的边距。如果未指定字段,则使用缺省的输出边距宽度;否则,字段宽度确定列显的空格字符数。

%o

将指定的整数列显为无符号八进制值。如果使用 %#o,则替换格式将为输出添加前缀 '0'。

%p

将指定的指针 (void *) 列显为十六进制值。

%q

将指定的整数列显为带符号八进制值。如果使用 %#o,则替换格式将为输出添加前缀 '0'。

%r

在当前输出基数中将指定的整数列显为无符号值。用户可以使用 $d dcmd 更改输出基数。如果指定 %#r,则替换格式将为值添加相应的基数前缀: '0i'(用于二进制)、'0o'(用于八进制)、'0t'(用于十进制)或 '0x'(用于十六进制)。

%R

在当前输出基数中将指定的整数列显为带符号值。如果指定 %#R,则替换格式将为值添加相应的基数前缀。

%s

列显指定的字符串 (char *)。如果字符串指针为 NULL,则列显字符串 '<NULL>'。

%t

前移一个或多个制表停止位置。如果未指定宽度,则输出前移到下一个制表停止位置;否则,字段宽度确定前移多少个制表停止位置。

%T

将输出列前移到字段宽度的下一个倍数。如果未指定字段宽度,则不执行操作。如果当前输出列不是字段宽度的倍数,则将添加空格以前移输出列。

%u

将指定的整数列显为无符号十进制值。如果指定 %#u,则替换格式将为值添加前缀 '0t'。

%x

将指定的整数列显为十六进制值。字符 a-f 用作代表值 10-15 的符号。如果指定 %#x,则替换格式将为值添加前缀 '0x'。

%X

将指定的整数列显为十六进制值。字符 A-F 用作值 10-15 的位。如果指定 %#X,则替换格式将为值添加前缀 '0X'。

%Y

将指定的 time_t 列显为字符串 'year month day HH:MM:SS'。