Воспроизвести до момента создания некоторого управляемого объекта в WinDbg TTD

Используя WinDbg с включенным TTD, как воспроизвести момент создания какого-либо управляемого объекта? Допустим, у меня есть его адрес, полученный с помощью!clrstack -a или !dso

1 ответ

Решение

Есть несколько способов сделать это. Если у вас есть адрес объекта и вы хотите вернуться к его созданию, вы можете использовать ba (прерывание при доступе). При создании объекта адрес таблицы методов записывается в первое слово (4 байта для 32-битных, 8 байтов для 64-битных). Таким образом, добавление точки останова для каждого доступа на запись и движение назад остановятся при создании объекта. Другой способ - добавить точки останова, указывающие на все конструкторы объекта, а также в обратном направлении. Также обратите внимание, что все это также может быть выполнено с помощью фильтрации команды '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-битного используйте адрес +4 во втором параметре. Параметр -g будет отображаться в формате сетки.

Подход 2:

Получите адрес (а) конструкторов, перечислив таблицу методов класса:

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")

Надеюсь, это сработает для вас.

Другие вопросы по тегам