回放在 WinDbg TTD 中创建某个托管对象的时刻
Play back to the moment of creation of some managed object in WinDbg TTD
使用启用了 TTD 的 WinDbg,如何回放到创建某个托管对象的时刻?
可以说我确实使用 !clrstack -a
或 !dso
获得了它的地址
有几种方法可以做到这一点。如果你有对象的地址并想回到它的创建,你可以使用 ba (访问中断)。创建对象时,方法 Table 地址被写入第一个字(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
(...)
方法一:
你想在创建这个对象时停止,你可以使用(对于 32 位使用 w4):
ba w8 000001e9849cd4b8
g-
使用'dx'(注意地址必须是C++格式,以'0x'开头):
dx -g @$cursession.TTD.Memory(0x00001e9849cd4b8,0x00001e9849cd4b8+8,"w")
同样,对于 32 位,在第二个参数上使用地址+4。选项 -g 将以网格格式显示。
方法二:
通过列出 class 的方法 table 获取构造函数的地址:
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")
希望对你有用。
使用启用了 TTD 的 WinDbg,如何回放到创建某个托管对象的时刻?
可以说我确实使用 !clrstack -a
或 !dso
有几种方法可以做到这一点。如果你有对象的地址并想回到它的创建,你可以使用 ba (访问中断)。创建对象时,方法 Table 地址被写入第一个字(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
(...)
方法一: 你想在创建这个对象时停止,你可以使用(对于 32 位使用 w4):
ba w8 000001e9849cd4b8
g-
使用'dx'(注意地址必须是C++格式,以'0x'开头):
dx -g @$cursession.TTD.Memory(0x00001e9849cd4b8,0x00001e9849cd4b8+8,"w")
同样,对于 32 位,在第二个参数上使用地址+4。选项 -g 将以网格格式显示。
方法二:
通过列出 class 的方法 table 获取构造函数的地址:
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")
希望对你有用。