[0.2.x] added : stackFrame class

git-svn-id: https://pykd.svn.codeplex.com/svn@78613 9b283d60-5439-405e-af05-b73fd8c4d996
This commit is contained in:
SND\kernelnet_cp 2012-08-08 08:01:25 +00:00 committed by Mikhail I. Izmestev
parent 8c7ef0441d
commit ced206cc0a
7 changed files with 135 additions and 57 deletions

View File

@ -32,8 +32,16 @@ std::string getRegNameByIndex( ULONG index );
BaseTypeVariant getRegVariantValue( ULONG index ); BaseTypeVariant getRegVariantValue( ULONG index );
ULONG64 getRegInstructionPointer(); ULONG64 getRegInstructionPointer();
// ýòî íóæíî ñäåëàòü ïî-äðóãîìó! // Stack and local variables
//std::string getSymbolByOffset( ULONG64 offset ); 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 );
}; };

View File

@ -417,6 +417,10 @@
/> />
</FileConfiguration> </FileConfiguration>
</File> </File>
<File
RelativePath=".\stkframe.cpp"
>
</File>
<File <File
RelativePath=".\typedvar.cpp" RelativePath=".\typedvar.cpp"
> >
@ -479,6 +483,10 @@
RelativePath=".\stdafx.h" RelativePath=".\stdafx.h"
> >
</File> </File>
<File
RelativePath=".\stkframe.h"
>
</File>
<File <File
RelativePath=".\symengine.h" RelativePath=".\symengine.h"
> >

View File

@ -17,6 +17,7 @@
#include "typedvar.h" #include "typedvar.h"
#include "cpureg.h" #include "cpureg.h"
#include "disasm.h" #include "disasm.h"
#include "stkframe.h"
using namespace pykd; 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( loadSignQWords_, loadSignQWords, 2, 3 );
BOOST_PYTHON_FUNCTION_OVERLOADS( compareMemory_, compareMemory, 3, 4 ); BOOST_PYTHON_FUNCTION_OVERLOADS( compareMemory_, compareMemory, 3, 4 );
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS( StackFrame_getLocals, StackFrame::getLocals, 0, 1 );
BOOST_PYTHON_MODULE( pykd ) BOOST_PYTHON_MODULE( pykd )
{ {
@ -157,6 +159,11 @@ BOOST_PYTHON_MODULE( pykd )
python::def( "wrmsr", &setMSR, python::def( "wrmsr", &setMSR,
"Set MSR value" ); "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", "intBase", python::no_init ) python::class_<intBase>( "intBase", "intBase", python::no_init )
.def( python::init<python::object&>() ) .def( python::init<python::object&>() )
.def( "__eq__", &intBase::eq ) .def( "__eq__", &intBase::eq )
@ -294,6 +301,23 @@ BOOST_PYTHON_MODULE( pykd )
.def( "name", &CpuReg::name, "The name of the regsiter" ) .def( "name", &CpuReg::name, "The name of the regsiter" )
.def( "index", &CpuReg::index, "The index of thr register" ); .def( "index", &CpuReg::index, "The index of thr register" );
python::class_<StackFrame>( "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>("disasm", "Class disassemble a processor instructions" ) python::class_<Disasm>("disasm", "Class disassemble a processor instructions" )
.def( python::init<>( "constructor" ) ) .def( python::init<>( "constructor" ) )
.def( python::init<ULONG64>( boost::python::args("offset"), "constructor" ) ) .def( python::init<ULONG64>( boost::python::args("offset"), "constructor" ) )

View File

@ -41,6 +41,11 @@
//#endif // __field_ecount_opt //#endif // __field_ecount_opt
// //
// //
#include <vector>
#include <string>
#include <list>
#define BOOST_PYTHON_STATIC_LIB #define BOOST_PYTHON_STATIC_LIB
#pragma warning(push) #pragma warning(push)

View File

@ -4,6 +4,7 @@
#include "stdafx.h" #include "stdafx.h"
#include "stkframe.h" #include "stkframe.h"
#include "dbgengine.h"
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -11,14 +12,13 @@ namespace pykd {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
StackFrame::StackFrame(DebugClientPtr client, const DEBUG_STACK_FRAME &frame) StackFrame::StackFrame( const STACK_FRAME_DESC& desc )
: m_client(client)
, m_frameNumber(frame.FrameNumber)
, m_instructionOffset(frame.InstructionOffset)
, m_returnOffset(frame.ReturnOffset)
, m_frameOffset(frame.FrameOffset)
, m_stackOffset(frame.StackOffset)
{ {
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) ULONG frameCount = getStackTraceFrameCount();
: m_client->getThreadContext()->forkByStackFrame(*this);
return m_client->getLocals(ctx); std::vector<STACK_FRAME_DESC> 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 } // namespace pykd
////////////////////////////////////////////////////////////////////////////////

View File

@ -4,7 +4,7 @@
#pragma once #pragma once
#include "dbgclient.h" #include "dbgengine.h"
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -15,24 +15,28 @@ namespace pykd {
class StackFrame class StackFrame
{ {
public: public:
StackFrame(DebugClientPtr client, const DEBUG_STACK_FRAME &frame); StackFrame( const STACK_FRAME_DESC& desc );
ULONG m_frameNumber; // python::dict getLocals(ContextPtr ctx = ContextPtr());
ULONG64 m_instructionOffset;
ULONG64 m_returnOffset;
ULONG64 m_frameOffset;
ULONG64 m_stackOffset;
python::dict getLocals(ContextPtr ctx = ContextPtr());
std::string print() const; 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 } // namespace pykd
////////////////////////////////////////////////////////////////////////////////

View File

@ -333,34 +333,6 @@ bool is64bitSystem()
return hres == S_OK; 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 ) 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<DEBUG_STACK_FRAME> 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 } // end pykd namespace