diff --git a/pykd/dbgengine.h b/pykd/dbgengine.h index 95905f6..188717e 100644 --- a/pykd/dbgengine.h +++ b/pykd/dbgengine.h @@ -69,8 +69,8 @@ struct STACK_FRAME_DESC { ULONG64 stackOffset; }; +void getCurrentFrame(STACK_FRAME_DESC &frame ); void getStackTrace(std::vector &frames); - void getStackTraceWow64(std::vector &frames); // callback events diff --git a/pykd/stkframe.cpp b/pykd/stkframe.cpp index db6c66d..fe2d870 100644 --- a/pykd/stkframe.cpp +++ b/pykd/stkframe.cpp @@ -347,6 +347,167 @@ ULONG StackFrame::getParamCount() //////////////////////////////////////////////////////////////////////////////// +python::object StackFrame::getLocalByIndex( ULONG index ) +{ + 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( 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; + ULONG i = 0; + for (; itVar != symList.end(); ++itVar, ++i) + { + if ( i == index ) + { + symVar = *itVar; + break; + } + } + + if ( itVar == symList.end() ) + { + // find inners scopes + SymbolPtrList scopeList = func->findChildren(SymTagBlock); + SymbolPtrList::iterator itScope = scopeList.begin(); + + ULONG ipRva = static_cast( 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, ++i) + { + if ( i == index ) + { + symVar = *itVar; + break; + } + } + } + } + } + + if ( !symVar ) + throw DbgException("local var not found"); + + ULONG64 varAddr; + const LocationType locType = static_cast(symVar->getLocType()); + switch (locType) + { + case LocIsStatic: + varAddr = mod->getBase() + symVar->getRva(); + break; + + case LocIsRegRel: + { + RegRealativeId rri; + rri = static_cast(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::getParamByIndex( ULONG index ) +{ + 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( 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 ( ULONG i = 0; itVar != symList.end(); ++itVar ) + { + if ( (*itVar)->getDataKind() == DataIsParam ) + { + if ( i == index ) + { + symVar = *itVar; + break; + } + + i++; + } + } + + if ( !symVar ) + throw DbgException("local var not found"); + + ULONG64 varAddr; + const LocationType locType = static_cast(symVar->getLocType()); + switch (locType) + { + case LocIsStatic: + varAddr = mod->getBase() + symVar->getRva(); + break; + + case LocIsRegRel: + { + RegRealativeId rri; + rri = static_cast(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::list getCurrentStack() { std::vector frames; @@ -385,9 +546,9 @@ python::list getCurrentStackWow64() StackFramePtr getCurrentStackFrame() { - std::vector frames; - getStackTrace( frames ); - return StackFramePtr( new StackFrame( frames[0] ) ); + STACK_FRAME_DESC frame; + getCurrentFrame( frame ); + return StackFramePtr( new StackFrame( frame ) ); } /////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/stkframe.h b/pykd/stkframe.h index dd8f912..0afa784 100644 --- a/pykd/stkframe.h +++ b/pykd/stkframe.h @@ -46,13 +46,9 @@ public: python::object getParamByName( const std::string& name ); - python::object getLocalByIndex( ULONG index ){ - return python::long_(0); - } + python::object getLocalByIndex( ULONG index ); - python::object getParamByIndex( ULONG index ){ - return python::long_(0); - } + python::object getParamByIndex( ULONG index ); public: @@ -126,7 +122,7 @@ private: } python::object getVarByIndex(ULONG index) const { - return python::long_(0L); + return m_frame->getParamByIndex(index); } }; diff --git a/pykd/win/dbgeng.cpp b/pykd/win/dbgeng.cpp index 13146a6..f3f6d67 100644 --- a/pykd/win/dbgeng.cpp +++ b/pykd/win/dbgeng.cpp @@ -863,6 +863,33 @@ static void buildStacksFrames( /////////////////////////////////////////////////////////////////////////////// +void getCurrentFrame(STACK_FRAME_DESC &frame ) +{ + PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate ); + + HRESULT hres; + + frame.number = 0; + + hres = g_dbgEng->registers->GetInstructionOffset2( DEBUG_REGSRC_FRAME, &frame.instructionOffset ); + if ( FAILED(hres) ) + throw DbgException( "IDebugRegisters2::GetInstructionOffset2", hres ); + + hres = g_dbgEng->control->GetReturnOffset( &frame.returnOffset ); + if ( FAILED(hres) ) + throw DbgException( "IDebugControl::GetReturnOffset", hres ); + + hres = g_dbgEng->registers->GetFrameOffset2( DEBUG_REGSRC_FRAME, &frame.frameOffset ); + if ( FAILED(hres) ) + throw DbgException( "IDebugRegisters2::GetFrameOffset2", hres ); + + hres = g_dbgEng->registers->GetStackOffset2( DEBUG_REGSRC_FRAME, &frame.stackOffset ); + if ( FAILED(hres) ) + throw DbgException( "IDebugRegisters2::GetStackOffset2", hres ); +} + +/////////////////////////////////////////////////////////////////////////////// + void getStackTrace(std::vector &frames) { PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate ); diff --git a/test/scripts/localstest.py b/test/scripts/localstest.py index 726e992..403e748 100644 --- a/test/scripts/localstest.py +++ b/test/scripts/localstest.py @@ -23,6 +23,7 @@ def testEnumWindowsProc1Locals(testCase, locals): testCase.assertEqual( DataIsStaticLocal, locals["staticVar"].dataKind() ) testCase.assertEqual( locals["dwProccessId"] + 1, locals["staticVar"] ) + class LocalVarsTest(unittest.TestCase): def testLocalVariable(self): @@ -41,3 +42,8 @@ class LocalVarsTest(unittest.TestCase): locals = pykd.getLocals() self.assertEqual( len(locals), 2 ) self.assertTrue( locals[0] == 7 or locals[1] == 7 ) + + funcParams = pykd.getParams() + self.assertEqual( len(funcParams), 2 ) + self.assertTrue( funcParams[0] == 7 or funcParams[1] == 7 ) +