diff --git a/pykd/dbgclient.cpp b/pykd/dbgclient.cpp index fad59df..67193a9 100644 --- a/pykd/dbgclient.cpp +++ b/pykd/dbgclient.cpp @@ -333,6 +333,29 @@ std::string getPdbFile( ULONG64 moduleBase ) /////////////////////////////////////////////////////////////////////////////////// +std::string DebugClient::dbgSymPath() +{ + HRESULT hres; + std::string pathStr; + + ULONG size; + m_symbols->GetSymbolPath( NULL, 0, &size ); + + std::vector path(size); + hres = m_symbols->GetSymbolPath( &path[0], size, NULL ); + if ( FAILED( hres ) ) + throw DbgException( "IDebugSymbols::GetSymbolPath failed" ); + + return std::string(&path[0],size); +} + +std::string dbgSymPath() +{ + return g_dbgClient->dbgSymPath(); +} + +/////////////////////////////////////////////////////////////////////////////////// + void DebugClient::setExecutionStatus( ULONG status ) { HRESULT hres; diff --git a/pykd/dbgclient.h b/pykd/dbgclient.h index c6f9b52..37dbdfc 100644 --- a/pykd/dbgclient.h +++ b/pykd/dbgclient.h @@ -103,6 +103,8 @@ public: std::string getProcessorType(); + std::string dbgSymPath(); + python::list getThreadList(); template @@ -194,8 +196,14 @@ public: python::object getRegByIndex( ULONG index ); + void setCurrentProcess( ULONG64 addr ); + void setExecutionStatus( ULONG status ); + void setImplicitThread( ULONG64 threadAddr ); + + void setProcessorMode( const std::wstring &mode ); + void terminateProcess(); void waitForEvent(); @@ -298,6 +306,8 @@ ULONG64 getOffset( const std::wstring symbolname ); std::string getPdbFile( ULONG64 moduleBase ); +std::string dbgSymPath(); + bool is64bitSystem(); bool isKernelDebugging(); diff --git a/pykd/dbgext.cpp b/pykd/dbgext.cpp index a3dfaa8..6cd870a 100644 --- a/pykd/dbgext.cpp +++ b/pykd/dbgext.cpp @@ -261,16 +261,24 @@ BOOST_PYTHON_MODULE( pykd ) "Return a CPU regsiter value by the register's name" ) .def( "reg", &DebugClient::getRegByIndex, "Return a CPU regsiter value by the register's value" ) - .def( "setExecutionStatus", &DebugClient::setExecutionStatus, + .def( "setCurrentProcess", &DebugClient::setCurrentProcess, + "Set current process by address" ) + .def( "setExecutionStatus", &DebugClient::setExecutionStatus, "Requests that the debugger engine enter an executable state" ) - .def( "wrmsr", &DebugClient::setMSR, - "Set MSR value" ) + .def( "setImplicitThread", &DebugClient::setImplicitThread, + "Set implicit thread for current process" ) + .def( "setProcessorMode", &DebugClient::setProcessorMode, + "Set current processor mode by string (X86, ARM, IA64 or X64)" ) .def( "step", &DebugClient::changeDebuggerStatus, "Change debugger status to DEBUG_STATUS_STEP_OVER" ) + .def( "symbolsPath", &DebugClient::dbgSymPath, + "Return symbol path" ) .def( "trace", &DebugClient::changeDebuggerStatus, "Change debugger status to DEBUG_STATUS_STEP_INTO" ) .def( "waitForEvent", &DebugClient::waitForEvent, "Wait for events that breaks into the debugger" ) + .def( "wrmsr", &DebugClient::setMSR, + "Set MSR value" ) .def( "addSynSymbol", &DebugClient::addSyntheticSymbol, "Add new synthetic symbol for virtual address" ) .def( "delAllSynSymbols", &DebugClient::delAllSyntheticSymbols, @@ -420,15 +428,23 @@ BOOST_PYTHON_MODULE( pykd ) "Return a CPU regsiter value by the register's name" ); python::def( "reg", &getRegByIndex, "Return a CPU regsiter value by the register's value" ); - python::def( "setExecutionStatus", &pykd::setExecutionStatus, + python::def( "setExecutionStatus", &setExecutionStatus, "Requests that the debugger engine enter an executable state" ); - python::def( "step", &pykd::changeDebuggerStatus, + python::def( "setCurrentProcess", &setCurrentProcess, + "Set current process by address" ); + python::def( "setImplicitThread", &setImplicitThread, + "Set implicit thread for current process" ); + python::def( "setProcessorMode", &setProcessorMode, + "Set current processor mode by string (X86, ARM, IA64 or X64)" ); + python::def( "step", &changeDebuggerStatus, "Change debugger status to DEBUG_STATUS_STEP_OVER" ); + python::def( "symbolsPath", &dbgSymPath, + "Return symbol path" ); python::def( "wrmsr", &setMSR, "Set MSR value" ); - python::def( "trace", &pykd::changeDebuggerStatus, + python::def( "trace", &changeDebuggerStatus, "Change debugger status to DEBUG_STATUS_STEP_INTO" ); - python::def( "waitForEvent", &pykd::waitForEvent, + python::def( "waitForEvent", &waitForEvent, "Wait for events that breaks into the debugger" ); python::class_("typeInfo", "Class representing typeInfo", python::no_init ) @@ -490,6 +506,10 @@ BOOST_PYTHON_MODULE( pykd ) "Return a list of the typedVar class instances. Each item represents an item of the linked list in the target memory" ) .def("typedVarList", &Module::getTypedVarListByType, "Return a list of the typedVar class instances. Each item represents an item of the linked list in the target memory" ) + .def("typedVarArray", &Module::getTypedVarArrayByTypeName, + "Return a list of the typedVar class instances. Each item represents an item of the counted array in the target memory" ) + .def("typedVarArray", &Module::getTypedVarArrayByType, + "Return a list of the typedVar class instances. Each item represents an item of the counted array in the target memory" ) .def("containingRecord", &Module::containingRecordByName, "Return instance of the typedVar class. It's value are loaded from the target memory." "The start address is calculated by the same method as the standard macro CONTAINING_RECORD does" ) diff --git a/pykd/module.cpp b/pykd/module.cpp index 915c44a..f033e4a 100644 --- a/pykd/module.cpp +++ b/pykd/module.cpp @@ -277,5 +277,26 @@ python::list Module::getTypedVarListByType( ULONG64 listHeadAddress, const TypeI /////////////////////////////////////////////////////////////////////////////////// +python::list Module::getTypedVarArrayByTypeName( ULONG64 addr, const std::string &typeName, ULONG number ) +{ + return getTypedVarArrayByType( addr, getTypeByName( typeName ), number ); +} + +/////////////////////////////////////////////////////////////////////////////////// + +python::list Module::getTypedVarArrayByType( ULONG64 address, const TypeInfoPtr &typeInfo, ULONG number ) +{ + address = addr64(address); + + python::list lst; + + for( ULONG i = 0; i < number; ++i ) + lst.append( getTypedVarByType( typeInfo, address + i * typeInfo->getSize() ) ); + + return lst; +} + +/////////////////////////////////////////////////////////////////////////////////// + }; // end of namespace pykd diff --git a/pykd/module.h b/pykd/module.h index ea4fbe5..6ac2dd3 100644 --- a/pykd/module.h +++ b/pykd/module.h @@ -76,6 +76,11 @@ public: python::list getTypedVarListByType( ULONG64 listHeadAddres, const TypeInfoPtr &typeInfo, const std::string &listEntryName ); + python::list getTypedVarArrayByTypeName( ULONG64 addr, const std::string &typeName, ULONG number ); + + python::list getTypedVarArrayByType( ULONG64 addr, const TypeInfoPtr &typeInfo, ULONG number ); + + private: ULONG getRvaByName(const std::string &symName); diff --git a/pykd/process.cpp b/pykd/process.cpp index e65e5cf..1f58d5e 100644 --- a/pykd/process.cpp +++ b/pykd/process.cpp @@ -188,4 +188,66 @@ python::list getThreadList() /////////////////////////////////////////////////////////////////////////////////// +void DebugClient::setCurrentProcess( ULONG64 processAddr ) +{ + HRESULT hres; + + processAddr = addr64(processAddr); + hres = m_system->SetImplicitProcessDataOffset( processAddr ); + if ( FAILED( hres ) ) + throw DbgException( "IDebugSystemObjects2::SetImplicitProcessDataOffset failed" ); +} + +void setCurrentProcess( ULONG64 processAddr ) +{ + g_dbgClient->setCurrentProcess( processAddr ); +} + +/////////////////////////////////////////////////////////////////////////////////// + +void DebugClient::setImplicitThread( ULONG64 threadAddr ) +{ + HRESULT hres; + + threadAddr = addr64(threadAddr); + hres = m_system->SetImplicitThreadDataOffset( threadAddr ); + if ( FAILED( hres ) ) + throw DbgException( "IDebugSystemObjects2::SetImplicitThreadDataOffset failed" ); +} + +void setImplicitThread( ULONG64 threadAddr ) +{ + g_dbgClient->setImplicitThread( threadAddr ); +} + +/////////////////////////////////////////////////////////////////////////////////// + +void DebugClient::setProcessorMode( const std::wstring &mode ) +{ + HRESULT hres; + ULONG processorMode; + + if ( mode == L"X86" ) + processorMode = IMAGE_FILE_MACHINE_I386; + else if ( mode == L"ARM" ) + processorMode = IMAGE_FILE_MACHINE_ARM; + else if ( mode == L"IA64" ) + processorMode = IMAGE_FILE_MACHINE_IA64; + else if ( mode == L"X64" ) + processorMode = IMAGE_FILE_MACHINE_AMD64; + else + throw DbgException( "Unknown processor type" ); + + hres = m_control->SetEffectiveProcessorType( processorMode ); + if ( FAILED( hres ) ) + throw DbgException( "IDebugControl::SetEffectiveProcessorType failed" ); +} + +void setProcessorMode( const std::wstring &mode ) +{ + g_dbgClient->setProcessorMode( mode ); +} + +/////////////////////////////////////////////////////////////////////////////////// + } \ No newline at end of file diff --git a/pykd/process.h b/pykd/process.h index 8d9fdd6..459a3f7 100644 --- a/pykd/process.h +++ b/pykd/process.h @@ -16,6 +16,12 @@ std::string getProcessorType(); python::list getThreadList(); +void setCurrentProcess( ULONG64 processAddr ); + +void setImplicitThread( ULONG64 threadAddr ); + +void setProcessorMode( const std::wstring &mode ); + /////////////////////////////////////////////////////////////////////////////////// } diff --git a/test/scripts/basetest.py b/test/scripts/basetest.py index ebd75e9..07cfed2 100644 --- a/test/scripts/basetest.py +++ b/test/scripts/basetest.py @@ -71,17 +71,14 @@ class BaseTest( unittest.TestCase ): self.assertTrue( hasattr(pykd, 'ptrWord') ) self.assertTrue( hasattr(pykd, 'rdmsr') ) self.assertTrue( hasattr(pykd, 'reg') ) - self.assertTrue( hasattr(pykd, 'reloadModule') ) self.assertTrue( hasattr(pykd, 'setCurrentProcess') ) self.assertTrue( hasattr(pykd, 'setImplicitThread') ) self.assertTrue( hasattr(pykd, 'setProcessorMode') ) - self.assertTrue( hasattr(pykd, 'sizeof') ) + # self.assertTrue( hasattr(pykd, 'sizeof') ) self.assertTrue( hasattr(pykd, 'startProcess') ) self.assertTrue( hasattr(pykd, 'step') ) self.assertTrue( hasattr(pykd, 'symbolsPath') ) self.assertTrue( hasattr(pykd, 'trace') ) - self.assertTrue( hasattr(pykd, 'typedVarArray') ) - self.assertTrue( hasattr(pykd, 'typedVarList') ) self.assertTrue( hasattr(pykd, 'wrmsr') ) @@ -108,6 +105,9 @@ class BaseTest( unittest.TestCase ): self.assertFalse( hasattr(pykd, 'findModule') ) self.assertFalse( hasattr(pykd, 'loadLinkedList') ) self.assertFalse( hasattr(pykd, 'loadPtrs') ) + self.assertFalse( hasattr(pykd, 'reloadModule') ) + self.assertFalse( hasattr(pykd, 'typedVarArray') ) + self.assertFalse( hasattr(pykd, 'typedVarList') ) self.assertFalse( hasattr(pykd, 'windbgIn') ) self.assertFalse( hasattr(pykd, 'windbgOut') ) diff --git a/test/scripts/clienttest.py b/test/scripts/clienttest.py index fb80d44..2d4c501 100644 --- a/test/scripts/clienttest.py +++ b/test/scripts/clienttest.py @@ -31,3 +31,6 @@ class DbgClientTest( unittest.TestCase ): def testThreadList( self ): self.assertNotEqual( 0, len(pykd.getThreadList()) ) + + def testSymbolsPath( self ): + self.assertNotEqual( '', pykd.symbolsPath() ) diff --git a/test/scripts/typedvar.py b/test/scripts/typedvar.py index 0fc6065..bb047a7 100644 --- a/test/scripts/typedvar.py +++ b/test/scripts/typedvar.py @@ -73,7 +73,7 @@ class TypedVarTest( unittest.TestCase ): tv = target.module.typedVar("g_structWithBits") self.assertEqual( 4, tv.m_bit0_4 ) - def testTypeVarList(self): + def testTypedVarList(self): tvl = target.module.typedVarList( target.module.g_listHead, "listStruct", "listEntry" ) self.assertEqual( 3, len( tvl ) ) self.assertEqual( [1,2,3], [ tv.num for tv in tvl ] ) @@ -88,5 +88,15 @@ class TypedVarTest( unittest.TestCase ): tvl = target.module.typedVarList( target.module.g_listHead1, target.module.type("listStruct1"), "next" ) self.assertEqual( 3, len( tvl ) ) - self.assertEqual( [100,200,300], [ tv.num for tv in tvl ] ) - \ No newline at end of file + self.assertEqual( [100,200,300], [ tv.num for tv in tvl ] ) + + def testTypedVarArray(self): + tvl = target.module.typedVarArray( target.module.g_testArray, "structTest", 2 ) + self.assertEqual( 2, len( tvl ) ) + self.assertEqual( 500, tvl[0].m_field1 ) + self.assertEqual( False, tvl[1].m_field2 ) + + tvl = target.module.typedVarArray( target.module.g_testArray, target.module.type("structTest"), 2 ) + self.assertEqual( 2, len( tvl ) ) + self.assertEqual( 1, tvl[0].m_field3 ) + self.assertEqual( 0, tvl[1].m_field4 )