代码之家  ›  专栏  ›  技术社区  ›  Dominique

如何避免将DbgCommand命令写入日志文件

  •  3
  • Dominique  · 技术社区  · 7 年前

    我有一个恼人的问题 Pykd.pyd :我在脚本中使用它,启动了几个 DbgCommand 功能,如:

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

    这是为了得到 CMap 对象由于这是在一个脚本中完成的,使用了很多很多对象,我在中使用了日志文件 Windbg (菜单 edit , Open/Close Log File ),这里有一个问题:
    当看到这个 托管代码中设置断点 窗口,我只看到 DBG命令 调用,但在日志文件中我也看到了命令本身:

    托管代码中设置断点 窗口:

    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
    

    我怎样才能避免 DBG命令 正在将命令写入日志文件?

    同时我发现一个参数 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
    

    看来 抑制输出 是为了不显示 DBG命令 结果显示在屏幕上,而我对不显示感兴趣 DBG命令 在日志中输入。

    让我解释一下 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
    

    我已尝试删除 <应用程序名称> 和/或 __ptr64 但这似乎并不能解决问题。此外 dt 和“x/2” ! “(格式不正确)清楚地表明存在提到的类型。似乎 类型DVAR 在处理 __ptr64 标签有解决办法吗?

    编辑
    我刚刚尝试过使用pykd_团队的Python命令,但它似乎仍然不起作用(这次是在 动态数组 对象),如您所见:

    启动我的脚本会得到以下结果:

      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无法处理星号引起的( * )在类型定义中。为了避免上述问题,我可以使用任何转义字符吗?

    3 回复  |  直到 6 年前
        1
  •  1
  •   ussrhero    7 年前

    使用pykd。typedVar类。它是专门为这种情况设计的

        2
  •  0
  •   pykd_team    7 年前

    尝试更改:

    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 )
    
        3
  •  0
  •   pykd_team    7 年前

    尝试枚举模块的类型(使用通配符掩码),并找到CMap的确切符号名。

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

    我可以尝试在一个小示例中重现一个问题,但我需要知道您的Visual Studio版本。