Как избежать записи команды DbgCommand в файл журнала

У меня раздражающая проблема с Pykd.pyd: Я использую его в сценарии, запускаю несколько DbgCommand функции, такие как:

DbgCommand("dt 0x000000eab8748430 CMap<int,int,CUIntArray *,CUIntArray *> m_nCount")

Это для получения размера CMap объект. Поскольку это делается в сценарии, используя множество объектов, я использую файлы журналов в Windbg (меню edit, Open/Close Log File) и вот подвох:
Глядя на это в Windbg окно, я вижу только результаты DbgCommand звонки, но в лог-файле я вижу и саму команду:

Windbg окно:

000000eab87488f0    CMap<int,int,CUIntArray *,CUIntArray *>  Size:[0]  // formatted DbgCommand result
000000eab8748930    CMap<int,int,CUIntArray *,CUIntArray *>  Size:[0]  // formatted DbgCommand result

Журнальный файл:

dt 0x000000eab87488f0 CMap<int,int,CUIntArray *,CUIntArray *> m_nCount // DbgCommand command
000000eab87488f0    CMap<int,int,CUIntArray *,CUIntArray *>  Size:[0]  // formatted DbgCommand result
dt 0x000000eab8748930 CMap<int,int,CUIntArray *,CUIntArray *> m_nCount // DbgCommand command
000000eab8748930    CMap<int,int,CUIntArray *,CUIntArray *>  Size:[0]  // formatted DbgCommand result

Как я могу избежать DbgCommand команды записываются в лог-файл?

Между тем я узнал, что параметр suppressoutput существует, что может быть использовано для того, чтобы не показывать результат команды на экране, но это не то, что я имею в виду, как вы можете видеть в следующих выдержках:

выдержка из тестового сценария:

dprintln("1 : x /2 <application_name>!CStringList::CStringList, true")
dbgCommand("x /2 <application_name>!CStringList::CStringList", True)
dprintln("2 : x /2 <application_name>!CStringList::CStringList, false")
dbgCommand("x /2 <application_name>!CStringList::CStringList", False)
dprintln("3")

Результат на экране:

1 : x /2 <application_name>!CStringList::CStringList, true
2 : x /2 <application_name>!CStringList::CStringList, false
004b6d3e          <application_name>!CStringList::CStringList
3

Результат в лог-файле:

1 : x /2 <Application>!CStringList::CStringList, true
x /2 <Application>!CStringList::CStringList
004b6d3e          <Application>!CStringList::CStringList
2 : x /2 <Application>!CStringList::CStringList, false
x /2 <Application>!CStringList::CStringList
004b6d3e          <Application>!CStringList::CStringList
3

Кажется, что suppressoutput предназначен для не показ DbgCommand результат на экране, в то время как меня интересует не показывать DbgCommand ввод в логах.

Позвольте мне объяснить, что не так с typedvar решение:

По какой-то странной причине CMap а также CArray объекты не могут быть использованы простым способом (стандарт windbg команда), как вы можете видеть здесь:

0000000000335e90    <application_name>!CMap<ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t> > >,wchar_t const * __ptr64,int,int>

Как вы видете, dt не работает на этом:

dt 0x0000000000335e90 <application_name>!CMap<ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t> > >,wchar_t const * __ptr64,int,int>
Symbol <application_name>!CMap<ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t> > >,wchar_t const * __ptr64,int,int> not found

Это можно сделать, удалив <application_name> а также __ptr64 (не забудьте про пространство):

0:000> dt 0x0000000000335e90 CMap<ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t> > >,wchar_t const *,int,int>
<application_name>!CMap<ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t> > >,wchar_t const *,int,int>
   +0x000 __VFN_table : 0x00000001`3fc77ac8 
   +0x008 m_pHashTable     : (null) 
   +0x010 m_nHashTableSize : 0x11
   +0x018 m_nCount         : 0n0
   +0x020 m_pFreeList      : (null) 
   +0x028 m_pBlocks        : (null) 
   +0x030 m_nBlockSize     : 0n10

Это похоже на следующее x /2 *!* результат:

00000001`3fc77ac8 <application_name>!CMap<ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t> > >,wchar_t const * __ptr64,int,int>::`vftable'

Однако, если я попытаюсь использовать typedVar похоже не работает

if type_name.find("CMap<") != -1:
    dprintln("original type name : [%s]" % type_name)
    dprintln(("pointer : [0x" + pointer_format + "]") % ptr)
    var =  typedVar(type_name, ptr) # before translation of __ptr64
    nieuwe_grootte1 = var.m_nCount
    type_name = type_name.replace(application_name + "!","") # Normally type_name starts with "<application_name>!CMap<...", it must become "CMap<..."
    type_name = type_name.replace(" __ptr64","")             # apparently, when the CMap definition contains __ptr64, it doesn't work
                                                             # dt 0x000000eab8748430 CMap<int,int,CUIntArray *,CUIntArray *> m_nCount seems to work

    dprintln("after replacements type name : [%s]" % type_name)
    var =  typedVar(type_name, ptr) # after translation of __ptr64
    nieuwe_grootte2 = var.m_nCount

    grootte_result = dbgCommand(("dt 0x" + pointer_format + " %s m_nCount") % (ptr,type_name)).split(' : ')
    grootte = grootte_result[-1].split('\n')[0] # list[-1] is Python for "take the last entry of a list"
    grootte = grootte.replace("0n","")
    dprintln((pointer_format + "\t%s\t Size:[%s, %d, %d]") % (ptr, type_name, grootte, nieuwe_grootte1, nieuwe_grootte2))

Это дает следующие результаты:

original type name : [<application_name>!CMap<unsigned int,unsigned int,enum CService::PARAMETER_TYPE,enum CService::PARAMETER_TYPE>]
pointer : [0x00000000003355e0]
after replacements type name : [CMap<unsigned int,unsigned int,enum CService::PARAMETER_TYPE,enum CService::PARAMETER_TYPE>]
00000000003355e0    CMap<unsigned int,unsigned int,enum CService::PARAMETER_TYPE,enum CService::PARAMETER_TYPE>  Size:[105, 105, 105]
original type name : [<application_name>!CMap<ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t> > >,wchar_t const * __ptr64,int,int>]
pointer : [0x0000000000335640]

Traceback (most recent call last):

  File "C:\Program Files (x86)\Windows Kits\10\Debuggers\x86\heap_stat_extra.py", line 215, in <module>
    var =  typedVar(type_name, ptr) # before translation of __ptr64

TypeException: <application_name>!CMap<ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t> > >,wchar_t const * __ptr64,int,int> : invalid type name

Я уже пытался удалить <application_name> и / или __ptr64 но, похоже, не решить проблему. Более того, результат dt и "x / 2 !" (это неправильно форматирует) ясно указывает, что упомянутый тип присутствует. Кажется, что typedVar есть реальные проблемы, связанные с __ptr64 тег. Есть ли обходной путь для этого?

редактировать
Я только что попробовал, используя команды Python из pykd_team, но все же, похоже, не работает (на этот раз на CArray объекты), как вы можете видеть:

Запуск моего скрипта дает следующий результат:

  File "C:\Temp_Folder\blabla\heap_stat_logs_backup.py", line 232, in <module>
    collection_Size = typedVar(type_name, ptr).m_nCount

TypeException: CArray<CSyncRules::VersionRestriction *,CSyncRules::VersionRestriction * const &> : invalid type name

Попытка выяснить, каково правильное имя класса:

0:000> !py
Python 2.7.10 (default, May 23 2015, 09:40:32) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> app = pykd.module("<Application>")
>>> for tp in app.enumTypes("*CArray*"):
...   print tp
... 
CArray<CSyncRules::VersionRestriction *,CSyncRules::VersionRestriction * const &>
...

Как видите, имя класса является точным соответствием, но все же есть TypeException, Ты хоть представляешь, что делать сейчас? (Кстати, я работаю с Visual Studio Professional 2017)

Новое редактирование

Скорее всего, проблема вызвана PYKD, не способным обрабатывать знаки звездочки (*) в определениях типов. Есть ли какой-нибудь escape-символ, который я могу использовать, чтобы избежать упомянутых проблем?

3 ответа

Используйте класс pykd.typedVar. Он специально разработан для таких случаев

Попробуйте изменить:

dt 0x000000eab87488f0 CMap<int,int,CUIntArray *,CUIntArray *> m_nCount

чтобы:

var =  typedVar("CMap<int,int,CUIntArray *,CUIntArray *>", 0x000000eab87488f0 )
print var
print var.m_nCount
print var.m_nCount * 2

Вы можете получить доступ к любому полю класса CMap и работать с ним, поскольку они являются естественными типами Python.

Если вы собираетесь получать typedVar несколько раз, вы можете кэшировать информацию о типах, чтобы избежать проблем с производительностью:

CMap = typeInfo("CMap<int,int,CUIntArray *,CUIntArray *>")
var = typedVar( CMap, 0x000000eab87488f0 )

Попробуйте перечислить типы для вашего модуля (с маской подстановочного знака) и найти точное имя символа для CMap.

app = pykd.module("<application_name>")
for tp in app.enumTypes("CMap*"):
   print tp

Я могу попытаться воспроизвести проблему на небольшом примере, но мне нужно знать вашу версию Visual Studio.

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