使用启用 TTD 的 WinDbg,如何回放创建某个托管对象的时刻?可以说我确实使用!clrstack -a
或获得了它的地址!dso
问问题
74 次
1 回答
2
有几种方法可以做到这一点。如果您有对象的地址并想返回到它的创建,您可以使用 ba(访问中断)。创建对象时,方法表地址被写入第一个字(32 位为 4 个字节,64 位为 8 个字节)。因此,为每个写访问添加断点并返回将在对象创建时停止。另一种方法是添加指向对象的所有构造函数的断点,并且还向后。另请注意,所有这些也可以通过“dx”命令通过断点地址或构造函数调用过滤来完成。
想象一下你有这个输出:
0:016> !dso
OS Thread Id: 0x2f54 (16)
RSP/REG Object Name
000000A2CD5FC770 000001e9849cd4b8 ConceptNetConsole1.SampleClass1
(...)
0:016> !DumpObj /d 000001e9849cd4b8
Name: ConceptNetConsole1.SampleClass1
MethodTable: 00007ffb85545ef8 <<< This is the method table
EEClass: 00007ffb85542d68
Size: 136(0x88) bytes
File: C:\Projects\ConceptNetConsole1\ConceptNetConsole1\bin\x64\Release\ConceptNetConsole1.exe
Fields:
MT Field Offset Type VT Attr Value Name
00007ffbe38e70b0 40005a8 8 System.Object 0 instance 000001e9849cd718 __identity
(...)
方法 1:并且您想在创建此对象时停止您可以使用(对于 32 位使用 w4):
ba w8 000001e9849cd4b8
g-
使用“dx”(注意地址必须是 C++ 格式,以“0x”开头):
dx -g @$cursession.TTD.Memory(0x00001e9849cd4b8,0x00001e9849cd4b8+8,"w")
同样,对于 32 位,在第二个参数上使用 address+4。选项 -g 将以网格格式显示。
方法二:
通过列出类的方法表来获取构造函数的地址:
0:016> !dumpmt -md 00007ffb85545ef8
EEClass: 00007ffb85542d68
Module: 00007ffb85545408
Name: ConceptNetConsole1.SampleClass1
mdToken: 0000000002000005
File: C:\Projects\ConceptNetConsole1\ConceptNetConsole1\bin\x64\Release\ConceptNetConsole1.exe
BaseSize: 0x88
ComponentSize: 0x0
Slots in VTable: 23
Number of IFaces in IFaceMap: 0
--------------------------------------
MethodDesc Table
Entry MethodDesc JIT Name
00007ffbe36fb1f0 00007ffbe3257538 PreJIT System.Object.ToString()
00007ffbe36ffd90 00007ffbe3257540 PreJIT System.Object.Equals(System.Object)
00007ffbe3721dc0 00007ffbe3257568 PreJIT System.Object.GetHashCode()
00007ffbe36fce50 00007ffbe3257580 PreJIT System.Object.Finalize()
00007ffbe37d8f40 00007ffbe333cfd0 PreJIT System.MarshalByRefObject.GetLifetimeService()
00007ffbe36f8b10 00007ffbe333cfd8 PreJIT System.MarshalByRefObject.InitializeLifetimeService()
00007ffbe37cbd80 00007ffbe333cfe0 PreJIT System.MarshalByRefObject.CreateObjRef(System.Type)
00007ffb85560090 00007ffb85545d58 JIT ConceptNetConsole1.SampleClass1..ctor() <<< This is the constructor
(...)
您可以简单地在 'Entry' 地址设置断点(或使用 !sos.bpmd)并返回:
bp 00007ffb85560090
g-
或者使用 'dx' 显示调用代码的所有场合(请注意,代码再次调整为看起来像 C++ '0x' 并且也在引号中):
dx -g @$cursession.TTD.Calls("0x00007ffb85560090")
希望对你有效。
于 2019-09-05T20:07:20.323 回答