+ get local variables dict {name: typedVar, ....}
 ~ DiaSymbol::findEx add default params
 ~ re-query pdb-file name for module
 + dataKind for typedVar

git-svn-id: https://pykd.svn.codeplex.com/svn@73103 9b283d60-5439-405e-af05-b73fd8c4d996
This commit is contained in:
SND\EreTIk_cp 2012-01-11 22:23:29 +00:00 committed by Mikhail I. Izmestev
parent 43cc22a89f
commit b708cfefe4
19 changed files with 365 additions and 64 deletions

View File

@ -193,7 +193,7 @@ void DebugClient::startProcess( const std::wstring &processName )
if ( FAILED( hres ) ) if ( FAILED( hres ) )
throw DbgException( "IDebugControl::SetEngineOptions failed" ); throw DbgException( "IDebugControl::SetEngineOptions failed" );
std::vector< std::wstring::value_type> cmdLine( processName.size() + 1 ); std::vector< std::wstring::value_type > cmdLine( processName.size() + 1 );
wcscpy_s( &cmdLine[0], cmdLine.size(), processName.c_str() ); wcscpy_s( &cmdLine[0], cmdLine.size(), processName.c_str() );
hres = m_client->CreateProcessWide( 0, &cmdLine[0], DEBUG_PROCESS | DETACHED_PROCESS ); hres = m_client->CreateProcessWide( 0, &cmdLine[0], DEBUG_PROCESS | DETACHED_PROCESS );

View File

@ -240,6 +240,9 @@ public:
); );
} }
python::dict getLocals(
Ctx::ContextPtr ctx = Ctx::ContextPtr( reinterpret_cast<Ctx::Registers *>(0) )
);
public: public:
CComPtr<IDebugClient4>& CComPtr<IDebugClient4>&
@ -398,6 +401,13 @@ inline Ctx::ContextPtr getThreadContext() {
return g_dbgClient->getThreadContext(); return g_dbgClient->getThreadContext();
} }
inline python::dict getLocals(
Ctx::ContextPtr ctx = Ctx::ContextPtr( reinterpret_cast<Ctx::Registers *>(0) )
)
{
return g_dbgClient->getLocals(ctx);
}
///////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////
template<ULONG status> template<ULONG status>

View File

@ -78,6 +78,7 @@ BOOST_PYTHON_FUNCTION_OVERLOADS( loadSignWords_, loadSignWords, 2, 3 );
BOOST_PYTHON_FUNCTION_OVERLOADS( loadSignDWords_, loadSignDWords, 2, 3 ); BOOST_PYTHON_FUNCTION_OVERLOADS( loadSignDWords_, loadSignDWords, 2, 3 );
BOOST_PYTHON_FUNCTION_OVERLOADS( loadSignQWords_, loadSignQWords, 2, 3 ); BOOST_PYTHON_FUNCTION_OVERLOADS( loadSignQWords_, loadSignQWords, 2, 3 );
BOOST_PYTHON_FUNCTION_OVERLOADS( compareMemory_, compareMemory, 3, 4 ); BOOST_PYTHON_FUNCTION_OVERLOADS( compareMemory_, compareMemory, 3, 4 );
BOOST_PYTHON_FUNCTION_OVERLOADS( getLocals_, getLocals, 0, 1 );
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS( DebugClient_loadChars, DebugClient::loadChars, 2, 3 ); BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS( DebugClient_loadChars, DebugClient::loadChars, 2, 3 );
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS( DebugClient_loadWChars, DebugClient::loadWChars, 2, 3 ); BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS( DebugClient_loadWChars, DebugClient::loadWChars, 2, 3 );
@ -90,7 +91,8 @@ BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS( DebugClient_loadSignWords, DebugClient::
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS( DebugClient_loadSignDWords, DebugClient::loadSignDWords, 2, 3 ); BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS( DebugClient_loadSignDWords, DebugClient::loadSignDWords, 2, 3 );
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS( DebugClient_loadSignQWords, DebugClient::loadSignQWords, 2, 3 ); BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS( DebugClient_loadSignQWords, DebugClient::loadSignQWords, 2, 3 );
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS( DebugClient_compareMemory, DebugClient::compareMemory, 3, 4 ); BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS( DebugClient_compareMemory, DebugClient::compareMemory, 3, 4 );
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS( DebugClient_getLocals, DebugClient::getLocals, 0, 1 );
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS( pyDia_Symbol_findChildrenEx, pyDia::Symbol::findChildrenEx, 1, 3 );
#define DEF_PY_CONST_ULONG(x) \ #define DEF_PY_CONST_ULONG(x) \
python::scope().attr(#x) = ULONG(##x) python::scope().attr(#x) = ULONG(##x)
@ -287,6 +289,8 @@ BOOST_PYTHON_MODULE( pykd )
"Get the page size for the currently executing processor context" ) "Get the page size for the currently executing processor context" )
.def( "getContext", &DebugClient::getThreadContext, .def( "getContext", &DebugClient::getThreadContext,
"Get context of current thread (register values)" ) "Get context of current thread (register values)" )
.def( "getLocals", &DebugClient::getLocals, DebugClient_getLocals( python::args( "ctx" ),
"Get list of local variables" ) )
.def( "addSynSymbol", &DebugClient::addSyntheticSymbol, .def( "addSynSymbol", &DebugClient::addSyntheticSymbol,
"Add new synthetic symbol for virtual address" ) "Add new synthetic symbol for virtual address" )
.def( "delAllSynSymbols", &DebugClient::delAllSyntheticSymbols, .def( "delAllSynSymbols", &DebugClient::delAllSyntheticSymbols,
@ -460,6 +464,8 @@ BOOST_PYTHON_MODULE( pykd )
"Get the page size for the currently executing processor context" ); "Get the page size for the currently executing processor context" );
python::def( "getContext", &getThreadContext, python::def( "getContext", &getThreadContext,
"Get context of current thread (register values)" ); "Get context of current thread (register values)" );
python::def( "getLocals", &getLocals, getLocals_( python::args( "ctx" ),
"Get list of local variables" ) );
python::class_<TypeInfo, TypeInfoPtr, python::bases<intBase>, boost::noncopyable >("typeInfo", "Class representing typeInfo", python::no_init ) python::class_<TypeInfo, TypeInfoPtr, python::bases<intBase>, boost::noncopyable >("typeInfo", "Class representing typeInfo", python::no_init )
.def( "name", &TypeInfo::getName ) .def( "name", &TypeInfo::getName )
@ -483,6 +489,8 @@ BOOST_PYTHON_MODULE( pykd )
"Return offset to parent" ) "Return offset to parent" )
.def("field", &TypedVar::getField, .def("field", &TypedVar::getField,
"Return field of structure as an object attribute" ) "Return field of structure as an object attribute" )
.def( "dataKind", &TypedVar::getDataKind,
"Retrieves the variable classification of a data: DataIsXxx")
.def("deref", &TypedVar::deref, .def("deref", &TypedVar::deref,
"Return value by pointer" ) "Return value by pointer" )
.def("__getattr__", &TypedVar::getField, .def("__getattr__", &TypedVar::getField,
@ -615,12 +623,12 @@ BOOST_PYTHON_MODULE( pykd )
"Return tuple<ID, VALUE> by index"); "Return tuple<ID, VALUE> by index");
python::def( "diaLoadPdb", &pyDia::GlobalScope::loadPdb, python::def( "diaLoadPdb", &pyDia::GlobalScope::loadPdb,
"Open pdb file for quering debug symbols. Return DiaSymbol of global scope"); "Open pdb file for querying debug symbols. Return DiaSymbol of global scope");
python::class_<pyDia::Symbol, pyDia::SymbolPtr>( python::class_<pyDia::Symbol, pyDia::SymbolPtr>(
"DiaSymbol", "class wrapper for MS DIA Symbol", python::no_init ) "DiaSymbol", "class wrapper for MS DIA Symbol", python::no_init )
.def( "findEx", &pyDia::Symbol::findChildrenEx, .def( "findEx", &pyDia::Symbol::findChildrenEx, pyDia_Symbol_findChildrenEx( python::args( "symTag", "name", "cmpFlags" ) ,
"Retrieves the children of the symbol" ) "Retrieves the children of the symbol" ) )
.def( "find", &pyDia::Symbol::findChildren, .def( "find", &pyDia::Symbol::findChildren,
"Retrieves the children of the symbol" ) "Retrieves the children of the symbol" )
.def( "size", &pyDia::Symbol::getSize, .def( "size", &pyDia::Symbol::getSize,

View File

@ -59,7 +59,7 @@ void Exception::exceptionTranslate( const Exception &e )
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
std::list< SymbolPtr > Symbol::findChildrenImpl( SymbolPtrList Symbol::findChildrenImpl(
ULONG symTag, ULONG symTag,
const std::string &name, const std::string &name,
DWORD nameCmpFlags DWORD nameCmpFlags
@ -89,7 +89,7 @@ std::list< SymbolPtr > Symbol::findChildrenImpl(
if (S_OK != hres) if (S_OK != hres)
throw Exception("Call IDiaSymbol::findChildren", hres); throw Exception("Call IDiaSymbol::findChildren", hres);
std::list< SymbolPtr > childList; SymbolPtrList childList;
DiaSymbolPtr child; DiaSymbolPtr child;
ULONG celt; ULONG celt;

View File

@ -55,6 +55,7 @@ private:
class Symbol; class Symbol;
typedef boost::shared_ptr< Symbol > SymbolPtr; typedef boost::shared_ptr< Symbol > SymbolPtr;
typedef std::list< SymbolPtr > SymbolPtrList;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Symbol // Symbol
@ -77,16 +78,16 @@ public:
} }
std::list< SymbolPtr > findChildrenImpl( SymbolPtrList findChildrenImpl(
ULONG symTag, ULONG symTag,
const std::string &name, const std::string &name = "",
DWORD nameCmpFlags DWORD nameCmpFlags = 0
); );
python::list findChildrenEx( python::list findChildrenEx(
ULONG symTag, ULONG symTag,
const std::string &name, const std::string &name = "",
DWORD nameCmpFlags DWORD nameCmpFlags = 0
) )
{ {
return toPyList( findChildrenImpl(symTag, name, nameCmpFlags) ); return toPyList( findChildrenImpl(symTag, name, nameCmpFlags) );

190
pykd/livevar.cpp Normal file
View File

@ -0,0 +1,190 @@
////////////////////////////////////////////////////////////////////////////////
#include <stdafx.h>
#include "dbgclient.h"
////////////////////////////////////////////////////////////////////////////////
namespace pykd {
////////////////////////////////////////////////////////////////////////////////
namespace impl {
////////////////////////////////////////////////////////////////////////////////
struct addLocals {
python::dict &m_locals;
const Module &m_module;
ULONG m_rva;
Ctx::ContextPtr m_ctx;
IDebugClient4 *m_client;
void append(pyDia::SymbolPtr symParent);
private:
void appendVar(pyDia::SymbolPtr symData);
TypedVarPtr getTypeVarByOffset(
pyDia::SymbolPtr symData,
ULONG64 varOffset
);
};
////////////////////////////////////////////////////////////////////////////////
struct Exception : public DbgException {
Exception() : DbgException("build list of locals: internal exception")
{
}
};
////////////////////////////////////////////////////////////////////////////////
void addLocals::append(pyDia::SymbolPtr symParent)
{
// add all local variables
pyDia::SymbolPtrList lstLocals = symParent->findChildrenImpl(SymTagData);
pyDia::SymbolPtrList::iterator it = lstLocals.begin();
while (it != lstLocals.end())
{
try
{
appendVar(*it);
}
catch (const DbgException &e)
{
DBG_UNREFERENCED_LOCAL_VARIABLE(e);
}
++it;
}
// process all scopes
pyDia::SymbolPtrList lstScopes = symParent->findChildrenImpl(SymTagBlock);
it = lstScopes.begin();
while ( it != lstScopes.end() )
{
const ULONG scopeRva = (*it)->getRva();
if ( (scopeRva <= m_rva) && (scopeRva + (*it)->getSize() > m_rva) )
append(*it);
++it;
}
}
////////////////////////////////////////////////////////////////////////////////
void addLocals::appendVar(pyDia::SymbolPtr symData)
{
TypedVarPtr typedVar;
std::string varName = symData->getName();
switch (symData->getLocType())
{
case LocIsStatic:
typedVar =
getTypeVarByOffset(
symData,
m_module.getBase() + symData->getRva() );
break;
case LocIsRegRel:
typedVar =
getTypeVarByOffset(
symData,
m_ctx->getValue( symData->getRegisterId() )+ symData->getOffset() );
break;
case LocIsEnregistered: // FIXME
default:
throw Exception();
}
typedVar->setDataKind( symData->getDataKind() );
m_locals[varName] = typedVar;
}
////////////////////////////////////////////////////////////////////////////////
TypedVarPtr addLocals::getTypeVarByOffset(
pyDia::SymbolPtr symData,
ULONG64 varOffset
)
{
pyDia::SymbolPtr symType = symData->getType();
TypeInfoPtr typeInfo = TypeInfo::getTypeInfo( symType );
return TypedVar::getTypedVar( m_client, typeInfo, varOffset );
}
////////////////////////////////////////////////////////////////////////////////
static ULONG getUnnamedChildRva(
pyDia::SymbolPtr symParent,
ULONG SymTag
)
{
pyDia::SymbolPtrList childs = symParent->findChildrenImpl(SymTag);
if (childs.empty())
throw Exception();
return (*childs.begin())->getRva();
}
////////////////////////////////////////////////////////////////////////////////
static bool isOutOfDebugRange(
ULONG rva,
pyDia::SymbolPtr symFunc
)
{
try
{
if (rva < getUnnamedChildRva(symFunc, SymTagFuncDebugStart))
return true;
if (rva > getUnnamedChildRva(symFunc, SymTagFuncDebugEnd))
return true;
}
catch (const DbgException &)
{
}
return false;
}
}
////////////////////////////////////////////////////////////////////////////////
python::dict DebugClient::getLocals(Ctx::ContextPtr ctx OPTIONAL)
{
if (!ctx)
ctx = getThreadContext();
const ULONG64 instrPtr = ctx->getIp();
Module mod = loadModuleByOffset( instrPtr );
const ULONG rva = static_cast<ULONG>( instrPtr - mod.getBase() );
pyDia::GlobalScopePtr globScope = mod.getDia();
LONG funcDispl;
pyDia::SymbolPtr symFunc =
globScope->findByRvaImpl(rva, SymTagFunction, funcDispl);
if (impl::isOutOfDebugRange(rva, symFunc))
return python::dict(); // out of function debug range
python::dict locals;
impl::addLocals Locals = { locals, mod, rva, ctx, m_client };
Locals.append(symFunc);
return locals;
}
////////////////////////////////////////////////////////////////////////////////
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -135,6 +135,24 @@ Module::getPdbName()
if ( FAILED( hres ) ) if ( FAILED( hres ) )
throw DbgException( "IDebugAdvanced2::GetSymbolInformation failed" ); throw DbgException( "IDebugAdvanced2::GetSymbolInformation failed" );
if (!*moduleInfo.LoadedPdbName)
{
reloadSymbols();
hres = m_advanced->GetSymbolInformation(
DEBUG_SYMINFO_IMAGEHLP_MODULEW64,
m_base,
0,
&moduleInfo,
sizeof(moduleInfo),
NULL,
NULL,
0,
NULL );
if ( FAILED( hres ) )
throw DbgException( "IDebugAdvanced2::GetSymbolInformation failed" );
}
char pdbName[ 256 ]; char pdbName[ 256 ];
WideCharToMultiByte( CP_ACP, 0, moduleInfo.LoadedPdbName, 256, pdbName, 256, NULL, NULL ); WideCharToMultiByte( CP_ACP, 0, moduleInfo.LoadedPdbName, 256, pdbName, 256, NULL, NULL );

View File

@ -28,15 +28,15 @@ public:
return m_imageName; return m_imageName;
} }
ULONG64 getBase() { ULONG64 getBase() const {
return m_base; return m_base;
} }
ULONG64 getEnd() { ULONG64 getEnd() const {
return m_base + m_size; return m_base + m_size;
} }
ULONG getSize() { ULONG getSize() const {
return m_size; return m_size;
} }
@ -80,17 +80,16 @@ public:
python::list getTypedVarArrayByType( ULONG64 addr, const TypeInfoPtr &typeInfo, ULONG number ); python::list getTypedVarArrayByType( ULONG64 addr, const TypeInfoPtr &typeInfo, ULONG number );
private:
ULONG getRvaByName(const std::string &symName);
pyDia::GlobalScopePtr& getDia() { pyDia::GlobalScopePtr& getDia() {
if (!m_dia) if (!m_dia)
m_dia = pyDia::GlobalScope::loadPdb( getPdbName() ); m_dia = pyDia::GlobalScope::loadPdb( getPdbName() );
return m_dia; return m_dia;
} }
private:
ULONG getRvaByName(const std::string &symName);
BaseTypeVariant getValue() { BaseTypeVariant getValue() {
return BaseTypeVariant(m_base); return BaseTypeVariant(m_base);
} }

View File

@ -409,6 +409,10 @@
RelativePath=".\inteventhandler.cpp" RelativePath=".\inteventhandler.cpp"
> >
</File> </File>
<File
RelativePath=".\livevar.cpp"
>
</File>
<File <File
RelativePath=".\module.cpp" RelativePath=".\module.cpp"
> >

View File

@ -57,7 +57,8 @@ TypedVarPtr TypedVar::getTypedVar( IDebugClient4 *client, const TypeInfoPtr& t
TypedVar::TypedVar ( IDebugClient4 *client, const TypeInfoPtr& typeInfo, ULONG64 offset ) : TypedVar::TypedVar ( IDebugClient4 *client, const TypeInfoPtr& typeInfo, ULONG64 offset ) :
DbgObject( client ), DbgObject( client ),
m_typeInfo( typeInfo ), m_typeInfo( typeInfo ),
m_offset( offset ) m_offset( offset ),
m_dataKind( DataIsGlobal )
{ {
m_size = m_typeInfo->getSize(); m_size = m_typeInfo->getSize();
} }

View File

@ -61,6 +61,14 @@ public:
return getElementByIndex( boost::apply_visitor( VariantToULong(), tv->getValue() ) ); return getElementByIndex( boost::apply_visitor( VariantToULong(), tv->getValue() ) );
} }
ULONG getDataKind() const {
return m_dataKind;
}
void setDataKind(ULONG dataKind) {
m_dataKind = dataKind;
}
protected: protected:
TypedVar ( IDebugClient4 *client, const TypeInfoPtr& typeInfo, ULONG64 offset ); TypedVar ( IDebugClient4 *client, const TypeInfoPtr& typeInfo, ULONG64 offset );
@ -74,6 +82,8 @@ protected:
ULONG64 m_offset; ULONG64 m_offset;
ULONG m_size; ULONG m_size;
ULONG m_dataKind;
}; };
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////

View File

@ -65,7 +65,7 @@ BaseTypeVariant TypeInfo::getValue()
return (LONG64)m_constantValue.llVal; return (LONG64)m_constantValue.llVal;
} }
throw DbgException( "Failed to convert constatnt type" ); throw DbgException( "Failed to convert constant type" );
} }
///////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////
@ -392,11 +392,11 @@ TypeInfoPtr TypeInfo::getRecurciveComplexType( TypeInfoPtr &lowestType, std::str
python::dict EnumTypeInfo::asMap() python::dict EnumTypeInfo::asMap()
{ {
python::dict dct; python::dict dct;
std::list< pyDia::SymbolPtr > symbolsList = m_dia->findChildrenImpl(SymTagData, "", nsfCaseSensitive ); pyDia::SymbolPtrList symbolsList = m_dia->findChildrenImpl(SymTagData, "", nsfCaseSensitive );
for ( std::list< pyDia::SymbolPtr >::iterator it = symbolsList.begin(); it != symbolsList.end(); it++ ) for ( pyDia::SymbolPtrList::iterator it = symbolsList.begin(); it != symbolsList.end(); it++ )
{ {
CComVariant val; CComVariant val;

View File

@ -21,33 +21,9 @@ class DbgClientTest( unittest.TestCase ):
"""Size of memory page must be >= 4kb""" """Size of memory page must be >= 4kb"""
self.assertTrue( pykd.getPageSize() >= 4*1024 ) self.assertTrue( pykd.getPageSize() >= 4*1024 )
def testCurrentThreadContext( self ):
"""Some check of current thread context content"""
ctx = pykd.getContext()
# for reg in ctx:
# regName = ""
# if ctx.processorType() == "X86":
# regName = pykd.diaI386Regs[ reg[0] ]
# else:
# regName = pykd.diaAmd64Regs[ reg[0] ]
# pykd.dprint( "\n" + regName + ": 0x%x " % reg[1])
self.assertNotEqual( 0, len(ctx) )
self.assertNotEqual( 0, ctx.ip() )
self.assertNotEqual( 0, ctx.csp() )
self.assertEqual( (ctx.get(pykd.CV_REG_AH) << 8) | ctx.get(pykd.CV_REG_AL), ctx.get(pykd.CV_REG_AX) )
self.assertEqual( ctx.get(pykd.CV_REG_AX), ctx.get(pykd.CV_REG_EAX) & 0xffff )
if ctx.processorType() == "X64":
self.assertEqual( ctx.get(pykd.CV_REG_EAX), ctx.get(pykd.CV_AMD64_RAX) & 0xffffffff )
self.assertEqual( (ctx.get(pykd.CV_REG_DH) << 8) | ctx.get(pykd.CV_REG_DL), ctx.get(pykd.CV_REG_DX) )
self.assertEqual( ctx.get(pykd.CV_REG_DX), ctx.get(pykd.CV_REG_EDX) & 0xffff )
if ctx.processorType() == "X64":
self.assertEqual( ctx.get(pykd.CV_REG_EDX), ctx.get(pykd.CV_AMD64_RDX) & 0xffffffff )
def testIsDumpAnalyzing( self ): def testIsDumpAnalyzing( self ):
self.assertFalse( pykd.isDumpAnalyzing() ) self.assertFalse( pykd.isDumpAnalyzing() )
def testExecutionStatus( self ): def testExecutionStatus( self ):
self.assertEqual( pykd.DEBUG_STATUS_BREAK, pykd.getExecutionStatus() ) self.assertEqual( pykd.DEBUG_STATUS_BREAK, pykd.getExecutionStatus() )
pykd.setExecutionStatus( pykd.DEBUG_STATUS_GO ) pykd.setExecutionStatus( pykd.DEBUG_STATUS_GO )

View File

@ -0,0 +1,32 @@
"""Local variables tests"""
import unittest
import target
import pykd
class LocalVarsTest(unittest.TestCase):
def testLocalVariable(self):
"""Start new process and break in targetapp!EnumWindowsProc"""
testClient = pykd.createDbgClient()
testClient.startProcess( target.appPath + " -testEnumWindows" )
testClient.go() # initial breakpoint -> wmain
testClient.go() # wmain -> targetapp!EnumWindowsProc
# pykd.dprint( "\n" + testClient.dbgCommand("u") )
locals = testClient.getLocals()
self.assertNotEqual( 0, locals["hWindow"] )
self.assertEqual( pykd.DataIsParam, locals["hWindow"].dataKind() )
self.assertEqual( 6, locals["lParam"] )
self.assertEqual( pykd.DataIsParam, locals["lParam"].dataKind() )
self.assertNotEqual( 0, locals["dwProccessId"] )
self.assertEqual( pykd.DataIsLocal, locals["dwProccessId"].dataKind() )
self.assertNotEqual( 0, locals["staticVar"] )
self.assertEqual( pykd.DataIsStaticLocal, locals["staticVar"].dataKind() )
self.assertEqual( locals["dwProccessId"], locals["staticVar"] )

View File

@ -24,6 +24,8 @@ import memtest
import intbase import intbase
import synsymtest import synsymtest
import ehloadtest import ehloadtest
import thrdctxtest
import localstest
def getTestSuite( singleName = "" ): def getTestSuite( singleName = "" ):
if singleName == "": if singleName == "":
@ -39,7 +41,9 @@ def getTestSuite( singleName = "" ):
unittest.TestLoader().loadTestsFromTestCase( memtest.MemoryTest ), unittest.TestLoader().loadTestsFromTestCase( memtest.MemoryTest ),
unittest.TestLoader().loadTestsFromTestCase( intbase.IntBaseTest ), unittest.TestLoader().loadTestsFromTestCase( intbase.IntBaseTest ),
unittest.TestLoader().loadTestsFromTestCase( synsymtest.SynSymTest ), unittest.TestLoader().loadTestsFromTestCase( synsymtest.SynSymTest ),
unittest.TestLoader().loadTestsFromTestCase( ehloadtest.EhLoadTest ) unittest.TestLoader().loadTestsFromTestCase( thrdctxtest.ThreadContextTest ),
unittest.TestLoader().loadTestsFromTestCase( ehloadtest.EhLoadTest ),
unittest.TestLoader().loadTestsFromTestCase( localstest.LocalVarsTest )
] ) ] )
else: else:
return unittest.TestSuite( unittest.TestLoader().loadTestsFromName( singleName ) ) return unittest.TestSuite( unittest.TestLoader().loadTestsFromName( singleName ) )
@ -48,21 +52,21 @@ def getTestSuite( singleName = "" ):
if __name__ == "__main__": if __name__ == "__main__":
target.appPath = sys.argv[1] target.appPath = sys.argv[1]
target.moduleName = os.path.splitext(os.path.basename(target.appPath))[0] target.moduleName = os.path.splitext(os.path.basename(target.appPath))[0]
print "\nTest module: %s" % target.appPath print "\nTest module: %s" % target.appPath
pykd.startProcess( target.appPath ) pykd.startProcess( target.appPath )
target.module = pykd.loadModule( target.moduleName ) target.module = pykd.loadModule( target.moduleName )
target.module.reload(); target.module.reload();
pykd.go() pykd.go()
suite = getTestSuite() suite = getTestSuite()
#suite = getTestSuite( "typedvar.TypedVarTest.testBitField" ) #suite = getTestSuite( "typedvar.TypedVarTest.testBitField" )
#suite = getTestSuite( "typeinfo.TypeInfoTest.testBitField" ) #suite = getTestSuite( "typeinfo.TypeInfoTest.testBitField" )
unittest.TextTestRunner(stream=sys.stdout, verbosity=2).run( suite ) unittest.TextTestRunner(stream=sys.stdout, verbosity=2).run( suite )
#a = raw_input("\npress return\n") #raw_input("\npress return\n")

View File

@ -0,0 +1,33 @@
"""Tests of thread context"""
import unittest
import target
import pykd
class ThreadContextTest( unittest.TestCase ):
def testCurrentThreadContext( self ):
"""Some checks of current thread context content"""
ctx = pykd.getContext()
# for reg in ctx:
# regName = ""
# if ctx.processorType() == "X86":
# regName = pykd.diaI386Regs[ reg[0] ]
# else:
# regName = pykd.diaAmd64Regs[ reg[0] ]
# pykd.dprint( "\n" + regName + ": 0x%x " % reg[1])
self.assertNotEqual( 0, len(ctx) )
self.assertNotEqual( 0, ctx.ip() )
self.assertNotEqual( 0, ctx.csp() )
def testComplexRegisters( self ):
"""Test of "sub-"registers"""
ctx = pykd.getContext()
self.assertEqual( (ctx.get(pykd.CV_REG_AH) << 8) | ctx.get(pykd.CV_REG_AL), ctx.get(pykd.CV_REG_AX) )
self.assertEqual( ctx.get(pykd.CV_REG_AX), ctx.get(pykd.CV_REG_EAX) & 0xffff )
if ctx.processorType() == "X64":
self.assertEqual( ctx.get(pykd.CV_REG_EAX), ctx.get(pykd.CV_AMD64_RAX) & 0xffffffff )
self.assertEqual( (ctx.get(pykd.CV_REG_DH) << 8) | ctx.get(pykd.CV_REG_DL), ctx.get(pykd.CV_REG_DX) )
self.assertEqual( ctx.get(pykd.CV_REG_DX), ctx.get(pykd.CV_REG_EDX) & 0xffff )
if ctx.processorType() == "X64":
self.assertEqual( ctx.get(pykd.CV_REG_EDX), ctx.get(pykd.CV_AMD64_RDX) & 0xffffffff )

View File

@ -21,7 +21,8 @@ class TypedVarTest( unittest.TestCase ):
self.assertEqual( -2, target.module.typedVar( "g_shortValue" ) ) self.assertEqual( -2, target.module.typedVar( "g_shortValue" ) )
self.assertEqual( -4, target.module.typedVar( "g_longValue" ) ) self.assertEqual( -4, target.module.typedVar( "g_longValue" ) )
self.assertEqual( -8, target.module.typedVar( "g_longlongValue" ) ) self.assertEqual( -8, target.module.typedVar( "g_longlongValue" ) )
self.assertEqual( True, target.module.typedVar( "g_constBoolValue" ) ) try: self.assertEqual( True, target.module.typedVar( "g_constBoolValue" ) )
except pykd.DiaException: self.assertTrue( False )
def testGetAddress( self ): def testGetAddress( self ):
tv = target.module.typedVar( "structTest", target.module.g_structTest ) tv = target.module.typedVar( "structTest", target.module.g_structTest )

View File

@ -261,17 +261,22 @@ void FuncWithName1(int a)
BOOL CALLBACK EnumWindowsProc( BOOL CALLBACK EnumWindowsProc(
HWND hWindow, HWND hWindow,
LPARAM lParam const LPARAM lParam
) )
{ {
DWORD dwProccessId = 0; DWORD dwProccessId = 0;
if (hWindow) if (hWindow)
std::cout << lParam; std::cout << lParam;
if (hWindow)
{ {
static ULONGLONG staticVar = 0;
DWORD dwThreadId = ::GetWindowThreadProcessId(hWindow, &dwProccessId); DWORD dwThreadId = ::GetWindowThreadProcessId(hWindow, &dwProccessId);
std::cout << dwProccessId << dwThreadId; staticVar = dwProccessId;
__debugbreak();
std::cout << dwProccessId << dwThreadId << staticVar;
} }
return FALSE; return hWindow ? FALSE : TRUE;
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -309,6 +314,9 @@ int _tmain(int argc, _TCHAR* argv[])
// run with parameters // run with parameters
if ( !_tcsicmp(argv[1], _T("-testLoadUnload")) ) if ( !_tcsicmp(argv[1], _T("-testLoadUnload")) )
return doLoadUnload(); return doLoadUnload();
if ( !_tcsicmp(argv[1], _T("-testEnumWindows")) )
return ::EnumWindows(&EnumWindowsProc, 6);
} }
__debugbreak(); __debugbreak();
@ -316,8 +324,6 @@ int _tmain(int argc, _TCHAR* argv[])
__debugbreak(); __debugbreak();
FuncWithName0(); FuncWithName0();
FuncWithName1(2); FuncWithName1(2);
EnumWindows(&::EnumWindowsProc, 6);
} }
catch(std::exception & ex) catch(std::exception & ex)
{ {

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="windows-1251"?> <?xml version="1.0" encoding="windows-1251"?>
<VisualStudioProject <VisualStudioProject
ProjectType="Visual C++" ProjectType="Visual C++"
Version="9,00" Version="9.00"
Name="targetapp" Name="targetapp"
ProjectGUID="{C6254E16-AB8E-41EE-887D-31458E93FC68}" ProjectGUID="{C6254E16-AB8E-41EE-887D-31458E93FC68}"
RootNamespace="targetapp" RootNamespace="targetapp"
@ -428,6 +428,10 @@
RelativePath="..\scripts\intbase.py" RelativePath="..\scripts\intbase.py"
> >
</File> </File>
<File
RelativePath="..\scripts\localstest.py"
>
</File>
<File <File
RelativePath="..\scripts\memtest.py" RelativePath="..\scripts\memtest.py"
> >
@ -452,6 +456,10 @@
RelativePath="..\scripts\target.py" RelativePath="..\scripts\target.py"
> >
</File> </File>
<File
RelativePath="..\scripts\thrdctxtest.py"
>
</File>
<File <File
RelativePath="..\scripts\typedvar.py" RelativePath="..\scripts\typedvar.py"
> >