From e8c6ac7b19a2458efb8ce2e0a64240edfec7383e Mon Sep 17 00:00:00 2001 From: "SND\\EreTIk_cp" Date: Fri, 9 Sep 2011 10:53:12 +0000 Subject: [PATCH 01/21] [~] workitem/9499 workaround git-svn-id: https://pykd.svn.codeplex.com/svn@69661 9b283d60-5439-405e-af05-b73fd8c4d996 --- samples/portmsg.py | 81 ++++++++++++++++++++++++++++++++++----------- samples/rpcSrvIf.py | 19 ++++++----- 2 files changed, 72 insertions(+), 28 deletions(-) diff --git a/samples/portmsg.py b/samples/portmsg.py index c1addc8..7f4ce83 100644 --- a/samples/portmsg.py +++ b/samples/portmsg.py @@ -29,11 +29,11 @@ DispFormatsLength = { } -def PrintPortMesage(messageAddr, printFormat="b", use32=False, moduleName="nt"): +def PrintPortMesage(messageAddr, printFormat="b", use32=False): """ Print _PORT_MESSAGE header and dump of message dump - Usage: portmsg messageAddr, printFormat[=b], use32[=False], moduleName[=nt] + Usage: portmsg messageAddr, printFormat[=b], use32[=False] When: messageAddr - address of port message printFormat - string of display format ("d+printFormat"). @@ -42,37 +42,80 @@ def PrintPortMesage(messageAddr, printFormat="b", use32=False, moduleName="nt"): http://msdn.microsoft.com/en-us/library/ff542790(VS.85).aspx use32 - use _PORT_MESSAGE32 (instead of _PORT_MESSAGE) structure (True or False) - moduleName - module name with _PORT_MESSAGE structure in symbols """ - messageTypeName = "_PORT_MESSAGE" - if (use32): - messageTypeName = "_PORT_MESSAGE32" + # WOW64 workaround: !!! workitem/9499 !!!! + dynPtr = typeInfo("", "portmsg *") - messageHeader = typedVar(moduleName, messageTypeName, messageAddr) + + def buildPortMessageType(): + clientIdType = typeInfo("portmsg~_CLIENT_ID") + clientIdType.append(dynPtr, "UniqueProcess") + clientIdType.append(dynPtr, "UniqueThread") + + print clientIdType + + portMsgType = typeInfo("portmsg~_PORT_MESSAGE") + portMsgType.append(ushort_t, "DataLength") + portMsgType.append(ushort_t, "TotalLength") + portMsgType.append(ushort_t, "Type") + portMsgType.append(ushort_t, "DataInfoOffset") + portMsgType.append(clientIdType, "ClientId") + portMsgType.append(ulong_t, "MessageId") + portMsgType.append(ulong_t, "CallbackId") + return portMsgType + + def buildPortMessage32Type(): + + clientIdType = typeInfo("portmsg~_CLIENT_ID32") + clientIdType.append(ulong_t, "UniqueProcess") + clientIdType.append(ulong_t, "UniqueThread") + + portMsgType = typeInfo("portmsg~_PORT_MESSAGE32", 4) + portMsgType.append(ushort_t, "DataLength") + portMsgType.append(ushort_t, "TotalLength") + portMsgType.append(ushort_t, "Type") + portMsgType.append(ushort_t, "DataInfoOffset") + portMsgType.append(clientIdType, "ClientId") + portMsgType.append(ulong_t, "MessageId") + portMsgType.append(ulong_t, "CallbackId") + return portMsgType + + + if (use32): + messageTypeName = buildPortMessage32Type() + else: + messageTypeName = buildPortMessageType() + + messageHeader = typedVar(messageTypeName, messageAddr) if (None == messageHeader): dprintln("ERROR: Getting (" + moduleName + "!" + messageTypeName + " *)(0x%x) failed" % messageAddr ) return - dprintln( "Data length : %3d (0x%02x)" % (messageHeader.u1.s1.DataLength, messageHeader.u1.s1.DataLength) ) - dprintln( "Total length : %3d (0x%02x)" % (messageHeader.u1.s1.TotalLength, messageHeader.u1.s1.TotalLength) ) - calcHeaderLen = messageHeader.u1.s1.TotalLength - messageHeader.u1.s1.DataLength - headerLen = sizeof(moduleName, messageTypeName) + dprintln( "Data length : %3d (0x%02x)" % (messageHeader.DataLength, messageHeader.DataLength) ) + dprintln( "Total length : %3d (0x%02x)" % (messageHeader.TotalLength, messageHeader.TotalLength) ) + calcHeaderLen = messageHeader.TotalLength - messageHeader.DataLength + headerLen = messageTypeName.size() if (calcHeaderLen != headerLen): dprintln( "WARRING: calculated size (%2d (0x%02x)) of LPC-header does not match with symbols information (%2d (0x%02x))" % (calcHeaderLen, calcHeaderLen, headerLen, headerLen) ) - if (messageHeader.u2.s2.Type in LpcMessageType): - dprintln( "Message type : " + LpcMessageType[messageHeader.u2.s2.Type] ) + if (messageHeader.Type in LpcMessageType): + dprintln( "Message type : " + LpcMessageType[messageHeader.Type] ) else: - dprintln( "Message type : %3d (0x%x)" % (messageHeader.u2.s2.Type, messageHeader.u2.s2.Type) ) - procFindStr = "%d(0x%x)" % (messageHeader.ClientId.UniqueProcess, messageHeader.ClientId.UniqueProcess, messageHeader.ClientId.UniqueProcess) - dprintln( "Client ID : process= " + procFindStr + ", thread= %d(0x%x)" % (messageHeader.ClientId.UniqueThread, messageHeader.ClientId.UniqueThread), True) - dprintln( "View/Callback : %d (0x%x)" % (messageHeader.ClientViewSize, messageHeader.ClientViewSize) ) + dprintln( "Message type : %3d (0x%x)" % (messageHeader.Type, messageHeader.Type) ) + + procFindStr = "" + if isKernelDebugging(): + procFindStr = "%d(0x%x)" % (messageHeader.ClientId.UniqueProcess, messageHeader.ClientId.UniqueProcess, messageHeader.ClientId.UniqueProcess) + else: + procFindStr = "%d(0x%x)" % (messageHeader.ClientId.UniqueProcess, messageHeader.ClientId.UniqueProcess) + dprintln( "Client ID : process= " + procFindStr + ", thread= %d(0x%x)" % (messageHeader.ClientId.UniqueThread, messageHeader.ClientId.UniqueThread), isKernelDebugging()) + dprintln( "View/Callback : %d (0x%x)" % (messageHeader.CallbackId, messageHeader.CallbackId) ) if (printFormat not in DispFormatsLength): dprintln( "WARRING: Unknown (" + printFormat + ") diplay fromat. Use \"b\"" ) printFormat = "b" dataAddr = messageHeader.getAddress() + headerLen printCommand = "d" + printFormat + " 0x%x" % dataAddr - dataCount = messageHeader.u1.s1.DataLength / DispFormatsLength[printFormat] + dataCount = messageHeader.DataLength / DispFormatsLength[printFormat] printCommand += " L 0x%x " % dataCount dprintln( "Dump of message data:", True ) dprintln( dbgCommand(printCommand) ) @@ -86,7 +129,5 @@ if __name__ == "__main__": PrintPortMesage(expr(sys.argv[1]), sys.argv[2]) elif (4 == argc): PrintPortMesage(expr(sys.argv[1]), sys.argv[2], sys.argv[3] == "True") - elif (5 == argc): - PrintPortMesage(expr(sys.argv[1]), sys.argv[2], sys.argv[3] == "True", sys.argv[4]) else: dprintln(PrintPortMesage.__doc__, True) diff --git a/samples/rpcSrvIf.py b/samples/rpcSrvIf.py index 090f423..223dba1 100644 --- a/samples/rpcSrvIf.py +++ b/samples/rpcSrvIf.py @@ -39,6 +39,9 @@ def rpcSrvIf(ifSpec): return formatGuid(synId.SyntaxGUID) + " " + formatRpcVer(synId.SyntaxVersion) + # WOW64 workaround: !!! workitem/9499 !!!! + dynPtr = typeInfo("", "rpcSrvIf *") + # prepare structures for parsing commGuid = typeInfo("rpcSrvIf~_GUID") commGuid.append(ulong_t, "data1") @@ -60,24 +63,24 @@ def rpcSrvIf(ifSpec): prcDispatchTable = typeInfo("rpcSrvIf~_RPC_DISPATCH_TABLE") prcDispatchTable.append(uint_t, "DispatchTableCount") - prcDispatchTable.append(ptr_t, "DispatchTable") - prcDispatchTable.append(ptr_t, "Reserved") + prcDispatchTable.append(dynPtr, "DispatchTable") + prcDispatchTable.append(dynPtr, "Reserved") # print prcDispatchTable midlServerInfoHeader = typeInfo("rpcSrvIf~_MIDL_SERVER_INFO_hdr") - midlServerInfoHeader.append(ptr_t, "pStubDesc") - midlServerInfoHeader.append(ptr_t, "DispatchTable") + midlServerInfoHeader.append(dynPtr, "pStubDesc") + midlServerInfoHeader.append(dynPtr, "DispatchTable") # print midlServerInfoHeader rpcServerInterface = typeInfo("rpcSrvIf~_RPC_SERVER_INTERFACE") rpcServerInterface.append(uint_t, "Length") rpcServerInterface.append(rpcSintaxIdentifier, "InterfaceId") rpcServerInterface.append(rpcSintaxIdentifier, "TransferSyntax") - rpcServerInterface.append(ptr_t, "DispatchTable") # -> prcDispatchTable + rpcServerInterface.append(dynPtr, "DispatchTable") # -> prcDispatchTable rpcServerInterface.append(uint_t, "RpcProtseqEndpointCount") - rpcServerInterface.append(ptr_t, "RpcProtseqEndpoint") - rpcServerInterface.append(ptr_t, "DefaultManagerEpv") - rpcServerInterface.append(ptr_t, "InterpreterInfo") # -> midlServerInfoHeader + rpcServerInterface.append(dynPtr, "RpcProtseqEndpoint") + rpcServerInterface.append(dynPtr, "DefaultManagerEpv") + rpcServerInterface.append(dynPtr, "InterpreterInfo") # -> midlServerInfoHeader rpcServerInterface.append(uint_t, "Flags") # print rpcServerInterface From 1f20a6f16840924b243458f70656eb2dc1f8c506 Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Fri, 16 Sep 2011 12:31:57 +0000 Subject: [PATCH 02/21] [pykd] added : assembly routine ( sssemble a single processor instruction ) git-svn-id: https://pykd.svn.codeplex.com/svn@69800 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/dbgext.cpp | 2 +- pykd/disasm.cpp | 15 +++++++++++++++ pykd/disasm.h | 3 +++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/pykd/dbgext.cpp b/pykd/dbgext.cpp index 26befd6..7ab0a0d 100644 --- a/pykd/dbgext.cpp +++ b/pykd/dbgext.cpp @@ -221,7 +221,7 @@ BOOST_PYTHON_MODULE( pykd ) "Delete synthetic symbols by virtual address" ); boost::python::def( "delSynSymbolsMask", &delSyntheticSymbolsMask, "Delete synthetic symbols by mask of module and symbol name"); - + boost::python::def( "assembly", &assembly, "Assemble a single processor instruction" ); boost::python::class_( "typeInfo", "Class representing non-primitive type info: structure, union, etc. attributes is a fields of non-primitive type" ) diff --git a/pykd/disasm.cpp b/pykd/disasm.cpp index b2b3b5f..52498fb 100644 --- a/pykd/disasm.cpp +++ b/pykd/disasm.cpp @@ -46,4 +46,19 @@ void disasm::doDisasm() m_disasm = std::string( buffer, disasmSize - 2); } +///////////////////////////////////////////////////////////////////////////////// + +ULONG64 +assembly( ULONG64 offset, const std::string &instr ) +{ + HRESULT hres; + + ULONG64 endOffset = 0; + hres = dbgExt->control->Assemble( offset, instr.c_str(), &endOffset ); + if ( FAILED( hres ) ) + throw DbgException( "IDebugControl::Assemble failed" ); + + return endOffset; +} + ///////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/pykd/disasm.h b/pykd/disasm.h index 95ba472..890e672 100644 --- a/pykd/disasm.h +++ b/pykd/disasm.h @@ -51,4 +51,7 @@ private: std::string m_disasm; }; +ULONG64 +assembly( ULONG64 offset, const std::string &instr ); + ///////////////////////////////////////////////////////////////////////////////// From 549cb797c1e15c242b50626dc1eb62b82157e429 Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Mon, 19 Sep 2011 08:33:46 +0000 Subject: [PATCH 03/21] [pykd] fixed: issue 9518 ( Problem with dbgCommand('!analyze -v') ) git-svn-id: https://pykd.svn.codeplex.com/svn@69869 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/dbgio.cpp | 4 ++-- pykd/pykd.rc | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pykd/dbgio.cpp b/pykd/dbgio.cpp index f49bb38..ca4adac 100644 --- a/pykd/dbgio.cpp +++ b/pykd/dbgio.cpp @@ -14,7 +14,7 @@ void dbgPrint::dprint( const boost::python::object& obj, bool dml ) { std::wstring str = boost::python::extract( obj ); - HRESULT hres = dbgExt->control4->ControlledOutputWide( dml ? DEBUG_OUTCTL_AMBIENT_DML : DEBUG_OUTCTL_AMBIENT_TEXT, DEBUG_OUTPUT_NORMAL, str.c_str() ); + HRESULT hres = dbgExt->control4->ControlledOutputWide( dml ? DEBUG_OUTCTL_AMBIENT_DML : DEBUG_OUTCTL_AMBIENT_TEXT, DEBUG_OUTPUT_NORMAL, L"%ws", str.c_str() ); std::wcout << str; } @@ -26,7 +26,7 @@ void dbgPrint::dprintln( const boost::python::object& obj, bool dml ) std::wstring str = boost::python::extract( obj ); str += L"\r\n"; - dbgExt->control4->ControlledOutputWide( dml ? DEBUG_OUTCTL_AMBIENT_DML : DEBUG_OUTCTL_AMBIENT_TEXT, DEBUG_OUTPUT_NORMAL, str.c_str() ); + dbgExt->control4->ControlledOutputWide( dml ? DEBUG_OUTCTL_AMBIENT_DML : DEBUG_OUTCTL_AMBIENT_TEXT, DEBUG_OUTPUT_NORMAL, L"%ws", str.c_str() ); std::wcout << str; } diff --git a/pykd/pykd.rc b/pykd/pykd.rc index 54ff864..6555650 100644 --- a/pykd/pykd.rc +++ b/pykd/pykd.rc @@ -53,8 +53,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,0,19,0 - PRODUCTVERSION 0,0,19,0 + FILEVERSION 0,0,20,0 + PRODUCTVERSION 0,0,20,0 FILEFLAGSMASK 0x17L #ifdef _DEBUG FILEFLAGS 0x1L @@ -70,11 +70,11 @@ BEGIN BLOCK "041904b0" BEGIN VALUE "FileDescription", "pykd - python extension for windbg" - VALUE "FileVersion", "0, 0, 19, 0" + VALUE "FileVersion", "0, 0, 20, 0" VALUE "InternalName", "pykd" VALUE "OriginalFilename", "pykd.dll" VALUE "ProductName", "pykd - python extension for windbg" - VALUE "ProductVersion", "0, 0, 19, 0" + VALUE "ProductVersion", "0, 0, 20, 0" END END BLOCK "VarFileInfo" From 9603376e2984b20dc48ec270b5e2a2514bbb013d Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Tue, 20 Sep 2011 06:49:43 +0000 Subject: [PATCH 04/21] [pykd] fixed: TLS problem git-svn-id: https://pykd.svn.codeplex.com/svn@69886 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/dbgext.cpp | 2 +- pykd/pyaux.h | 53 +++++++++++++++++++++++++++++++++++-------------- 2 files changed, 39 insertions(+), 16 deletions(-) diff --git a/pykd/dbgext.cpp b/pykd/dbgext.cpp index 7ab0a0d..9a01a05 100644 --- a/pykd/dbgext.cpp +++ b/pykd/dbgext.cpp @@ -39,7 +39,7 @@ DbgExt *dbgExt = NULL; dbgClient g_dbgClient; // контескт исполнения нити питона -__declspec( thread ) PyThreadStatePtr ptrPyThreadState = NULL; +PyThreadStateSaver g_pyThreadState; ////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/pyaux.h b/pykd/pyaux.h index 843dc31..b18cdcb 100644 --- a/pykd/pyaux.h +++ b/pykd/pyaux.h @@ -1,9 +1,41 @@ #pragma once +#include + /////////////////////////////////////////////////////////////////////////////// -typedef PyThreadState *PyThreadStatePtr; -extern __declspec( thread ) PyThreadStatePtr ptrPyThreadState; +class PyThreadStateSaver { + +public: + + PyThreadStateSaver() { + m_index = TlsAlloc(); + } + + ~PyThreadStateSaver() { + TlsFree( m_index ); + } + + void saveState() { + TlsSetValue( m_index, PyEval_SaveThread() ); + } + + void restoreState() { + PyThreadState* state = (PyThreadState*)TlsGetValue( m_index ); + if ( state ) + PyEval_RestoreThread( state ); + } + +private: + + DWORD m_index; +}; + +extern PyThreadStateSaver g_pyThreadState; + + +//typedef PyThreadState *PyThreadStatePtr; +//extern __declspec( thread ) PyThreadStatePtr ptrPyThreadState; // --> call back // { PyThread_StateSave state( winext->getThreadState() ); @@ -19,22 +51,13 @@ class PyThread_StateSave { public: PyThread_StateSave() - : m_bRestored(false) { - if (ptrPyThreadState) - { - PyEval_RestoreThread( ptrPyThreadState ); - m_bRestored = true; - } + g_pyThreadState.restoreState(); } ~PyThread_StateSave() { - if ( m_bRestored ) - ptrPyThreadState = PyEval_SaveThread(); + g_pyThreadState.saveState(); } - -private: - bool m_bRestored; }; // { PyThread_StateRestore state; @@ -46,11 +69,11 @@ class PyThread_StateRestore public: PyThread_StateRestore() { - ptrPyThreadState = PyEval_SaveThread(); + g_pyThreadState.saveState(); } ~PyThread_StateRestore() { - PyEval_RestoreThread( ptrPyThreadState ); + g_pyThreadState.restoreState(); } }; From 26c2b2d11740b29331801bfbdacbe79c42743830 Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Thu, 22 Sep 2011 06:51:22 +0000 Subject: [PATCH 05/21] [pykd] refactored: disasm class git-svn-id: https://pykd.svn.codeplex.com/svn@69944 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/dbgext.cpp | 7 ++++--- pykd/disasm.cpp | 56 ++++++++++++++++++++++++++++++------------------- pykd/disasm.h | 27 ++++++++++++++---------- 3 files changed, 54 insertions(+), 36 deletions(-) diff --git a/pykd/dbgext.cpp b/pykd/dbgext.cpp index 9a01a05..9d6fc40 100644 --- a/pykd/dbgext.cpp +++ b/pykd/dbgext.cpp @@ -221,7 +221,6 @@ BOOST_PYTHON_MODULE( pykd ) "Delete synthetic symbols by virtual address" ); boost::python::def( "delSynSymbolsMask", &delSyntheticSymbolsMask, "Delete synthetic symbols by mask of module and symbol name"); - boost::python::def( "assembly", &assembly, "Assemble a single processor instruction" ); boost::python::class_( "typeInfo", "Class representing non-primitive type info: structure, union, etc. attributes is a fields of non-primitive type" ) @@ -380,12 +379,14 @@ BOOST_PYTHON_MODULE( pykd ) boost::python::class_("disasm", "Class disassemble a processor instructions", boost::python::no_init ) .def( boost::python::init<>( "constructor" ) ) .def( boost::python::init( boost::python::args("offset"), "constructor" ) ) - .def( "next", &disasm::next, "Disassemble next instruction" ) + .def( "disasm", &disasm::disassemble, "Disassemble next instruction" ) + .def( "sasm", &disasm::assembly, "Insert assemblied instuction to current offset" ) .def( "begin", &disasm::begin, "Return begin offset" ) .def( "current", &disasm::current, "Return current offset" ) .def( "length", &disasm::length, "Return current instruction length" ) .def( "instruction", &disasm::instruction, "Returm current disassembled instruction" ) - .def( "ea", &disasm::ea, "Return effective address for last disassembled instruction or 0" ); + .def( "ea", &disasm::ea, "Return effective address for last disassembled instruction or 0" ) + .def( "reset", &disasm::reset, "Reset current offset to begin" ); // исключения diff --git a/pykd/disasm.cpp b/pykd/disasm.cpp index 52498fb..4780633 100644 --- a/pykd/disasm.cpp +++ b/pykd/disasm.cpp @@ -2,7 +2,26 @@ #include "dbgext.h" #include "disasm.h" #include "dbgexcept.h" -#include "dbgmem.h" + +///////////////////////////////////////////////////////////////////////////////// + +disasm::disasm( ULONG64 offset ) +{ + HRESULT hres; + + m_beginOffset = addr64(offset); + + if ( m_beginOffset == 0 ) + { + hres = dbgExt->registers->GetInstructionOffset( &m_beginOffset ); + if ( FAILED( hres ) ) + throw DbgException( "IDebugRegisters::GetInstructionOffset failed" ); + } + + m_currentOffset = m_beginOffset; + + doDisasm(); +} ///////////////////////////////////////////////////////////////////////////////// @@ -11,23 +30,11 @@ void disasm::doDisasm() HRESULT hres; char buffer[0x100]; ULONG disasmSize = 0; - ULONG64 offset = addr64(m_currentOffset); ULONG64 endOffset = 0; - - if ( m_beginOffset == 0 ) - { - ULONG64 currentOffset = 0; - - hres = dbgExt->registers->GetInstructionOffset( ¤tOffset ); - if ( FAILED( hres ) ) - throw DbgException( "IDebugRegisters::GetInstructionOffset failed" ); - - offset += currentOffset; - } - + hres = dbgExt->control->Disassemble( - offset, + m_currentOffset, DEBUG_DISASM_EFFECTIVE_ADDRESS, buffer, sizeof(buffer), @@ -41,24 +48,29 @@ void disasm::doDisasm() if ( FAILED( hres ) ) m_ea = 0; - m_length = (ULONG)(endOffset - offset); + m_length = (ULONG)(endOffset - m_currentOffset); m_disasm = std::string( buffer, disasmSize - 2); } ///////////////////////////////////////////////////////////////////////////////// -ULONG64 -assembly( ULONG64 offset, const std::string &instr ) +std::string +disasm::assembly( const std::string &instr ) { HRESULT hres; ULONG64 endOffset = 0; - hres = dbgExt->control->Assemble( offset, instr.c_str(), &endOffset ); + hres = dbgExt->control->Assemble( m_currentOffset, instr.c_str(), &endOffset ); if ( FAILED( hres ) ) - throw DbgException( "IDebugControl::Assemble failed" ); + throw DbgException( "IDebugControl::Assemble failed" ); - return endOffset; + m_currentOffset = endOffset; + + doDisasm(); + + return m_disasm; } -///////////////////////////////////////////////////////////////////////////////// \ No newline at end of file +///////////////////////////////////////////////////////////////////////////////// + diff --git a/pykd/disasm.h b/pykd/disasm.h index 890e672..5c54503 100644 --- a/pykd/disasm.h +++ b/pykd/disasm.h @@ -1,23 +1,31 @@ #pragma once +#include "dbgmem.h" + ///////////////////////////////////////////////////////////////////////////////// class disasm { public: - disasm( ULONG64 offset = 0) : - m_beginOffset( offset ), - m_currentOffset( offset ) { - doDisasm(); - } + disasm( ULONG64 offset = 0); - std::string next() { + std::string disassemble() { + std::string s = m_disasm; m_currentOffset += m_length; doDisasm(); - return m_disasm; - } + return s; + } + std::string reset() { + + m_currentOffset = m_beginOffset; + doDisasm(); + return m_disasm; + } + + std::string + assembly( const std::string &instr ); std::string instruction() const { return m_disasm; @@ -51,7 +59,4 @@ private: std::string m_disasm; }; -ULONG64 -assembly( ULONG64 offset, const std::string &instr ); - ///////////////////////////////////////////////////////////////////////////////// From 4dc9bba0482d71819b533b09c3e60027eb39063b Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Mon, 26 Sep 2011 12:06:00 +0000 Subject: [PATCH 06/21] [pykd] fixed: issue 9555 ( dbgModuleClass.name() corrupts output ) git-svn-id: https://pykd.svn.codeplex.com/svn@70041 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/dbgio.cpp | 3 +- pykd/dbgmodule.cpp | 11 ++- pykd/dbgsystem.cpp | 174 ++++++++++++--------------------------------- 3 files changed, 54 insertions(+), 134 deletions(-) diff --git a/pykd/dbgio.cpp b/pykd/dbgio.cpp index ca4adac..a3e3a51 100644 --- a/pykd/dbgio.cpp +++ b/pykd/dbgio.cpp @@ -24,9 +24,8 @@ void dbgPrint::dprint( const boost::python::object& obj, bool dml ) void dbgPrint::dprintln( const boost::python::object& obj, bool dml ) { std::wstring str = boost::python::extract( obj ); - str += L"\r\n"; - dbgExt->control4->ControlledOutputWide( dml ? DEBUG_OUTCTL_AMBIENT_DML : DEBUG_OUTCTL_AMBIENT_TEXT, DEBUG_OUTPUT_NORMAL, L"%ws", str.c_str() ); + dbgExt->control4->ControlledOutputWide( dml ? DEBUG_OUTCTL_AMBIENT_DML : DEBUG_OUTCTL_AMBIENT_TEXT, DEBUG_OUTPUT_NORMAL, L"%ws\r\n", str.c_str() ); std::wcout << str; } diff --git a/pykd/dbgmodule.cpp b/pykd/dbgmodule.cpp index 4ca1a06..c7650b4 100644 --- a/pykd/dbgmodule.cpp +++ b/pykd/dbgmodule.cpp @@ -68,6 +68,9 @@ void queryModuleParams( NULL, 0, NULL ); + + std::vector nameBuf(moduleNameChars); + name.resize(moduleNameChars + 1); hres = dbgExt->symbols->GetModuleNames( moduleIndex, @@ -75,14 +78,16 @@ void queryModuleParams( NULL, 0, NULL, - &name[0], - (ULONG)name.size(), + &nameBuf[0], + nameBuf.size(), NULL, NULL, 0, NULL ); if ( FAILED( hres ) ) throw DbgException( "IDebugSymbol::GetModuleNames failed" ); + + name = std::string( &nameBuf[0] ); } ///////////////////////////////////////////////////////////////////////////////// @@ -106,7 +111,7 @@ dbgModuleClass::dbgModuleClass( const std::string &name, ULONG64 base, ULONG siz m_base( addr64(base) ), m_end( addr64(base) + size ) { - reloadSymbols(); + //reloadSymbols(); std::string pattern = name + "!*"; ULONG64 enumHandle = 0; diff --git a/pykd/dbgsystem.cpp b/pykd/dbgsystem.cpp index 25f003a..069ef41 100644 --- a/pykd/dbgsystem.cpp +++ b/pykd/dbgsystem.cpp @@ -1,6 +1,5 @@ #include "stdafx.h" -#include #include "dbgext.h" #include "dbgexcept.h" #include "dbgsystem.h" @@ -13,23 +12,11 @@ is64bitSystem() { HRESULT hres; - try { - - hres = dbgExt->control->IsPointer64Bit(); + hres = dbgExt->control->IsPointer64Bit(); + if ( FAILED( hres ) ) + throw DbgException( "IDebugControl::IsPointer64Bit failed" ); - return hres == S_OK; - - } - catch( std::exception &e ) - { - dbgExt->control->Output( DEBUG_OUTPUT_ERROR, "pykd error: %s\n", e.what() ); - } - catch(...) - { - dbgExt->control->Output( DEBUG_OUTPUT_ERROR, "pykd unexpected error\n" ); - } - - return false; + return hres == S_OK; } /////////////////////////////////////////////////////////////////////////////////// @@ -48,29 +35,16 @@ dbgSymPath() HRESULT hres; std::string pathStr; - try { - - ULONG size; - dbgExt->symbols->GetSymbolPath( NULL, 0, &size ); + ULONG size; + dbgExt->symbols->GetSymbolPath( NULL, 0, &size ); + std::vector path(size); - hres = dbgExt->symbols->GetSymbolPath( &path[0], size, NULL ); - if ( FAILED( hres ) ) - throw DbgException( "IDebugSymbols::GetSymbolPath failed" ); + hres = dbgExt->symbols->GetSymbolPath( &path[0], size, NULL ); + if ( FAILED( hres ) ) + throw DbgException( "IDebugSymbols::GetSymbolPath failed" ); - pathStr = &path[0]; - - } - catch( std::exception &e ) - { - dbgExt->control->Output( DEBUG_OUTPUT_ERROR, "pykd error: %s\n", e.what() ); - } - catch(...) - { - dbgExt->control->Output( DEBUG_OUTPUT_ERROR, "pykd unexpected error\n" ); - } - - return pathStr; + return std::string(&path[0]); } @@ -81,39 +55,29 @@ getPdbFile( ULONG64 moduleBase ) { HRESULT hres; - try { - - IMAGEHLP_MODULEW64 imageHelpInfo = { 0 }; - hres = - dbgExt->advanced2->GetSymbolInformation( - DEBUG_SYMINFO_IMAGEHLP_MODULEW64, - moduleBase, - 0, - &imageHelpInfo, - sizeof( imageHelpInfo ), - NULL, - NULL, - 0, - NULL ); - - char fileName[ 256 ]; - WideCharToMultiByte( CP_ACP, 0, imageHelpInfo.LoadedPdbName, 256, fileName, 256, NULL, NULL ); - - return std::string( fileName ); + IMAGEHLP_MODULEW64 imageHelpInfo = { 0 }; + + hres = + dbgExt->advanced2->GetSymbolInformation( + DEBUG_SYMINFO_IMAGEHLP_MODULEW64, + moduleBase, + 0, + &imageHelpInfo, + sizeof( imageHelpInfo ), + NULL, + NULL, + 0, + NULL ); + + if ( FAILED( hres ) ) + throw DbgException( "IDebugAdvanced2::GetSymbolInformation failed" ); + + char fileName[ 256 ]; + WideCharToMultiByte( CP_ACP, 0, imageHelpInfo.LoadedPdbName, 256, fileName, 256, NULL, NULL ); - } - catch( std::exception &e ) - { - dbgExt->control->Output( DEBUG_OUTPUT_ERROR, "pykd error: %s\n", e.what() ); - } - catch(...) - { - dbgExt->control->Output( DEBUG_OUTPUT_ERROR, "pykd unexpected error\n" ); - } - - return std::string(); + return std::string( fileName ); } /////////////////////////////////////////////////////////////////////////////////// @@ -121,26 +85,10 @@ getPdbFile( ULONG64 moduleBase ) void reloadModule( const char * moduleName ) { - HRESULT hres; - - try { - - // подавить вывод сообщений об отсутствии символов - OutputReader outputReader( dbgExt->client ); + // подавить вывод сообщений об отсутствии символов + OutputReader outputReader( dbgExt->client ); - hres = dbgExt->symbols->Reload( moduleName ); - - //if ( FAILED( hres ) ) - // throw DbgException( "IDebugSymbol::Reload failed" ); - } - catch( std::exception &e ) - { - dbgExt->control->Output( DEBUG_OUTPUT_ERROR, "pykd error: %s\n", e.what() ); - } - catch(...) - { - dbgExt->control->Output( DEBUG_OUTPUT_ERROR, "pykd unexpected error\n" ); - } + dbgExt->symbols->Reload( moduleName ); } /////////////////////////////////////////////////////////////////////////////////// @@ -148,31 +96,15 @@ reloadModule( const char * moduleName ) bool isKernelDebugging() { - HRESULT hres; - bool result = false; - - try { + HRESULT hres; + ULONG debugClass, debugQualifier; - ULONG debugClass, debugQualifier; + hres = dbgExt->control->GetDebuggeeType( &debugClass, &debugQualifier ); - hres = dbgExt->control->GetDebuggeeType( &debugClass, &debugQualifier ); - - if ( FAILED( hres ) ) - throw DbgException( "IDebugControl::GetDebuggeeType failed" ); + if ( FAILED( hres ) ) + throw DbgException( "IDebugControl::GetDebuggeeType failed" ); - result = debugClass == DEBUG_CLASS_KERNEL; - - } - catch( std::exception &e ) - { - dbgExt->control->Output( DEBUG_OUTPUT_ERROR, "pykd error: %s\n", e.what() ); - } - catch(...) - { - dbgExt->control->Output( DEBUG_OUTPUT_ERROR, "pykd unexpected error\n" ); - } - - return result; + return debugClass == DEBUG_CLASS_KERNEL; } /////////////////////////////////////////////////////////////////////////////////// @@ -181,30 +113,14 @@ bool isDumpAnalyzing() { HRESULT hres; - bool result = false; - - try { + ULONG debugClass, debugQualifier; - ULONG debugClass, debugQualifier; + hres = dbgExt->control->GetDebuggeeType( &debugClass, &debugQualifier ); - hres = dbgExt->control->GetDebuggeeType( &debugClass, &debugQualifier ); - - if ( FAILED( hres ) ) - throw DbgException( "IDebugControl::GetDebuggeeType failed" ); + if ( FAILED( hres ) ) + throw DbgException( "IDebugControl::GetDebuggeeType failed" ); - result = debugQualifier >= DEBUG_DUMP_SMALL; - - } - catch( std::exception &e ) - { - dbgExt->control->Output( DEBUG_OUTPUT_ERROR, "pykd error: %s\n", e.what() ); - } - catch(...) - { - dbgExt->control->Output( DEBUG_OUTPUT_ERROR, "pykd unexpected error\n" ); - } - - return result; + return debugQualifier >= DEBUG_DUMP_SMALL; } /////////////////////////////////////////////////////////////////////////////////// From a7855ea4d182eb9bb724c2b3051a92b7e20f4f0a Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Wed, 28 Sep 2011 07:45:52 +0000 Subject: [PATCH 07/21] [pykd] added: debuggerPath routine ( Return full path to the process image that uses pykd ) git-svn-id: https://pykd.svn.codeplex.com/svn@70089 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/dbgext.cpp | 4 +++- pykd/dbgsystem.cpp | 12 ++++++++++++ pykd/dbgsystem.h | 4 ++++ pykd/pykd.vcproj | 8 ++++---- pykd/pykd_2008.vcproj | 8 ++++---- 5 files changed, 27 insertions(+), 9 deletions(-) diff --git a/pykd/dbgext.cpp b/pykd/dbgext.cpp index 9d6fc40..e93212f 100644 --- a/pykd/dbgext.cpp +++ b/pykd/dbgext.cpp @@ -221,6 +221,8 @@ BOOST_PYTHON_MODULE( pykd ) "Delete synthetic symbols by virtual address" ); boost::python::def( "delSynSymbolsMask", &delSyntheticSymbolsMask, "Delete synthetic symbols by mask of module and symbol name"); + boost::python::def( "debuggerPath", &getDebuggerImage, + "Return full path to the process image that uses pykd" ); boost::python::class_( "typeInfo", "Class representing non-primitive type info: structure, union, etc. attributes is a fields of non-primitive type" ) @@ -253,7 +255,7 @@ BOOST_PYTHON_MODULE( pykd ) DEF_PY_GLOBAL( "ulong_t", TypeInfo("", "unsigned long") ); DEF_PY_GLOBAL( "int_t", TypeInfo("", "int") ); DEF_PY_GLOBAL( "uint_t", TypeInfo("", "unsigned int") ); - DEF_PY_GLOBAL( "ptr_t", TypeInfo("", "void*") ); + //DEF_PY_GLOBAL( "ptr_t", TypeInfo("", "void*") ); DEF_PY_GLOBAL( "double_t", TypeInfo("", "double") ); DEF_PY_GLOBAL( "longlong_t", TypeInfo("", "int64") ); DEF_PY_GLOBAL( "ulonglong_t", TypeInfo("", "unsigned int64") ); diff --git a/pykd/dbgsystem.cpp b/pykd/dbgsystem.cpp index 069ef41..2cf890a 100644 --- a/pykd/dbgsystem.cpp +++ b/pykd/dbgsystem.cpp @@ -1,5 +1,7 @@ #include "stdafx.h" +#include + #include "dbgext.h" #include "dbgexcept.h" #include "dbgsystem.h" @@ -124,3 +126,13 @@ isDumpAnalyzing() } /////////////////////////////////////////////////////////////////////////////////// + +std::string +getDebuggerImage() +{ + std::vector buffer(MAX_PATH); + GetModuleFileNameExA( GetCurrentProcess(), NULL, &buffer[0], buffer.size() ); + return std::string( &buffer[0] ); +} + +/////////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/pykd/dbgsystem.h b/pykd/dbgsystem.h index 7b52da9..88e337b 100644 --- a/pykd/dbgsystem.h +++ b/pykd/dbgsystem.h @@ -28,4 +28,8 @@ isKernelDebugging(); bool isDumpAnalyzing(); +std::string +getDebuggerImage(); + + ///////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/pykd/pykd.vcproj b/pykd/pykd.vcproj index 41a9c66..d121df2 100644 --- a/pykd/pykd.vcproj +++ b/pykd/pykd.vcproj @@ -66,7 +66,7 @@ /> Date: Wed, 28 Sep 2011 13:14:01 +0000 Subject: [PATCH 08/21] [pykd] fixed: issue 9560 ( dbgCommand truncates long output string ) git-svn-id: https://pykd.svn.codeplex.com/svn@70097 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/dbgio.cpp | 38 ++++++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/pykd/dbgio.cpp b/pykd/dbgio.cpp index a3e3a51..bf9944a 100644 --- a/pykd/dbgio.cpp +++ b/pykd/dbgio.cpp @@ -14,9 +14,22 @@ void dbgPrint::dprint( const boost::python::object& obj, bool dml ) { std::wstring str = boost::python::extract( obj ); - HRESULT hres = dbgExt->control4->ControlledOutputWide( dml ? DEBUG_OUTCTL_AMBIENT_DML : DEBUG_OUTCTL_AMBIENT_TEXT, DEBUG_OUTPUT_NORMAL, L"%ws", str.c_str() ); - - std::wcout << str; + if ( isWindbgExt() ) + { + + for ( size_t i = 0; i < str.size() / 100 + 1; ++i ) + { + dbgExt->control4->ControlledOutputWide( + dml ? DEBUG_OUTCTL_AMBIENT_DML : DEBUG_OUTCTL_AMBIENT_TEXT, DEBUG_OUTPUT_NORMAL, + L"%ws", + str.substr( i*100, min( str.size() - i*100, 100 ) ).c_str() + ); + } + } + else + { + std::wcout << str; + } } ///////////////////////////////////////////////////////////////////////////////// @@ -24,10 +37,23 @@ void dbgPrint::dprint( const boost::python::object& obj, bool dml ) void dbgPrint::dprintln( const boost::python::object& obj, bool dml ) { std::wstring str = boost::python::extract( obj ); + str += L"\r\n"; - dbgExt->control4->ControlledOutputWide( dml ? DEBUG_OUTCTL_AMBIENT_DML : DEBUG_OUTCTL_AMBIENT_TEXT, DEBUG_OUTPUT_NORMAL, L"%ws\r\n", str.c_str() ); - - std::wcout << str; + if ( isWindbgExt() ) + { + for ( size_t i = 0; i < str.size() / 100 + 1; ++i ) + { + dbgExt->control4->ControlledOutputWide( + dml ? DEBUG_OUTCTL_AMBIENT_DML : DEBUG_OUTCTL_AMBIENT_TEXT, DEBUG_OUTPUT_NORMAL, + L"%ws", + str.substr( i*100, min( str.size() - i*100, 100 ) ).c_str() + ); + } + } + else + { + std::wcout << str; + } } ///////////////////////////////////////////////////////////////////////////////// From f2a16323d4d5e87ee903be654518cd0468829df3 Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Thu, 29 Sep 2011 06:03:19 +0000 Subject: [PATCH 09/21] ready for release 0.0.20 git-svn-id: https://pykd.svn.codeplex.com/svn@70108 9b283d60-5439-405e-af05-b73fd8c4d996 --- changelog | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/changelog b/changelog index 6e64dc9..d07be10 100644 --- a/changelog +++ b/changelog @@ -1,3 +1,18 @@ +version 0.0.20 29/09/2011 + +[+] added : routine breakin ( Break into debugger ) +[+] added : cpuReg constructor with index parameter +[+] added : attachProcess routine ( attach debugger to the exsisting process ) +[+] added : attachKernel routine ( attach debugger to a kernel target ) +[+] added : TypedVar instantiation by symbol name +[+] added : Exception debug event +[+] added : assembly method for disasm class +[+] added : debuggerPath routine ( Return full path to the process image that uses pykd ) + +[!] fixed: issue 9219 ( the call of the go() routine results in a deadlock for multithreading app ) +[!] fixed: issue 9518 ( Problem with dbgCommand('!analyze -v') ) +[!] fixed: issue 9555 ( dbgModuleClass.name() corrupts output ) + version 0.0.19 28/07/2011 [+] added : typedVar::data method ( Return raw string object with data stream ) From 0fe8942713cd33859f571ce3fd51d356332b4fb7 Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Thu, 29 Sep 2011 11:04:47 +0000 Subject: [PATCH 10/21] [pykd] fixed: WindbgGlobalSession destructor git-svn-id: https://pykd.svn.codeplex.com/svn@70119 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/dbgext.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pykd/dbgext.cpp b/pykd/dbgext.cpp index e93212f..0e1fe34 100644 --- a/pykd/dbgext.cpp +++ b/pykd/dbgext.cpp @@ -688,8 +688,8 @@ private: } ~WindbgGlobalSession() { - Py_Finalize(); g_dbgClient.removeEventsMgr(); + Py_Finalize(); } boost::python::object main; From df5da9c55d7b59b21a10e439a99f7e7fd9221004 Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Fri, 30 Sep 2011 08:49:24 +0000 Subject: [PATCH 11/21] [pykd] fixed: WindbgGlobalSession constructor git-svn-id: https://pykd.svn.codeplex.com/svn@70143 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/dbgext.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/pykd/dbgext.cpp b/pykd/dbgext.cpp index 0e1fe34..97e93b6 100644 --- a/pykd/dbgext.cpp +++ b/pykd/dbgext.cpp @@ -654,8 +654,10 @@ private: PyImport_AppendInittab("pykd", initpykd ); + PyEval_InitThreads(); + Py_Initialize(); - + main = boost::python::import("__main__"); boost::python::object main_namespace = main.attr("__dict__"); @@ -688,7 +690,9 @@ private: } ~WindbgGlobalSession() { + g_dbgClient.removeEventsMgr(); + Py_Finalize(); } @@ -697,6 +701,8 @@ private: static volatile LONG sessionCount; static WindbgGlobalSession *windbgGlobalSession; + + PyThreadState *initThreadState; }; volatile LONG WindbgGlobalSession::sessionCount = 0; From b8950859beda687221333f3b5ce6eba04f72ac81 Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Mon, 3 Oct 2011 05:42:02 +0000 Subject: [PATCH 12/21] [pykd] fixed: removed Py_Finalize: it is not properly supported by boost::python git-svn-id: https://pykd.svn.codeplex.com/svn@70172 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/dbgext.cpp | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/pykd/dbgext.cpp b/pykd/dbgext.cpp index 97e93b6..c6c2b6a 100644 --- a/pykd/dbgext.cpp +++ b/pykd/dbgext.cpp @@ -677,23 +677,12 @@ private: main_namespace[ key ] = pykd_namespace[ key ]; } - //// перенаправление стандартных потоков ВВ - //boost::python::object sys = boost::python::import( "sys"); - // - //dbgOut dout; - //sys.attr("stdout") = boost::python::object( dout ); - - //dbgIn din; - //sys.attr("stdin") = boost::python::object( din ); - // g_dbgClient.startEventsMgr(); - } + } ~WindbgGlobalSession() { - g_dbgClient.removeEventsMgr(); - - Py_Finalize(); + g_dbgClient.removeEventsMgr(); } boost::python::object main; @@ -702,7 +691,6 @@ private: static WindbgGlobalSession *windbgGlobalSession; - PyThreadState *initThreadState; }; volatile LONG WindbgGlobalSession::sessionCount = 0; From c9b63b1bdbce0137deb6004007327bc04fc19fb9 Mon Sep 17 00:00:00 2001 From: "SND\\EreTIk_cp" Date: Mon, 3 Oct 2011 19:47:03 +0000 Subject: [PATCH 13/21] [+] getProcessorType: type of physical processor git-svn-id: https://pykd.svn.codeplex.com/svn@70185 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/dbgext.cpp | 2 ++ pykd/dbgprocess.cpp | 46 +++++++++++++++++++++++++++++++++------------ pykd/dbgprocess.h | 7 +++++-- 3 files changed, 41 insertions(+), 14 deletions(-) diff --git a/pykd/dbgext.cpp b/pykd/dbgext.cpp index c6c2b6a..1958efb 100644 --- a/pykd/dbgext.cpp +++ b/pykd/dbgext.cpp @@ -213,6 +213,8 @@ BOOST_PYTHON_MODULE( pykd ) "Return current processor mode as string: X86, ARM, IA64 or X64" ); boost::python::def( "setProcessorMode", &setProcessorMode, "Set current processor mode by string (X86, ARM, IA64 or X64)" ); + boost::python::def( "getProcessorType", &getProcessorType, + "Returns physical processor type as string: X86, ARM, IA64 or X64"); boost::python::def( "addSynSymbol", &addSyntheticSymbol, "Add new synthetic symbol for virtual address" ); boost::python::def( "delAllSynSymbols", &delAllSyntheticSymbols, diff --git a/pykd/dbgprocess.cpp b/pykd/dbgprocess.cpp index 78284fe..ec58d82 100644 --- a/pykd/dbgprocess.cpp +++ b/pykd/dbgprocess.cpp @@ -119,17 +119,10 @@ getCurrentStack() } ///////////////////////////////////////////////////////////////////////////////// - -std::string -getProcessorMode() +// Processor type to string +///////////////////////////////////////////////////////////////////////////////// +static std::string processorToStr(ULONG processorMode) { - HRESULT hres; - - ULONG processorMode; - hres = dbgExt->control->GetEffectiveProcessorType( &processorMode ); - if ( FAILED( hres ) ) - throw DbgException( "IDebugControl::GetEffectiveProcessorType failed" ); - switch( processorMode ) { case IMAGE_FILE_MACHINE_I386: @@ -146,7 +139,36 @@ getProcessorMode() } throw DbgException( "Unknown CPU type" ); +} +///////////////////////////////////////////////////////////////////////////////// + +std::string +getProcessorMode() +{ + HRESULT hres; + + ULONG processorMode; + hres = dbgExt->control->GetEffectiveProcessorType( &processorMode ); + if ( FAILED( hres ) ) + throw DbgException( "IDebugControl::GetEffectiveProcessorType failed" ); + + return processorToStr(processorMode); +} + +///////////////////////////////////////////////////////////////////////////////// + +std::string +getProcessorType() +{ + HRESULT hres; + + ULONG processorMode; + hres = dbgExt->control->GetActualProcessorType( &processorMode ); + if ( FAILED( hres ) ) + throw DbgException( "IDebugControl::GetEffectiveProcessorType failed" ); + + return processorToStr(processorMode); } ///////////////////////////////////////////////////////////////////////////////// @@ -167,13 +189,13 @@ setProcessorMode( else if ( mode == "X64" ) processorMode = IMAGE_FILE_MACHINE_AMD64; else - throw DbgException( "Unknown processor type" ); + throw DbgException( "Unknown processor type" ); hres = dbgExt->control->SetEffectiveProcessorType( processorMode ); if ( FAILED( hres ) ) throw DbgException( "IDebugControl::SetEffectiveProcessorType failed" ); -} +} ///////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/dbgprocess.h b/pykd/dbgprocess.h index 1425c7b..88ccc6b 100644 --- a/pykd/dbgprocess.h +++ b/pykd/dbgprocess.h @@ -40,11 +40,14 @@ public: std::string getProcessorMode(); +std::string +getProcessorType(); + void setProcessorMode( const std::string &mode ); - -ULONG64 + +ULONG64 getCurrentProcess(); VOID From 43aa5d787c1865fa64ba39381250d0dddbfa9077 Mon Sep 17 00:00:00 2001 From: "SND\\EreTIk_cp" Date: Tue, 4 Oct 2011 08:11:57 +0000 Subject: [PATCH 14/21] [+] script: switch x86(WOW64) <-> x64 processor mode. And execute commands (if specified) git-svn-id: https://pykd.svn.codeplex.com/svn@70198 9b283d60-5439-405e-af05-b73fd8c4d996 --- samples/wow64sw.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 samples/wow64sw.py diff --git a/samples/wow64sw.py b/samples/wow64sw.py new file mode 100644 index 0000000..23b5f32 --- /dev/null +++ b/samples/wow64sw.py @@ -0,0 +1,18 @@ +""" +Switch x86(WOW64) <-> x64 processor mode +And execute commands (if specified) +""" + +import sys +from pykd import * + +if __name__ == "__main__": + if getProcessorType() == "X64": + setProcessorMode( {"X64": "X86", "X86": "X64"}[ getProcessorMode() ] ) + if len(sys.argv) > 1: + command = "" + for arg in sys.argv[1:]: + command = command + " " + arg + dprintln( dbgCommand(command) ) + else: + dprintln("For \"X64\" processor only") From 37ce97f561ff1bfb274b2b43ec4c54497b8851c6 Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Tue, 4 Oct 2011 12:20:14 +0000 Subject: [PATCH 15/21] [pykd] fixed : PyState save/restore git-svn-id: https://pykd.svn.codeplex.com/svn@70203 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/dbgext.cpp | 110 +++++++++++++++++------------------------------- pykd/dbgext.h | 62 +++++++++++++++++++++++++++ pykd/pyaux.h | 18 ++++++-- 3 files changed, 114 insertions(+), 76 deletions(-) diff --git a/pykd/dbgext.cpp b/pykd/dbgext.cpp index 1958efb..42a9658 100644 --- a/pykd/dbgext.cpp +++ b/pykd/dbgext.cpp @@ -213,8 +213,6 @@ BOOST_PYTHON_MODULE( pykd ) "Return current processor mode as string: X86, ARM, IA64 or X64" ); boost::python::def( "setProcessorMode", &setProcessorMode, "Set current processor mode by string (X86, ARM, IA64 or X64)" ); - boost::python::def( "getProcessorType", &getProcessorType, - "Returns physical processor type as string: X86, ARM, IA64 or X64"); boost::python::def( "addSynSymbol", &addSyntheticSymbol, "Add new synthetic symbol for virtual address" ); boost::python::def( "delAllSynSymbols", &delAllSyntheticSymbols, @@ -615,85 +613,43 @@ BOOST_PYTHON_MODULE( pykd ) ///////////////////////////////////////////////////////////////////////////////// -class WindbgGlobalSession -{ -public: - - static - boost::python::object - global() { - return windbgGlobalSession->main.attr("__dict__"); - } - - static - VOID - StartWindbgSession() { - if ( 1 == InterlockedIncrement( &sessionCount ) ) - { - windbgGlobalSession = new WindbgGlobalSession(); - } - } - - static - VOID - StopWindbgSession() { - if ( 0 == InterlockedDecrement( &sessionCount ) ) - { - delete windbgGlobalSession; - windbgGlobalSession = NULL; - } - } - - static - bool isInit() { - return windbgGlobalSession != NULL; - } - - -private: - - WindbgGlobalSession() { +WindbgGlobalSession::WindbgGlobalSession() { - PyImport_AppendInittab("pykd", initpykd ); + PyImport_AppendInittab("pykd", initpykd ); - PyEval_InitThreads(); + PyEval_InitThreads(); - Py_Initialize(); + Py_Initialize(); - main = boost::python::import("__main__"); - - boost::python::object main_namespace = main.attr("__dict__"); - - - // делаем аналог from pykd import * - boost::python::object pykd = boost::python::import( "pykd" ); - - boost::python::dict pykd_namespace( pykd.attr("__dict__") ); - - boost::python::list iterkeys( pykd_namespace.iterkeys() ); - - for (int i = 0; i < boost::python::len(iterkeys); i++) - { - std::string key = boost::python::extract(iterkeys[i]); - - main_namespace[ key ] = pykd_namespace[ key ]; - } - - g_dbgClient.startEventsMgr(); - } + main = boost::python::import("__main__"); - ~WindbgGlobalSession() { + boost::python::object main_namespace = main.attr("__dict__"); - g_dbgClient.removeEventsMgr(); - } - - boost::python::object main; - static volatile LONG sessionCount; + // делаем аналог from pykd import * + boost::python::object pykd = boost::python::import( "pykd" ); - static WindbgGlobalSession *windbgGlobalSession; + boost::python::dict pykd_namespace( pykd.attr("__dict__") ); + + boost::python::list iterkeys( pykd_namespace.iterkeys() ); + + for (int i = 0; i < boost::python::len(iterkeys); i++) + { + std::string key = boost::python::extract(iterkeys[i]); + + main_namespace[ key ] = pykd_namespace[ key ]; + } + + g_dbgClient.startEventsMgr(); -}; + pyState = PyEval_SaveThread(); + } + + +WindbgGlobalSession::~WindbgGlobalSession() { + + g_dbgClient.removeEventsMgr(); +} volatile LONG WindbgGlobalSession::sessionCount = 0; @@ -831,7 +787,10 @@ py( PDEBUG_CLIENT4 client, PCSTR args) { DbgExt ext( client ); + WindbgGlobalSession::RestorePyState(); + PyThreadState *globalInterpreter = PyThreadState_Swap( NULL ); + PyThreadState *localInterpreter = Py_NewInterpreter(); try { @@ -944,7 +903,10 @@ py( PDEBUG_CLIENT4 client, PCSTR args) } Py_EndInterpreter( localInterpreter ); + PyThreadState_Swap( globalInterpreter ); + + WindbgGlobalSession::SavePyState(); return S_OK; } @@ -957,6 +919,8 @@ pycmd( PDEBUG_CLIENT4 client, PCSTR args ) { DbgExt ext( client ); + WindbgGlobalSession::RestorePyState(); + try { // перенаправление стандартных потоков ВВ @@ -1090,6 +1054,8 @@ pycmd( PDEBUG_CLIENT4 client, PCSTR args ) { dbgExt->control->Output( DEBUG_OUTPUT_ERROR, "unexpected error" ); } + + WindbgGlobalSession::SavePyState(); return S_OK; } diff --git a/pykd/dbgext.h b/pykd/dbgext.h index 39c0f55..bee1a26 100644 --- a/pykd/dbgext.h +++ b/pykd/dbgext.h @@ -40,4 +40,66 @@ private: extern DbgExt *dbgExt; +class WindbgGlobalSession +{ +public: + + static + boost::python::object + global() { + return windbgGlobalSession->main.attr("__dict__"); + } + + static + VOID + StartWindbgSession() { + if ( 1 == InterlockedIncrement( &sessionCount ) ) + { + windbgGlobalSession = new WindbgGlobalSession(); + } + } + + static + VOID + StopWindbgSession() { + if ( 0 == InterlockedDecrement( &sessionCount ) ) + { + delete windbgGlobalSession; + windbgGlobalSession = NULL; + } + } + + static + bool isInit() { + return windbgGlobalSession != NULL; + } + + static + VOID + RestorePyState() { + PyEval_RestoreThread( windbgGlobalSession->pyState ); + } + + static + VOID + SavePyState() { + windbgGlobalSession->pyState = PyEval_SaveThread(); + } + +private: + + WindbgGlobalSession(); + + ~WindbgGlobalSession(); + + boost::python::object main; + + PyThreadState *pyState; + + static volatile LONG sessionCount; + + static WindbgGlobalSession *windbgGlobalSession; + +}; + bool isWindbgExt(); diff --git a/pykd/pyaux.h b/pykd/pyaux.h index b18cdcb..8e85f5c 100644 --- a/pykd/pyaux.h +++ b/pykd/pyaux.h @@ -17,13 +17,23 @@ public: } void saveState() { - TlsSetValue( m_index, PyEval_SaveThread() ); + if ( !isWindbgExt() ) + TlsSetValue( m_index, PyEval_SaveThread() ); + else + WindbgGlobalSession::SavePyState(); } void restoreState() { - PyThreadState* state = (PyThreadState*)TlsGetValue( m_index ); - if ( state ) - PyEval_RestoreThread( state ); + if ( !isWindbgExt() ) + { + PyThreadState* state = (PyThreadState*)TlsGetValue( m_index ); + if ( state ) + PyEval_RestoreThread( state ); + } + else + { + WindbgGlobalSession::RestorePyState(); + } } private: From d7cbbd016abe9013a28dab4a8aee390075d29c8f Mon Sep 17 00:00:00 2001 From: "SND\\EreTIk_cp" Date: Tue, 4 Oct 2011 12:37:25 +0000 Subject: [PATCH 16/21] [~] getProcessorType [~] remove debug print, correct struct size git-svn-id: https://pykd.svn.codeplex.com/svn@70204 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/dbgext.cpp | 2 ++ pykd_2008.sln | 8 +------- samples/portmsg.py | 8 +++----- 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/pykd/dbgext.cpp b/pykd/dbgext.cpp index 42a9658..bbe2732 100644 --- a/pykd/dbgext.cpp +++ b/pykd/dbgext.cpp @@ -213,6 +213,8 @@ BOOST_PYTHON_MODULE( pykd ) "Return current processor mode as string: X86, ARM, IA64 or X64" ); boost::python::def( "setProcessorMode", &setProcessorMode, "Set current processor mode by string (X86, ARM, IA64 or X64)" ); + boost::python::def( "getProcessorType", &getProcessorType, + "Return type of physical processor: X86, ARM, IA64 or X64" ); boost::python::def( "addSynSymbol", &addSyntheticSymbol, "Add new synthetic symbol for virtual address" ); boost::python::def( "delAllSynSymbols", &delAllSyntheticSymbols, diff --git a/pykd_2008.sln b/pykd_2008.sln index e339971..cd63036 100644 --- a/pykd_2008.sln +++ b/pykd_2008.sln @@ -10,16 +10,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "targetapp", "test\targetapp EndProject Global GlobalSection(TeamFoundationVersionControl) = preSolution - SccNumberOfProjects = 3 + SccNumberOfProjects = 1 SccEnterpriseProvider = {4CA58AB2-18FA-4F8D-95D4-32DDF27D184C} SccTeamFoundationServer = https://tfs.codeplex.com/tfs/TFS08 SccLocalPath0 = . - SccProjectUniqueName1 = pykd\\pykd_2008.vcproj - SccProjectName1 = pykd - SccLocalPath1 = pykd - SccProjectUniqueName2 = test\\targetapp\\targetapp.vcproj - SccProjectName2 = test/targetapp - SccLocalPath2 = test\\targetapp EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 diff --git a/samples/portmsg.py b/samples/portmsg.py index 7f4ce83..591a946 100644 --- a/samples/portmsg.py +++ b/samples/portmsg.py @@ -53,8 +53,6 @@ def PrintPortMesage(messageAddr, printFormat="b", use32=False): clientIdType.append(dynPtr, "UniqueProcess") clientIdType.append(dynPtr, "UniqueThread") - print clientIdType - portMsgType = typeInfo("portmsg~_PORT_MESSAGE") portMsgType.append(ushort_t, "DataLength") portMsgType.append(ushort_t, "TotalLength") @@ -62,7 +60,7 @@ def PrintPortMesage(messageAddr, printFormat="b", use32=False): portMsgType.append(ushort_t, "DataInfoOffset") portMsgType.append(clientIdType, "ClientId") portMsgType.append(ulong_t, "MessageId") - portMsgType.append(ulong_t, "CallbackId") + portMsgType.append(ulonglong_t, "ClientViewSize") return portMsgType def buildPortMessage32Type(): @@ -78,7 +76,7 @@ def PrintPortMesage(messageAddr, printFormat="b", use32=False): portMsgType.append(ushort_t, "DataInfoOffset") portMsgType.append(clientIdType, "ClientId") portMsgType.append(ulong_t, "MessageId") - portMsgType.append(ulong_t, "CallbackId") + portMsgType.append(ulong_t, "ClientViewSize") return portMsgType @@ -109,7 +107,7 @@ def PrintPortMesage(messageAddr, printFormat="b", use32=False): else: procFindStr = "%d(0x%x)" % (messageHeader.ClientId.UniqueProcess, messageHeader.ClientId.UniqueProcess) dprintln( "Client ID : process= " + procFindStr + ", thread= %d(0x%x)" % (messageHeader.ClientId.UniqueThread, messageHeader.ClientId.UniqueThread), isKernelDebugging()) - dprintln( "View/Callback : %d (0x%x)" % (messageHeader.CallbackId, messageHeader.CallbackId) ) + dprintln( "View/Callback : %d (0x%x)" % (messageHeader.ClientViewSize, messageHeader.ClientViewSize) ) if (printFormat not in DispFormatsLength): dprintln( "WARRING: Unknown (" + printFormat + ") diplay fromat. Use \"b\"" ) printFormat = "b" From 071ae4e12ae4ec039e4e766577eb602e1e80e12f Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Wed, 5 Oct 2011 08:13:51 +0000 Subject: [PATCH 17/21] [pykd] added : unicode support for dbgCommand routine git-svn-id: https://pykd.svn.codeplex.com/svn@70214 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/dbgcmd.cpp | 4 ++-- pykd/dbgcmd.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pykd/dbgcmd.cpp b/pykd/dbgcmd.cpp index c25cbd6..5dc55bd 100644 --- a/pykd/dbgcmd.cpp +++ b/pykd/dbgcmd.cpp @@ -11,7 +11,7 @@ /////////////////////////////////////////////////////////////////////////////// std::string -dbgCommand( const std::string &command ) +dbgCommand( const std::wstring &command ) { HRESULT hres; @@ -19,7 +19,7 @@ dbgCommand( const std::string &command ) { PyThread_StateRestore pyThreadRestore; - hres = dbgExt->control->Execute( DEBUG_OUTCTL_THIS_CLIENT, command.c_str(), 0 ); + hres = dbgExt->control4->ExecuteWide( DEBUG_OUTCTL_THIS_CLIENT, command.c_str(), 0 ); } if ( FAILED( hres ) ) throw DbgException( "IDebugControl::Execute failed" ); diff --git a/pykd/dbgcmd.h b/pykd/dbgcmd.h index d59ad02..9b361e9 100644 --- a/pykd/dbgcmd.h +++ b/pykd/dbgcmd.h @@ -7,7 +7,7 @@ ///////////////////////////////////////////////////////////////////////////////// std::string -dbgCommand( const std::string &command ); +dbgCommand( const std::wstring &command ); template void From d7f76b4b5ba3a63747dcc11a3ec536b2fcc1580e Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Wed, 5 Oct 2011 09:01:15 +0000 Subject: [PATCH 18/21] [samples] added: a very simple debugger git-svn-id: https://pykd.svn.codeplex.com/svn@70215 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/dbgext.cpp | 2 +- samples/debug.py | 218 ------------------------------ samples/debug/debug.py | 119 ++++++++++++++++ samples/debug/widgets/__init__.py | 13 ++ samples/debug/widgets/cmd.py | 50 +++++++ samples/debug/widgets/disasm.py | 28 ++++ samples/debug/widgets/regs.py | 48 +++++++ samples/debug/widgets/stack.py | 32 +++++ 8 files changed, 291 insertions(+), 219 deletions(-) delete mode 100644 samples/debug.py create mode 100644 samples/debug/debug.py create mode 100644 samples/debug/widgets/__init__.py create mode 100644 samples/debug/widgets/cmd.py create mode 100644 samples/debug/widgets/disasm.py create mode 100644 samples/debug/widgets/regs.py create mode 100644 samples/debug/widgets/stack.py diff --git a/pykd/dbgext.cpp b/pykd/dbgext.cpp index bbe2732..e75d0bf 100644 --- a/pykd/dbgext.cpp +++ b/pykd/dbgext.cpp @@ -384,7 +384,7 @@ BOOST_PYTHON_MODULE( pykd ) .def( boost::python::init<>( "constructor" ) ) .def( boost::python::init( boost::python::args("offset"), "constructor" ) ) .def( "disasm", &disasm::disassemble, "Disassemble next instruction" ) - .def( "sasm", &disasm::assembly, "Insert assemblied instuction to current offset" ) + .def( "asm", &disasm::assembly, "Insert assemblied instuction to current offset" ) .def( "begin", &disasm::begin, "Return begin offset" ) .def( "current", &disasm::current, "Return current offset" ) .def( "length", &disasm::length, "Return current instruction length" ) diff --git a/samples/debug.py b/samples/debug.py deleted file mode 100644 index c00194d..0000000 --- a/samples/debug.py +++ /dev/null @@ -1,218 +0,0 @@ -# -# -# - -from PySide.QtCore import * -from PySide.QtGui import * - -import pykd - - -class UpdateEvent( QEvent ): - def __init__(self): - QEvent.__init__(self, QEvent.Type(QEvent.User + 1)) - - -class GoThread( QThread ): - - def __init__(self, func): - QThread.__init__(self) - self.start() - self.func = func - - def run(self): - self.func() - app.postEvent( mainForm, UpdateEvent() ) - self.exit() - - -class DisasmWidget( QDockWidget ): - - def __init__( self ): - QDockWidget.__init__( self ) - self.setWindowTitle( "Disassembler" ) - self.textArea = QTextEdit() - self.textArea.setReadOnly( True ) - self.setWidget( self.textArea ) - - - def onUpdate( self ): - - disasm = pykd.disasm() - disasmStr = disasm.instruction() + "\n" - for i in xrange(50): - disasmStr += disasm.next() + "\n" - - self.textArea.setPlainText( disasmStr ) - - -class RegistersWidget( QDockWidget ): - - def __init__( self ): - QDockWidget.__init__( self ) - self.setWindowTitle( "Registers" ) - self.textArea = QTextEdit() - self.setWidget( self.textArea ) - - def onUpdate( self ): - - s = "" - - for reg in self.getRegisterSet(): - s += "%s %x ( %d )\r\n" % ( reg.name(), reg.value(), reg.value() ) - - self.textArea.setPlainText( s ) - - - def getRegisterSet(self): - regSet=[] - try: - i = 0 - while True: - reg = pykd.cpuReg(i) - regSet.append(reg) - i += 1 - - except pykd.BaseException: - pass - - return regSet - - -class StackWidget( QDockWidget ): - - def __init__( self ): - QDockWidget.__init__( self ) - self.setWindowTitle( "Stack" ) - self.textArea = QTextEdit() - self.setWidget( self.textArea ) - - def onUpdate( self ): - - s = "" - - stackFrames = pykd.getCurrentStack() - for frame in stackFrames: - s += pykd.findSymbol( frame.instructionOffset ) + " (%x)" % frame.instructionOffset + "\n" - - self.textArea.setPlainText( s ) - - -class MainForm( QMainWindow ): - - updated = Signal() - - def __init__( self ): - - - QMainWindow.__init__( self, None ) - self.setWindowTitle("Pykd Debugger Sample") - self.setDockNestingEnabled( True ) - - self.goThread = None - - - fileMenu = QMenu( "&File" ) - fileMenu.addAction( "Open process...", self.onOpenProcess ) - fileMenu.addAction( "Exit", self.onExit ) - self.menuBar().addMenu( fileMenu ) - - - debugMenu = QMenu( "Debug" ) - debugMenu.addAction( "Break", self.onBreak ) - debugMenu.addAction( "Go", self.onGo ) - debugMenu.addAction( "Step", self.onStep ) - self.menuBar().addMenu( debugMenu ) - - - viewMenu = QMenu( "View" ) - viewMenu.addAction( "Disasm", self.onDisasmShow ) - viewMenu.addAction( "Regsiters", self.onRegistersShow ) - viewMenu.addAction( "Stack", self.onStackShow ) - self.menuBar().addMenu( viewMenu ) - - self.disasmWidget = DisasmWidget() - self.disasmWidget.setVisible( False ) - self.addDockWidget( Qt.LeftDockWidgetArea, self.disasmWidget ) - self.updated.connect(self.disasmWidget.onUpdate ) - - self.registersWidget = RegistersWidget() - self.registersWidget.setVisible( False ) - self.addDockWidget( Qt.LeftDockWidgetArea, self.registersWidget ) - self.updated.connect(self.registersWidget.onUpdate ) - - self.stackWidget = StackWidget() - self.stackWidget.setVisible( False ) - self.addDockWidget( Qt.LeftDockWidgetArea, self.stackWidget ) - self.updated.connect(self.stackWidget.onUpdate ) - - self.resize( 800, 600 ) - - - - def stopGoThread( self ): - - if self.goThread != None and self.goThread.isRunning(): - self.goThread.quit() - self.goThread.wait(10000) - - - def event( self, ev ): - - if ev.type() == QEvent.User + 1: - self.onUpdate() - return True - else: - return QMainWindow.event( self, ev ) - - - - def onOpenProcess( self ): - fileDlg = QFileDialog( self ) - fileDlg.setNameFilter( self.tr("Executable (*.exe)" ) ) - - pykd.startProcess( fileDlg.getOpenFileName()[0] ) - - self.goThread = GoThread( pykd.go ) - - - def onBreak( self ): - pykd.breakin() - - def onGo( self ): - self.stopGoThread() - self.goThread = GoThread( pykd.go ) - - def onStep( self ): - self.stopGoThread() - self.goThread = GoThread( pykd.step ) - - def onExit( self ): - self.close() - - def onDisasmShow( self ): - self.disasmWidget.setVisible( not self.disasmWidget.isVisible() ) - - def onRegistersShow( self ): - self.registersWidget.setVisible( not self.registersWidget.isVisible() ) - - - def onStackShow( self ): - self.stackWidget.setVisible( not self.stackWidget.isVisible() ) - - def onUpdate( self ): - self.updated.emit() - - -def main(): - - global app - global mainForm - - app = QApplication( [] ) - mainForm = MainForm() - mainForm.show() - exitres = app.exec_() - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/samples/debug/debug.py b/samples/debug/debug.py new file mode 100644 index 0000000..8a8e34e --- /dev/null +++ b/samples/debug/debug.py @@ -0,0 +1,119 @@ +# +# +# + +from PySide.QtCore import * +from PySide.QtGui import * + +import pykd +import widgets + +class UpdateEvent( QEvent ): + def __init__(self): + QEvent.__init__(self, QEvent.Type(QEvent.User + 1)) + + +class GoThread( QThread ): + + def __init__(self, func): + QThread.__init__(self) + self.start() + self.func = func + + def run(self): + self.func() + app.postEvent( mainForm, UpdateEvent() ) + self.exit() + + +class MainForm( QMainWindow ): + + updated = Signal() + + def __init__( self ): + + + QMainWindow.__init__( self, None ) + self.setWindowTitle("Pykd Debugger Sample") + self.setDockNestingEnabled( True ) + + self.goThread = None + + + self.fileMenu = QMenu( "&File" ) + self.fileMenu.addAction( "Open process...", self.onOpenProcess ) + self.fileMenu.addAction( "Exit", self.onExit ) + self.menuBar().addMenu( self.fileMenu ) + + + self.debugMenu = QMenu( "Debug" ) + self.debugMenu.addAction( "Break", self.onBreak ) + self.debugMenu.addAction( "Go", self.onGo ) + self.debugMenu.addAction( "Step", self.onStep ) + self.menuBar().addMenu( self.debugMenu ) + + + self.viewMenu = QMenu( "View" ) + self.menuBar().addMenu( self.viewMenu ) + + self.resize( 800, 600 ) + + widgets.register( self ) + + + def stopGoThread( self ): + + if self.goThread != None and self.goThread.isRunning(): + self.goThread.quit() + self.goThread.wait(10000) + + + def event( self, ev ): + + if ev.type() == QEvent.User + 1: + self.onUpdate() + return True + else: + return QMainWindow.event( self, ev ) + + + + def onOpenProcess( self ): + fileDlg = QFileDialog( self ) + fileDlg.setNameFilter( self.tr("Executable (*.exe)" ) ) + + pykd.startProcess( fileDlg.getOpenFileName()[0] ) + + self.goThread = GoThread( pykd.go ) + + + def onBreak( self ): + pykd.breakin() + + def onGo( self ): + self.stopGoThread() + self.goThread = GoThread( pykd.go ) + + def onStep( self ): + self.stopGoThread() + self.goThread = GoThread( pykd.step ) + + def onExit( self ): + self.close() + + def onUpdate( self ): + self.updated.emit() + + +def main(): + + global app + global mainForm + + app = QApplication( [] ) + mainForm = MainForm() + mainForm.show() + exitres = app.exec_() + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/samples/debug/widgets/__init__.py b/samples/debug/widgets/__init__.py new file mode 100644 index 0000000..204a79c --- /dev/null +++ b/samples/debug/widgets/__init__.py @@ -0,0 +1,13 @@ + +import regs +import disasm +import stack +import cmd + + +def register( mainFrame ): + cmd.CmdWidget( mainFrame ) + regs.RegistersWidget( mainFrame ) + disasm.DisasmWidget( mainFrame ) + stack.StackWidget( mainFrame ) + \ No newline at end of file diff --git a/samples/debug/widgets/cmd.py b/samples/debug/widgets/cmd.py new file mode 100644 index 0000000..cd46870 --- /dev/null +++ b/samples/debug/widgets/cmd.py @@ -0,0 +1,50 @@ + + +from PySide.QtCore import * +from PySide.QtGui import * + +import pykd + + +class CmdWidget( QDockWidget ): + + def __init__( self, parent ): + QDockWidget.__init__( self ) + self.setWindowTitle( "Commands" ) + + self.inCmd = QLineEdit() + self.inCmd.returnPressed.connect( self.onCommandInput ) + + self.outCmd = QTextEdit() + self.outCmd.setReadOnly( True ) + + + layout = QVBoxLayout() + layout.addWidget( self.outCmd ) + layout.addWidget( self.inCmd ) + + + + layoutWidget = QWidget() + layoutWidget.setLayout( layout ) + + self.setWidget( layoutWidget ) + + self.setVisible( False ) + parent.addDockWidget( Qt.LeftDockWidgetArea, self ) + parent.viewMenu.addAction( "Commands", self.onCommandsShow ) + + + def onCommandsShow( self ): + self.setVisible( not self.isVisible() ) + + + def onCommandInput( self ): + self.inCmd.setReadOnly( True ) + cmdLine = self.inCmd.text() + self.inCmd.setText( "running %s" % cmdLine ) + self.outCmd.append( pykd.dbgCommand( cmdLine ) ) + self.inCmd.setText( "" ) + self.inCmd.setReadOnly( False ) + + diff --git a/samples/debug/widgets/disasm.py b/samples/debug/widgets/disasm.py new file mode 100644 index 0000000..d5d4fd0 --- /dev/null +++ b/samples/debug/widgets/disasm.py @@ -0,0 +1,28 @@ + +from PySide.QtCore import * +from PySide.QtGui import * + +import pykd + + +class DisasmWidget( QDockWidget ): + + def __init__( self, parent ): + QDockWidget.__init__( self ) + self.setWindowTitle( "Disassembler" ) + self.textArea = QTextEdit() + self.setWidget( self.textArea ) + self.setVisible( False ) + parent.addDockWidget( Qt.LeftDockWidgetArea, self ) + parent.updated.connect(self.onUpdate ) + parent.viewMenu.addAction( "Disassembler", self.onDisassemblerShow ) + + + def onUpdate( self ): + disasm = pykd.disasm() + self.textArea.setPlainText( "\n".join( [ disasm.disasm() for i in xrange(50) ] ) ) + + + def onDisassemblerShow( self ): + self.setVisible( not self.isVisible() ) + \ No newline at end of file diff --git a/samples/debug/widgets/regs.py b/samples/debug/widgets/regs.py new file mode 100644 index 0000000..82f9ef2 --- /dev/null +++ b/samples/debug/widgets/regs.py @@ -0,0 +1,48 @@ + + +from PySide.QtCore import * +from PySide.QtGui import * + +import pykd + + +class RegistersWidget( QDockWidget ): + + def __init__( self, parent ): + QDockWidget.__init__( self ) + self.setWindowTitle( "Registers" ) + self.textArea = QTextEdit() + self.setWidget( self.textArea ) + self.setVisible( False ) + parent.addDockWidget( Qt.LeftDockWidgetArea, self ) + parent.updated.connect(self.onUpdate ) + parent.viewMenu.addAction( "Regsiters", self.onRegistersShow ) + + + def onUpdate( self ): + + s = "" + + for reg in self.getRegisterSet(): + s += "%s %x ( %d )\r\n" % ( reg.name(), reg.value(), reg.value() ) + + self.textArea.setPlainText( s ) + + + def getRegisterSet(self): + regSet=[] + try: + i = 0 + while True: + reg = pykd.cpuReg(i) + regSet.append(reg) + i += 1 + + except pykd.BaseException: + pass + + return regSet + + def onRegistersShow( self ): + self.setVisible( not self.isVisible() ) + diff --git a/samples/debug/widgets/stack.py b/samples/debug/widgets/stack.py new file mode 100644 index 0000000..91a83fa --- /dev/null +++ b/samples/debug/widgets/stack.py @@ -0,0 +1,32 @@ + +from PySide.QtCore import * +from PySide.QtGui import * + +import pykd + + +class StackWidget( QDockWidget ): + + def __init__( self, parent ): + QDockWidget.__init__( self ) + self.setWindowTitle( "Stack" ) + self.textArea = QTextEdit() + self.setWidget( self.textArea ) + self.setVisible( False ) + parent.addDockWidget( Qt.LeftDockWidgetArea, self ) + parent.updated.connect(self.onUpdate ) + parent.viewMenu.addAction( "Stack", self.onStackShow ) + + + def onUpdate( self ): + s = "" + + stackFrames = pykd.getCurrentStack() + for frame in stackFrames: + s += pykd.findSymbol( frame.instructionOffset ) + " (%x)" % frame.instructionOffset + "\n" + + self.textArea.setPlainText( s ) + + + def onStackShow( self ): + self.setVisible( not self.isVisible() ) From ed042c6107c71216bf73d75dec0c05bc90b7b0a6 Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Wed, 5 Oct 2011 11:34:40 +0000 Subject: [PATCH 19/21] [pykd] updated: changelog git-svn-id: https://pykd.svn.codeplex.com/svn@70217 9b283d60-5439-405e-af05-b73fd8c4d996 --- changelog | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/changelog b/changelog index d07be10..fff709e 100644 --- a/changelog +++ b/changelog @@ -1,5 +1,6 @@ -version 0.0.20 29/09/2011 +version 0.0.20 05/10/2011 +[+] added : routine getProcessorType ( return type of physical processor ) [+] added : routine breakin ( Break into debugger ) [+] added : cpuReg constructor with index parameter [+] added : attachProcess routine ( attach debugger to the exsisting process ) From 3e06179b52d83cd8d273908b00c4aadcf2485c3f Mon Sep 17 00:00:00 2001 From: "SND\\air_max_cp" Date: Thu, 6 Oct 2011 21:17:14 +0000 Subject: [PATCH 20/21] setup: version increment git-svn-id: https://pykd.svn.codeplex.com/svn@70234 9b283d60-5439-405e-af05-b73fd8c4d996 --- setup/pykd_setup_common.nsh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup/pykd_setup_common.nsh b/setup/pykd_setup_common.nsh index 4e3070a..0f28456 100644 --- a/setup/pykd_setup_common.nsh +++ b/setup/pykd_setup_common.nsh @@ -27,7 +27,7 @@ SetCompressor LZMA !define PRODUCT_SHORT_NAME "pykd" !define PRODUCT_FULL_NAME "Python extension for WinDbg" -!define PRODUCT_VERSION "0.0.0.19" +!define PRODUCT_VERSION "0.0.0.20" !define PRODUCT_URL "http://pykd.codeplex.com/" !define PRODUCT_NAME_AND_VERSION "${PRODUCT_FULL_NAME} ${PRODUCT_ARCH} ${PRODUCT_VERSION}" !define PRODUCT_MANUFACTURER "PyKd Team" From 6db15dc2c71f29804b6b82545524459e4f9e9ee0 Mon Sep 17 00:00:00 2001 From: "SND\\air_max_cp" Date: Fri, 7 Oct 2011 06:48:17 +0000 Subject: [PATCH 21/21] [snippets] stlp.py: workaround for missing ptr_t type. git-svn-id: https://pykd.svn.codeplex.com/svn@70241 9b283d60-5439-405e-af05-b73fd8c4d996 --- snippets/stlp.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/snippets/stlp.py b/snippets/stlp.py index 4376c79..e5c4d5a 100644 --- a/snippets/stlp.py +++ b/snippets/stlp.py @@ -3,15 +3,18 @@ import sys from pykd import * +def ptr_t(): + return is64bitSystem() and ulonglong_t or ulong_t + StlpNodeBase = typeInfo() -StlpNodeBase.append(ptr_t, "color") -StlpNodeBase.append(ptr_t, "parent") -StlpNodeBase.append(ptr_t, "left") -StlpNodeBase.append(ptr_t, "right") +StlpNodeBase.append(ptr_t(), "color") +StlpNodeBase.append(ptr_t(), "parent") +StlpNodeBase.append(ptr_t(), "left") +StlpNodeBase.append(ptr_t(), "right") StlpMap = typeInfo() StlpMap.append(StlpNodeBase, "header") -StlpMap.append(ptr_t, "node_count") +StlpMap.append(ptr_t(), "node_count") def stlpMapIncrement(addr): node = StlpNodeBase.load(addr)