mirror of
https://github.com/ivellioscolin/pykd.git
synced 2025-04-29 11:53:23 +08:00
[0.1.x]
+ fork new thread context by stack frame + test of local variables of previous stack frame git-svn-id: https://pykd.svn.codeplex.com/svn@73627 9b283d60-5439-405e-af05-b73fd8c4d996
This commit is contained in:
parent
da5633cc12
commit
bbe357cf31
@ -129,10 +129,7 @@ ThreadContext::ThreadContext( IDebugClient4 *client ) :
|
||||
return;
|
||||
}
|
||||
|
||||
std::stringstream sstream;
|
||||
sstream << __FUNCTION__ << ":\n";
|
||||
sstream << "Unsupported processor type: 0x" << std::hex << m_processorType;
|
||||
throw DbgException( sstream.str() );
|
||||
throwUnsupportedProcessor(__FUNCTION__);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
@ -191,6 +188,29 @@ ULONG64 ThreadContext::getSp() const
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ContextPtr ThreadContext::forkByStackFrame(DEBUG_STACK_FRAME &frame) const
|
||||
{
|
||||
ContextPtr newContext( new ThreadContext(*this) );
|
||||
switch (m_processorType)
|
||||
{
|
||||
case IMAGE_FILE_MACHINE_I386:
|
||||
newContext->m_regValues[CV_REG_EIP] = frame.InstructionOffset;
|
||||
newContext->m_regValues[CV_REG_EBP] = frame.FrameOffset;
|
||||
newContext->m_regValues[CV_REG_ESP] = frame.StackOffset;
|
||||
return newContext;
|
||||
|
||||
case IMAGE_FILE_MACHINE_AMD64:
|
||||
newContext->m_regValues[CV_AMD64_RIP] = frame.InstructionOffset;
|
||||
newContext->m_regValues[CV_AMD64_RBP] = frame.FrameOffset;
|
||||
newContext->m_regValues[CV_AMD64_RSP] = frame.StackOffset;
|
||||
return newContext;
|
||||
}
|
||||
|
||||
throwUnsupportedProcessor(__FUNCTION__);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
python::object ThreadContext::getByIndex(ULONG ind) const
|
||||
{
|
||||
RegValues::const_iterator it = m_regValues.begin();
|
||||
@ -345,4 +365,30 @@ bool ThreadContext::getSubValue(ULONG cvRegId, ULONG64 &val) const
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ThreadContext::throwUnsupportedProcessor(PCSTR szFunction) const
|
||||
{
|
||||
std::stringstream sstream;
|
||||
sstream << szFunction << ":\n";
|
||||
sstream << "Unsupported processor type: 0x" << std::hex << m_processorType;
|
||||
throw DbgException( sstream.str() );
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::string printStackFrame(DEBUG_STACK_FRAME &frame)
|
||||
{
|
||||
std::stringstream sstream;
|
||||
|
||||
sstream << std::dec << "(" << frame.FrameNumber << ")";
|
||||
|
||||
sstream << " ip= 0x" << std::hex << frame.InstructionOffset;
|
||||
sstream << ", ret= 0x" << std::hex << frame.ReturnOffset;
|
||||
sstream << ", frame= 0x" << std::hex << frame.FrameOffset;
|
||||
sstream << ", stack= 0x" << std::hex << frame.StackOffset;
|
||||
|
||||
return sstream.str();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
|
@ -10,6 +10,14 @@
|
||||
|
||||
namespace pykd {
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class ThreadContext;
|
||||
typedef boost::shared_ptr< ThreadContext > ContextPtr;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::string processorToStr(ULONG processorMode);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -17,7 +25,6 @@ std::string processorToStr(ULONG processorMode);
|
||||
class ThreadContext : private DbgObject
|
||||
{
|
||||
public:
|
||||
|
||||
ThreadContext( IDebugClient4 *client );
|
||||
|
||||
// get register value by ID
|
||||
@ -45,6 +52,8 @@ public:
|
||||
return pykd::processorToStr(m_processorType);
|
||||
}
|
||||
|
||||
ContextPtr forkByStackFrame(DEBUG_STACK_FRAME &frame) const;
|
||||
|
||||
private:
|
||||
|
||||
// query i386 registers
|
||||
@ -56,6 +65,8 @@ private:
|
||||
// try query as "sub-register"
|
||||
bool getSubValue(ULONG cvRegId, ULONG64 &val) const;
|
||||
|
||||
void __declspec(noreturn) throwUnsupportedProcessor(PCSTR szFunction) const;
|
||||
|
||||
private:
|
||||
typedef std::map<ULONG, ULONG64> RegValues;
|
||||
RegValues m_regValues;
|
||||
@ -65,7 +76,7 @@ private:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef boost::shared_ptr< ThreadContext > ContextPtr;
|
||||
std::string printStackFrame(DEBUG_STACK_FRAME &frame);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
@ -632,7 +632,9 @@ BOOST_PYTHON_MODULE( pykd )
|
||||
.def_readonly( "stackOffset", &DEBUG_STACK_FRAME::StackOffset,
|
||||
"Return a frame's stack offset" )
|
||||
.def_readonly( "frameNumber", &DEBUG_STACK_FRAME::FrameNumber,
|
||||
"Return a frame's number" );
|
||||
"Return a frame's number" )
|
||||
.def( "__str__", &printStackFrame,
|
||||
"Return stacks frame as string");
|
||||
|
||||
python::class_<ThreadContext, ContextPtr>(
|
||||
"Context", "Context of thread (register values)", python::no_init )
|
||||
@ -646,6 +648,8 @@ BOOST_PYTHON_MODULE( pykd )
|
||||
"Get register value by ID (CV_REG_XXX)" )
|
||||
.def( "processorType", &ThreadContext::getProcessorType,
|
||||
"Get processor ThreadContext as string")
|
||||
.def( "fork", &ThreadContext::forkByStackFrame,
|
||||
"Create new thread context by stackFrame")
|
||||
.def("__len__", &ThreadContext::getCount,
|
||||
"Return count of registers")
|
||||
.def("__getitem__", &ThreadContext::getByIndex,
|
||||
|
@ -8,14 +8,14 @@ class LocalVarsTest(unittest.TestCase):
|
||||
def testLocalVariable(self):
|
||||
"""Start new process and test local variables"""
|
||||
|
||||
testClient = pykd.createDbgClient()
|
||||
testClient.startProcess( target.appPath + " -testEnumWindows" )
|
||||
newClnt = pykd.createDbgClient()
|
||||
newClnt.startProcess( target.appPath + " -testEnumWindows" )
|
||||
|
||||
testClient.go() # initial breakpoint -> wmain
|
||||
testClient.go() # wmain -> targetapp!EnumWindowsProc1
|
||||
# pykd.dprint( "\n" + testClient.dbgCommand("u") )
|
||||
newClnt.go() # initial breakpoint -> wmain
|
||||
newClnt.go() # wmain -> targetapp!EnumWindowsProc1
|
||||
# pykd.dprint( "\n" + newClnt.dbgCommand("u") )
|
||||
|
||||
locals = testClient.getLocals()
|
||||
locals = newClnt.getLocals()
|
||||
|
||||
self.assertNotEqual( 0, locals["hWindow"] )
|
||||
self.assertEqual( pykd.DataIsParam, locals["hWindow"].dataKind() )
|
||||
@ -31,9 +31,20 @@ class LocalVarsTest(unittest.TestCase):
|
||||
|
||||
self.assertEqual( locals["dwProccessId"] + 1, locals["staticVar"] )
|
||||
|
||||
testClient.go() # targetapp!EnumWindowsProc1 -> targetapp!EnumWindowsProc2
|
||||
locals = testClient.getLocals()
|
||||
newClnt.go() # targetapp!EnumWindowsProc1 -> targetapp!functionCalledFromEnumWindowsProc1
|
||||
|
||||
# get local variables from previous stack frame
|
||||
prevStackThreadCtx = newClnt.getContext().fork( newClnt.getCurrentStack()[1] )
|
||||
prevLocals = newClnt.getLocals( prevStackThreadCtx )
|
||||
|
||||
self.assertEqual( len(prevLocals), len(locals) )
|
||||
for varName in locals.iterkeys():
|
||||
self.assertEqual( prevLocals[varName], locals[varName] )
|
||||
|
||||
newClnt.go() # targetapp!EnumWindowsProc1 -> targetapp!EnumWindowsProc2
|
||||
locals = newClnt.getLocals()
|
||||
self.assertEqual( len(locals), 2 )
|
||||
locValues = locals.values()
|
||||
self.assertTrue( locValues[0] == 7 or locValues[1] == 7 )
|
||||
|
||||
|
||||
|
@ -303,6 +303,16 @@ void FuncWithName1(int a)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma optimize("g", off)
|
||||
VOID functionCalledFromEnumWindowsProc1(DWORD dwProcessId)
|
||||
{
|
||||
DWORD dwCurrentProcessId = GetCurrentProcessId();
|
||||
if (dwCurrentProcessId != dwProcessId)
|
||||
std::cout << dwCurrentProcessId << dwProcessId;
|
||||
__debugbreak();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
BOOL CALLBACK EnumWindowsProc1(
|
||||
HWND hWindow,
|
||||
const LPARAM lParam
|
||||
@ -318,6 +328,7 @@ BOOL CALLBACK EnumWindowsProc1(
|
||||
DWORD dwThreadId = ::GetWindowThreadProcessId(hWindow, &dwProccessId);
|
||||
staticVar = dwProccessId + 1;
|
||||
__debugbreak();
|
||||
functionCalledFromEnumWindowsProc1(dwProccessId);
|
||||
std::cout << dwProccessId << dwThreadId << staticVar;
|
||||
}
|
||||
return hWindow ? FALSE : TRUE;
|
||||
|
Loading…
Reference in New Issue
Block a user