Windbg 别名替换损坏了吗?简化示例

Windbg alias replacement broken? Simplified example

昨天我问了一个关于 windbg 别名 () 行为的问题,得到了一些有用的答案。

现在我有一个简化的示例,它显示了我所看到的行为,没有任何循环。别名替换似乎被简单地破坏了,关于 .block {} 的文档基本上是错误的。

foo.windbg 脚本中,我有以下内容:

;aS ${/v:foo} 1
al
.block 
{
  .echo foo
}

我运行脚本用

$$><foo.windbg

如果别名 foo 在 运行 脚本之前没有定义(或者如果它已经被定义为 1 ),这按预期工作。但是,如果我已经将 foo 定义为不同的值,例如0

;aS ${/v:foo} 0

然后当我 运行 脚本 foo 被设置为 1(我可以从 al 命令中看到脚本),但脚本中的命令 .echo foo 会生成 0。甚至 foo 的引用也在 .block{}.

如果块语句中的右花括号紧跟在对 foo

的引用之后,则有效
;aS ${/v:foo} 1
al
.block 
{
  .echo foo}

这没有帮助,因为这意味着您不能使用别名,除非它恰好位于 .block{} 或其他复合语句的末尾。我虽然用 ${foo} 引用别名会有帮助,但没有用。

从我上一个问题的答案中,我看到在设置别名之前删除 (ad) 别名似乎在某些情况下可以解决问题。刚刚使用

ad foo
如果未定义 foo

将导致脚本出错,因此我无法使用它。使用

ad *

有效,但会删除所有别名,包括我已经创建并想使用的别名。我试过了

.if (${/d:foo}) {ad ${/v:foo}}

但这给出了相同的行为,其中 foo 在脚本中进一步使用时被替换为旧值。所以我想解决方法是用

启动脚本
aS ${/v:foo} dummy
ad ${/v:foo}

这似乎有效。

所以基本问题是别名替换失败(在某些情况下),除非别名后跟某些语句的右大括号,如 .block。 windbg 文档中的所有示例恰好都是这样做的,and/or 首先删除所有别名并以此方式解决问题。

我知道我在打死马,但这种行为有解释吗?我糊涂了吗?它似乎完全损坏了,而且对于我想使用别名的方式来说,没用。

谢谢, 戴夫

看来你有很多问题。是关于删除别名,使用别名,运行脚本,理解WinDbg ...

正在删除别名

其中之一是“如何在事先不知道别名是否定义的情况下删除它?”答案是 .block{ad /q ${/v:foo}}.

如何在脚本中使用别名

接下来我要建议的是:不要使用没有别名语法的别名。这与其说是为了 WinDbg 本身,不如说是为了脚本的读者和可维护性。

当我看到一行时

.echo foo

然后我希望它打印“foo”而不是其他任何东西。当我看到一行

.echo ${foo}

然后我知道有一个变量或别名涉及。

别名的概念错误:无法转义它们

实际上我认为这是一个概念性错误,因为在 WinDbg 中没有可靠的方法来回显文字“foo”,但在大多数回显场景中我只想让它这样做而不是其他

0:000> as foo oops
0:000> .echo foo
oops
0:000> .echo "foo"
oops
0:000> .echo ${foo}
oops
0:000> .echo "${foo}"
oops
0:000> .echo ${/v:foo}
${/v:foo}
0:000> .echo "${/v:foo}"
${/v:foo}
0:000> .printf "foo"
oops
0:000> .printf "${foo}"
oops
0:000> .printf "${/v:foo}"
${/v:foo}

然后您会像您一样发现错误:

0:000> .printf "foo\n"
foo

您使用别名

感谢您提供小型 MRE 来重现您的问题。据我所知,您似乎在尝试使用变量之类的别名。

让我们想想别名是什么:如果您有一个经常需要的命令但它太长或太复杂而无法键入,那么您可以在 Linux 上使用别名。我为 ls -l 定义了 ll 的别名,为 cd .. 定义了 cd.. ,因为我有点习惯了 Windows 语法。

问题是:WinDbg 别名不是您从 Linux 了解到的别名。它更像是一个进行愚蠢搜索和替换的预处理器定义。

在您目前介绍的案例中,它与使用缩写来缩短输入或避免输入错误无关。您似乎为其分配了一个值。在那种情况下,您应该考虑使用伪寄存器,例如 $t1.

运行 个脚本

您是 运行 具有 $$>< 的脚本并且该方法具有 属性 的

Condenses to single command block: Yes

它将做什么:它用分号连接文件中的所有行。任何你必须忍受的后果。请参阅“进一步阅读”,了解这是如何导致问题的。

进一步阅读

看来你。那 post 会让你抓耳挠腮。您将在那里学到什么:

  • 您不能简单地使用 ; 作为分隔符来连接命令
  • 你不能简单地写空语句
  • WinDbg 对空格敏感(有时)
  • 一行并不总是一行
  • 字符串转义被破坏
  • 评论并不总是评论

但是为什么呢?

警告:前面纯属猜测。我从未在 Microsoft 工作过。

这是为什么? WinDbg 的存在时间令人难以置信。我电脑上最旧的版本是 1999 年的 4.0.18 版,可能是为 Windows NT 4 SP 6 开发的。我可以想象 Windows NT 3 的 WinDbg 3 版本也存在,所以它potential 可以追溯到 1993 年。

当时没有IDE“查找参考”或“查找用法”等功能,因此很难进行影响分析,我相信开发人员通常不清楚哪一方像 as 这样的新命令可能会产生影响。

结合 WinDbg 仅是 Microsoft 内部工具的印象以及“开发人员将知道他们在做什么”,这为我们提供了一个有用但总体上存在缺陷的工具。

WinDbg 的开发可能并未考虑到清晰的路线图。它可能没有你称之为“架构”的东西。一些开发人员正在调试一些复杂的东西,并认为向其他人提供一种脚本以简化调试会很棒。因此,WinDbg 可能更像是我们今天称为命令的有用代码片段的集合,但它们没有通用的词法分析器或解析器,例如。

我在查询中没有看到可靠的用例,所以我不会参与别名辩论;

此外,该查询有点 xy 问题,因为您认为使用别名是解决人为问题的出路,而不是谈论您要解决的实际问题。

但是如果你想要一些现代的 UserVariables 尝试检查 Javascript 你可能可以将你想要的东西拉到一个标准的 es6 兼容框架

0:000> dx Debugger.State.UserVariables
Debugger.State.UserVariables                
0:000> dx @$foo = "sugar"
@$foo = "sugar"  : sugar
    Length           : 0x5
    
0:000> dx @$blah = "honey"
@$blah = "honey" : honey
    Length           : 0x5

0:000> dx -r0 "i want "+ @$foo+ " mixed With "+@$blah
"i want "+ @$foo+" mixed With "+@$blah : i want sugar mixed With honey

只是为了完成这里的循环是 javascript 将用户提供的参数与已经存在的 UserVariable 进行比较并进行一些调试打印

"use strict";
function foo(argu) 
{
    for (var i in host.namespace.Debugger.State.UserVariables)
    {
            if(i===argu)
            {
                host.diagnostics.debugLog("hi " + i +" with me ");
                var tmp = "host.namespace.Debugger.State.UserVariables." + i
                var boo = eval(tmp)
                host.diagnostics.debugLog(boo +"\n")                
            }
    }    
}

使用

创建几个用户变量
dx @$foo = "sugar"
dx @$bar = "honey"
dx @$blah = "milk"
0:000> dx Debugger.State.UserVariables
Debugger.State.UserVariables                
    foo              : sugar
    bar              : honey
    blah             : milk

加载脚本并使用它

0:000> .scriptload d:\test.js
JavaScript script successfully loaded from 'd:\test.js'
0:000> dx @$scriptContents.foo("bar")
hi bar with me honey
@$scriptContents.foo("bar")
0:000> dx @$scriptContents.foo("foo")
hi foo with me sugar
@$scriptContents.foo("foo")
0:000> dx @$scriptContents.foo("blah")
hi blah with me milk
@$scriptContents.foo("blah")