如何避免将 DbgCommand 命令写入日志文件 [英] How to avoid the DbgCommand command being written to the logfile

查看:28
本文介绍了如何避免将 DbgCommand 命令写入日志文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在使用 Pykd.pyd 时遇到了一个烦人的问题:我在脚本中使用它,启动几个 DbgCommand 函数,例如:

I'm having an annoying issue with Pykd.pyd: I'm using it in a script, launching several DbgCommand functions, like:

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

这用于获取CMap 对象的大小.由于这是在脚本中完成的,使用了大量对象,我在 Windbg 中使用日志文件(菜单 editOpen/Close Log File>),这是一个问题:
Windbg 窗口中查看时,我只看到 DbgCommand 调用的结果,但在日志文件中我也看到了命令本身:

This for getting the size of the CMap object. As this is done in a script, using lots and lots of objects, I am using logfiles in Windbg (menu edit, Open/Close Log File), and here's the catch:
When looking at this in Windbg window, I only see the results of the DbgCommand calls, but in the logfile I see the command itself too:

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 命令写入日志文件?

How can I avoid DbgCommand commands being written to the logfile?

同时我发现存在一个参数suppressoutput,它可以用于不在屏幕上显示命令的结果,但这不是我的意思,正如你在以下摘录:

Meanwhile I've found out that a parameter suppressoutput exists, which can be used for not showing the result of the command on screen, but this is not what I mean, as you can see in following excerpts:

测试脚本摘录:

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 输入日志.

It seems that suppressoutput is meant for not showing DbgCommand result on screen, while I'm interested in not showing DbgCommand input in the logs.

让我解释一下 typedvar 解决方案有什么问题:

Let me explain what's wrong with the typedvar solution:

由于一些奇怪的原因,CMapCArray 对象不能以简单的方式使用(标准的 windbg 命令),因为你可以在这里看到:

For some strange reason, CMap and CArray objects can't be used in a simple way (standard windbg command), as you can see here:

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

如您所见,dt 对此不起作用:

As you can see, dt does not work on this:

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

这可以通过删除 __ptr64(不要忘记空格)来处理:

This can be handled by removing the <application_name> and __ptr64 (don't forget the space):

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 *!* 结果一致:

This seems to correspond with following x /2 *!* result:

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 它似乎不起作用:

However if I try to use typedVar it seems not to work:

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 !" 的结果(格式不正确)清楚地表明存在上述类型.typedVar 似乎在处理 __ptr64 标签时存在实际问题.有解决方法吗?

I have already tried removing <application_name> and/or __ptr64 but it seems not to solve the issue. Moreover, the result of dt and "x /2 !" (this does not format correctly) clearly indicate that the mentioned type is present. It seems that typedVar has real problems dealing with the __ptr64 tag. Is there a workaround for this?

编辑
我刚刚尝试过,使用来自 pykd_team 的 Python 命令,但它似乎仍然不起作用(这次是在 CArray 对象上),如您所见:

Edit
I've just tried, using the Python commands from pykd_team, but still it seems not to be working (this time on CArray objects), as you can see:

启动我的脚本给出以下结果:

Launching my script gives following result:

  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

试图调查什么是正确的类名:

Trying to investigate what's the correct classname:

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)

As you can see, the classname is an exact match, but yet there's a TypeException. Do you have any idea what to do now? (By the way, I'm working with Visual Studio Professional 2017)

新编辑

问题很可能是由 PYKD 引起的,无法处理类型定义中的星号 (*).我可以使用任何转义字符来避免上述问题吗?

Most probably the issue is caused by PYKD, not being able to handle the asterisk signs (*) in the type definitions. Is there any escape character I can use in order to avoid the mentioned problems?

推荐答案

使用 pykd.typedVar 类.专为此类情况设计

Use pykd.typedVar class. It is specialy designed for such cases

这篇关于如何避免将 DbgCommand 命令写入日志文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆