From dd5ebf105ada4af65722cd51b98ee2c18a4b06f1 Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Fri, 21 Oct 2011 07:13:31 +0000 Subject: [PATCH] [0.1.x] added : MemoryException class [0.1.x] added : loadChars [0.1.x] added : loadWChars git-svn-id: https://pykd.svn.codeplex.com/svn@70662 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/dbgclient.h | 34 +++++++++---- pykd/dbgexcept.cpp | 14 +++++- pykd/dbgexcept.h | 53 +++++++++++++++++++++ pykd/dbgext.cpp | 35 ++++++++++++-- pykd/dbgmem.cpp | 84 +++++++++++++++++++++++++++++++++ pykd/dbgmem.h | 17 +++++++ pykd/dbgobj.h | 6 +++ test/scripts/pykdtest.py | 4 +- test/targetapp/targetapp.cpp | 6 +++ test/targetapp/targetapp.vcproj | 4 ++ 10 files changed, 239 insertions(+), 18 deletions(-) diff --git a/pykd/dbgclient.h b/pykd/dbgclient.h index ae5f5ac..3782425 100644 --- a/pykd/dbgclient.h +++ b/pykd/dbgclient.h @@ -41,9 +41,17 @@ public: public: + ULONG64 addr64( ULONG64 addr ); + + DbgOut dout() { + return DbgOut( m_client ); + } + + DbgIn din() { + return DbgIn( m_client ); + } + std::string dbgCommand( const std::wstring &command ); - - void loadDump( const std::wstring &fileName ); void startProcess( const std::wstring &processName ); @@ -64,6 +72,8 @@ public: bool isDumpAnalyzing(); + void loadDump( const std::wstring &fileName ); + Module loadModule( const std::string &moduleName ) { return Module( m_client, moduleName ); } @@ -76,15 +86,9 @@ public: return DbgExtensionPtr( new DbgExtension( m_client, extPath ) ); } - ULONG64 addr64( ULONG64 addr ); + std::string loadChars( ULONG64 address, ULONG number, bool phyAddr = FALSE ); - DbgOut dout() { - return DbgOut( m_client ); - } - - DbgIn din() { - return DbgIn( m_client ); - } + std::wstring loadWChars( ULONG64 address, ULONG number, bool phyAddr = FALSE ); void dprint( const std::wstring &str, bool dml = false ); @@ -94,10 +98,14 @@ public: void eprintln( const std::wstring &str ); + void readMemory( ULONG64 address, PVOID buffer, ULONG length, bool phyAddr = FALSE ); + void setExecutionStatus( ULONG status ); void waitForEvent(); + void writeMemory( ULONG64 address, PVOID buffer, ULONG length, bool phyAddr = FALSE ); + public: CComPtr& @@ -115,6 +123,12 @@ public: return m_control; } + + PyThreadStateSaver& + getThreadState() { + return m_pyThreadState; + } + private: DebugClient( IDebugClient4 *client ) : DbgObject( client ) {} diff --git a/pykd/dbgexcept.cpp b/pykd/dbgexcept.cpp index 63c1818..c50ca12 100644 --- a/pykd/dbgexcept.cpp +++ b/pykd/dbgexcept.cpp @@ -1,24 +1,34 @@ #include "stdafx.h" #include "dbgexcept.h" -using namespace pykd; +namespace pykd { //////////////////////////////////////////////////////////////////////////////// PyObject *DbgException::baseExceptTypeObject = NULL; +PyObject *MemoryException::memoryExceptionTypeObject = NULL; ///////////////////////////////////////////////////////////////////////////////// void DbgException::exceptionTranslate( const DbgException &e ) { - boost::python::object pyExcept(e); + python::object pyExcept(e); PyErr_SetObject( baseExceptTypeObject, pyExcept.ptr() ); } ///////////////////////////////////////////////////////////////////////////////// +void MemoryException::exceptionTranslate( const MemoryException &e ) +{ + python::object pyExcept(e); + PyErr_SetObject( memoryExceptionTypeObject, pyExcept.ptr() ); +} + +///////////////////////////////////////////////////////////////////////////////// + +}; // end namespace pykd diff --git a/pykd/dbgexcept.h b/pykd/dbgexcept.h index 02ce927..fd7c8e8 100644 --- a/pykd/dbgexcept.h +++ b/pykd/dbgexcept.h @@ -35,6 +35,59 @@ private: static PyObject *baseExceptTypeObject; }; +/////////////////////////////////////////////////////////////////////////////////// + +class MemoryException : public DbgException +{ +public: + + MemoryException( ULONG64 targetAddr, bool phyAddr = false ) : + m_targetAddress( targetAddr ), + DbgException( MemoryException::DescMaker( targetAddr, phyAddr ).desc() ) + {} + + static + void + exceptionTranslate( const MemoryException &e ); + + static void setTypeObject(PyObject *p) { + memoryExceptionTypeObject = p; + } + + ULONG64 + getAddress() const { + return m_targetAddress; + } + +private: + + ULONG64 m_targetAddress; + + static PyObject *memoryExceptionTypeObject; + + class DescMaker { + public: + DescMaker( ULONG64 addr, bool phyAddr ) + { + std::stringstream sstr; + if ( phyAddr ) + sstr << "Memory exception at 0x" << std::hex << addr << " target physical address"; + else + sstr << "Memory exception at 0x" << std::hex << addr << " target virtual address"; + m_desc = sstr.str(); + } + + const std::string& + desc() const { + return m_desc; + } + + private: + std::string m_desc; + }; +}; + + /////////////////////////////////////////////////////////////////////////////////// }; // namespace pykd diff --git a/pykd/dbgext.cpp b/pykd/dbgext.cpp index 8e8b9f3..14d3c1f 100644 --- a/pykd/dbgext.cpp +++ b/pykd/dbgext.cpp @@ -15,6 +15,7 @@ #include "dbgevent.h" #include "typeinfo.h" #include "typedvar.h" +#include "dbgmem.h" using namespace pykd; @@ -51,8 +52,15 @@ static python::dict genDict(const pyDia::Symbol::ValueNameEntry srcValues[], siz //////////////////////////////////////////////////////////////////////////////// -BOOST_PYTHON_FUNCTION_OVERLOADS( dprint_, dprint, 1, 2 ) -BOOST_PYTHON_FUNCTION_OVERLOADS( dprintln_, dprintln, 1, 2 ) +BOOST_PYTHON_FUNCTION_OVERLOADS( dprint_, dprint, 1, 2 ); +BOOST_PYTHON_FUNCTION_OVERLOADS( dprintln_, dprintln, 1, 2 ); + +BOOST_PYTHON_FUNCTION_OVERLOADS( loadChars_, loadChars, 2, 3 ); +BOOST_PYTHON_FUNCTION_OVERLOADS( loadWChars_, loadWChars, 2, 3 ); + +BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS( DebugClient_loadChars, DebugClient::loadChars, 2, 3 ); +BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS( DebugClient_loadWChars, DebugClient::loadWChars, 2, 3 ); + #define DEF_PY_CONST_ULONG(x) \ python::scope().attr(#x) = ULONG(##x) @@ -80,6 +88,10 @@ BOOST_PYTHON_MODULE( pykd ) "Check if it is a dump analyzing ( not living debuggee )" ) .def( "isKernelDebugging", &pykd::DebugClient::isKernelDebugging, "Check if kernel dubugging is running" ) + .def( "loadChars", &pykd::DebugClient::loadChars, DebugClient_loadChars( python::args( "address", "count", "phyAddr" ), + "Load string from target memory" ) ) + .def( "loadWChars", &pykd::DebugClient::loadWChars, DebugClient_loadWChars( python::args( "address", "count", "phyAddr" ), + "Load string from target memory" ) ) .def ( "loadExt", &pykd::DebugClient::loadExtension, "Load a debuger extension" ) .def( "loadModule", &pykd::DebugClient::loadModule, @@ -123,6 +135,10 @@ BOOST_PYTHON_MODULE( pykd ) "Check if it is a dump analyzing ( not living debuggee )" ); python::def( "isKernelDebugging", &pykd::isKernelDebugging, "Check if kernel dubugging is running" ); + python::def( "loadChars", &loadChars, loadChars_( python::args( "address", "count", "phyAddr" ), + "Load string from target memory" ) ); + python::def( "loadWChars", &loadWChars, loadWChars_( python::args( "address", "count", "phyAddr" ), + "Load string from target memory" ) ); python::def( "loadExt", &pykd::loadExtension, "Load a debuger extension" ); python::def( "loadModule", &pykd::loadModule, @@ -205,7 +221,7 @@ BOOST_PYTHON_MODULE( pykd ) python::class_( "eventHandler", "Base class for overriding and handling debug notifications" ) .def( python::init<>() ) - .def( python::init() ) + .def( python::init() ) .def( "onBreakpoint", &pykd::EventHandlerWrap::onBreakpoint, "Triggered breakpoint event. Parameter is dict:\n" "{\"Id\":int, \"BreakType\":int, \"ProcType\":int, \"Flags\":int, \"Offset\":int," @@ -396,7 +412,7 @@ BOOST_PYTHON_MODULE( pykd ) "Get exception description" ) .def( "__str__", &pykd::DbgException::print); pykd::DbgException::setTypeObject( dbgExceptionClass.ptr() ); - boost::python::register_exception_translator( + python::register_exception_translator( &pykd::DbgException::exceptionTranslate ); // DIA exceptions @@ -406,9 +422,18 @@ BOOST_PYTHON_MODULE( pykd ) diaException .def( "hres", &pyDia::Exception::getRes ); pyDia::Exception::setTypeObject( diaException.ptr() ); - boost::python::register_exception_translator( + python::register_exception_translator( &pyDia::Exception::exceptionTranslate ); + // Memory exception + python::class_ > memException( + "MemoryException", "Target memory access exception class", + python::no_init ); + memException.def( "getAddress", &pykd::MemoryException::getAddress, "Return a target address where the exception occurs" ); + pykd::MemoryException::setTypeObject( memException.ptr() ); + python::register_exception_translator( + &pykd::MemoryException::exceptionTranslate ); + DEF_PY_CONST_ULONG( DEBUG_CLASS_UNINITIALIZED ); DEF_PY_CONST_ULONG( DEBUG_CLASS_KERNEL ); DEF_PY_CONST_ULONG( DEBUG_CLASS_USER_WINDOWS ); diff --git a/pykd/dbgmem.cpp b/pykd/dbgmem.cpp index 719791d..ae1c306 100644 --- a/pykd/dbgmem.cpp +++ b/pykd/dbgmem.cpp @@ -42,6 +42,68 @@ addr64( ULONG64 addr) ///////////////////////////////////////////////////////////////////////////////////// +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 ); +} + +///////////////////////////////////////////////////////////////////////////////////// + +std::string DebugClient::loadChars( ULONG64 address, ULONG number, bool phyAddr ) +{ + std::vector buffer(number); + + ULONG bufferSize = sizeof(std::vector::value_type)*buffer.size(); + + if (number) + readMemory( address, &buffer[0], bufferSize, phyAddr ); + + return std::string( buffer.begin(), buffer.end() ); +} + +std::string loadChars( ULONG64 address, ULONG number, bool phyAddr ) +{ + return g_dbgClient->loadChars( address, number, phyAddr ); +} + +///////////////////////////////////////////////////////////////////////////////////// + +std::wstring DebugClient::loadWChars( ULONG64 address, ULONG number, bool phyAddr ) +{ + std::vector buffer(number); + + ULONG bufferSize = sizeof(std::vector::value_type)*buffer.size(); + + if (number) + readMemory( address, &buffer[0], bufferSize, phyAddr ); + + return std::wstring( buffer.begin(), buffer.end() ); +} + +std::wstring loadWChars( ULONG64 address, ULONG number, bool phyAddr ) +{ + return g_dbgClient->loadWChars( address, number, phyAddr ); +} + +///////////////////////////////////////////////////////////////////////////////////// + }; // end of pykd @@ -49,6 +111,28 @@ addr64( ULONG64 addr) + + + + + + + + + + + + + + + + + + + + + + //#include // //#include "dbgext.h" diff --git a/pykd/dbgmem.h b/pykd/dbgmem.h index 5927204..96d610b 100644 --- a/pykd/dbgmem.h +++ b/pykd/dbgmem.h @@ -9,6 +9,20 @@ addr64( ULONG64 addr ); /////////////////////////////////////////////////////////////////////////////////// +void +readMemory( ULONG64 address, PVOID buffer, ULONG length, BOOLEAN phyAddr = FALSE ); + +void +writeMemory( ULONG64 address, PVOID buffer, ULONG length, BOOLEAN phyAddr = FALSE ); + +/////////////////////////////////////////////////////////////////////////////////// + +std::string loadChars( ULONG64 address, ULONG number, bool phyAddr = FALSE ); + +std::wstring loadWChars( ULONG64 address, ULONG number, bool phyAddr = FALSE ); + +/////////////////////////////////////////////////////////////////////////////////// + }; @@ -16,6 +30,9 @@ addr64( ULONG64 addr ); + + + //#include // /////////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/dbgobj.h b/pykd/dbgobj.h index f8e1dc4..c6ee9e2 100644 --- a/pykd/dbgobj.h +++ b/pykd/dbgobj.h @@ -31,6 +31,10 @@ protected: hres = client->QueryInterface( __uuidof(IDebugAdvanced2), (void**)&m_advanced ); if ( FAILED( hres ) ) throw DbgException("QueryInterface IDebugAdvanced2 failed"); + + hres = client->QueryInterface( __uuidof(IDebugDataSpaces), (void**)&m_dataSpaces ); + if ( FAILED( hres ) ) + throw DbgException("QueryInterface IDebugDataSpaces failed"); } virtual ~DbgObject() {}; @@ -40,6 +44,8 @@ protected: CComPtr m_control; CComPtr m_symbols; CComPtr m_advanced; + CComPtr m_dataSpaces; + }; diff --git a/test/scripts/pykdtest.py b/test/scripts/pykdtest.py index 08ffa24..ef0f5f2 100644 --- a/test/scripts/pykdtest.py +++ b/test/scripts/pykdtest.py @@ -20,6 +20,7 @@ import dbgcmd import clienttest import eventtest import typedvar +import memtest def getTestSuite( singleName = "" ): if singleName == "": @@ -31,7 +32,8 @@ def getTestSuite( singleName = "" ): unittest.TestLoader().loadTestsFromTestCase( typedvar.TypedVarTest ), unittest.TestLoader().loadTestsFromTestCase( dbgcmd.DbgcmdTest ), unittest.TestLoader().loadTestsFromTestCase( clienttest.DbgClientTest ), - unittest.TestLoader().loadTestsFromTestCase( eventtest.EventTest ) + unittest.TestLoader().loadTestsFromTestCase( eventtest.EventTest ), + unittest.TestLoader().loadTestsFromTestCase( memtest.MemoryTest ) ] ) else: return unittest.TestSuite( unittest.TestLoader().loadTestsFromName( singleName ) ) diff --git a/test/targetapp/targetapp.cpp b/test/targetapp/targetapp.cpp index b0bd603..8cb9f82 100644 --- a/test/targetapp/targetapp.cpp +++ b/test/targetapp/targetapp.cpp @@ -53,6 +53,9 @@ structTest g_testArray[2] = { { 0, 500, true, 1 }, { 2, 1500, false, 1 } }; structTest *g_structTestPtr = &g_structTest; structTest **g_structTestPtrPtr = &g_structTestPtr; +char helloStr[] = "Hello"; +wchar_t helloWStr[] = L"Hello"; + class classChild : public classBase { public: int m_childField; @@ -87,6 +90,9 @@ void FuncWithName0() std::cout << g_testArray[1].m_field3; std::cout << g_structTestPtr->m_field3; std::cout << (*g_structTestPtrPtr)->m_field3; + + std::cout << helloStr; + std::wcout << helloWStr; } void FuncWithName1(int a) diff --git a/test/targetapp/targetapp.vcproj b/test/targetapp/targetapp.vcproj index c15aa01..8a932f0 100644 --- a/test/targetapp/targetapp.vcproj +++ b/test/targetapp/targetapp.vcproj @@ -420,6 +420,10 @@ RelativePath="..\scripts\eventtest.py" > + +