使用别名
别名 是自动替换为其他字符串的字符串。 可以在调试器命令中使用它们,并避免重新设置某些常见短语的tyty。
别名由 一个别名 和一个等效的 别名组成。 使用别名作为调试器命令的一部分时,该名称将自动替换为等效的别名。 在分析或执行命令之前,将立即进行此替换。
调试器支持三种类型的别名:
可以设置和命名 用户命名别名。
可以设置 固定名称别名,但它们命名为 $u 0、 $u 1、... $u 9。
调试器设置并命名 自动别名。
定义 User-Named 别名
定义用户命名别名时,可以选择别名和等效的别名:
别名可以是不包含空格的任何字符串。
别名等效项可以是任何字符串。 如果在键盘上输入,别名等效项不能包含前导空格或回车符。 或者,可以将它设置为等于内存中的字符串、数值表达式的值、文件的内容、环境变量的值或一个或多个调试器命令的输出。
别名和别名等效项都区分大小写。
若要定义或重新定义用户命名的别名,请使用 作为 (Set Alias) 或 aS (Set Alias) 命令。
若要删除别名,请使用 ad (Delete Alias) 命令。
若要列出所有当前用户命名的别名,请使用 al (List Aliases) 命令。
定义 Fixed-Name 别名
有 10 个固定名称别名。 其别名为 $u 0、 $u 1、... $u 9。 其别名等效项可以是不包含 ENTER 击键的任何字符串。
使用 r (Registers) 命令定义固定名称别名的等效别名。 定义固定名称别名时,必须在字母“u”之前插入一个句点 (.) 。 等号 (=) 后面的文本是等效的别名。 别名等效项可以包含空格或分号,但前导空格和尾随空格将被忽略。 除非要在结果) 中加上引号,否则不应将别名等效项括在引号 (中。
注意 不要对固定名称别名使用 r (Registers) 命令混淆。 这些别名不是寄存器或伪寄存器,即使你使用 r 命令设置它们的别名等效项。 无需在这些别名之前添加 at (@) 符号,并且不能使用 r 命令 显示 这些别名之一的值。
默认情况下,如果未定义固定名称别名,则它是空字符串。
自动别名
调试器设置以下自动别名。
别名名称 | 等效别名 |
---|---|
$ntnsym |
计算机本机体系结构上 NT 符号的最合适的模块。 此别名可以等于 ntdll 或 nt。 |
$ntwsym |
在使用 WOW64 的 32 位调试过程中,最适合 NT 符号的模块。 此别名可以是 ntdll32 或其他 32 位版本的 Ntdll.dll。 |
$ntsym |
与当前计算机模式匹配的 NT 符号的最合适的模块。 在本机模式下调试时,此别名与 $ntnsym 相同。 在非本机模式下调试时,调试器会尝试查找与此模式匹配的模块。 (例如,在使用 WOW64 的 32 位调试期间,此别名与 $ntwsym.) |
$CurrentDumpFile |
调试器加载的最后一个转储文件的名称。 |
$CurrentDumpPath |
调试器加载的最后一个转储文件的目录路径。 |
$CurrentDumpArchiveFile |
调试器加载的上一个转储存档文件 (CAB 文件) 的名称。 |
$CurrentDumpArchivePath |
调试器加载的最后一个转储存档文件 (CAB 文件的目录路径) 。 |
自动别名类似于 自动伪寄存器,不同之处在于,可以将自动别名与别名相关的令牌 ((如 ${ }) )一起使用,而不能对这些令牌使用伪寄存器。
在调试器命令窗口中使用别名
定义别名后,可以在任何命令条目中使用它。 别名会自动替换为等效的别名。 因此,可以将别名用作表达式或宏。
即使别名用引号引起来,它也会正确展开。 由于别名等效项可以包含任意数量的引号或分号,因此别名等效项可以表示多个命令。
仅当名称与其他字符之间用空格分隔时,才会识别用户命名别名。 其别名的第一个字符必须以行开头或后跟空格、分号或引号。 其别名的最后一个字符必须以行尾或后跟空格、分号或引号。
注意 在 “调试器命令”窗口中 输入以“as”、“aS”、“ad”或“al”开头的任何文本都不会收到别名替换。 此限制可防止别名命令呈现为不可操作。 但是,此限制还意味着,在行上跟随 ad 或 al 的命令不会替换其别名。 如果希望在以这些字符串之一开头的行中替换别名,请在别名前面添加分号。
但是,可以使用 ${ } 令牌扩展用户命名别名,即使它位于其他文本旁边也是如此。 还可以将此令牌与某些开关一起使用,以防止扩展别名或显示某些与别名相关的值。 有关这些情况的详细信息,请参阅 ${ } (别名解释器) 。
固定名称别名从行中的任何点正确展开,无论它如何嵌入到行的文本中。
不能使用仅在 WinDbg (.open 中可用的命令, .write_cmd_hist (写入命令历史记录) 、 .lsrcpath 和 .lsrcfix) 以及一些其他命令 (.hh、 .cls、 .wtitle、 .remote、kernel-mode .restart 和带有别名的用户模式 .restart) 。
在脚本文件中使用别名
在脚本文件中使用别名时,必须特别小心,确保别名在正确的时间扩展。 请考虑以下脚本:
.foreach (value {dd 610000 L4})
{
as /x ${/v:myAlias} value + 1
.echo value myAlias
}
ad myAlias
第一次通过 循环时 , as, aS (Set Alias) 命令将值分配给 myAlias。 分配给 myAlias 的值为 1 加 610000, (dd 命令) 的第一个输出。 但是,执行 .echo (Echo Comment) 命令时,myAlias 尚未展开,因此,我们不会看到610001,而是看到文本“myAlias”。
0:001> $$>< c:\Script02.txt
00610000 myAlias
00905a4d 0x610001
00000003 0x905a4e
00000004 0x4
0000ffff 0x5
问题是,在输入新的代码块之前,myAlias 不会展开。 循环的下一个条目是一个新块,因此 myAlias 会扩展到610001。 但为时已晚:我们应该看到610001第一次通过循环,而不是第二次。可以通过将 .echo (Echo Comment) 命令包含在新块中来解决此问题,如以下脚本所示。
.foreach (value {dd 610000 L4})
{
as /x ${/v:myAlias} value + 1
.block{.echo value myAlias}
}
ad myAlias
使用更改后的脚本,我们得到以下正确的输出。
0:001> $$>< c:\Script01.txt
00610000 0x610001
00905a4d 0x905a4e
00000003 0x4
00000004 0x5
0000ffff 0x10000
有关详细信息,请参阅 .block 和 ${ } (别名解释器) 。
在别名中使用 .foreach 令牌
在别名的定义中使用 .foreach 令牌时,必须特别小心,以确保扩展令牌。 请考虑以下命令序列。
r $t0 = 5
ad myAlias
.foreach /pS 2 /ps 2 (Token {?@$t0}) {as myAlias Token}
al
第一个命令将 $t 0 伪寄存器的值设置为 5。 第二个命令删除以前可能已分配给 myAlias 的任何值。 第三个命令采用 ?@$t 0 命令的第三个标记,并尝试将该令牌的值分配给 myAlias。 第四个命令列出所有别名及其值。 我们预期 myAlias 的值为 5,但该值为单词“Token”。
Alias Value
------- -------
myAlias Token
问题是 as 命令 位于 .foreach 循环正文中行的开头。 当行以 as 命令开头时,不会展开该行中的别名和标记。 如果在 as 命令之前放置分号或空格,则会展开任何已具有值的别名或标记。 在此示例中,myAlias 未展开,因为它还没有值。 令牌已展开,因为它的值为 5。 下面是相同的命令序列,在 作为 命令之前添加分号。
r $t0 = 5
ad myAlias
.foreach /pS 2 /ps 2 (Token {?@$t0}) {;as myAlias Token}
al
现在,我们得到了预期的输出。
Alias Value
------- -------
myAlias 5
递归别名
可以在任何别名的定义中使用固定名称别名。 还可以在固定名称别名的定义中使用用户命名别名。 但是,若要在另一个用户命名别名的定义中使用用户命名别名,必须在 as 或 aS 命令之前添加一个分号,否则该行上不会发生别名替换。
使用此类型的递归定义时,每个别名在使用后都会立即转换。 例如,以下示例显示 3,而不是 7。
0:000> r $.u2=2
0:000> r $.u1=1+$u2
0:000> r $.u2=6
0:000> ? $u1
Evaluate expression: 3 = 00000003
同样,以下示例显示 3,而不是 7。
0:000> as fred 2
0:000> r $.u1= 1 + fred
0:000> as fred 6
0:000> ? $u1
Evaluate expression: 3 = 00000003
还允许使用以下示例,并显示 9。
0:000> r $.u0=2
0:000> r $.u0=7+$u0
0:000> ? $u0
Evaluate expression: 9 = 00000009
别名示例
可以使用别名,这样就不必键入长符号名称或复杂符号名称,如以下示例所示。
0:000> as Short usersrv!NameTooLongToWantToType
0:000> dw Short +8
以下示例类似于前面的示例,但它使用固定名称别名。
0:000> r $.u0=usersrv!NameTooLongToWantToType
0:000> dw $u0+8
可以将别名用作频繁使用的命令的宏。 以下示例将 eax 和 ebx 寄存器递增两次。
0:000> as GoUp r eax=eax+1; r ebx=ebx+1
0:000> GoUp
0:000> GoUp
以下示例使用别名来简化命令的键入。
0:000> as Cmd "dd esp 14; g"
0:000> bp MyApi Cmd
以下示例类似于前面的示例,但它使用固定名称别名。
0:000> r $.u5="dd esp 14; g"
0:000> bp MyApi $u5
上述两个示例等效于以下命令。
0:000> bp MyApi "dd esp 14; g"
Tools.ini 文件
在 CDB (和 NTSD) 中,可以在 tools.ini 文件中预定义固定名称别名。 若要预定义固定名称别名,请将所需的 $u 字段添加到 [NTSD] 条目,如以下示例所示。
[NTSD]
$u1:_ntdll!_RtlRaiseException
$u2:"dd esp 14;g"
$u9:$u1 + 42
不能在 Tools.ini 文件中设置用户命名别名。
Fixed-Name 别名与 User-Named 别名
与固定命名别名相比,用户名别名更易于使用。 其定义语法更简单,可以使用 al (List Aliases) 命令列出它们。
如果固定命名的别名在其他文本旁边使用,则会替换它们。 若要在用户命名别名位于其他文本旁边时替换该别名,请将它括在 ${ } (别名解释器) 令牌中。
固定名称别名替换发生在用户命名别名替换之前。