最近我问a question并使用.foreach收到了很好的答案。 现在我有一个包含很多非常大的char []的转储。我做了
.logopen c:\mychararrays.log
!dumpheap -type System.Char[]
.logclose
我已经删除了所有人类可读的内容,例如摘要等。 现在该文件有很多行,包括对象地址,方法表和大小:
03d74c88 52b8b680 5570670
042c4cf8 52b8b680 5762890
...
21a1d6e0 52b8b680 6010030
我已经使用过了
.foreach /ps 2 /f (chararray "c:\mychararrays.log") { !do ${chararray} }
转储.NET对象,但这不会转储char []的完整文本,只会转储前128个字符。 不幸的是,这些char []的开头总是一样的。
我想做点什么
.foreach /f (chararray "c:\mychararrays.log") { du <token 1 of line>+8 L? 0n<token 3 of line> }
为每行打印完整的char []。默认情况下,WinDbg会将一行中的标记分开并逐个处理,因此该命令只有一个标记可供使用。
我已经通过在Notepad ++中进行正则表达式替换来解决这个问题。 我只是想知道是否有一个“原生”WinDbg解决方案。
Find: ([^ ]*) [^ ]* ([^ ]*).*
Replace: du \1+8 L? 0n\2
然后将结果作为脚本运行:
$<c:\mychararrays.log
注意:这花了很长时间,所以我决定切换到
Find: ([^ ]*) [^ ]* ([^ ]*).*
Replace: .writemem c:\s\1.txt \1+8 L? 0n\2
答案 0 :(得分:1)
如果您知道最大大小,则可以将该大小指定为du
,并且它将在第一个空终止符处停止打印。例如,如果我知道最大值为10,000,000,那么即使长度为320个字符,下面的内容也会正确打印:
0:000> du 00000000033495d8 +10 L?0n10000000
00000000`033495e8 "PermissionSetty.PermissionSeting"
00000000`03349628 "Permission, System.Drawing, Vers"
00000000`03349668 "ion=2.0.0.0, Culture=neutral, Pu"
00000000`033496a8 "blicKeyToken=b03f5f7f11d50a3a619"
00000000`033496e8 "34e0899AD9D5DCC1DD9AD23613210290"
00000000`03349728 "0B723CF980957FC4E177108FC607774F"
00000000`03349768 "29E8320E92EA05ECE4E821C0A5EFE8F1"
00000000`033497a8 "645C4C0C93C1AB99285D622CAA652C1D"
00000000`033497e8 "FAD63D745D6F2DE5F17E5EAF0FC4963D"
00000000`03349828 "261C8A12436518206DC093344D5AD293"
00000000`03349868 ""
这是空终结符00000000`03349868:
0:000> db 00000000`03349868 l2
00000000`03349868 00 00
所以尽管我给了du
1000万的范围,但它知道要停在第一个空终止符。
BTW这是64位进程的转储,这可能是我对char缓冲区的偏移量与你的不同的原因。
如果您绝对需要实际大小,那么我们可以将其作为对象地址的偏移量来抓取,这样您就不需要尝试将该值作为另一个标记来获取。但希望最大值适合你。
答案 1 :(得分:0)
尝试使用windbg pykd.codeplex.com的python扩展。使用python,您可以获得RE,灵活的脚本语言并快速解决您的问题
答案 2 :(得分:0)
尽管它不依赖于任何扩展名,等等,但这可能并不是您正在寻找的“本地”解决方案(5年前,我知道-我将发布为参考),但我相信您可以通过一些簿记和仔细的别名/伪注册管理来实现。
一般的想法是foreach
循环的主块接收每个令牌,并记住并在所有用于主要处理的令牌被存储时使用它们。 >。以下脚本中的内容列出了当前目标中以“ ora *”开头的已加载模块,并列出了它们的起始地址和 size (单行/模块中不可用) lm
输出):
ad /q startAddress;
ad /q endAddress;
r $t0=0;
.foreach /pS 8 (token {lmn m ora*}) {
r $t0=@$t0 + 1;
.if (@$t0 % 4 == 1) { as ${/v:startAddress} ${token}};
.if (@$t0 % 4 == 2) { as ${/v:endAddress} ${token}};
.if (@$t0 % 4 == 0) {.printf "${token}=%x,%x\n", ${startAddress}, ${endAddress} - ${startAddress}};
}
您可能已经猜到了,主要要求是每行中肯定有N个令牌(在我的示例中为4个)(或者如果可以将某个令牌标识为“标记”,也可以用来重置我用模运算完成的计数器)。也就是说,如果行的令牌数量不同(由于文件名中的空格等),这将无法解决。
单行复制粘贴:
ad /q startAddress; ad /q endAddress; r $t0=0; .foreach /pS 8 (token {lmn m ora*}) {r $t0=@$t0 + 1; .if (@$t0 % 4 == 1) { as ${/v:startAddress} ${token}}; .if (@$t0 % 4 == 2) { as ${/v:endAddress} ${token}}; .if (@$t0 % 4 == 0) {.printf "${token}=%x,%x\n", ${startAddress}, ${endAddress} - ${startAddress}}; }
还要注意,如果要处理的令牌是数字的,则使用伪寄存器而不是别名会使事情变得容易一些,因为您可以避免WinDbg的别名特质!即使我的令牌确实是数字的,我还是在这里使用别名来提供更通用的示例/模板。