From b708cfefe42e8ea935ff5f3e8156f6c8cdc56e5e Mon Sep 17 00:00:00 2001 From: "SND\\EreTIk_cp" Date: Wed, 11 Jan 2012 22:23:29 +0000 Subject: [PATCH] [0.1.x] + 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 --- pykd/dbgclient.cpp | 2 +- pykd/dbgclient.h | 10 ++ pykd/dbgext.cpp | 16 ++- pykd/diawrapper.cpp | 4 +- pykd/diawrapper.h | 11 +- pykd/livevar.cpp | 190 ++++++++++++++++++++++++++++++++ pykd/module.cpp | 18 +++ pykd/module.h | 15 ++- pykd/pykd_2008.vcproj | 4 + pykd/typedvar.cpp | 3 +- pykd/typedvar.h | 10 ++ pykd/typeinfo.cpp | 8 +- test/scripts/clienttest.py | 26 +---- test/scripts/localstest.py | 32 ++++++ test/scripts/pykdtest.py | 18 +-- test/scripts/thrdctxtest.py | 33 ++++++ test/scripts/typedvar.py | 3 +- test/targetapp/targetapp.cpp | 16 ++- test/targetapp/targetapp.vcproj | 10 +- 19 files changed, 365 insertions(+), 64 deletions(-) create mode 100644 pykd/livevar.cpp create mode 100644 test/scripts/localstest.py create mode 100644 test/scripts/thrdctxtest.py diff --git a/pykd/dbgclient.cpp b/pykd/dbgclient.cpp index 67193a9..20bd201 100644 --- a/pykd/dbgclient.cpp +++ b/pykd/dbgclient.cpp @@ -193,7 +193,7 @@ void DebugClient::startProcess( const std::wstring &processName ) if ( FAILED( hres ) ) 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() ); hres = m_client->CreateProcessWide( 0, &cmdLine[0], DEBUG_PROCESS | DETACHED_PROCESS ); diff --git a/pykd/dbgclient.h b/pykd/dbgclient.h index 52eec42..1661cbc 100644 --- a/pykd/dbgclient.h +++ b/pykd/dbgclient.h @@ -240,6 +240,9 @@ public: ); } + python::dict getLocals( + Ctx::ContextPtr ctx = Ctx::ContextPtr( reinterpret_cast(0) ) + ); public: CComPtr& @@ -398,6 +401,13 @@ inline Ctx::ContextPtr getThreadContext() { return g_dbgClient->getThreadContext(); } +inline python::dict getLocals( + Ctx::ContextPtr ctx = Ctx::ContextPtr( reinterpret_cast(0) ) +) +{ + return g_dbgClient->getLocals(ctx); +} + ///////////////////////////////////////////////////////////////////////////////// template diff --git a/pykd/dbgext.cpp b/pykd/dbgext.cpp index 5a6080b..750879d 100644 --- a/pykd/dbgext.cpp +++ b/pykd/dbgext.cpp @@ -78,6 +78,7 @@ BOOST_PYTHON_FUNCTION_OVERLOADS( loadSignWords_, loadSignWords, 2, 3 ); BOOST_PYTHON_FUNCTION_OVERLOADS( loadSignDWords_, loadSignDWords, 2, 3 ); BOOST_PYTHON_FUNCTION_OVERLOADS( loadSignQWords_, loadSignQWords, 2, 3 ); 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_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_loadSignQWords, DebugClient::loadSignQWords, 2, 3 ); 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) \ python::scope().attr(#x) = ULONG(##x) @@ -287,6 +289,8 @@ BOOST_PYTHON_MODULE( pykd ) "Get the page size for the currently executing processor context" ) .def( "getContext", &DebugClient::getThreadContext, "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, "Add new synthetic symbol for virtual address" ) .def( "delAllSynSymbols", &DebugClient::delAllSyntheticSymbols, @@ -460,6 +464,8 @@ BOOST_PYTHON_MODULE( pykd ) "Get the page size for the currently executing processor context" ); python::def( "getContext", &getThreadContext, "Get context of current thread (register values)" ); + python::def( "getLocals", &getLocals, getLocals_( python::args( "ctx" ), + "Get list of local variables" ) ); python::class_, boost::noncopyable >("typeInfo", "Class representing typeInfo", python::no_init ) .def( "name", &TypeInfo::getName ) @@ -483,6 +489,8 @@ BOOST_PYTHON_MODULE( pykd ) "Return offset to parent" ) .def("field", &TypedVar::getField, "Return field of structure as an object attribute" ) + .def( "dataKind", &TypedVar::getDataKind, + "Retrieves the variable classification of a data: DataIsXxx") .def("deref", &TypedVar::deref, "Return value by pointer" ) .def("__getattr__", &TypedVar::getField, @@ -615,12 +623,12 @@ BOOST_PYTHON_MODULE( pykd ) "Return tuple by index"); 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_( "DiaSymbol", "class wrapper for MS DIA Symbol", python::no_init ) - .def( "findEx", &pyDia::Symbol::findChildrenEx, - "Retrieves the children of the symbol" ) + .def( "findEx", &pyDia::Symbol::findChildrenEx, pyDia_Symbol_findChildrenEx( python::args( "symTag", "name", "cmpFlags" ) , + "Retrieves the children of the symbol" ) ) .def( "find", &pyDia::Symbol::findChildren, "Retrieves the children of the symbol" ) .def( "size", &pyDia::Symbol::getSize, diff --git a/pykd/diawrapper.cpp b/pykd/diawrapper.cpp index 51ccfc6..b9b07dc 100644 --- a/pykd/diawrapper.cpp +++ b/pykd/diawrapper.cpp @@ -59,7 +59,7 @@ void Exception::exceptionTranslate( const Exception &e ) //////////////////////////////////////////////////////////////////////////////// -std::list< SymbolPtr > Symbol::findChildrenImpl( +SymbolPtrList Symbol::findChildrenImpl( ULONG symTag, const std::string &name, DWORD nameCmpFlags @@ -89,7 +89,7 @@ std::list< SymbolPtr > Symbol::findChildrenImpl( if (S_OK != hres) throw Exception("Call IDiaSymbol::findChildren", hres); - std::list< SymbolPtr > childList; + SymbolPtrList childList; DiaSymbolPtr child; ULONG celt; diff --git a/pykd/diawrapper.h b/pykd/diawrapper.h index 8530299..231890a 100644 --- a/pykd/diawrapper.h +++ b/pykd/diawrapper.h @@ -55,6 +55,7 @@ private: class Symbol; typedef boost::shared_ptr< Symbol > SymbolPtr; +typedef std::list< SymbolPtr > SymbolPtrList; //////////////////////////////////////////////////////////////////////////////// // Symbol @@ -77,16 +78,16 @@ public: } - std::list< SymbolPtr > findChildrenImpl( + SymbolPtrList findChildrenImpl( ULONG symTag, - const std::string &name, - DWORD nameCmpFlags + const std::string &name = "", + DWORD nameCmpFlags = 0 ); python::list findChildrenEx( ULONG symTag, - const std::string &name, - DWORD nameCmpFlags + const std::string &name = "", + DWORD nameCmpFlags = 0 ) { return toPyList( findChildrenImpl(symTag, name, nameCmpFlags) ); diff --git a/pykd/livevar.cpp b/pykd/livevar.cpp new file mode 100644 index 0000000..c3d0718 --- /dev/null +++ b/pykd/livevar.cpp @@ -0,0 +1,190 @@ + +//////////////////////////////////////////////////////////////////////////////// + +#include + +#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( 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; +} + +//////////////////////////////////////////////////////////////////////////////// + +} + +//////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/module.cpp b/pykd/module.cpp index 274c554..4bf34e8 100644 --- a/pykd/module.cpp +++ b/pykd/module.cpp @@ -135,6 +135,24 @@ Module::getPdbName() if ( FAILED( hres ) ) 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 ]; WideCharToMultiByte( CP_ACP, 0, moduleInfo.LoadedPdbName, 256, pdbName, 256, NULL, NULL ); diff --git a/pykd/module.h b/pykd/module.h index 6ac2dd3..c854270 100644 --- a/pykd/module.h +++ b/pykd/module.h @@ -28,15 +28,15 @@ public: return m_imageName; } - ULONG64 getBase() { + ULONG64 getBase() const { return m_base; } - ULONG64 getEnd() { + ULONG64 getEnd() const { return m_base + m_size; } - ULONG getSize() { + ULONG getSize() const { return m_size; } @@ -80,17 +80,16 @@ public: python::list getTypedVarArrayByType( ULONG64 addr, const TypeInfoPtr &typeInfo, ULONG number ); - -private: - - ULONG getRvaByName(const std::string &symName); - pyDia::GlobalScopePtr& getDia() { if (!m_dia) m_dia = pyDia::GlobalScope::loadPdb( getPdbName() ); return m_dia; } +private: + + ULONG getRvaByName(const std::string &symName); + BaseTypeVariant getValue() { return BaseTypeVariant(m_base); } diff --git a/pykd/pykd_2008.vcproj b/pykd/pykd_2008.vcproj index 4f8e900..41a976e 100644 --- a/pykd/pykd_2008.vcproj +++ b/pykd/pykd_2008.vcproj @@ -409,6 +409,10 @@ RelativePath=".\inteventhandler.cpp" > + + diff --git a/pykd/typedvar.cpp b/pykd/typedvar.cpp index 841a9a5..ddf717e 100644 --- a/pykd/typedvar.cpp +++ b/pykd/typedvar.cpp @@ -57,7 +57,8 @@ TypedVarPtr TypedVar::getTypedVar( IDebugClient4 *client, const TypeInfoPtr& t TypedVar::TypedVar ( IDebugClient4 *client, const TypeInfoPtr& typeInfo, ULONG64 offset ) : DbgObject( client ), m_typeInfo( typeInfo ), - m_offset( offset ) + m_offset( offset ), + m_dataKind( DataIsGlobal ) { m_size = m_typeInfo->getSize(); } diff --git a/pykd/typedvar.h b/pykd/typedvar.h index 57b9033..6abd28f 100644 --- a/pykd/typedvar.h +++ b/pykd/typedvar.h @@ -61,6 +61,14 @@ public: return getElementByIndex( boost::apply_visitor( VariantToULong(), tv->getValue() ) ); } + ULONG getDataKind() const { + return m_dataKind; + } + + void setDataKind(ULONG dataKind) { + m_dataKind = dataKind; + } + protected: TypedVar ( IDebugClient4 *client, const TypeInfoPtr& typeInfo, ULONG64 offset ); @@ -74,6 +82,8 @@ protected: ULONG64 m_offset; ULONG m_size; + + ULONG m_dataKind; }; /////////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/typeinfo.cpp b/pykd/typeinfo.cpp index c0e07b9..aafd551 100644 --- a/pykd/typeinfo.cpp +++ b/pykd/typeinfo.cpp @@ -65,7 +65,7 @@ BaseTypeVariant TypeInfo::getValue() 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 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; diff --git a/test/scripts/clienttest.py b/test/scripts/clienttest.py index 29cfdee..fdcf4ac 100644 --- a/test/scripts/clienttest.py +++ b/test/scripts/clienttest.py @@ -21,33 +21,9 @@ class DbgClientTest( unittest.TestCase ): """Size of memory page must be >= 4kb""" 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 ): self.assertFalse( pykd.isDumpAnalyzing() ) - + def testExecutionStatus( self ): self.assertEqual( pykd.DEBUG_STATUS_BREAK, pykd.getExecutionStatus() ) pykd.setExecutionStatus( pykd.DEBUG_STATUS_GO ) diff --git a/test/scripts/localstest.py b/test/scripts/localstest.py new file mode 100644 index 0000000..e71b78d --- /dev/null +++ b/test/scripts/localstest.py @@ -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"] ) diff --git a/test/scripts/pykdtest.py b/test/scripts/pykdtest.py index b8ce67b..35adcd6 100644 --- a/test/scripts/pykdtest.py +++ b/test/scripts/pykdtest.py @@ -24,6 +24,8 @@ import memtest import intbase import synsymtest import ehloadtest +import thrdctxtest +import localstest def getTestSuite( singleName = "" ): if singleName == "": @@ -39,7 +41,9 @@ def getTestSuite( singleName = "" ): unittest.TestLoader().loadTestsFromTestCase( memtest.MemoryTest ), unittest.TestLoader().loadTestsFromTestCase( intbase.IntBaseTest ), 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: return unittest.TestSuite( unittest.TestLoader().loadTestsFromName( singleName ) ) @@ -48,21 +52,21 @@ def getTestSuite( singleName = "" ): if __name__ == "__main__": target.appPath = sys.argv[1] - + target.moduleName = os.path.splitext(os.path.basename(target.appPath))[0] print "\nTest module: %s" % target.appPath - + pykd.startProcess( target.appPath ) target.module = pykd.loadModule( target.moduleName ) target.module.reload(); - + pykd.go() - + suite = getTestSuite() #suite = getTestSuite( "typedvar.TypedVarTest.testBitField" ) #suite = getTestSuite( "typeinfo.TypeInfoTest.testBitField" ) - + unittest.TextTestRunner(stream=sys.stdout, verbosity=2).run( suite ) - #a = raw_input("\npress return\n") + #raw_input("\npress return\n") diff --git a/test/scripts/thrdctxtest.py b/test/scripts/thrdctxtest.py new file mode 100644 index 0000000..158b454 --- /dev/null +++ b/test/scripts/thrdctxtest.py @@ -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 ) diff --git a/test/scripts/typedvar.py b/test/scripts/typedvar.py index ba79301..0331211 100644 --- a/test/scripts/typedvar.py +++ b/test/scripts/typedvar.py @@ -21,7 +21,8 @@ class TypedVarTest( unittest.TestCase ): self.assertEqual( -2, target.module.typedVar( "g_shortValue" ) ) self.assertEqual( -4, target.module.typedVar( "g_longValue" ) ) 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 ): tv = target.module.typedVar( "structTest", target.module.g_structTest ) diff --git a/test/targetapp/targetapp.cpp b/test/targetapp/targetapp.cpp index 0fe1acf..80fd968 100644 --- a/test/targetapp/targetapp.cpp +++ b/test/targetapp/targetapp.cpp @@ -261,17 +261,22 @@ void FuncWithName1(int a) BOOL CALLBACK EnumWindowsProc( HWND hWindow, - LPARAM lParam + const LPARAM lParam ) { DWORD dwProccessId = 0; if (hWindow) std::cout << lParam; + + if (hWindow) { + static ULONGLONG staticVar = 0; 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 if ( !_tcsicmp(argv[1], _T("-testLoadUnload")) ) return doLoadUnload(); + + if ( !_tcsicmp(argv[1], _T("-testEnumWindows")) ) + return ::EnumWindows(&EnumWindowsProc, 6); } __debugbreak(); @@ -316,8 +324,6 @@ int _tmain(int argc, _TCHAR* argv[]) __debugbreak(); FuncWithName0(); FuncWithName1(2); - - EnumWindows(&::EnumWindowsProc, 6); } catch(std::exception & ex) { diff --git a/test/targetapp/targetapp.vcproj b/test/targetapp/targetapp.vcproj index 01b805a..d726ee9 100644 --- a/test/targetapp/targetapp.vcproj +++ b/test/targetapp/targetapp.vcproj @@ -1,7 +1,7 @@ + + @@ -452,6 +456,10 @@ RelativePath="..\scripts\target.py" > + +