diff --git a/pykd/dbgclient.h b/pykd/dbgclient.h index 05dbeda..bed696d 100644 --- a/pykd/dbgclient.h +++ b/pykd/dbgclient.h @@ -101,6 +101,8 @@ public: std::string getProcessorType(); + python::list getThreadList(); + template void changeDebuggerStatus(); @@ -110,6 +112,8 @@ public: bool isDumpAnalyzing(); + bool isVaValid( ULONG64 addr ); + void loadDump( const std::wstring &fileName ); Module loadModuleByName( const std::string &moduleName ) { diff --git a/pykd/dbgext.cpp b/pykd/dbgext.cpp index 9c82f71..d646326 100644 --- a/pykd/dbgext.cpp +++ b/pykd/dbgext.cpp @@ -171,14 +171,18 @@ BOOST_PYTHON_MODULE( pykd ) "Return current processor mode as string: X86, ARM, IA64 or X64" ) .def( "getProcessorType", &DebugClient::getProcessorType, "Return type of physical processor: X86, ARM, IA64 or X64" ) + .def( "getThreadList", &DebugClient::getThreadList, + "Return list of threads (each item is numeric identifier of thread)" ) .def( "go", &DebugClient::changeDebuggerStatus, "Change debugger status to DEBUG_STATUS_GO" ) .def( "is64bitSystem", &DebugClient::is64bitSystem, "Check if target system has 64 address space" ) - .def( "isDumpAnalyzing", &pykd::DebugClient::isDumpAnalyzing, + .def( "isDumpAnalyzing", &DebugClient::isDumpAnalyzing, "Check if it is a dump analyzing ( not living debuggee )" ) - .def( "isKernelDebugging", &pykd::DebugClient::isKernelDebugging, + .def( "isKernelDebugging", &DebugClient::isKernelDebugging, "Check if kernel dubugging is running" ) + .def( "isValid", &DebugClient::isVaValid, + "Check if the virtual address is valid" ) .def( "loadBytes", &DebugClient::loadBytes, DebugClient_loadBytes( python::args( "offset", "count", "phyAddr" ), "Read the block of the target's memory and return it as list of unsigned bytes" ) ) .def( "loadWords", &DebugClient::loadWords, DebugClient_loadWords( python::args( "offset", "count", "phyAddr" ), @@ -302,6 +306,8 @@ BOOST_PYTHON_MODULE( pykd ) "Return current processor mode as string: X86, ARM, IA64 or X64" ); python::def( "getProcessorType", &getProcessorType, "Return type of physical processor: X86, ARM, IA64 or X64" ); + python::def( "getThreadList", &getThreadList, + "Return list of threads (each item is numeric identifier of thread)" ); python::def( "is64bitSystem", &is64bitSystem, "Check if target system has 64 address space" ); python::def( "isDumpAnalyzing", &isDumpAnalyzing, @@ -310,6 +316,8 @@ BOOST_PYTHON_MODULE( pykd ) "Check if kernel dubugging is running" ); python::def( "isWindbgExt", &WindbgGlobalSession::isInit, "Check if script works in windbg context" ); + python::def( "isValid", &isVaValid, + "Check if the virtual address is valid" ); python::def( "loadBytes", &loadBytes, loadBytes_( python::args( "offset", "count", "phyAddr" ), "Read the block of the target's memory and return it as liat of unsigned bytes" ) ); python::def( "loadWords", &loadWords, loadWords_( python::args( "offset", "count", "phyAddr" ), diff --git a/pykd/dbgmem.cpp b/pykd/dbgmem.cpp index ac4707f..836de29 100644 --- a/pykd/dbgmem.cpp +++ b/pykd/dbgmem.cpp @@ -73,6 +73,33 @@ addr64( ULONG64 addr) ///////////////////////////////////////////////////////////////////////////////////// +bool DebugClient::isVaValid( ULONG64 addr ) +{ + HRESULT hres; + ULONG offsetInfo; + + hres = + m_dataSpaces->GetOffsetInformation( + DEBUG_DATA_SPACE_VIRTUAL, + DEBUG_OFFSINFO_VIRTUAL_SOURCE, + addr, + &offsetInfo, + sizeof( offsetInfo ), + NULL ); + + if ( FAILED( hres ) ) + throw DbgException( "IDebugDataSpace4::GetOffsetInformation failed" ); + + return offsetInfo != DEBUG_VSOURCE_INVALID; +} + +bool isVaValid( ULONG64 addr ) +{ + return g_dbgClient->isVaValid( addr ); +} + +///////////////////////////////////////////////////////////////////////////////////// + void readMemory( IDebugDataSpaces4* dbgDataSpace, ULONG64 address, PVOID buffer, ULONG length, bool phyAddr = FALSE ) { @@ -91,51 +118,8 @@ readMemory( IDebugDataSpaces4* dbgDataSpace, ULONG64 address, PVOID buffer, ULO throw MemoryException( address, phyAddr ); } -//void DebugClient::readMemory( ULONG64 address, PVOID buffer, ULONG length, bool phyAddr ) -//{ -// HRESULT hres; -// -// if ( phyAddr == false ) -// { -// hres = m_dataSpaces->ReadVirtual( address, buffer, length, NULL ); -// } -// else -// { -// hres = m_dataSpaces->ReadPhysical( address, buffer, length, NULL ); -// } -// -// if ( FAILED( hres ) ) -// throw MemoryException( address, phyAddr ); -//} -// -//void readMemory( ULONG64 address, PVOID buffer, ULONG length, bool phyAddr ) -//{ -// return g_dbgClient->readMemory( address, buffer, length, phyAddr ); -//} - ///////////////////////////////////////////////////////////////////////////////////// -//bool DebugClient::compareMemory( ULONG64 addr1, ULONG64 addr2, ULONG length, bool phyAddr ) -//{ -// bool result = false; -// -// addr1 = addr64( addr1 ); -// addr2 = addr64( addr2 ); -// -// std::vector m1(length); -// std::vector m2(length); -// -// readMemory( addr1, &m1[0], length, phyAddr ); -// readMemory( addr2, &m2[0], length, phyAddr ); -// -// return std::equal( m1.begin(), m1.end(), m2.begin() ); -//} -// -//bool compareMemory( ULONG64 addr1, ULONG64 addr2, ULONG length, bool phyAddr ) -//{ -// return g_dbgClient->compareMemory( addr1, addr2, length, phyAddr ); -//} - bool compareMemoryRange( IDebugDataSpaces4* dbgDataSpace, ULONG64 addr1, ULONG64 addr2, ULONG length, bool phyAddr ) { bool result = false; diff --git a/pykd/dbgmem.h b/pykd/dbgmem.h index 4b53c23..4c6ee63 100644 --- a/pykd/dbgmem.h +++ b/pykd/dbgmem.h @@ -9,6 +9,9 @@ namespace pykd { ULONG64 addr64( ULONG64 addr ); +bool +isVaValid( ULONG64 addr ); + /////////////////////////////////////////////////////////////////////////////////// void diff --git a/pykd/process.cpp b/pykd/process.cpp index 2efe157..e65e5cf 100644 --- a/pykd/process.cpp +++ b/pykd/process.cpp @@ -138,4 +138,54 @@ std::string getProcessorType() /////////////////////////////////////////////////////////////////////////////////// +python::list DebugClient::getThreadList() +{ + HRESULT hres; + ULONG i; + ULONG oldThreadId = 0; + ULONG threadCount; + + hres = m_system->GetNumberThreads( &threadCount ); + if ( FAILED( hres ) ) + throw DbgException( "IDebugSystemObjects::GetNumberThreads failed" ); + + std::vector threadIds(threadCount); + hres = m_system->GetThreadIdsByIndex( 0, threadCount, &threadIds[0], NULL ); + if ( FAILED( hres ) ) + throw DbgException( "IDebugSystemObjects::GetThreadIdsByIndex failed" ); + + hres = m_system->GetCurrentThreadId( &oldThreadId ); + if ( FAILED( hres ) ) + throw DbgException( "IDebugSystemObjects::GetCurrentThreadId failed" ); + + boost::python::list threadList; + + for ( i = 0; i < threadCount; ++i ) + { + m_system->SetCurrentThreadId( threadIds[i] ); + + ULONG64 threadOffset; + hres = m_system->GetCurrentThreadDataOffset( &threadOffset ); + + if ( FAILED( hres ) ) + { + m_system->SetCurrentThreadId( oldThreadId ); + throw DbgException( "IDebugSystemObjects::GetCurrentThreadDataOffset failed" ); + } + + threadList.append( threadOffset ); + } + + m_system->SetCurrentThreadId( oldThreadId ); + + return threadList; +} + +python::list getThreadList() +{ + return g_dbgClient->getThreadList(); +} + +/////////////////////////////////////////////////////////////////////////////////// + } \ No newline at end of file diff --git a/pykd/process.h b/pykd/process.h index fc4215e..8d9fdd6 100644 --- a/pykd/process.h +++ b/pykd/process.h @@ -14,6 +14,8 @@ std::string getProcessorMode(); std::string getProcessorType(); +python::list getThreadList(); + /////////////////////////////////////////////////////////////////////////////////// } diff --git a/test/scripts/clienttest.py b/test/scripts/clienttest.py index 145fff0..fb80d44 100644 --- a/test/scripts/clienttest.py +++ b/test/scripts/clienttest.py @@ -22,9 +22,12 @@ class DbgClientTest( unittest.TestCase ): pykd.waitForEvent() self.assertEqual( pykd.DEBUG_STATUS_BREAK, pykd.getExecutionStatus() ) - def testPdbFile( self ): - self.assertNotEqual( '', target.module ) - - def testProcessorMode( self ): - self.assertNotEqual( '', pykd.getProcessorMode() ) - self.assertNotEqual( '', pykd.getProcessorType() ) + def testPdbFile( self ): + self.assertNotEqual( '', pykd.getPdbFile( target.module.begin() ) ) + + def testProcessorMode( self ): + self.assertNotEqual( '', pykd.getProcessorMode() ) + self.assertNotEqual( '', pykd.getProcessorType() ) + + def testThreadList( self ): + self.assertNotEqual( 0, len(pykd.getThreadList()) ) diff --git a/test/scripts/memtest.py b/test/scripts/memtest.py index 4251775..1b8821d 100644 --- a/test/scripts/memtest.py +++ b/test/scripts/memtest.py @@ -81,3 +81,9 @@ class MemoryTest( unittest.TestCase ): def testCStr( self ): self.assertEqual( 'Hello', pykd.loadCStr( target.module.helloStr ) ) self.assertEqual( u'Hello', pykd.loadWStr( target.module.helloWStr ) ) + + def testVaValid( self ): + self.assertTrue( pykd.isValid( target.module.begin() ) ) + self.assertFalse( pykd.isValid( 0 ) ) + self.assertFalse( pykd.isValid( 0xDEADBEAF ) ) +