From ced206cc0ac46681402692d9c67e80a33cbe6e5e Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Wed, 8 Aug 2012 08:01:25 +0000 Subject: [PATCH] [0.2.x] added : stackFrame class git-svn-id: https://pykd.svn.codeplex.com/svn@78613 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/dbgengine.h | 14 +++++++-- pykd/pykd_2008.vcproj | 8 +++++ pykd/pymod.cpp | 24 +++++++++++++++ pykd/stdafx.h | 5 +++ pykd/stkframe.cpp | 37 ++++++++++++++-------- pykd/stkframe.h | 32 ++++++++++--------- pykd/win/dbgeng.cpp | 72 ++++++++++++++++++++++++++----------------- 7 files changed, 135 insertions(+), 57 deletions(-) diff --git a/pykd/dbgengine.h b/pykd/dbgengine.h index aa2b7f2..8d768a3 100644 --- a/pykd/dbgengine.h +++ b/pykd/dbgengine.h @@ -32,8 +32,16 @@ std::string getRegNameByIndex( ULONG index ); BaseTypeVariant getRegVariantValue( ULONG index ); ULONG64 getRegInstructionPointer(); -// это нужно сделать по-другому! -//std::string getSymbolByOffset( ULONG64 offset ); - +// Stack and local variables +struct STACK_FRAME_DESC { + ULONG number; + ULONG64 instructionOffset; + ULONG64 returnOffset; + ULONG64 frameOffset; + ULONG64 stackOffset; +}; + +ULONG getStackTraceFrameCount(); +void getStackTrace( STACK_FRAME_DESC* frames, ULONG frameCount, ULONG* frameReturned = NULL ); }; diff --git a/pykd/pykd_2008.vcproj b/pykd/pykd_2008.vcproj index dcff298..b7ea18b 100644 --- a/pykd/pykd_2008.vcproj +++ b/pykd/pykd_2008.vcproj @@ -417,6 +417,10 @@ /> + + @@ -479,6 +483,10 @@ RelativePath=".\stdafx.h" > + + diff --git a/pykd/pymod.cpp b/pykd/pymod.cpp index 11ecdba..6d3bbbe 100644 --- a/pykd/pymod.cpp +++ b/pykd/pymod.cpp @@ -17,6 +17,7 @@ #include "typedvar.h" #include "cpureg.h" #include "disasm.h" +#include "stkframe.h" using namespace pykd; @@ -43,6 +44,7 @@ BOOST_PYTHON_FUNCTION_OVERLOADS( loadSignDWords_, loadSignDWords, 2, 3 ); BOOST_PYTHON_FUNCTION_OVERLOADS( loadSignQWords_, loadSignQWords, 2, 3 ); BOOST_PYTHON_FUNCTION_OVERLOADS( compareMemory_, compareMemory, 3, 4 ); +BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS( StackFrame_getLocals, StackFrame::getLocals, 0, 1 ); BOOST_PYTHON_MODULE( pykd ) { @@ -157,6 +159,11 @@ BOOST_PYTHON_MODULE( pykd ) python::def( "wrmsr", &setMSR, "Set MSR value" ); + // stack and local variables + python::def( "getCurrentStack", &getCurrentStack, + "Return a current stack as a list of stackFrame objects" ); + + python::class_( "intBase", "intBase", python::no_init ) .def( python::init() ) .def( "__eq__", &intBase::eq ) @@ -294,6 +301,23 @@ BOOST_PYTHON_MODULE( pykd ) .def( "name", &CpuReg::name, "The name of the regsiter" ) .def( "index", &CpuReg::index, "The index of thr register" ); + python::class_( "stackFrame", + "Class representing a frame of the call stack", python::no_init ) + .def_readonly( "instructionOffset", &StackFrame::m_instructionOffset, + "Return a frame's instruction offset" ) + .def_readonly( "returnOffset", &StackFrame::m_returnOffset, + "Return a frame's return offset" ) + .def_readonly( "frameOffset", &StackFrame::m_frameOffset, + "Return a frame's offset" ) + .def_readonly( "stackOffset", &StackFrame::m_stackOffset, + "Return a frame's stack offset" ) + .def_readonly( "frameNumber", &StackFrame::m_frameNumber, + "Return a frame's number" ) + //.def( "getLocals", &StackFrame::getLocals, StackFrame_getLocals( python::args( "ctx" ), + // "Get list of local variables for this stack frame" ) ) + .def( "__str__", &StackFrame::print, + "Return stacks frame as a string"); + python::class_("disasm", "Class disassemble a processor instructions" ) .def( python::init<>( "constructor" ) ) .def( python::init( boost::python::args("offset"), "constructor" ) ) diff --git a/pykd/stdafx.h b/pykd/stdafx.h index b79c250..5f8e083 100644 --- a/pykd/stdafx.h +++ b/pykd/stdafx.h @@ -41,6 +41,11 @@ //#endif // __field_ecount_opt // // + +#include +#include +#include + #define BOOST_PYTHON_STATIC_LIB #pragma warning(push) diff --git a/pykd/stkframe.cpp b/pykd/stkframe.cpp index 639da60..e2b18f1 100644 --- a/pykd/stkframe.cpp +++ b/pykd/stkframe.cpp @@ -4,6 +4,7 @@ #include "stdafx.h" #include "stkframe.h" +#include "dbgengine.h" //////////////////////////////////////////////////////////////////////////////// @@ -11,14 +12,13 @@ namespace pykd { //////////////////////////////////////////////////////////////////////////////// -StackFrame::StackFrame(DebugClientPtr client, const DEBUG_STACK_FRAME &frame) - : m_client(client) - , m_frameNumber(frame.FrameNumber) - , m_instructionOffset(frame.InstructionOffset) - , m_returnOffset(frame.ReturnOffset) - , m_frameOffset(frame.FrameOffset) - , m_stackOffset(frame.StackOffset) +StackFrame::StackFrame( const STACK_FRAME_DESC& desc ) { + m_frameNumber = desc.number; + m_instructionOffset = desc.instructionOffset; + m_returnOffset = desc.returnOffset; + m_frameOffset = desc.frameOffset; + m_stackOffset = desc.stackOffset; } //////////////////////////////////////////////////////////////////////////////// @@ -40,16 +40,29 @@ std::string StackFrame::print() const //////////////////////////////////////////////////////////////////////////////// -python::dict StackFrame::getLocals(ContextPtr ctx /*= ContextPtr()*/) +python::list getCurrentStack() { - ctx = ctx ? ctx->forkByStackFrame(*this) - : m_client->getThreadContext()->forkByStackFrame(*this); - return m_client->getLocals(ctx); + ULONG frameCount = getStackTraceFrameCount(); + + std::vector frames(frameCount); + + getStackTrace( &frames[0], frameCount ); + + python::list frameList; + + for ( ULONG i = 0; i < frameCount; ++i ) + { + python::object frameObj( StackFrame( frames.at(i) ) ); + + frameList.append( frameObj ); + } + + return frameList; } //////////////////////////////////////////////////////////////////////////////// } // namespace pykd -//////////////////////////////////////////////////////////////////////////////// + diff --git a/pykd/stkframe.h b/pykd/stkframe.h index 7f1b712..75501f1 100644 --- a/pykd/stkframe.h +++ b/pykd/stkframe.h @@ -4,7 +4,7 @@ #pragma once -#include "dbgclient.h" +#include "dbgengine.h" //////////////////////////////////////////////////////////////////////////////// @@ -15,24 +15,28 @@ namespace pykd { class StackFrame { public: - StackFrame(DebugClientPtr client, const DEBUG_STACK_FRAME &frame); + StackFrame( const STACK_FRAME_DESC& desc ); - ULONG m_frameNumber; - - ULONG64 m_instructionOffset; - ULONG64 m_returnOffset; - ULONG64 m_frameOffset; - ULONG64 m_stackOffset; - - python::dict getLocals(ContextPtr ctx = ContextPtr()); +// python::dict getLocals(ContextPtr ctx = ContextPtr()); std::string print() const; -private: - DebugClientPtr m_client; + +public: + + ULONG m_frameNumber; + ULONG64 m_instructionOffset; + ULONG64 m_returnOffset; + ULONG64 m_frameOffset; + ULONG64 m_stackOffset; + }; -//////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +python::list getCurrentStack(); + +/////////////////////////////////////////////////////////////////////////////// } // namespace pykd -//////////////////////////////////////////////////////////////////////////////// + diff --git a/pykd/win/dbgeng.cpp b/pykd/win/dbgeng.cpp index 2d8c5f5..03095df 100644 --- a/pykd/win/dbgeng.cpp +++ b/pykd/win/dbgeng.cpp @@ -333,34 +333,6 @@ bool is64bitSystem() return hres == S_OK; } -/////////////////////////////////////////////////////////////////////////////////// - -std::string getSymbolByOffset( ULONG64 offset ) -{ - PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate ); - - HRESULT hres; - - char nameBuf[0x100]; - - hres = - g_dbgEng->symbols->GetNameByOffset( - offset, - nameBuf, - sizeof(nameBuf), - NULL, - NULL ); - - std::string fullName( nameBuf ); - - size_t symPos = fullName.find ( '!' ) + 1; - - std::string symbolName; - symbolName.assign( fullName, symPos, fullName.length() - symPos ); - - return symbolName; -} - /////////////////////////////////////////////////////////////////////////////// ULONG64 loadMSR( ULONG msr ) @@ -498,6 +470,50 @@ ULONG64 getRegInstructionPointer() /////////////////////////////////////////////////////////////////////////////// +ULONG getStackTraceFrameCount() +{ + PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate ); + + HRESULT hres; + ULONG filledFrames; + + hres = g_dbgEng->control->GetStackTrace( 0, 0, 0, NULL, 0, &filledFrames ); + if ( FAILED( hres ) ) + throw DbgException( "IDebugControl::GetStackTrace failed" ); + + return filledFrames; +} + +/////////////////////////////////////////////////////////////////////////////// + +void getStackTrace( STACK_FRAME_DESC* frames, ULONG frameCount, ULONG* frameReturned ) +{ + PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate ); + + HRESULT hres; + + ULONG filledFrames; + std::vector stack(frameCount); + + hres = g_dbgEng->control->GetStackTrace( 0, 0, 0, &stack[0], frameCount, &filledFrames); + if ( FAILED( hres ) ) + throw DbgException( "IDebugControl::GetStackTrace failed" ); + + for ( ULONG i = 0; i < filledFrames; ++i ) + { + frames[i].number = stack[i].FrameNumber; + frames[i].instructionOffset = stack[i].InstructionOffset; + frames[i].returnOffset = stack[i].ReturnOffset; + frames[i].frameOffset = stack[i].FrameOffset; + frames[i].stackOffset = stack[i].StackOffset; + } + + if ( frameReturned ) + *frameReturned = filledFrames; +} + +/////////////////////////////////////////////////////////////////////////////// + } // end pykd namespace