问题
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")
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
window:
000000eab87488f0 CMap<int,int,CUIntArray *,CUIntArray *> Size:[0] // formatted DbgCommand result
000000eab8748930 CMap<int,int,CUIntArray *,CUIntArray *> Size:[0] // formatted DbgCommand result
Logfile:
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
How can I avoid DbgCommand
commands being written to the logfile?
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:
test-script excerpt:
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")
Result on screen:
1 : x /2 <application_name>!CStringList::CStringList, true
2 : x /2 <application_name>!CStringList::CStringList, false
004b6d3e <application_name>!CStringList::CStringList
3
Result in logfile:
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
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.
Let me explain what's wrong with the typedvar
solution:
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>
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
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
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'
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))
This gives following results:
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
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?
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 &>
...
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)
New edit
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?
回答1:
Use pykd.typedVar class. It is specialy designed for such cases
回答2:
try to change:
dt 0x000000eab87488f0 CMap<int,int,CUIntArray *,CUIntArray *> m_nCount
to:
var = typedVar("CMap<int,int,CUIntArray *,CUIntArray *>", 0x000000eab87488f0 )
print var
print var.m_nCount
print var.m_nCount * 2
You can get access to any filed of CMap class and work with its as they are natural python types
If you are going to get typedVar multiple times you can cache type information to avoid performance problems:
CMap = typeInfo("CMap<int,int,CUIntArray *,CUIntArray *>")
var = typedVar( CMap, 0x000000eab87488f0 )
回答3:
Try to enumerate types for your module ( with wildcard mask ) and find exact symbol name for CMap.
app = pykd.module("<application_name>")
for tp in app.enumTypes("CMap*"):
print tp
I can try to reproduce an issue on a small example, but I need to know your Visual Studio version.
来源:https://stackoverflow.com/questions/47651846/how-to-avoid-the-dbgcommand-command-being-written-to-the-logfile