目录
别名是会自动替换为其他字符串的字符串。你可以在调试器命令中使用别名,以避免重复输入某些常用短语。
别名由别名名称和等效别名组成。当你在调试器命令中使用别名时,该名称会自动替换为等效别名。此替换会在命令解析或执行之前立即发生。
调试器支持3种别名:
(1) 可以设置和命名用户命名别名。
(2) 可以设置和命名固定名称别名,但其命名为 $u0, $u1, ..., $u9 。
(3) 调试器设置并命名自动别名。
1. 定义用户命名别名
定义用户命名别名时,可以选择别名名称及其等效项:
(1) 别名可以是任何不包含空格的字符串。
(2) 别名等效值可以是任何字符串。如果通过键盘输入,别名等效值不能包含前导空格或回车符。或者,可以将其设置为内存中的字符串、数值表达式的值、文件内容、环境变量的值,或一个或多个调试器命令的输出。
别名及其等效项均区分大小写。
用衣命名别名相关命令:
(1) 定义或重新定义用户命名别名:使用 `as`(设置别名)或 `aS`(设置别名)命令。
(2) 删除别名:使用 `ad`(alias delete)命令。
(3) 列出所有当前用户命名的别名: 使用 `al`( alias list)命令。
2. 定义固定名别名
共有 10 个固定名称别名,分别为 $u0 ,$u1,……,$u9 。它们的别名等效项可以是任何不包含回车键的字符串。
使用 r(寄存器)命令定义固定名称别名的等效项。定义固定名称别名时,必须在字母“u”前插入句点 (.)。等号 (=) 后面的文本即为别名等效项。别名等效项可以包含空格或分号,但前导空格和尾随空格将忽略。不应将别名等效项用引号括起来(除非你希望结果中包含引号)。
注意:不要因为使用 r (寄存器) 命令设置固定名称别名而感到困惑。即使你使用 r 命令设置它们的等效项,这些别名也不是寄存器或伪寄存器。r无需在这些别名前添加 @ 符号,也无法使用 r 命令显示这些别名的值。
默认情况下,如果你未定义固定名称的别名,则其值为空字符串。
3. 固定别名
调试器设置了以下自动别名。
| 别名 | 别名等价对象 |
| $ntnsym | 最适合计算机原生架构上 NT 符号的模块。此别名可以是 ntdll 或 nt。 |
| $ntwsym | 在使用 WOW64 进行 32 位调试时,最适合 NT 符号的模块。此别名可以是 ntdll32 或 Ntdll.dll 的其他 32 位版本。 |
| $ntsym | 最适用于当前机器模式的 NT 符号的模块。在本机模式下调试时,此别名与 $ntnsym 相同。在非本机模式下调试时,调试器会尝试查找与此模式匹配的模块。(例如,在使用 WOW64 进行 32 位调试时,此别名与 $ntwsym 相同。) |
| $CurrentDumpFile | 调试器加载的最后一个转储文件的名称。 |
| $CurrentDumpPath | 调试器加载的最后一个转储文件的目录路径。 |
| $CurrentDumpArchiveFile | 调试器加载的最后一个转储归档文件(CAB 文件)的名称。 |
| $CurrentDumpArchivePath | 调试器加载的最后一个转储归档文件(CAB 文件)的目录路径。 |
自动别名与自动伪寄存器类似,区别在于自动别名可以与别名相关的标记(例如 ${ })一起使用,而伪寄存器不能与这些标记一起使用。
4. 在调试器命名窗口中使用别名
定义别名后,即可在任何命令输入中使用它。别名会自动替换为等效的别名。因此,你可以将别名用作表达式或宏。
即使别名包含在引号中,它也能正确展开。由于等效的别名可以包含任意数量的引号或分号,因此它可以代表多个命令。
用户命名的别名只有在与其他字符之间用空格分隔时才能识别。别名的第一个字符必须位于行首,或者紧跟空格、分号或引号。别名的最后一个字符必须位于行尾,或者紧跟空格、分号或引号。
注意:在调试器命令窗口中输入的任何以“as”,“aS”,“ad”或“al”开头的文本都不会替换为别名。此限制是为了防止别名命令失效。然而,此限制也意味着,一行中紧随 `ad` 或 `al` 之后的命令的别名不会被替换。如果你希望替换以这些字符串开头的行中的别名,请在别名前添加分号。
但是,可以使用 `${ }` 标记展开用户命名的别名,即使它与其他文本相邻。还可以将此标记与某些开关一起使用,以阻止展开别名或显示某些与别名相关的值。有关这些情况的更多信息,请参阅 `${ }`(别名解释器)。
固定名称的别名可以从行中的任何位置正确展开,无论它如何嵌入到行文本中。
不能使用仅在 WinDbg 中可用的命令( .open、.write_cmd_hist(写入命令历史记录)、.lsrcpath 和 .lsrcfix)以及一些附加命令(.hh、.cls、.wtitle、.remote、内核模式 .restart 和用户模式 .restart)的别名。
5. 在脚本文件中使用别名
在脚本文件中使用别名时,必须特别注意确保别名在正确的时间展开。请看以下脚本:
.foreach (value {dd 610000 L4})
{
as /x ${/v:myAlias} value + 1
.echo value myAlias
}
ad myAlias
循环第一次执行时,`as, aS`(设置别名)命令会给 `myAlias` 赋值。赋值为 1 加上 610000(`dd` 命令的第一个输出)。然而,当执行 `.echo`(回显注释)命令时,`myAlias` 尚未展开,因此我们看到的不是 610001,而是文本“myAlias”。
0:001> $$>< c:\Script02.txt
00610000 myAlias
00905a4d 0x610001
00000003 0x905a4e
00000004 0x4
0000ffff 0x5
问题在于,只有进入新的代码块后,`myAlias` 才会被展开。循环的下一个入口点是一个新的代码块,因此 `myAlias` 被展开为 `610001`。但这为时已晚:我们应该在第一次循环时就看到 `610001`,而不是第二次。我们可以通过将 `.echo`(回显注释)命令放在一个新的代码块中来解决这个问题,如下面的脚本所示。
.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 和 ${ }(别名解释器)。
6. 在别名中使用 .foreach 标记(Token)
在别名定义中使用 `.foreach` 标记时,必须特别注意确保该标记被正确展开。请考虑以下命令序列。
r $t0 = 5
ad myAlias
.foreach /pS 2 /ps 2 (Token {?@$t0}) {as myAlias Token}
Al
第一条命令将 $t0 伪寄存器的值设置为 5。第二条命令删除之前可能分配给 myAlias 的所有值。第三条命令获取 ?@$t0 命令的第三个标记,并尝试将该标记的值赋给 myAlias。第四条命令列出所有别名及其值。我们预期 myAlias 的值为 5,但实际值为单词“Token”。
Alias Value
------- -------
myAlias Token
问题在于 `as` 命令位于 `.foreach` 循环体中该行的开头。当一行以 `as` 命令开头时,该行中的别名和标记不会被展开。如果在 `as` 命令前添加分号或空格,则任何已有值的别名或标记都会被展开。在本例中,`myAlias` 没有被展开,因为它还没有值。标记被展开,因为它有值为 5。以下是在 `as` 命令前添加分号后相同的命令序列。
r $t0 = 5
ad myAlias
.foreach /pS 2 /ps 2 (Token {?@$t0}) {;as myAlias Token}
Al
现在我们得到了预期的输出:
Alias Value
------- -------
myAlias 5
7. 递归别名
你可以在任何别名的定义中使用固定名称别名。您也可以在固定名称别名的定义中使用用户命名别名。但是,要在另一个用户命名别名的定义中使用用户命名别名,必须在 `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
8. 使用别名的例子
可以使用别名,这样就不必输入冗长或复杂的符号名称,如下例所示。
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"
8. Tools.ini文件
在 CDB(和 NTSD)中,可以在 tools.ini 文件中预定义固定名称别名。要预定义固定名称别名,请将所需的 $u 字段添加到 [NTSD] 条目中,如下例所示。
[NTSD]
$u1:_ntdll!_RtlRaiseException
$u2:"dd esp 14;g"
$u9:$u1 + 42
无法在 Tools.ini 文件中设置以用户命名的别名。
9. 固定命名别名对比用户命名别名
用户名别名比固定名称别名更容易使用。它们的定义语法更简单,可以使用 `al`(列出别名)命令列出它们。
如果固定名称别名与其他文本相邻,则会被替换。要使用户命名别名在与其他文本相邻时被替换,请将其包含在 `${ }`(别名解释器)标签中。
固定命名别名的替换发生在用户命名别名的替换之前。

701

被折叠的 条评论
为什么被折叠?



