mirror of
https://github.com/ivellioscolin/pykd.git
synced 2025-04-21 04:13:22 +08:00
[0.2.x] updated : working with local vars
git-svn-id: https://pykd.svn.codeplex.com/svn@81665 9b283d60-5439-405e-af05-b73fd8c4d996
This commit is contained in:
parent
6dc5ac2f20
commit
a1a69b9826
@ -1,209 +0,0 @@
|
|||||||
|
|
||||||
#include <stdafx.h>
|
|
||||||
|
|
||||||
#include "localvar.h"
|
|
||||||
#include "module.h"
|
|
||||||
#include "symengine.h"
|
|
||||||
#include "dbgengine.h"
|
|
||||||
#include "typedvar.h"
|
|
||||||
|
|
||||||
namespace pykd {
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
python::dict getLocals()
|
|
||||||
{
|
|
||||||
return getLocalsByFrame( getCurrentStackFrame() );
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
class BuildLocals
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
BuildLocals( ModulePtr mod, const StackFrame &frame )
|
|
||||||
: m_mod(mod), m_frame(frame), m_formalGen(0)
|
|
||||||
{
|
|
||||||
m_ipRva = static_cast<ULONG>(m_frame.m_instructionOffset - m_mod->getBase());
|
|
||||||
}
|
|
||||||
|
|
||||||
void process( SymbolPtr symParent );
|
|
||||||
|
|
||||||
python::dict &getResult() {
|
|
||||||
return m_dct;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void addVar(SymbolPtr symVar);
|
|
||||||
|
|
||||||
private:
|
|
||||||
ModulePtr m_mod;
|
|
||||||
const StackFrame &m_frame;
|
|
||||||
python::dict m_dct;
|
|
||||||
size_t m_formalGen;
|
|
||||||
ULONG m_ipRva;
|
|
||||||
};
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
void BuildLocals::process(
|
|
||||||
SymbolPtr symParent
|
|
||||||
)
|
|
||||||
{
|
|
||||||
// add vars from current scope
|
|
||||||
SymbolPtrList symList = symParent->findChildren(SymTagData);
|
|
||||||
SymbolPtrList::iterator itVar = symList.begin();
|
|
||||||
for (; itVar != symList.end(); ++itVar)
|
|
||||||
addVar(*itVar);
|
|
||||||
|
|
||||||
// find inners scopes
|
|
||||||
symList = symParent->findChildren(SymTagBlock);
|
|
||||||
SymbolPtrList::iterator itScope = symList.begin();
|
|
||||||
for (; itScope != symList.end(); ++itScope)
|
|
||||||
{
|
|
||||||
SymbolPtr scope = *itScope;
|
|
||||||
ULONG scopeRva = scope->getRva();
|
|
||||||
if (scopeRva <= m_ipRva && (scopeRva + scope->getSize()) > m_ipRva)
|
|
||||||
process(scope);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
void BuildLocals::addVar(SymbolPtr symVar)
|
|
||||||
{
|
|
||||||
std::string name;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
name = symVar->getName();
|
|
||||||
if (name.empty())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
catch (const SymbolException &except)
|
|
||||||
{
|
|
||||||
DBG_UNREFERENCED_PARAMETER(except);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_dct.has_key(name))
|
|
||||||
{
|
|
||||||
std::stringstream sstream;
|
|
||||||
sstream << name << "#" << std::dec << ++m_formalGen;
|
|
||||||
name = sstream.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_ASSERT(!m_dct.has_key(name));
|
|
||||||
if (m_dct.has_key(name))
|
|
||||||
return;
|
|
||||||
|
|
||||||
ULONG64 varAddr;
|
|
||||||
const LocationType locType = static_cast<LocationType>(symVar->getLocType());
|
|
||||||
switch (locType)
|
|
||||||
{
|
|
||||||
case LocIsStatic:
|
|
||||||
varAddr = m_mod->getBase() + symVar->getRva();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case LocIsRegRel:
|
|
||||||
{
|
|
||||||
RegRealativeId rri;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
rri = static_cast<RegRealativeId>(symVar->getRegRealativeId());
|
|
||||||
}
|
|
||||||
catch (const DbgException &except)
|
|
||||||
{
|
|
||||||
DBG_UNREFERENCED_PARAMETER(except);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
varAddr = m_frame.getValue(rri, symVar->getOffset());
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
BOOST_ASSERT(LocIsEnregistered == locType);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
TypeInfoPtr typeInfo = TypeInfo::getTypeInfo(symVar);
|
|
||||||
TypedVarPtr typedVar = TypedVar::getTypedVarByTypeInfo(typeInfo, varAddr);
|
|
||||||
typedVar->setDataKind( symVar->getDataKind() );
|
|
||||||
m_dct[name] = typedVar;
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
static bool IsInDebugRange(
|
|
||||||
SymbolPtr func,
|
|
||||||
ULONG ipRva
|
|
||||||
)
|
|
||||||
{
|
|
||||||
SymbolPtrList lstFuncDebugStart;
|
|
||||||
SymbolPtrList lstFuncDebugEnd;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
lstFuncDebugStart = func->findChildren(SymTagFuncDebugStart);
|
|
||||||
if (1 != lstFuncDebugStart.size())
|
|
||||||
{
|
|
||||||
BOOST_ASSERT(lstFuncDebugStart.empty());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
lstFuncDebugEnd = func->findChildren(SymTagFuncDebugEnd);
|
|
||||||
if (1 != lstFuncDebugEnd.size())
|
|
||||||
{
|
|
||||||
BOOST_ASSERT(lstFuncDebugEnd.empty());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (const SymbolException &except)
|
|
||||||
{
|
|
||||||
DBG_UNREFERENCED_PARAMETER(except);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
((*lstFuncDebugStart.begin())->getRva() <= ipRva) &&
|
|
||||||
((*lstFuncDebugEnd.begin())->getRva() >= ipRva);
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
python::dict getLocalsByFrame( const StackFrame &frame )
|
|
||||||
{
|
|
||||||
// query target fuction by $ip register
|
|
||||||
ModulePtr mod;
|
|
||||||
SymbolPtr func;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
mod = Module::loadModuleByOffset(frame.m_instructionOffset);
|
|
||||||
LONG displacemnt;
|
|
||||||
func = mod->getSymbolByVa(frame.m_instructionOffset, SymTagFunction, &displacemnt );
|
|
||||||
}
|
|
||||||
catch (const DbgException &except)
|
|
||||||
{
|
|
||||||
DBG_UNREFERENCED_PARAMETER(except);
|
|
||||||
return python::dict();
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef _DEBUG
|
|
||||||
std::string funcName;
|
|
||||||
funcName = func->getName();
|
|
||||||
#endif // _DEBUG
|
|
||||||
|
|
||||||
if (!IsInDebugRange(func, static_cast<ULONG>(frame.m_instructionOffset - mod->getBase())))
|
|
||||||
{
|
|
||||||
// not in debug range
|
|
||||||
return python::dict();
|
|
||||||
}
|
|
||||||
|
|
||||||
BuildLocals buildLocals(mod, frame);
|
|
||||||
buildLocals.process(func);
|
|
||||||
return buildLocals.getResult();
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
} //end pykd namespace
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "stkframe.h"
|
|
||||||
|
|
||||||
namespace pykd {
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
python::dict getLocals();
|
|
||||||
|
|
||||||
python::dict getLocalsByFrame( const StackFrame &frame );
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
} // end pykd namespace
|
|
||||||
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="windows-1251"?>
|
<?xml version="1.0" encoding="windows-1251"?>
|
||||||
<VisualStudioProject
|
<VisualStudioProject
|
||||||
ProjectType="Visual C++"
|
ProjectType="Visual C++"
|
||||||
Version="9.00"
|
Version="9,00"
|
||||||
Name="pykd"
|
Name="pykd"
|
||||||
ProjectGUID="{FE961905-666F-4908-A212-961465F46F13}"
|
ProjectGUID="{FE961905-666F-4908-A212-961465F46F13}"
|
||||||
RootNamespace="pykd"
|
RootNamespace="pykd"
|
||||||
@ -389,10 +389,6 @@
|
|||||||
RelativePath=".\eventhandler.cpp"
|
RelativePath=".\eventhandler.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
|
||||||
RelativePath=".\localvar.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
<File
|
||||||
RelativePath=".\module.cpp"
|
RelativePath=".\module.cpp"
|
||||||
>
|
>
|
||||||
@ -507,10 +503,6 @@
|
|||||||
RelativePath=".\eventhandler.h"
|
RelativePath=".\eventhandler.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
|
||||||
RelativePath=".\localvar.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
<File
|
||||||
RelativePath=".\module.h"
|
RelativePath=".\module.h"
|
||||||
>
|
>
|
||||||
|
@ -19,7 +19,6 @@
|
|||||||
#include "cpureg.h"
|
#include "cpureg.h"
|
||||||
#include "disasm.h"
|
#include "disasm.h"
|
||||||
#include "stkframe.h"
|
#include "stkframe.h"
|
||||||
#include "localvar.h"
|
|
||||||
#include "bpoint.h"
|
#include "bpoint.h"
|
||||||
|
|
||||||
#include "win/dbgio.h"
|
#include "win/dbgio.h"
|
||||||
@ -245,9 +244,14 @@ BOOST_PYTHON_MODULE( pykd )
|
|||||||
"Set current processor mode by string (X86, ARM, IA64 or X64)" );
|
"Set current processor mode by string (X86, ARM, IA64 or X64)" );
|
||||||
|
|
||||||
// stack and local variables
|
// stack and local variables
|
||||||
python::def( "getCurrentStack", &getCurrentStack,
|
python::def( "getStack", &getCurrentStack,
|
||||||
"Return a current stack as a list of stackFrame objects" );
|
"Return a current stack as a list of stackFrame objects" );
|
||||||
python::def( "getLocals", &getLocals, "Get list of local variables" );
|
python::def( "getFrame", &getCurrentStackFrame,
|
||||||
|
"Return a current stack frame" );
|
||||||
|
python::def( "getLocals", &getLocals,
|
||||||
|
"Get list of local variables" );
|
||||||
|
python::def( "getParams", &getParams,
|
||||||
|
"Get list of function arguments" );
|
||||||
|
|
||||||
// breakpoints
|
// breakpoints
|
||||||
python::def( "setBp", &setSoftwareBp, setSoftwareBp_( python::args( "offset", "callback" ),
|
python::def( "setBp", &setSoftwareBp, setSoftwareBp_( python::args( "offset", "callback" ),
|
||||||
@ -426,7 +430,13 @@ 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",
|
python::class_<ScopeVars,ScopeVarsPtr,boost::noncopyable>( "locals",
|
||||||
|
"Class for access to local vars", python::no_init )
|
||||||
|
.def("__len__", &ScopeVars::getVarCount )
|
||||||
|
.def("__getitem__", &ScopeVars::getVarByIndex )
|
||||||
|
.def("__getitem__", &ScopeVars::getVarByName );
|
||||||
|
|
||||||
|
python::class_<StackFrame, StackFramePtr,boost::noncopyable>( "stackFrame",
|
||||||
"Class representing a frame of the call stack", python::no_init )
|
"Class representing a frame of the call stack", python::no_init )
|
||||||
.def_readonly( "instructionOffset", &StackFrame::m_instructionOffset,
|
.def_readonly( "instructionOffset", &StackFrame::m_instructionOffset,
|
||||||
"Return a frame's instruction offset" )
|
"Return a frame's instruction offset" )
|
||||||
@ -438,8 +448,10 @@ BOOST_PYTHON_MODULE( pykd )
|
|||||||
"Return a frame's stack offset" )
|
"Return a frame's stack offset" )
|
||||||
.def_readonly( "frameNumber", &StackFrame::m_frameNumber,
|
.def_readonly( "frameNumber", &StackFrame::m_frameNumber,
|
||||||
"Return a frame's number" )
|
"Return a frame's number" )
|
||||||
.def( "getLocals", &StackFrame::getLocals,
|
.add_property( "locals", &StackFrame::getLocals,
|
||||||
"Get list of local variables for this stack frame" )
|
"Get list of local variables for this stack frame" )
|
||||||
|
.add_property( "params", &StackFrame::getParams,
|
||||||
|
"Get list of function params" )
|
||||||
.def( "__str__", &StackFrame::print,
|
.def( "__str__", &StackFrame::print,
|
||||||
"Return stacks frame as a string");
|
"Return stacks frame as a string");
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "stkframe.h"
|
#include "stkframe.h"
|
||||||
#include "dbgengine.h"
|
#include "dbgengine.h"
|
||||||
#include "localvar.h"
|
#include "module.h"
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@ -36,14 +36,21 @@ std::string StackFrame::print() const
|
|||||||
sstream << ", stack= 0x" << std::hex << m_stackOffset;
|
sstream << ", stack= 0x" << std::hex << m_stackOffset;
|
||||||
|
|
||||||
return sstream.str();
|
return sstream.str();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
python::dict StackFrame::getLocals() const
|
ScopeVarsPtr StackFrame::getLocals()
|
||||||
{
|
{
|
||||||
return getLocalsByFrame( *this );
|
return ScopeVarsPtr( new LocalVars( shared_from_this() ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
ScopeVarsPtr StackFrame::getParams()
|
||||||
|
{
|
||||||
|
return ScopeVarsPtr( new FunctionParams( shared_from_this() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
@ -63,6 +70,283 @@ ULONG64 StackFrame::getValue(RegRealativeId rri, LONG64 offset /*= 0*/) const
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static bool IsInDebugRange(
|
||||||
|
SymbolPtr func,
|
||||||
|
ULONG ipRva
|
||||||
|
)
|
||||||
|
{
|
||||||
|
SymbolPtrList lstFuncDebugStart;
|
||||||
|
SymbolPtrList lstFuncDebugEnd;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lstFuncDebugStart = func->findChildren(SymTagFuncDebugStart);
|
||||||
|
if (1 != lstFuncDebugStart.size())
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(lstFuncDebugStart.empty());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
lstFuncDebugEnd = func->findChildren(SymTagFuncDebugEnd);
|
||||||
|
if (1 != lstFuncDebugEnd.size())
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(lstFuncDebugEnd.empty());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (const SymbolException &except)
|
||||||
|
{
|
||||||
|
DBG_UNREFERENCED_PARAMETER(except);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
((*lstFuncDebugStart.begin())->getRva() <= ipRva) &&
|
||||||
|
((*lstFuncDebugEnd.begin())->getRva() >= ipRva);
|
||||||
|
}
|
||||||
|
|
||||||
|
python::object StackFrame::getLocalByName( const std::string& name )
|
||||||
|
{
|
||||||
|
ModulePtr mod = Module::loadModuleByOffset( m_instructionOffset);
|
||||||
|
|
||||||
|
LONG displacemnt;
|
||||||
|
SymbolPtr func = mod->getSymbolByVa( m_instructionOffset, SymTagFunction, &displacemnt );
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
std::string funcName;
|
||||||
|
funcName = func->getName();
|
||||||
|
#endif // _DEBUG
|
||||||
|
|
||||||
|
if (!IsInDebugRange(func, static_cast<ULONG>( m_instructionOffset - mod->getBase())))
|
||||||
|
{
|
||||||
|
throw DbgException("is not debug range");
|
||||||
|
}
|
||||||
|
|
||||||
|
// find var in current scope
|
||||||
|
SymbolPtrList symList = func->findChildren(SymTagData);
|
||||||
|
SymbolPtrList::iterator itVar = symList.begin();
|
||||||
|
SymbolPtr symVar;
|
||||||
|
for (; itVar != symList.end(); ++itVar)
|
||||||
|
{
|
||||||
|
if ( (*itVar)->getName() == name )
|
||||||
|
{
|
||||||
|
symVar = *itVar;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( itVar == symList.end() )
|
||||||
|
{
|
||||||
|
// find inners scopes
|
||||||
|
SymbolPtrList scopeList = func->findChildren(SymTagBlock);
|
||||||
|
SymbolPtrList::iterator itScope = scopeList.begin();
|
||||||
|
|
||||||
|
ULONG ipRva = static_cast<ULONG>( m_instructionOffset - mod->getBase());
|
||||||
|
|
||||||
|
for (; itScope != scopeList.end() && !symVar; ++itScope)
|
||||||
|
{
|
||||||
|
SymbolPtr scope = *itScope;
|
||||||
|
ULONG scopeRva = scope->getRva();
|
||||||
|
if (scopeRva <= ipRva && (scopeRva + scope->getSize()) > ipRva)
|
||||||
|
{
|
||||||
|
SymbolPtrList symList = scope->findChildren(SymTagData);
|
||||||
|
SymbolPtrList::iterator itVar = symList.begin();
|
||||||
|
|
||||||
|
for (; itVar != symList.end(); ++itVar)
|
||||||
|
{
|
||||||
|
if ( (*itVar)->getName() == name )
|
||||||
|
{
|
||||||
|
symVar = *itVar;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !symVar )
|
||||||
|
throw DbgException("local var not found");
|
||||||
|
|
||||||
|
ULONG64 varAddr;
|
||||||
|
const LocationType locType = static_cast<LocationType>(symVar->getLocType());
|
||||||
|
switch (locType)
|
||||||
|
{
|
||||||
|
case LocIsStatic:
|
||||||
|
varAddr = mod->getBase() + symVar->getRva();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LocIsRegRel:
|
||||||
|
{
|
||||||
|
RegRealativeId rri;
|
||||||
|
rri = static_cast<RegRealativeId>(symVar->getRegRealativeId());
|
||||||
|
varAddr = getValue(rri, symVar->getOffset());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
BOOST_ASSERT(LocIsEnregistered == locType);
|
||||||
|
throw DbgException("");
|
||||||
|
}
|
||||||
|
|
||||||
|
TypeInfoPtr typeInfo = TypeInfo::getTypeInfo(symVar);
|
||||||
|
TypedVarPtr typedVar = TypedVar::getTypedVarByTypeInfo(typeInfo, varAddr);
|
||||||
|
typedVar->setDataKind( symVar->getDataKind() );
|
||||||
|
|
||||||
|
return python::object( typedVar );
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
python::object StackFrame::getParamByName( const std::string& name )
|
||||||
|
{
|
||||||
|
ModulePtr mod = Module::loadModuleByOffset( m_instructionOffset);
|
||||||
|
|
||||||
|
LONG displacemnt;
|
||||||
|
SymbolPtr func = mod->getSymbolByVa( m_instructionOffset, SymTagFunction, &displacemnt );
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
std::string funcName;
|
||||||
|
funcName = func->getName();
|
||||||
|
#endif // _DEBUG
|
||||||
|
|
||||||
|
if (!IsInDebugRange(func, static_cast<ULONG>( m_instructionOffset - mod->getBase())))
|
||||||
|
{
|
||||||
|
throw DbgException("is not debug range");
|
||||||
|
}
|
||||||
|
|
||||||
|
// find var in current scope
|
||||||
|
SymbolPtrList symList = func->findChildren(SymTagData);
|
||||||
|
SymbolPtrList::iterator itVar = symList.begin();
|
||||||
|
SymbolPtr symVar;
|
||||||
|
for (; itVar != symList.end(); ++itVar)
|
||||||
|
{
|
||||||
|
if ( (*itVar)->getDataKind() == DataIsParam && (*itVar)->getName() == name )
|
||||||
|
{
|
||||||
|
symVar = *itVar;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !symVar )
|
||||||
|
throw DbgException("local var not found");
|
||||||
|
|
||||||
|
ULONG64 varAddr;
|
||||||
|
const LocationType locType = static_cast<LocationType>(symVar->getLocType());
|
||||||
|
switch (locType)
|
||||||
|
{
|
||||||
|
case LocIsStatic:
|
||||||
|
varAddr = mod->getBase() + symVar->getRva();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LocIsRegRel:
|
||||||
|
{
|
||||||
|
RegRealativeId rri;
|
||||||
|
rri = static_cast<RegRealativeId>(symVar->getRegRealativeId());
|
||||||
|
varAddr = getValue(rri, symVar->getOffset());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
BOOST_ASSERT(LocIsEnregistered == locType);
|
||||||
|
throw DbgException("");
|
||||||
|
}
|
||||||
|
|
||||||
|
TypeInfoPtr typeInfo = TypeInfo::getTypeInfo(symVar);
|
||||||
|
TypedVarPtr typedVar = TypedVar::getTypedVarByTypeInfo(typeInfo, varAddr);
|
||||||
|
typedVar->setDataKind( symVar->getDataKind() );
|
||||||
|
|
||||||
|
return python::object( typedVar );
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
ULONG StackFrame::getLocalCount()
|
||||||
|
{
|
||||||
|
ULONG count = 0;
|
||||||
|
|
||||||
|
ModulePtr mod;
|
||||||
|
mod = Module::loadModuleByOffset( m_instructionOffset);
|
||||||
|
|
||||||
|
LONG displacemnt;
|
||||||
|
SymbolPtr func = mod->getSymbolByVa( m_instructionOffset, SymTagFunction, &displacemnt );
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
std::string funcName;
|
||||||
|
funcName = func->getName();
|
||||||
|
#endif // _DEBUG
|
||||||
|
|
||||||
|
if (!IsInDebugRange(func, static_cast<ULONG>( m_instructionOffset - mod->getBase())))
|
||||||
|
{
|
||||||
|
throw DbgException("is not debug range");
|
||||||
|
}
|
||||||
|
|
||||||
|
// find var in current scope
|
||||||
|
SymbolPtrList symList = func->findChildren(SymTagData);
|
||||||
|
|
||||||
|
SymbolPtrList::iterator it;
|
||||||
|
for ( it = symList.begin(); it != symList.end(); it++ )
|
||||||
|
{
|
||||||
|
if ( (*it)->getName() != "" )
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// find inners scopes
|
||||||
|
SymbolPtrList scopeList = func->findChildren(SymTagBlock);
|
||||||
|
SymbolPtrList::iterator itScope = scopeList.begin();
|
||||||
|
|
||||||
|
ULONG ipRva = static_cast<ULONG>( m_instructionOffset - mod->getBase());
|
||||||
|
|
||||||
|
for (; itScope != scopeList.end(); ++itScope)
|
||||||
|
{
|
||||||
|
SymbolPtr scope = *itScope;
|
||||||
|
ULONG scopeRva = scope->getRva();
|
||||||
|
if (scopeRva <= ipRva && (scopeRva + scope->getSize()) > ipRva)
|
||||||
|
{
|
||||||
|
SymbolPtrList symList = scope->findChildren(SymTagData);
|
||||||
|
count += (ULONG)symList.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
ULONG StackFrame::getParamCount()
|
||||||
|
{
|
||||||
|
ULONG count = 0;
|
||||||
|
|
||||||
|
ModulePtr mod;
|
||||||
|
mod = Module::loadModuleByOffset( m_instructionOffset);
|
||||||
|
|
||||||
|
LONG displacemnt;
|
||||||
|
SymbolPtr func = mod->getSymbolByVa( m_instructionOffset, SymTagFunction, &displacemnt );
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
std::string funcName;
|
||||||
|
funcName = func->getName();
|
||||||
|
#endif // _DEBUG
|
||||||
|
|
||||||
|
if (!IsInDebugRange(func, static_cast<ULONG>( m_instructionOffset - mod->getBase())))
|
||||||
|
{
|
||||||
|
throw DbgException("is not debug range");
|
||||||
|
}
|
||||||
|
|
||||||
|
// find var in current scope
|
||||||
|
SymbolPtrList symList = func->findChildren(SymTagData);
|
||||||
|
|
||||||
|
SymbolPtrList::iterator it;
|
||||||
|
for ( it = symList.begin(); it != symList.end(); it++ )
|
||||||
|
{
|
||||||
|
if ( (*it)->getDataKind() == DataIsParam )
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
python::list getCurrentStack()
|
python::list getCurrentStack()
|
||||||
{
|
{
|
||||||
std::vector<STACK_FRAME_DESC> frames;
|
std::vector<STACK_FRAME_DESC> frames;
|
||||||
@ -72,7 +356,7 @@ python::list getCurrentStack()
|
|||||||
|
|
||||||
for ( ULONG i = 0; i < frames.size(); ++i )
|
for ( ULONG i = 0; i < frames.size(); ++i )
|
||||||
{
|
{
|
||||||
python::object frameObj( StackFrame( frames.at(i) ) );
|
python::object frameObj( StackFramePtr( new StackFrame( frames.at(i) ) ) );
|
||||||
frameList.append( frameObj );
|
frameList.append( frameObj );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,11 +365,25 @@ python::list getCurrentStack()
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
StackFrame getCurrentStackFrame()
|
StackFramePtr getCurrentStackFrame()
|
||||||
{
|
{
|
||||||
std::vector<STACK_FRAME_DESC> frames;
|
std::vector<STACK_FRAME_DESC> frames;
|
||||||
getStackTrace( frames );
|
getStackTrace( frames );
|
||||||
return frames[0];
|
return StackFramePtr( new StackFrame( frames[0] ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
ScopeVarsPtr getLocals()
|
||||||
|
{
|
||||||
|
return getCurrentStackFrame()->getLocals();
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
ScopeVarsPtr getParams()
|
||||||
|
{
|
||||||
|
return getCurrentStackFrame()->getParams();
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
105
pykd/stkframe.h
105
pykd/stkframe.h
@ -8,23 +8,52 @@
|
|||||||
#include "context.h"
|
#include "context.h"
|
||||||
#include "symengine.h"
|
#include "symengine.h"
|
||||||
|
|
||||||
|
#include <boost/enable_shared_from_this.hpp>
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
namespace pykd {
|
namespace pykd {
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
class StackFrame
|
class StackFrame;
|
||||||
|
typedef boost::shared_ptr<StackFrame> StackFramePtr;
|
||||||
|
|
||||||
|
class ScopeVars;
|
||||||
|
typedef boost::shared_ptr<ScopeVars> ScopeVarsPtr;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class StackFrame : public boost::enable_shared_from_this<StackFrame>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
StackFrame( const STACK_FRAME_DESC& desc );
|
StackFrame( const STACK_FRAME_DESC& desc );
|
||||||
|
|
||||||
python::dict getLocals() const;
|
ScopeVarsPtr getLocals();
|
||||||
|
|
||||||
|
ScopeVarsPtr getParams();
|
||||||
|
|
||||||
std::string print() const;
|
std::string print() const;
|
||||||
|
|
||||||
ULONG64 getValue(RegRealativeId rri, LONG64 offset = 0) const;
|
ULONG64 getValue(RegRealativeId rri, LONG64 offset = 0) const;
|
||||||
|
|
||||||
|
ULONG getLocalCount();
|
||||||
|
|
||||||
|
ULONG getParamCount();
|
||||||
|
|
||||||
|
python::object getLocalByName( const std::string& name );
|
||||||
|
|
||||||
|
python::object getParamByName( const std::string& name );
|
||||||
|
|
||||||
|
python::object getLocalByIndex( ULONG index ){
|
||||||
|
return python::long_(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
python::object getParamByIndex( ULONG index ){
|
||||||
|
return python::long_(0);
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ULONG m_frameNumber;
|
ULONG m_frameNumber;
|
||||||
@ -35,12 +64,82 @@ public:
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ScopeVars {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
ScopeVars( StackFramePtr &frame ) :
|
||||||
|
m_frame( frame )
|
||||||
|
{}
|
||||||
|
|
||||||
|
virtual ULONG getVarCount() const = 0;
|
||||||
|
virtual python::object getVarByName( const std::string &name ) = 0;
|
||||||
|
virtual python::object getVarByIndex(ULONG index) const = 0 ;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
StackFramePtr m_frame;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class LocalVars : public ScopeVars {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
LocalVars( StackFramePtr &frame ) :
|
||||||
|
ScopeVars( frame )
|
||||||
|
{}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
ULONG getVarCount() const {
|
||||||
|
return m_frame->getLocalCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
python::object getVarByName( const std::string &name ) {
|
||||||
|
return m_frame->getLocalByName( name );
|
||||||
|
}
|
||||||
|
|
||||||
|
python::object getVarByIndex(ULONG index) const {
|
||||||
|
return m_frame->getLocalByIndex( index );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class FunctionParams : public ScopeVars {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
FunctionParams( StackFramePtr &frame ) :
|
||||||
|
ScopeVars( frame )
|
||||||
|
{}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
ULONG getVarCount() const {
|
||||||
|
return m_frame->getParamCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
python::object getVarByName( const std::string &name ) {
|
||||||
|
return m_frame->getParamByName( name );
|
||||||
|
}
|
||||||
|
|
||||||
|
python::object getVarByIndex(ULONG index) const {
|
||||||
|
return python::long_(0L);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
StackFrame getCurrentStackFrame();
|
StackFramePtr getCurrentStackFrame();
|
||||||
|
|
||||||
python::list getCurrentStack();
|
python::list getCurrentStack();
|
||||||
|
|
||||||
|
ScopeVarsPtr getLocals();
|
||||||
|
|
||||||
|
ScopeVarsPtr getParams();
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
} // namespace pykd
|
} // namespace pykd
|
||||||
|
@ -35,10 +35,9 @@ class LocalVarsTest(unittest.TestCase):
|
|||||||
testEnumWindowsProc1Locals(self, pykd.getLocals())
|
testEnumWindowsProc1Locals(self, pykd.getLocals())
|
||||||
|
|
||||||
pykd.go() # targetapp!EnumWindowsProc1 -> targetapp!functionCalledFromEnumWindowsProc1
|
pykd.go() # targetapp!EnumWindowsProc1 -> targetapp!functionCalledFromEnumWindowsProc1
|
||||||
testEnumWindowsProc1Locals(self, pykd.getCurrentStack()[1].getLocals())
|
testEnumWindowsProc1Locals(self, pykd.getStack()[1].locals )
|
||||||
|
|
||||||
pykd.go() # targetapp!EnumWindowsProc1 -> targetapp!EnumWindowsProc2
|
pykd.go() # targetapp!EnumWindowsProc1 -> targetapp!EnumWindowsProc2
|
||||||
locals = pykd.getLocals()
|
locals = pykd.getLocals()
|
||||||
self.assertEqual( len(locals), 2 )
|
self.assertEqual( len(locals), 2 )
|
||||||
locValues = locals.values()
|
self.assertTrue( locals[0] == 7 or locals[1] == 7 )
|
||||||
self.assertTrue( locValues[0] == 7 or locValues[1] == 7 )
|
|
||||||
|
@ -63,11 +63,11 @@ class ModuleTest( unittest.TestCase ):
|
|||||||
fileName = pykd.getSourceFile(target.module.FuncWithName0 )
|
fileName = pykd.getSourceFile(target.module.FuncWithName0 )
|
||||||
self.assertTrue( re.search('targetapp\\.cpp', fileName ) )
|
self.assertTrue( re.search('targetapp\\.cpp', fileName ) )
|
||||||
fileName, lineNo, displacement = pykd.getSourceLine( target.module.FuncWithName0 + 2)
|
fileName, lineNo, displacement = pykd.getSourceLine( target.module.FuncWithName0 + 2)
|
||||||
self.assertEqual( 382, lineNo )
|
self.assertEqual( 393, lineNo )
|
||||||
self.assertTrue( re.search('targetapp\\.cpp', fileName ) )
|
self.assertTrue( re.search('targetapp\\.cpp', fileName ) )
|
||||||
self.assertEqual( 2, displacement )
|
self.assertEqual( 2, displacement )
|
||||||
fileName, lineNo, displacement = pykd.getSourceLine()
|
fileName, lineNo, displacement = pykd.getSourceLine()
|
||||||
self.assertEqual( 624, lineNo )
|
self.assertEqual( 639, lineNo )
|
||||||
|
|
||||||
def testEnumSymbols( self ):
|
def testEnumSymbols( self ):
|
||||||
lst = target.module.enumSymbols()
|
lst = target.module.enumSymbols()
|
||||||
|
@ -81,6 +81,13 @@ class TypeInfoTest( unittest.TestCase ):
|
|||||||
except pykd.SymbolException:
|
except pykd.SymbolException:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def testBaseTypePtr(self):
|
||||||
|
self.assertEqual("Int1B*", target.module.type( "Int1B*" ).name() )
|
||||||
|
self.assertEqual("Int1B", target.module.type( "Int1B*" ).deref().name() )
|
||||||
|
|
||||||
|
def testBaseTypeArray(self):
|
||||||
|
self.assertEqual("Int4B[20]", target.module.type( "Int4B[20]" ).name() )
|
||||||
|
|
||||||
def testName( self ):
|
def testName( self ):
|
||||||
ti1 = target.module.type( "classChild" )
|
ti1 = target.module.type( "classChild" )
|
||||||
self.assertEqual( "classChild", ti1.name() )
|
self.assertEqual( "classChild", ti1.name() )
|
||||||
@ -198,7 +205,12 @@ class TypeInfoTest( unittest.TestCase ):
|
|||||||
self.assertNotEqual( 0, ti.m_stdstr.staticOffset() )
|
self.assertNotEqual( 0, ti.m_stdstr.staticOffset() )
|
||||||
|
|
||||||
def testUdtSubscribe(self):
|
def testUdtSubscribe(self):
|
||||||
tv = pykd.typeInfo( "g_virtChild" )
|
ti = pykd.typeInfo( "g_virtChild" )
|
||||||
self.assertEqual( 5, len(tv) )
|
self.assertEqual( 5, len(ti) )
|
||||||
for field in tv:
|
for field in ti:
|
||||||
str( field )
|
str( field )
|
||||||
|
|
||||||
|
def testStructNullSize(self):
|
||||||
|
ti = target.module.type("structNullSize")
|
||||||
|
self.assertEqual( 0, len(ti) )
|
||||||
|
|
||||||
|
@ -84,6 +84,16 @@ struct structTest {
|
|||||||
structTest* m_field4;
|
structTest* m_field4;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct structNullSize {
|
||||||
|
};
|
||||||
|
|
||||||
|
structNullSize* g_nullSizeArray = 0;
|
||||||
|
|
||||||
|
struct structAbstract;
|
||||||
|
typedef struct structAbstract *pstructAbstract;
|
||||||
|
|
||||||
|
pstructAbstract g_structAbstract = 0;
|
||||||
|
|
||||||
structWithBits g_structWithBits = { 4, 1, 3};
|
structWithBits g_structWithBits = { 4, 1, 3};
|
||||||
|
|
||||||
structTest g_structTest = { 0, 500, true, 1, NULL };
|
structTest g_structTest = { 0, 500, true, 1, NULL };
|
||||||
@ -435,6 +445,9 @@ void FuncWithName0()
|
|||||||
|
|
||||||
std::cout << g_structTypeDef.m_field0;
|
std::cout << g_structTypeDef.m_field0;
|
||||||
|
|
||||||
|
std::cout << g_nullSizeArray;
|
||||||
|
std::cout << g_structAbstract;
|
||||||
|
|
||||||
//std::cout << g_virtChild.VirtualBaseClass1::m_baseField;
|
//std::cout << g_virtChild.VirtualBaseClass1::m_baseField;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user