美好的一天,
我有一个Windbg脚本,该脚本使用.do
循环在堆栈的框架周围进行迭代。对于每帧,它都使用!for_each_local
和$spat ("@#Local","foo")
来匹配我感兴趣的初始外观。然后,我使用dx @$t2 =
进行分配,并最终打印出我感兴趣的内容,即dx @$t2 = ((foobase*) this)->m_current->m_name
-大多数情况下可以正常工作。
每一次,框架中都会有this
,无法成功地使用dx
进行投射,因此就好像需要barbase
,而不是{ {1}} ... foobase
似乎还可以,因为我已经将其包装在dx
中,因此它最终包含导致脚本退出的 something (尽管尝试.foreach (output { dx @$t2 = ((foobase*) this)->m_current->m_name }) {}
)。
起初我并没有真正意识到发生了什么,但是执行.catch
可以帮助我确定内容为.printf "%ma\n", @$t2
,我认为暗示了无效的类型转换-如果是这样的话,这是很有意义的。我的脚本行在需要<HRESULT 0x80004002>
时使用foobase
。
如果是正确的,我正在寻找一种检查方法,然后再进一步研究脚本并尝试访问我知道的详细信息,这将导致脚本退出。
我似乎想出了一种复杂的方法...但是我想问问是否还有更好的方法...
barbase
是否可以在不使用别名的情况下检查.frame 0a $$ a frame with barbase, not foobase
dx @$t2 = ((foobase*) this)->m_name
.printf "%ma\n", @$t2 $$ prints <HRESULT 0x80004002>
as /c CastCheck .printf "%ma", @$t2
.if ($spat(@"${CastCheck}","<HRESULT 0x80004002>") = 1) { .printf "yes" } .else { .printf "no" } $$ prints yes
是否包含无效转换的指示符?
我之所以这样问,是因为使用别名引起了我很多困惑……在我的脚本中(要使其正常工作,而且看起来确实工作得很好),我不得不使用$t2
而不是{ {1}}(我可以在“命令窗口”中使用aS
很好,而且我不太理解为什么为什么阅读文档后需要更改为as
),并且我还需要以分号结束行(与脚本中的其他行不同),并且我需要在as
之前紧接着使用aS
,然后再快速使用,否则别名似乎迷路,以某种方式...所以您可以说使用此别名给我带来了一些麻烦。
因此,是否有 a)一种简单的方法来预先检查我正在查看的内容是ad /q CastCheck;
还是aS
,还是 b) 在投射尝试后是否检查foobase
是否包含此barbase
?如果我执行$t2
,它会显示<HRESULT 0x80004002>
... .printf "%d", @$t2
也代表什么吗?
或者其他任何想法(或问题)。
编辑:
我要尝试 并用命令窗口中的2个短代码来说明我的意思...其中第00帧包含一个5
,可以强制转换为5
,然后。this
可以很好地工作,并且第0a帧包含foobase
的{{1}}(但是我的脚本仍然没有期望它,并且我希望能够满足它的需求)... printf
仍将{em>东西放在this
中...我希望能够检测到它垃圾(或者预先检测,如果barbase
是dx
,我什至不应该尝试$t10
,因为它毫无意义,而且我对此也不感兴趣)。
dx
这是this
是barbase
,甚至没有0:038> .frame 00
00 00000006`3e2bc930 00007ffe`926293a8 BlahBlahBlah
0:038> dx @$t10 = ((foobase *) this)->m_name
@$t10 = ((foobase *) this)->m_name : 0x869c7b8 : "nice string" [Type: char *]
0:038> .printf "%ma\n", @$t10
nice string
的地方:
this
当放入循环中时,我发现当我尝试检查返回的字符串的长度时,脚本将在第0a帧上以barbase
退出由m_name
。
基本上,在第二个代码段中,我想要一种方法来检查0:038> .frame 0a
0a 00000006`3e2bd220 00007ffe`91ec7780 BlahBlahBlah
0:038> dx @$t10 = ((foobase *) this)->m_name
@$t10 = ((foobase *) this)->m_name : 0x2265646f00000005 : "--- memory read error at address 0x2265646f`00000005 ---" [Type: char *]
0:038> .printf "%ma\n", @$t10
<HRESULT 0x80004002>
是否为不是一个不错的字符串(可能是Memory access error
?),或者甚至更好,根本不做dx
和$t10
,因为我可以检查<HRESULT 0x80004002>
是dx
,而不是.printf
。
这是否更有意义,还是我应该重新开始?
答案 0 :(得分:1)
您尝试过,但是仍然含糊不清
您能解释一下.frame的必要性吗?
然后DX这个??
您可以将任何地址投射为任何类型
例如,在第一次运行中,我将其强制转换为正确的类型并枚举所有框架
在下一轮中,我将转换为伪类型并枚举
在这两个帧中只有一个具有this指针
当类型正确时,它会返回正确的成员
假的时候,它会返回假的东西
0:000> !for_each_frame dx ((Student *) this)->Name
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
00 000000c5`d6f6f8c0 00007ff7`2818117c thisptr!Student::PrintStudent+0x9 [f:\src\thisptr\thisptr.cpp @ 20]
((Student *) this)->Name : 0x7ff7282153e0 : "dave" [Type: char *]
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
01 000000c5`d6f6f8f0 00007ff7`281b6c20 thisptr!main+0x2c [f:\src\thisptr\thisptr.cpp @ 33]
Error: Unable to bind name 'this'
它找到了这个,但是找不到会员名称
0:000> !for_each_frame dx ((ntdll!_EPROCESS *) this)->Name
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
00 000000c5`d6f6f8c0 00007ff7`2818117c thisptr!Student::PrintStudent+0x9 [f:\src\thisptr\thisptr.cpp @ 20]
Error: Unable to bind name 'Name' <<<<<<
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
01 000000c5`d6f6f8f0 00007ff7`281b6c20 thisptr!main+0x2c [f:\src\thisptr\thisptr.cpp @ 33]
Error: Unable to bind name 'this'
您知道此指针的类型是什么,为什么要强制转换它?
您可以通过各种命令找到该ptr的类型,其中一些命令如下所示
0:000> dx this
this : 0xc5d6f6f910 [Type: Student *] <<<
[+0x000] Roll : 1 [Type: int]
[+0x008] Name : 0x7ff7282153e0 : "dave" [Type: char *]
[+0x010] Marks : 72.300000 [Type: double]
0:000> ?? this
class Student * 0x000000c5`d6f6f910 <<<
+0x000 Roll : 0n1
+0x008 Name : 0x00007ff7`282153e0 "dave"
+0x010 Marks : 72.299999999999997158
0:000> x /t this
000000c5`d6f6f8f0 class Student * this = 0x000000c5`d6f6f910 <<<
0:000> x /v /t this
prv local 000000c5`d6f6f8f0 8 class Student * this = 0x000000c5`d6f6f910
0:000> dt this
Local var @ 0xc5d6f6f8f0 Type Student*
0x000000c5`d6f6f910
+0x000 Roll : 0n1
+0x008 Name : 0x00007ff7`282153e0 "dave"
+0x010 Marks : 72.299999999999997158
0:000> dt /v this
Local var [AddrFlags 90 AddrOff 0000000000000030 Reg/Val rsp (7)] @ 0xc5d6f6f8f0 Type Student*
0x000000c5`d6f6f910 class Student, 5 elements, 0x18 bytes
+0x000 Roll : 0n1
+0x008 Name : 0x00007ff7`282153e0 "dave"
+0x010 Marks : 72.299999999999997158
<function> Student void (
int,
char*,
double)+000000c5`d6f6f910
<function> PrintStudent void ( void )+000000c5`d6f6f910
0:000> dt /v /t this
Local var [AddrFlags 90 AddrOff 0000000000000030 Reg/Val rsp (7)] @ 0xc5d6f6f8f0 Type Student*
0x000000c5`d6f6f910 class Student, 5 elements, 0x18 bytes
+0x000 Roll : 0n1
+0x008 Name : 0x00007ff7`282153e0 "dave"
+0x010 Marks : 72.299999999999997158
<function> Student void (
int,
char*,
double)+000000c5`d6f6f910
<function> PrintStudent void ( void )+000000c5`d6f6f910
答案 1 :(得分:0)
添加另一个答案以强调javascript的用法,而不是解析文本
javascript脚本支持已添加到windbg安静很久了 并得到了很大的改善
(要尝试使用最新的javascript功能,请在最新的Windows 10版本中使用windbg预览)
x / v / t或dv / t提供此指针的类型
javascript为这些对象提供了targetType属性
这是使用方法
使用以下内容创建一个.js文件foo.js
function typethis ( somevar )
{
host.diagnostics.debugLog( somevar.targetType , "\t" , JSON.stringify(somevar) , "\n" )
}
在windbg做
.load jsprovider
.scriptload x:\..\\..\foo.js
dx @$scriptcontents.functionname(argument) to run the script
结果将是
0:000> .load jsprovider
0:000> .scriptload f:\wdscr\typthis.js
JavaScript script successfully loaded from 'f:\wdscr\typthis.js'
0:000> dx @$scriptContents.typethis( this )
Student * {"Roll":1,"Name":{},"Marks":72.3}
@$scriptContents.typethis( this )