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")
昨天我问了一个关于 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
它将做什么:它用分号连接文件中的所有行。任何你必须忍受的后果。请参阅“进一步阅读”,了解这是如何导致问题的。
进一步阅读
看来你
- 您不能简单地使用
;
作为分隔符来连接命令 - 你不能简单地写空语句
- 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")