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