如何避免将 DbgCommand 命令写入日志文件
How to avoid the DbgCommand command being written to the logfile
我在使用 Pykd.pyd
时遇到了一个恼人的问题:我在脚本中使用它,启动了几个 DbgCommand
函数,例如:
DbgCommand("dt 0x000000eab8748430 CMap<int,int,CUIntArray *,CUIntArray *> m_nCount")
这用于获取 CMap
对象的大小。由于这是在脚本中完成的,使用了大量的对象,我在 Windbg
(菜单 edit
、Open/Close Log File
)中使用日志文件,这里是要点:
在 Windbg
window 中查看时,我只看到 DbgCommand
调用的结果,但在日志文件中我也看到命令本身:
Windbg
window:
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
来处理(不要忘记 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 *!*
结果:
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\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>
and/or __ptr64
但似乎无法解决问题。此外, dt
和 "x /2 !" 的结果(格式不正确)清楚地表明存在上述类型。似乎 typedVar
在处理 __ptr64
标签时确实存在问题。有解决办法吗?
编辑
我刚刚尝试过,使用 pykd_team 中的 Python 命令,但它似乎仍然无法正常工作(这次是在 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 引起的,无法处理类型定义中的星号 (*
)。我可以使用任何转义符来避免上述问题吗?
使用pykd.typedVarclass。专为此类情况设计
尝试改变:
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 的任何文件 class 并使用其自然 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 版本。
我在使用 Pykd.pyd
时遇到了一个恼人的问题:我在脚本中使用它,启动了几个 DbgCommand
函数,例如:
DbgCommand("dt 0x000000eab8748430 CMap<int,int,CUIntArray *,CUIntArray *> m_nCount")
这用于获取 CMap
对象的大小。由于这是在脚本中完成的,使用了大量的对象,我在 Windbg
(菜单 edit
、Open/Close Log File
)中使用日志文件,这里是要点:
在 Windbg
window 中查看时,我只看到 DbgCommand
调用的结果,但在日志文件中我也看到命令本身:
Windbg
window:
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
来处理(不要忘记 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 *!*
结果:
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\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>
and/or __ptr64
但似乎无法解决问题。此外, dt
和 "x /2 !" 的结果(格式不正确)清楚地表明存在上述类型。似乎 typedVar
在处理 __ptr64
标签时确实存在问题。有解决办法吗?
编辑
我刚刚尝试过,使用 pykd_team 中的 Python 命令,但它似乎仍然无法正常工作(这次是在 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 引起的,无法处理类型定义中的星号 (*
)。我可以使用任何转义符来避免上述问题吗?
使用pykd.typedVarclass。专为此类情况设计
尝试改变:
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 的任何文件 class 并使用其自然 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 版本。