From 02228e6714dc94c041e37404500d4ff8f40280ba Mon Sep 17 00:00:00 2001 From: "SND\\kernelnet_cp" Date: Mon, 13 Aug 2012 11:34:26 +0000 Subject: [PATCH] [0.2.x] added : loadDump, isKernelDebugging, isDumpAnalyzing routines git-svn-id: https://pykd.svn.codeplex.com/svn@78810 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/context.cpp | 1125 +++++++++++++++++++------------------- pykd/context.h | 98 ++-- pykd/dbgengine.h | 5 + pykd/livevar.cpp | 214 -------- pykd/localvar.cpp | 30 + pykd/module.cpp | 12 + pykd/module.h | 2 + pykd/pykd_2008.vcproj | 8 + pykd/pymod.cpp | 38 +- pykd/stkframe.cpp | 21 + pykd/stkframe.h | 5 +- pykd/win/dbgeng.cpp | 52 ++ test/scripts/pykdtest.py | 4 +- 13 files changed, 784 insertions(+), 830 deletions(-) delete mode 100644 pykd/livevar.cpp create mode 100644 pykd/localvar.cpp diff --git a/pykd/context.cpp b/pykd/context.cpp index 67781e4..f7a4ec2 100644 --- a/pykd/context.cpp +++ b/pykd/context.cpp @@ -13,571 +13,572 @@ namespace pykd { -//////////////////////////////////////////////////////////////////////////////// -// Fill 32-bit register context -//////////////////////////////////////////////////////////////////////////////// -template -void FillRegistersFromContext32( - ThreadContext::RegValues ®Values, - const TContext &Context -) -{ - regValues[CV_REG_DR0] = Context.Dr0; - regValues[CV_REG_DR1] = Context.Dr1; - regValues[CV_REG_DR2] = Context.Dr2; - regValues[CV_REG_DR3] = Context.Dr3; - regValues[CV_REG_DR6] = Context.Dr6; - regValues[CV_REG_DR7] = Context.Dr7; - - regValues[CV_REG_GS] = Context.SegGs; - regValues[CV_REG_FS] = Context.SegFs; - regValues[CV_REG_ES] = Context.SegEs; - regValues[CV_REG_DS] = Context.SegDs; - - regValues[CV_REG_EDI] = Context.Edi; - regValues[CV_REG_ESI] = Context.Esi; - regValues[CV_REG_EBX] = Context.Ebx; - regValues[CV_REG_EDX] = Context.Edx; - regValues[CV_REG_ECX] = Context.Ecx; - regValues[CV_REG_EAX] = Context.Eax; - - regValues[CV_REG_EBP] = Context.Ebp; - - regValues[CV_REG_ESP] = Context.Esp; - regValues[CV_REG_SS] = Context.SegSs; - - regValues[CV_REG_EIP] = Context.Eip; - regValues[CV_REG_CS] = Context.SegCs; - - regValues[CV_REG_EFLAGS] = Context.EFlags; -} - -///////////////////////////////////////////////////////////////////////////////// - -struct CvRegName -{ - CvRegName(CV_HREG_e cvValue, const std::string &name) - : m_cvValue( cvValue ), m_name( boost::to_lower_copy(name) ) - { - } - CV_HREG_e m_cvValue; - std::string m_name; -}; -#define _REG_NAME(prefix, regName) CvRegName(CV_##prefix##regName, #regName) - -///////////////////////////////////////////////////////////////////////////////// -#define _REG_X86(regName) _REG_NAME(REG_, regName) -static const CvRegName g_x86Registers[] = { - _REG_X86(DR0), _REG_X86(DR1), _REG_X86(DR2), _REG_X86(DR3), _REG_X86(DR6), _REG_X86(DR7), - _REG_X86(GS), _REG_X86(FS), _REG_X86(ES), _REG_X86(DS), - _REG_X86(EDI), _REG_X86(EBX), _REG_X86(EDX), _REG_X86(ECX), _REG_X86(EAX), - _REG_X86(EBP), _REG_X86(ESP), _REG_X86(SS), - _REG_X86(EIP), _REG_X86(CS), - CvRegName(CV_REG_EFLAGS, "efl") -}; -#undef _REG_X86 - -///////////////////////////////////////////////////////////////////////////////// -#define _REG_X64(regName) _REG_NAME(AMD64_, regName) -static const CvRegName g_x64Registers[] = { - _REG_X64(MXCSR), - _REG_X64(CS), _REG_X64(DS), _REG_X64(ES), _REG_X64(FS), _REG_X64(GS), _REG_X64(SS), - - _REG_X64(DR0), _REG_X64(DR1), _REG_X64(DR2), _REG_X64(DR3), _REG_X64(DR6), _REG_X64(DR7), - - _REG_X64(RAX), _REG_X64(RCX), _REG_X64(RDX), _REG_X64(RBX), _REG_X64(RSP), _REG_X64(RBP), _REG_X64(RSI), _REG_X64(RDI), - _REG_X64(R8), _REG_X64(R9), _REG_X64(R10), _REG_X64(R11), _REG_X64(R12), _REG_X64(R13), _REG_X64(R14), _REG_X64(R15), - - _REG_X64(RIP), - CvRegName(CV_AMD64_EFLAGS, "efl") -}; -#undef _REG_X64 - -#undef _REG_NAME - -///////////////////////////////////////////////////////////////////////////////// - -void ThreadContext::getI386Context() -{ - queryRegisters(g_x86Registers, _countof(g_x86Registers)); -} - -///////////////////////////////////////////////////////////////////////////////// - -void ThreadContext::getAmd64Context() -{ - queryRegisters(g_x64Registers, _countof(g_x64Registers)); -} - -///////////////////////////////////////////////////////////////////////////////// - -ThreadContext::ThreadContext( IDebugClient4 *client ) : - pykd::DbgObject( client ) -{ - HRESULT hres = m_control->GetEffectiveProcessorType(&m_processorType); - if (S_OK != hres) - throw DbgException( "IDebugControl::GetEffectiveProcessorType", hres ); - - switch (m_processorType) - { - case IMAGE_FILE_MACHINE_I386: - getI386Context(); - return; - - case IMAGE_FILE_MACHINE_AMD64: - getAmd64Context(); - return; - } - - throwUnsupportedProcessor(__FUNCTION__); -} - -///////////////////////////////////////////////////////////////////////////////// - -ThreadContext::ThreadContext( - IDebugClient4 *client, - ULONG processorType -) : pykd::DbgObject(client) - , m_processorType(processorType) -{ -} - -///////////////////////////////////////////////////////////////////////////////// - -void ThreadContext::queryRegisters( - const CvRegName *regs, - ULONG countOfRegs -) -{ - HRESULT hres; - - std::vector regIndices( countOfRegs ); - - for (ULONG i = 0; i < countOfRegs; ++i) - { - hres = m_registers->GetIndexByName(regs[i].m_name.c_str(), ®Indices[i]); - if (S_OK != hres) - throw DbgException( "IDebugRegisters::GetIndexByName", hres); - } - - std::vector regValues( countOfRegs ); - hres = - m_registers->GetValues( - static_cast(countOfRegs), - ®Indices[0], - 0, - ®Values[0]); - if (S_OK != hres) - throw DbgException( "IDebugRegisters::GetValues", hres); - - for (ULONG i = 0; i < countOfRegs; ++i) - { - const DEBUG_VALUE ®Value = regValues[i]; - switch (regValue.Type) - { - case DEBUG_VALUE_INT8: - m_regValues[regs[i].m_cvValue] = regValue.I8; - break; - case DEBUG_VALUE_INT16: - m_regValues[regs[i].m_cvValue] = regValue.I16; - break; - case DEBUG_VALUE_INT32: - m_regValues[regs[i].m_cvValue] = regValue.I32; - break; - case DEBUG_VALUE_INT64: - m_regValues[regs[i].m_cvValue] = regValue.I64; - break; - } - } -} - -///////////////////////////////////////////////////////////////////////////////// - -ContextPtr ThreadContext::getWow64Context( IDebugClient4 *client ) -{ - ContextPtr ptrContext( new ThreadContext(client, IMAGE_FILE_MACHINE_I386) ); - - ULONG processorType; - HRESULT hres = ptrContext->m_control->GetEffectiveProcessorType(&processorType); - if (S_OK != hres) - throw DbgException( "IDebugControl::GetEffectiveProcessorType", hres ); - if (IMAGE_FILE_MACHINE_I386 != processorType) - throw DbgException( "Only for WOW64 processor mode" ); - - hres = ptrContext->m_control->GetActualProcessorType(&processorType); - if (S_OK != hres) - throw DbgException( "IDebugControl::GetActualProcessorType", hres ); - if (IMAGE_FILE_MACHINE_AMD64 != processorType) - throw DbgException( "Only for WOW64 processor mode" ); - - // - // *** undoc *** - // !wow64exts.r - // http://www.woodmann.com/forum/archive/index.php/t-11162.html - // http://www.nynaeve.net/Code/GetThreadWow64Context.cpp - // - - ULONG64 teb64Address; - hres = ptrContext->m_system->GetCurrentThreadTeb(&teb64Address); - if (S_OK != hres) - throw DbgException( "IDebugSystemObjects::GetCurrentThreadTeb", hres); - - // ? @@C++(#FIELD_OFFSET(nt!_TEB64, TlsSlots)) - // hardcoded in !wow64exts.r (6.2.8250.0) - static const ULONG teb64ToTlsOffset = 0x01480; - static const ULONG WOW64_TLS_CPURESERVED = 1; - ULONG64 cpuAreaAddress; - ULONG readedBytes; - hres = - readVirtual( - ptrContext->m_dataSpaces, - teb64Address + teb64ToTlsOffset + (sizeof(ULONG64) * WOW64_TLS_CPURESERVED), - &cpuAreaAddress, - sizeof(cpuAreaAddress), - &readedBytes); - if (S_OK != hres || readedBytes != sizeof(cpuAreaAddress)) - throw DbgException( "IDebugDataSpaces::ReadVirtual", hres); - - // CPU Area is: - // +00 unknown ULONG - // +04 WOW64_CONTEXT struct - static const ULONG cpuAreaToWow64ContextOffset = sizeof(ULONG); - WOW64_CONTEXT Context = {0}; - hres = - readVirtual( - ptrContext->m_dataSpaces, - cpuAreaAddress + cpuAreaToWow64ContextOffset, - &Context, - sizeof(Context), - &readedBytes); - if (S_OK != hres || readedBytes != sizeof(Context)) - throw DbgException( "IDebugDataSpaces::ReadVirtual", hres); - - FillRegistersFromContext32(ptrContext->m_regValues, Context); - - return ptrContext; -} - -///////////////////////////////////////////////////////////////////////////////// - -ULONG64 ThreadContext::getValue(ULONG cvRegId) const -{ - ULONG64 val; - - if ( getValueNoThrow( cvRegId, val ) ) - return val; - - throw DbgException(__FUNCTION__ ": Register missing"); -} - -///////////////////////////////////////////////////////////////////////////////// - -ULONG64 ThreadContext::getValueByName( const std::string ®Name ) const -{ - std::string upcaseName = boost::to_upper_copy( regName ); - - if ( IMAGE_FILE_MACHINE_I386 == m_processorType ) - { - for ( ULONG i = 0; i < pyDia::Symbol::cntI386RegName; ++i ) - { - if ( upcaseName == pyDia::Symbol::i386RegName[i].second ) - return getValue( pyDia::Symbol::i386RegName[i].first ); - } - } - else - { - for ( ULONG i = 0; i < pyDia::Symbol::cntAmd64RegName; ++i ) - { - if ( upcaseName == pyDia::Symbol::amd64RegName[i].second ) - return getValue( pyDia::Symbol::amd64RegName[i].first ); - } - } - - throwUnsupportedProcessor(__FUNCTION__); -} +////////////////////////////////////////////////////////////////////////////////// +//// Fill 32-bit register context +////////////////////////////////////////////////////////////////////////////////// +//template +//void FillRegistersFromContext32( +// ThreadContext::RegValues ®Values, +// const TContext &Context +//) +//{ +// regValues[CV_REG_DR0] = Context.Dr0; +// regValues[CV_REG_DR1] = Context.Dr1; +// regValues[CV_REG_DR2] = Context.Dr2; +// regValues[CV_REG_DR3] = Context.Dr3; +// regValues[CV_REG_DR6] = Context.Dr6; +// regValues[CV_REG_DR7] = Context.Dr7; +// +// regValues[CV_REG_GS] = Context.SegGs; +// regValues[CV_REG_FS] = Context.SegFs; +// regValues[CV_REG_ES] = Context.SegEs; +// regValues[CV_REG_DS] = Context.SegDs; +// +// regValues[CV_REG_EDI] = Context.Edi; +// regValues[CV_REG_ESI] = Context.Esi; +// regValues[CV_REG_EBX] = Context.Ebx; +// regValues[CV_REG_EDX] = Context.Edx; +// regValues[CV_REG_ECX] = Context.Ecx; +// regValues[CV_REG_EAX] = Context.Eax; +// +// regValues[CV_REG_EBP] = Context.Ebp; +// +// regValues[CV_REG_ESP] = Context.Esp; +// regValues[CV_REG_SS] = Context.SegSs; +// +// regValues[CV_REG_EIP] = Context.Eip; +// regValues[CV_REG_CS] = Context.SegCs; +// +// regValues[CV_REG_EFLAGS] = Context.EFlags; +//} +// /////////////////////////////////////////////////////////////////////////////////// - -bool ThreadContext::getValueNoThrow(ULONG cvRegId, ULONG64 &val) const -{ - if ( getSubValue(cvRegId, val ) ) - return true; - - RegValues::const_iterator it = m_regValues.find(cvRegId); - if (it == m_regValues.end()) - return false; - - val = it->second; - return true; -} - +// +//struct CvRegName +//{ +// CvRegName(CV_HREG_e cvValue, const std::string &name) +// : m_cvValue( cvValue ), m_name( boost::to_lower_copy(name) ) +// { +// } +// CV_HREG_e m_cvValue; +// std::string m_name; +//}; +//#define _REG_NAME(prefix, regName) CvRegName(CV_##prefix##regName, #regName) +// /////////////////////////////////////////////////////////////////////////////////// - -ULONG64 ThreadContext::getIp() const -{ - return getValue( - IMAGE_FILE_MACHINE_I386 == m_processorType ? CV_REG_EIP : CV_AMD64_RIP - ); -} - -///////////////////////////////////////////////////////////////////////////////// - -ULONG64 ThreadContext::getRetReg() const -{ - return getValue( - IMAGE_FILE_MACHINE_I386 == m_processorType ? CV_REG_EAX : CV_AMD64_RAX - ); -} - -///////////////////////////////////////////////////////////////////////////////// - -ULONG64 ThreadContext::getSp() const -{ - return getValue( - IMAGE_FILE_MACHINE_I386 == m_processorType ? CV_REG_ESP : CV_AMD64_RSP - ); -} - -///////////////////////////////////////////////////////////////////////////////// - -ContextPtr ThreadContext::forkByStackFrame(const StackFrame &stkFrmae) const -{ - ContextPtr newContext( new ThreadContext(*this) ); - switch (m_processorType) - { - case IMAGE_FILE_MACHINE_I386: - newContext->m_regValues[CV_REG_EIP] = stkFrmae.m_instructionOffset; - newContext->m_regValues[CV_REG_EBP] = stkFrmae.m_frameOffset; - newContext->m_regValues[CV_REG_ESP] = stkFrmae.m_stackOffset; - return newContext; - - case IMAGE_FILE_MACHINE_AMD64: - newContext->m_regValues[CV_AMD64_RIP] = stkFrmae.m_instructionOffset; - newContext->m_regValues[CV_AMD64_RBP] = stkFrmae.m_frameOffset; - newContext->m_regValues[CV_AMD64_RSP] = stkFrmae.m_stackOffset; - return newContext; - } - - throwUnsupportedProcessor(__FUNCTION__); -} - -///////////////////////////////////////////////////////////////////////////////// - -python::object ThreadContext::getByIndex(ULONG ind) const -{ - RegValues::const_iterator it = m_regValues.begin(); - for (ULONG i = 0; it != m_regValues.end(); ++i, ++it ) - { - if (i == ind) - { - switch (m_processorType) - { - case IMAGE_FILE_MACHINE_I386: - - for ( ULONG j = 0; j < pyDia::Symbol::cntI386RegName; ++j ) - if ( pyDia::Symbol::i386RegName[j].first == it->first ) - return python::make_tuple( it->first, pyDia::Symbol::i386RegName[j].second, it->second); - - break; - - - case IMAGE_FILE_MACHINE_AMD64: - - for ( ULONG j = 0; j < pyDia::Symbol::cntAmd64RegName; ++j ) - if ( pyDia::Symbol::amd64RegName[j].first == it->first ) - return python::make_tuple( it->first, pyDia::Symbol::amd64RegName[j].second, it->second); - - break; - } - } - } - - throw PyException( PyExc_IndexError, "Index out of range"); -} - -///////////////////////////////////////////////////////////////////////////////// - -struct SubRegister { - ULONG m_fromReg; - ULONG m_bitsShift; - ULONG m_bitsMask; - - void set(ULONG fromReg, ULONG bitsShift, ULONG bitsMask) - { - m_fromReg = fromReg; m_bitsShift = bitsShift; m_bitsMask = bitsMask; - } -}; - -///////////////////////////////////////////////////////////////////////////////// - - -struct SubRegisterMapI386 { - - std::map subRegs; - - SubRegisterMapI386() - { - subRegs[CV_REG_AL].set(CV_REG_EAX, 0x00, 0xff); - subRegs[CV_REG_CL].set(CV_REG_ECX, 0x00, 0xff); - subRegs[CV_REG_DL].set(CV_REG_EDX, 0x00, 0xff); - subRegs[CV_REG_BL].set(CV_REG_EBX, 0x00, 0xff); - - subRegs[CV_REG_AH].set(CV_REG_EAX, 0x08, 0xff); - subRegs[CV_REG_CH].set(CV_REG_ECX, 0x08, 0xff); - subRegs[CV_REG_DH].set(CV_REG_EDX, 0x08, 0xff); - subRegs[CV_REG_BH].set(CV_REG_EBX, 0x08, 0xff); - - subRegs[CV_REG_AX].set(CV_REG_EAX, 0x00, 0xffff); - subRegs[CV_REG_CX].set(CV_REG_ECX, 0x00, 0xffff); - subRegs[CV_REG_DX].set(CV_REG_EDX, 0x00, 0xffff); - subRegs[CV_REG_BX].set(CV_REG_EBX, 0x00, 0xffff); - - subRegs[CV_REG_SP].set(CV_REG_ESP, 0x00, 0xffff); - subRegs[CV_REG_BP].set(CV_REG_EBP, 0x00, 0xffff); - subRegs[CV_REG_SI].set(CV_REG_ESI, 0x00, 0xffff); - subRegs[CV_REG_DI].set(CV_REG_EDI, 0x00, 0xffff); - } - -}; - -static const std::map g_SubRegistersI386 = SubRegisterMapI386().subRegs; - -///////////////////////////////////////////////////////////////////////////////// - -struct SubRegisterMapAmd64 { - - std::map subRegs; - - SubRegisterMapAmd64() - { - subRegs[CV_AMD64_AL].set(CV_AMD64_RAX, 0x00, 0xff); - subRegs[CV_AMD64_CL].set(CV_AMD64_RCX, 0x00, 0xff); - subRegs[CV_AMD64_DL].set(CV_AMD64_RDX, 0x00, 0xff); - subRegs[CV_AMD64_BL].set(CV_AMD64_RBX, 0x00, 0xff); - - subRegs[CV_AMD64_AH].set(CV_AMD64_RAX, 0x08, 0xff); - subRegs[CV_AMD64_CH].set(CV_AMD64_RCX, 0x08, 0xff); - subRegs[CV_AMD64_DH].set(CV_AMD64_RDX, 0x08, 0xff); - subRegs[CV_AMD64_BH].set(CV_AMD64_RBX, 0x08, 0xff); - - subRegs[CV_AMD64_AX].set(CV_AMD64_RAX, 0x00, 0xffff); - subRegs[CV_AMD64_CX].set(CV_AMD64_RCX, 0x00, 0xffff); - subRegs[CV_AMD64_DX].set(CV_AMD64_RDX, 0x00, 0xffff); - subRegs[CV_AMD64_BX].set(CV_AMD64_RBX, 0x00, 0xffff); - - subRegs[CV_AMD64_SP].set(CV_AMD64_RSP, 0x00, 0xffff); - subRegs[CV_AMD64_BP].set(CV_AMD64_RBP, 0x00, 0xffff); - subRegs[CV_AMD64_SI].set(CV_AMD64_RSI, 0x00, 0xffff); - subRegs[CV_AMD64_DI].set(CV_AMD64_RDI, 0x00, 0xffff); - - subRegs[CV_AMD64_EAX].set(CV_AMD64_RAX, 0x00, 0xffffffff); - subRegs[CV_AMD64_ECX].set(CV_AMD64_RCX, 0x00, 0xffffffff); - subRegs[CV_AMD64_EDX].set(CV_AMD64_RDX, 0x00, 0xffffffff); - subRegs[CV_AMD64_EBX].set(CV_AMD64_RBX, 0x00, 0xffffffff); - - subRegs[CV_AMD64_ESP].set(CV_AMD64_RSP, 0x00, 0xffffffff); - subRegs[CV_AMD64_EBP].set(CV_AMD64_RBP, 0x00, 0xffffffff); - subRegs[CV_AMD64_ESI].set(CV_AMD64_RSI, 0x00, 0xffffffff); - subRegs[CV_AMD64_EDI].set(CV_AMD64_RDI, 0x00, 0xffffffff); - - subRegs[CV_AMD64_R8B].set(CV_AMD64_R8, 0x00, 0xff); - subRegs[CV_AMD64_R9B].set(CV_AMD64_R9, 0x00, 0xff); - subRegs[CV_AMD64_R10B].set(CV_AMD64_R10, 0x00, 0xff); - subRegs[CV_AMD64_R11B].set(CV_AMD64_R11, 0x00, 0xff); - subRegs[CV_AMD64_R12B].set(CV_AMD64_R12, 0x00, 0xff); - subRegs[CV_AMD64_R13B].set(CV_AMD64_R13, 0x00, 0xff); - subRegs[CV_AMD64_R14B].set(CV_AMD64_R14, 0x00, 0xff); - subRegs[CV_AMD64_R15B].set(CV_AMD64_R15, 0x00, 0xff); - - subRegs[CV_AMD64_R8W].set(CV_AMD64_R8, 0x00, 0xffff); - subRegs[CV_AMD64_R9W].set(CV_AMD64_R9, 0x00, 0xffff); - subRegs[CV_AMD64_R10W].set(CV_AMD64_R10, 0x00, 0xffff); - subRegs[CV_AMD64_R11W].set(CV_AMD64_R11, 0x00, 0xffff); - subRegs[CV_AMD64_R12W].set(CV_AMD64_R12, 0x00, 0xffff); - subRegs[CV_AMD64_R13W].set(CV_AMD64_R13, 0x00, 0xffff); - subRegs[CV_AMD64_R14W].set(CV_AMD64_R14, 0x00, 0xffff); - subRegs[CV_AMD64_R15W].set(CV_AMD64_R15, 0x00, 0xffff); - - subRegs[CV_AMD64_R8D].set(CV_AMD64_R8, 0x00, 0xffffffff); - subRegs[CV_AMD64_R9D].set(CV_AMD64_R9, 0x00, 0xffffffff); - subRegs[CV_AMD64_R10D].set(CV_AMD64_R10, 0x00, 0xffffffff); - subRegs[CV_AMD64_R11D].set(CV_AMD64_R11, 0x00, 0xffffffff); - subRegs[CV_AMD64_R12D].set(CV_AMD64_R12, 0x00, 0xffffffff); - subRegs[CV_AMD64_R13D].set(CV_AMD64_R13, 0x00, 0xffffffff); - subRegs[CV_AMD64_R14D].set(CV_AMD64_R14, 0x00, 0xffffffff); - subRegs[CV_AMD64_R15D].set(CV_AMD64_R15, 0x00, 0xffffffff); - } -}; - -static const std::map g_SubRegistersAmd64 = SubRegisterMapAmd64().subRegs; - -///////////////////////////////////////////////////////////////////////////////// - -bool ThreadContext::getSubValue(ULONG cvRegId, ULONG64 &val) const -{ - const std::map *subRegs = NULL; - if (IMAGE_FILE_MACHINE_I386 == m_processorType) - subRegs = &g_SubRegistersI386; - else - subRegs = &g_SubRegistersAmd64; - - std::map::const_iterator itSubReg = - subRegs->find(cvRegId); - if (itSubReg == subRegs->end()) - return false; - - RegValues::const_iterator itFullReg = m_regValues.find(itSubReg->second.m_fromReg); - if (itFullReg == m_regValues.end()) - return false; - - val = (itFullReg->second >> itSubReg->second.m_bitsShift) & itSubReg->second.m_bitsMask; - - return true; -} - -///////////////////////////////////////////////////////////////////////////////// - -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 ThreadContext::print() const -{ - std::stringstream sstr; - - RegValues::const_iterator it = m_regValues.begin(); - for (; it != m_regValues.end(); ++it ) - { - switch (m_processorType) - { - case IMAGE_FILE_MACHINE_I386: - - for ( ULONG j = 0; j < pyDia::Symbol::cntI386RegName; ++j ) - if ( pyDia::Symbol::i386RegName[j].first == it->first ) - sstr << pyDia::Symbol::i386RegName[j].second << '=' << std::hex << it->second << std::endl; - - break; - - - case IMAGE_FILE_MACHINE_AMD64: - - for ( ULONG j = 0; j < pyDia::Symbol::cntAmd64RegName; ++j ) - if ( pyDia::Symbol::amd64RegName[j].first == it->first ) - sstr << pyDia::Symbol::amd64RegName[j].second << '=' << std::hex << it->second << std::endl; - - break; - } - - } - - return sstr.str(); -} +//#define _REG_X86(regName) _REG_NAME(REG_, regName) +//static const CvRegName g_x86Registers[] = { +// _REG_X86(DR0), _REG_X86(DR1), _REG_X86(DR2), _REG_X86(DR3), _REG_X86(DR6), _REG_X86(DR7), +// _REG_X86(GS), _REG_X86(FS), _REG_X86(ES), _REG_X86(DS), +// _REG_X86(EDI), _REG_X86(EBX), _REG_X86(EDX), _REG_X86(ECX), _REG_X86(EAX), +// _REG_X86(EBP), _REG_X86(ESP), _REG_X86(SS), +// _REG_X86(EIP), _REG_X86(CS), +// CvRegName(CV_REG_EFLAGS, "efl") +//}; +//#undef _REG_X86 +// +/////////////////////////////////////////////////////////////////////////////////// +//#define _REG_X64(regName) _REG_NAME(AMD64_, regName) +//static const CvRegName g_x64Registers[] = { +// _REG_X64(MXCSR), +// _REG_X64(CS), _REG_X64(DS), _REG_X64(ES), _REG_X64(FS), _REG_X64(GS), _REG_X64(SS), +// +// _REG_X64(DR0), _REG_X64(DR1), _REG_X64(DR2), _REG_X64(DR3), _REG_X64(DR6), _REG_X64(DR7), +// +// _REG_X64(RAX), _REG_X64(RCX), _REG_X64(RDX), _REG_X64(RBX), _REG_X64(RSP), _REG_X64(RBP), _REG_X64(RSI), _REG_X64(RDI), +// _REG_X64(R8), _REG_X64(R9), _REG_X64(R10), _REG_X64(R11), _REG_X64(R12), _REG_X64(R13), _REG_X64(R14), _REG_X64(R15), +// +// _REG_X64(RIP), +// CvRegName(CV_AMD64_EFLAGS, "efl") +//}; +//#undef _REG_X64 +// +//#undef _REG_NAME +// +/////////////////////////////////////////////////////////////////////////////////// +// +//void ThreadContext::getI386Context() +//{ +// queryRegisters(g_x86Registers, _countof(g_x86Registers)); +//} +// +/////////////////////////////////////////////////////////////////////////////////// +// +//void ThreadContext::getAmd64Context() +//{ +// queryRegisters(g_x64Registers, _countof(g_x64Registers)); +//} +// +/////////////////////////////////////////////////////////////////////////////////// +// +//ThreadContext::ThreadContext( IDebugClient4 *client ) : +// pykd::DbgObject( client ) +//{ +// HRESULT hres = m_control->GetEffectiveProcessorType(&m_processorType); +// if (S_OK != hres) +// throw DbgException( "IDebugControl::GetEffectiveProcessorType", hres ); +// +// switch (m_processorType) +// { +// case IMAGE_FILE_MACHINE_I386: +// getI386Context(); +// return; +// +// case IMAGE_FILE_MACHINE_AMD64: +// getAmd64Context(); +// return; +// } +// +// throwUnsupportedProcessor(__FUNCTION__); +//} +// +/////////////////////////////////////////////////////////////////////////////////// +// +//ThreadContext::ThreadContext( +// IDebugClient4 *client, +// ULONG processorType +//) : pykd::DbgObject(client) +// , m_processorType(processorType) +//{ +//} +// +/////////////////////////////////////////////////////////////////////////////////// +// +//void ThreadContext::queryRegisters( +// const CvRegName *regs, +// ULONG countOfRegs +//) +//{ +// HRESULT hres; +// +// std::vector regIndices( countOfRegs ); +// +// for (ULONG i = 0; i < countOfRegs; ++i) +// { +// hres = m_registers->GetIndexByName(regs[i].m_name.c_str(), ®Indices[i]); +// if (S_OK != hres) +// throw DbgException( "IDebugRegisters::GetIndexByName", hres); +// } +// +// std::vector regValues( countOfRegs ); +// hres = +// m_registers->GetValues( +// static_cast(countOfRegs), +// ®Indices[0], +// 0, +// ®Values[0]); +// if (S_OK != hres) +// throw DbgException( "IDebugRegisters::GetValues", hres); +// +// for (ULONG i = 0; i < countOfRegs; ++i) +// { +// const DEBUG_VALUE ®Value = regValues[i]; +// switch (regValue.Type) +// { +// case DEBUG_VALUE_INT8: +// m_regValues[regs[i].m_cvValue] = regValue.I8; +// break; +// case DEBUG_VALUE_INT16: +// m_regValues[regs[i].m_cvValue] = regValue.I16; +// break; +// case DEBUG_VALUE_INT32: +// m_regValues[regs[i].m_cvValue] = regValue.I32; +// break; +// case DEBUG_VALUE_INT64: +// m_regValues[regs[i].m_cvValue] = regValue.I64; +// break; +// } +// } +//} +// +/////////////////////////////////////////////////////////////////////////////////// +// +//ContextPtr ThreadContext::getWow64Context( IDebugClient4 *client ) +//{ +// ContextPtr ptrContext( new ThreadContext(client, IMAGE_FILE_MACHINE_I386) ); +// +// ULONG processorType; +// HRESULT hres = ptrContext->m_control->GetEffectiveProcessorType(&processorType); +// if (S_OK != hres) +// throw DbgException( "IDebugControl::GetEffectiveProcessorType", hres ); +// if (IMAGE_FILE_MACHINE_I386 != processorType) +// throw DbgException( "Only for WOW64 processor mode" ); +// +// hres = ptrContext->m_control->GetActualProcessorType(&processorType); +// if (S_OK != hres) +// throw DbgException( "IDebugControl::GetActualProcessorType", hres ); +// if (IMAGE_FILE_MACHINE_AMD64 != processorType) +// throw DbgException( "Only for WOW64 processor mode" ); +// +// // +// // *** undoc *** +// // !wow64exts.r +// // http://www.woodmann.com/forum/archive/index.php/t-11162.html +// // http://www.nynaeve.net/Code/GetThreadWow64Context.cpp +// // +// +// ULONG64 teb64Address; +// hres = ptrContext->m_system->GetCurrentThreadTeb(&teb64Address); +// if (S_OK != hres) +// throw DbgException( "IDebugSystemObjects::GetCurrentThreadTeb", hres); +// +// // ? @@C++(#FIELD_OFFSET(nt!_TEB64, TlsSlots)) +// // hardcoded in !wow64exts.r (6.2.8250.0) +// static const ULONG teb64ToTlsOffset = 0x01480; +// static const ULONG WOW64_TLS_CPURESERVED = 1; +// ULONG64 cpuAreaAddress; +// ULONG readedBytes; +// hres = +// readVirtual( +// ptrContext->m_dataSpaces, +// teb64Address + teb64ToTlsOffset + (sizeof(ULONG64) * WOW64_TLS_CPURESERVED), +// &cpuAreaAddress, +// sizeof(cpuAreaAddress), +// &readedBytes); +// if (S_OK != hres || readedBytes != sizeof(cpuAreaAddress)) +// throw DbgException( "IDebugDataSpaces::ReadVirtual", hres); +// +// // CPU Area is: +// // +00 unknown ULONG +// // +04 WOW64_CONTEXT struct +// static const ULONG cpuAreaToWow64ContextOffset = sizeof(ULONG); +// WOW64_CONTEXT Context = {0}; +// hres = +// readVirtual( +// ptrContext->m_dataSpaces, +// cpuAreaAddress + cpuAreaToWow64ContextOffset, +// &Context, +// sizeof(Context), +// &readedBytes); +// if (S_OK != hres || readedBytes != sizeof(Context)) +// throw DbgException( "IDebugDataSpaces::ReadVirtual", hres); +// +// FillRegistersFromContext32(ptrContext->m_regValues, Context); +// +// return ptrContext; +//} +// +/////////////////////////////////////////////////////////////////////////////////// +// +//ULONG64 ThreadContext::getValue(ULONG cvRegId) const +//{ +// ULONG64 val; +// +// if ( getValueNoThrow( cvRegId, val ) ) +// return val; +// +// throw DbgException(__FUNCTION__ ": Register missing"); +//} +// +/////////////////////////////////////////////////////////////////////////////////// +// +//ULONG64 ThreadContext::getValueByName( const std::string ®Name ) const +//{ +// std::string upcaseName = boost::to_upper_copy( regName ); +// +// if ( IMAGE_FILE_MACHINE_I386 == m_processorType ) +// { +// for ( ULONG i = 0; i < pyDia::Symbol::cntI386RegName; ++i ) +// { +// if ( upcaseName == pyDia::Symbol::i386RegName[i].second ) +// return getValue( pyDia::Symbol::i386RegName[i].first ); +// } +// } +// else +// { +// for ( ULONG i = 0; i < pyDia::Symbol::cntAmd64RegName; ++i ) +// { +// if ( upcaseName == pyDia::Symbol::amd64RegName[i].second ) +// return getValue( pyDia::Symbol::amd64RegName[i].first ); +// } +// } +// +// throwUnsupportedProcessor(__FUNCTION__); +//} +// +///////////////////////////////////////////////////////////////////////////////////// +// +//bool ThreadContext::getValueNoThrow(ULONG cvRegId, ULONG64 &val) const +//{ +// if ( getSubValue(cvRegId, val ) ) +// return true; +// +// RegValues::const_iterator it = m_regValues.find(cvRegId); +// if (it == m_regValues.end()) +// return false; +// +// val = it->second; +// return true; +//} +// +///////////////////////////////////////////////////////////////////////////////////// +// +//ULONG64 ThreadContext::getIp() const +//{ +// return getValue( +// IMAGE_FILE_MACHINE_I386 == m_processorType ? CV_REG_EIP : CV_AMD64_RIP +// ); +//} +// +/////////////////////////////////////////////////////////////////////////////////// +// +//ULONG64 ThreadContext::getRetReg() const +//{ +// return getValue( +// IMAGE_FILE_MACHINE_I386 == m_processorType ? CV_REG_EAX : CV_AMD64_RAX +// ); +//} +// +/////////////////////////////////////////////////////////////////////////////////// +// +//ULONG64 ThreadContext::getSp() const +//{ +// return getValue( +// IMAGE_FILE_MACHINE_I386 == m_processorType ? CV_REG_ESP : CV_AMD64_RSP +// ); +//} +// +/////////////////////////////////////////////////////////////////////////////////// +// +//ContextPtr ThreadContext::forkByStackFrame(const StackFrame &stkFrmae) const +//{ +// ContextPtr newContext( new ThreadContext(*this) ); +// switch (m_processorType) +// { +// case IMAGE_FILE_MACHINE_I386: +// newContext->m_regValues[CV_REG_EIP] = stkFrmae.m_instructionOffset; +// newContext->m_regValues[CV_REG_EBP] = stkFrmae.m_frameOffset; +// newContext->m_regValues[CV_REG_ESP] = stkFrmae.m_stackOffset; +// return newContext; +// +// case IMAGE_FILE_MACHINE_AMD64: +// newContext->m_regValues[CV_AMD64_RIP] = stkFrmae.m_instructionOffset; +// newContext->m_regValues[CV_AMD64_RBP] = stkFrmae.m_frameOffset; +// newContext->m_regValues[CV_AMD64_RSP] = stkFrmae.m_stackOffset; +// return newContext; +// } +// +// throwUnsupportedProcessor(__FUNCTION__); +//} +// +/////////////////////////////////////////////////////////////////////////////////// +// +//python::object ThreadContext::getByIndex(ULONG ind) const +//{ +// RegValues::const_iterator it = m_regValues.begin(); +// for (ULONG i = 0; it != m_regValues.end(); ++i, ++it ) +// { +// if (i == ind) +// { +// switch (m_processorType) +// { +// case IMAGE_FILE_MACHINE_I386: +// +// for ( ULONG j = 0; j < pyDia::Symbol::cntI386RegName; ++j ) +// if ( pyDia::Symbol::i386RegName[j].first == it->first ) +// return python::make_tuple( it->first, pyDia::Symbol::i386RegName[j].second, it->second); +// +// break; +// +// +// case IMAGE_FILE_MACHINE_AMD64: +// +// for ( ULONG j = 0; j < pyDia::Symbol::cntAmd64RegName; ++j ) +// if ( pyDia::Symbol::amd64RegName[j].first == it->first ) +// return python::make_tuple( it->first, pyDia::Symbol::amd64RegName[j].second, it->second); +// +// break; +// } +// } +// } +// +// throw PyException( PyExc_IndexError, "Index out of range"); +//} +// +/////////////////////////////////////////////////////////////////////////////////// +// +//struct SubRegister { +// ULONG m_fromReg; +// ULONG m_bitsShift; +// ULONG m_bitsMask; +// +// void set(ULONG fromReg, ULONG bitsShift, ULONG bitsMask) +// { +// m_fromReg = fromReg; m_bitsShift = bitsShift; m_bitsMask = bitsMask; +// } +//}; +// +/////////////////////////////////////////////////////////////////////////////////// +// +// +//struct SubRegisterMapI386 { +// +// std::map subRegs; +// +// SubRegisterMapI386() +// { +// subRegs[CV_REG_AL].set(CV_REG_EAX, 0x00, 0xff); +// subRegs[CV_REG_CL].set(CV_REG_ECX, 0x00, 0xff); +// subRegs[CV_REG_DL].set(CV_REG_EDX, 0x00, 0xff); +// subRegs[CV_REG_BL].set(CV_REG_EBX, 0x00, 0xff); +// +// subRegs[CV_REG_AH].set(CV_REG_EAX, 0x08, 0xff); +// subRegs[CV_REG_CH].set(CV_REG_ECX, 0x08, 0xff); +// subRegs[CV_REG_DH].set(CV_REG_EDX, 0x08, 0xff); +// subRegs[CV_REG_BH].set(CV_REG_EBX, 0x08, 0xff); +// +// subRegs[CV_REG_AX].set(CV_REG_EAX, 0x00, 0xffff); +// subRegs[CV_REG_CX].set(CV_REG_ECX, 0x00, 0xffff); +// subRegs[CV_REG_DX].set(CV_REG_EDX, 0x00, 0xffff); +// subRegs[CV_REG_BX].set(CV_REG_EBX, 0x00, 0xffff); +// +// subRegs[CV_REG_SP].set(CV_REG_ESP, 0x00, 0xffff); +// subRegs[CV_REG_BP].set(CV_REG_EBP, 0x00, 0xffff); +// subRegs[CV_REG_SI].set(CV_REG_ESI, 0x00, 0xffff); +// subRegs[CV_REG_DI].set(CV_REG_EDI, 0x00, 0xffff); +// } +// +//}; +// +//static const std::map g_SubRegistersI386 = SubRegisterMapI386().subRegs; +// +/////////////////////////////////////////////////////////////////////////////////// +// +//struct SubRegisterMapAmd64 { +// +// std::map subRegs; +// +// SubRegisterMapAmd64() +// { +// subRegs[CV_AMD64_AL].set(CV_AMD64_RAX, 0x00, 0xff); +// subRegs[CV_AMD64_CL].set(CV_AMD64_RCX, 0x00, 0xff); +// subRegs[CV_AMD64_DL].set(CV_AMD64_RDX, 0x00, 0xff); +// subRegs[CV_AMD64_BL].set(CV_AMD64_RBX, 0x00, 0xff); +// +// subRegs[CV_AMD64_AH].set(CV_AMD64_RAX, 0x08, 0xff); +// subRegs[CV_AMD64_CH].set(CV_AMD64_RCX, 0x08, 0xff); +// subRegs[CV_AMD64_DH].set(CV_AMD64_RDX, 0x08, 0xff); +// subRegs[CV_AMD64_BH].set(CV_AMD64_RBX, 0x08, 0xff); +// +// subRegs[CV_AMD64_AX].set(CV_AMD64_RAX, 0x00, 0xffff); +// subRegs[CV_AMD64_CX].set(CV_AMD64_RCX, 0x00, 0xffff); +// subRegs[CV_AMD64_DX].set(CV_AMD64_RDX, 0x00, 0xffff); +// subRegs[CV_AMD64_BX].set(CV_AMD64_RBX, 0x00, 0xffff); +// +// subRegs[CV_AMD64_SP].set(CV_AMD64_RSP, 0x00, 0xffff); +// subRegs[CV_AMD64_BP].set(CV_AMD64_RBP, 0x00, 0xffff); +// subRegs[CV_AMD64_SI].set(CV_AMD64_RSI, 0x00, 0xffff); +// subRegs[CV_AMD64_DI].set(CV_AMD64_RDI, 0x00, 0xffff); +// +// subRegs[CV_AMD64_EAX].set(CV_AMD64_RAX, 0x00, 0xffffffff); +// subRegs[CV_AMD64_ECX].set(CV_AMD64_RCX, 0x00, 0xffffffff); +// subRegs[CV_AMD64_EDX].set(CV_AMD64_RDX, 0x00, 0xffffffff); +// subRegs[CV_AMD64_EBX].set(CV_AMD64_RBX, 0x00, 0xffffffff); +// +// subRegs[CV_AMD64_ESP].set(CV_AMD64_RSP, 0x00, 0xffffffff); +// subRegs[CV_AMD64_EBP].set(CV_AMD64_RBP, 0x00, 0xffffffff); +// subRegs[CV_AMD64_ESI].set(CV_AMD64_RSI, 0x00, 0xffffffff); +// subRegs[CV_AMD64_EDI].set(CV_AMD64_RDI, 0x00, 0xffffffff); +// +// subRegs[CV_AMD64_R8B].set(CV_AMD64_R8, 0x00, 0xff); +// subRegs[CV_AMD64_R9B].set(CV_AMD64_R9, 0x00, 0xff); +// subRegs[CV_AMD64_R10B].set(CV_AMD64_R10, 0x00, 0xff); +// subRegs[CV_AMD64_R11B].set(CV_AMD64_R11, 0x00, 0xff); +// subRegs[CV_AMD64_R12B].set(CV_AMD64_R12, 0x00, 0xff); +// subRegs[CV_AMD64_R13B].set(CV_AMD64_R13, 0x00, 0xff); +// subRegs[CV_AMD64_R14B].set(CV_AMD64_R14, 0x00, 0xff); +// subRegs[CV_AMD64_R15B].set(CV_AMD64_R15, 0x00, 0xff); +// +// subRegs[CV_AMD64_R8W].set(CV_AMD64_R8, 0x00, 0xffff); +// subRegs[CV_AMD64_R9W].set(CV_AMD64_R9, 0x00, 0xffff); +// subRegs[CV_AMD64_R10W].set(CV_AMD64_R10, 0x00, 0xffff); +// subRegs[CV_AMD64_R11W].set(CV_AMD64_R11, 0x00, 0xffff); +// subRegs[CV_AMD64_R12W].set(CV_AMD64_R12, 0x00, 0xffff); +// subRegs[CV_AMD64_R13W].set(CV_AMD64_R13, 0x00, 0xffff); +// subRegs[CV_AMD64_R14W].set(CV_AMD64_R14, 0x00, 0xffff); +// subRegs[CV_AMD64_R15W].set(CV_AMD64_R15, 0x00, 0xffff); +// +// subRegs[CV_AMD64_R8D].set(CV_AMD64_R8, 0x00, 0xffffffff); +// subRegs[CV_AMD64_R9D].set(CV_AMD64_R9, 0x00, 0xffffffff); +// subRegs[CV_AMD64_R10D].set(CV_AMD64_R10, 0x00, 0xffffffff); +// subRegs[CV_AMD64_R11D].set(CV_AMD64_R11, 0x00, 0xffffffff); +// subRegs[CV_AMD64_R12D].set(CV_AMD64_R12, 0x00, 0xffffffff); +// subRegs[CV_AMD64_R13D].set(CV_AMD64_R13, 0x00, 0xffffffff); +// subRegs[CV_AMD64_R14D].set(CV_AMD64_R14, 0x00, 0xffffffff); +// subRegs[CV_AMD64_R15D].set(CV_AMD64_R15, 0x00, 0xffffffff); +// } +//}; +// +//static const std::map g_SubRegistersAmd64 = SubRegisterMapAmd64().subRegs; +// +/////////////////////////////////////////////////////////////////////////////////// +// +//bool ThreadContext::getSubValue(ULONG cvRegId, ULONG64 &val) const +//{ +// const std::map *subRegs = NULL; +// if (IMAGE_FILE_MACHINE_I386 == m_processorType) +// subRegs = &g_SubRegistersI386; +// else +// subRegs = &g_SubRegistersAmd64; +// +// std::map::const_iterator itSubReg = +// subRegs->find(cvRegId); +// if (itSubReg == subRegs->end()) +// return false; +// +// RegValues::const_iterator itFullReg = m_regValues.find(itSubReg->second.m_fromReg); +// if (itFullReg == m_regValues.end()) +// return false; +// +// val = (itFullReg->second >> itSubReg->second.m_bitsShift) & itSubReg->second.m_bitsMask; +// +// return true; +//} +// +/////////////////////////////////////////////////////////////////////////////////// +// +//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 ThreadContext::print() const +//{ +// std::stringstream sstr; +// +// RegValues::const_iterator it = m_regValues.begin(); +// for (; it != m_regValues.end(); ++it ) +// { +// switch (m_processorType) +// { +// case IMAGE_FILE_MACHINE_I386: +// +// for ( ULONG j = 0; j < pyDia::Symbol::cntI386RegName; ++j ) +// if ( pyDia::Symbol::i386RegName[j].first == it->first ) +// sstr << pyDia::Symbol::i386RegName[j].second << '=' << std::hex << it->second << std::endl; +// +// break; +// +// +// case IMAGE_FILE_MACHINE_AMD64: +// +// for ( ULONG j = 0; j < pyDia::Symbol::cntAmd64RegName; ++j ) +// if ( pyDia::Symbol::amd64RegName[j].first == it->first ) +// sstr << pyDia::Symbol::amd64RegName[j].second << '=' << std::hex << it->second << std::endl; +// +// break; +// } +// +// } +// +// return sstr.str(); +//} ///////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/context.h b/pykd/context.h index abd4a59..79060db 100644 --- a/pykd/context.h +++ b/pykd/context.h @@ -1,10 +1,9 @@ #pragma once #include -#include +//#include #include "context.h" -#include "dbgobj.h" #include "dbgexcept.h" namespace pykd { @@ -24,72 +23,77 @@ std::string processorToStr(ULONG processorMode); //////////////////////////////////////////////////////////////////////////////// -class ThreadContext : private DbgObject +class ThreadContext { -public: - typedef std::map RegValues; +//public: + //typedef std::map RegValues; - ThreadContext( IDebugClient4 *client ); - static ContextPtr getWow64Context( IDebugClient4 *client ); + //ThreadContext(); + ////static ContextPtr getWow64Context(); - // get register value by ID - ULONG64 getValue(ULONG cvRegId) const; - ULONG64 getValueByName( const std::string ®Name ) const; - bool getValueNoThrow(ULONG cvRegId, ULONG64 &val) const; + //// get register value by ID + //ULONG64 getValue(ULONG cvRegId) const; + //ULONG64 getValueByName( const std::string ®Name ) const; + //bool getValueNoThrow(ULONG cvRegId, ULONG64 &val) const; - // get @$ip pseudo register - ULONG64 getIp() const; + //// get @$ip pseudo register + //ULONG64 getIp() const; - // get @$retreg pseudo register - ULONG64 getRetReg() const; + //// get @$retreg pseudo register + //ULONG64 getRetReg() const; - // get @$csp pseudo register - ULONG64 getSp() const; + //// get @$csp pseudo register + //ULONG64 getSp() const; - // enumerate register values: tuple - ULONG getCount() const { - return static_cast( m_regValues.size() ); - } + //// enumerate register values: tuple + //ULONG getCount() const { + // return static_cast( m_regValues.size() ); + //} - python::object getByIndex(ULONG ind) const; + //python::object getByIndex(ULONG ind) const; - // get processor type - std::string getProcessorType() const { - return pykd::processorToStr(m_processorType); - } + //// get processor type + //std::string getProcessorType() const { + // return pykd::processorToStr(m_processorType); + //} - ContextPtr forkByStackFrame(const StackFrame &stkFrmae) const; + //ContextPtr forkByStackFrame(const StackFrame &stkFrmae) const; - std::string print() const; + //std::string print() const; -protected: - ThreadContext( - IDebugClient4 *client, - ULONG processorType - ); +//protected: + //ThreadContext( + // ULONG processorType + //); - void queryRegisters( - const CvRegName *regs, - ULONG countOfRegs - ); + //void queryRegisters( + // const CvRegName *regs, + // ULONG countOfRegs + //); - // query i386 registers - void getI386Context(); + //// query i386 registers + //void getI386Context(); - // query AMD64 registers - void getAmd64Context(); + //// query AMD64 registers + //void getAmd64Context(); - // try query as "sub-register" - bool getSubValue(ULONG cvRegId, ULONG64 &val) const; + //// try query as "sub-register" + //bool getSubValue(ULONG cvRegId, ULONG64 &val) const; - void __declspec(noreturn) throwUnsupportedProcessor(PCSTR szFunction) const; + //void __declspec(noreturn) throwUnsupportedProcessor(PCSTR szFunction) const; -private: - RegValues m_regValues; +//private: + //RegValues m_regValues; - ULONG m_processorType; + //ULONG m_processorType; }; +//////////////////////////////////////////////////////////////////////////////// +// +//ContextPtr getThreadContext(); +// +//python::dict getLocals( ContextPtr ctx = getThreadContext() ); + //////////////////////////////////////////////////////////////////////////////// } diff --git a/pykd/dbgengine.h b/pykd/dbgengine.h index 8d768a3..d434bea 100644 --- a/pykd/dbgengine.h +++ b/pykd/dbgengine.h @@ -10,6 +10,11 @@ ULONG startProcess( const std::wstring &processName ); void detachProcess( ULONG processId = -1); void terminateProcess( ULONG processId = -1); +void loadDump( const std::wstring &fileName ); + +bool isDumpAnalyzing(); +bool isKernelDebugging(); + void debugGo(); // system properties diff --git a/pykd/livevar.cpp b/pykd/livevar.cpp deleted file mode 100644 index a1dc6aa..0000000 --- a/pykd/livevar.cpp +++ /dev/null @@ -1,214 +0,0 @@ - -//////////////////////////////////////////////////////////////////////////////// - -#include - -#include "dbgclient.h" - -//////////////////////////////////////////////////////////////////////////////// - -namespace pykd { - -//////////////////////////////////////////////////////////////////////////////// - -namespace impl { - -//////////////////////////////////////////////////////////////////////////////// - -struct addLocals { - python::dict &m_locals; - const ModulePtr m_module; - ULONG m_rva; - ContextPtr m_ctx; - IDebugClient4 *m_client; - ULONG m_formalNameCounter; - CComPtr< IDebugDataSpaces4 > m_dataSpaces; - - void append(pyDia::SymbolPtr symParent); - -private: - void appendVar(pyDia::SymbolPtr symData); - - void generateUniqueName(std::string &varName); - - TypedVarPtr getTypeVarByOffset( - pyDia::SymbolPtr symData, - ULONG64 varOffset - ); -}; - -//////////////////////////////////////////////////////////////////////////////// - -struct Exception : public DbgException { - Exception() : DbgException("build list of locals: internal exception") - { - } -}; - -//////////////////////////////////////////////////////////////////////////////// - -void addLocals::append(pyDia::SymbolPtr symParent) -{ - // add all local variables - pyDia::SymbolPtrList lstLocals = symParent->findChildrenImpl(SymTagData); - pyDia::SymbolPtrList::iterator it = lstLocals.begin(); - while (it != lstLocals.end()) - { - try - { - appendVar(*it); - } - catch (const DbgException &e) - { - DBG_UNREFERENCED_LOCAL_VARIABLE(e); - } - ++it; - } - - // process all scopes - pyDia::SymbolPtrList lstScopes = symParent->findChildrenImpl(SymTagBlock); - it = lstScopes.begin(); - while ( it != lstScopes.end() ) - { - const ULONG scopeRva = (*it)->getRva(); - if ( (scopeRva <= m_rva) && (scopeRva + (*it)->getSize() > m_rva) ) - append(*it); - ++it; - } -} - -//////////////////////////////////////////////////////////////////////////////// - -void addLocals::appendVar(pyDia::SymbolPtr symData) -{ - TypedVarPtr typedVar; - - std::string varName = symData->getName(); - - // check name for unique. f.e. may be may be somewhat parameters - // with name "__formal" - generateUniqueName(varName); - - switch (symData->getLocType()) - { - case LocIsStatic: - typedVar = - getTypeVarByOffset( - symData, - m_module->getBase() + symData->getRva() ); - break; - - case LocIsRegRel: - typedVar = - getTypeVarByOffset( - symData, - m_ctx->getValue( symData->getRegisterId() )+ symData->getOffset() ); - break; - - case LocIsEnregistered: // FIXME - default: - throw ImplementException(__FILE__,__LINE__,"Fix ME"); - } - typedVar->setDataKind( symData->getDataKind() ); - m_locals[varName] = typedVar; -} - -//////////////////////////////////////////////////////////////////////////////// - -void addLocals::generateUniqueName(std::string &varName) -{ - if ( !m_locals.has_key(varName) ) - return; - - std::string origVarName = varName; - while ( m_locals.has_key(varName) ) - { - std::stringstream sstream; - sstream << origVarName << ++m_formalNameCounter; - varName = sstream.str(); - } -} - -//////////////////////////////////////////////////////////////////////////////// - -TypedVarPtr addLocals::getTypeVarByOffset( - pyDia::SymbolPtr symData, - ULONG64 varOffset -) -{ - pyDia::SymbolPtr symType = symData->getType(); - - TypeInfoPtr typeInfo = TypeInfo::getTypeInfo( symType ); - - return TypedVar::getTypedVar( m_client, typeInfo, VarDataMemory::factory(m_dataSpaces, varOffset) ); -} - -//////////////////////////////////////////////////////////////////////////////// - -static ULONG getUnnamedChildRva( - pyDia::SymbolPtr symParent, - ULONG SymTag -) -{ - pyDia::SymbolPtrList childs = symParent->findChildrenImpl(SymTag); - if (childs.empty()) - throw Exception(); - - return (*childs.begin())->getRva(); -} - -//////////////////////////////////////////////////////////////////////////////// - -static bool isOutOfDebugRange( - ULONG rva, - pyDia::SymbolPtr symFunc -) -{ - try - { - if (rva < getUnnamedChildRva(symFunc, SymTagFuncDebugStart)) - return true; - - if (rva > getUnnamedChildRva(symFunc, SymTagFuncDebugEnd)) - return true; - } - catch (const DbgException &) - { - } - return false; -} - -} - -//////////////////////////////////////////////////////////////////////////////// - -python::dict DebugClient::getLocals(ContextPtr ctx OPTIONAL) -{ - if (!ctx) - ctx = getThreadContext(); - - const ULONG64 instrPtr = ctx->getIp(); - - ModulePtr mod = loadModuleByOffset( instrPtr ); - const ULONG rva = static_cast( instrPtr - mod->getBase() ); - - pyDia::GlobalScopePtr globScope = mod->getDia(); - LONG funcDispl; - pyDia::SymbolPtr symFunc = - globScope->findByRvaImpl(rva, SymTagFunction, funcDispl); - if (impl::isOutOfDebugRange(rva, symFunc)) - return python::dict(); // out of function debug range - - python::dict locals; - impl::addLocals Locals = { locals, mod, rva, ctx, m_client, 0, m_dataSpaces }; - - Locals.append(symFunc); - - return locals; -} - -//////////////////////////////////////////////////////////////////////////////// - -} - -//////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/localvar.cpp b/pykd/localvar.cpp new file mode 100644 index 0000000..66d563f --- /dev/null +++ b/pykd/localvar.cpp @@ -0,0 +1,30 @@ + +#include + +#include "localvar.h" +#include "module.h" +#include "symengine.h" +#include "dbgengine.h" +#include "typedvar.h" + +namespace pykd { + +/////////////////////////////////////////////////////////////////////////////// + +python::dict getLocals() +{ + return getLocalsByFrame( getCurrentStackFrame() ); +} + +/////////////////////////////////////////////////////////////////////////////// + +python::dict getLocalsByFrame( StackFrame &frame ) +{ + python::dict dct; + return dct; +} + +/////////////////////////////////////////////////////////////////////////////// + +} //end pykd namespace + diff --git a/pykd/module.cpp b/pykd/module.cpp index 1981e97..c882b29 100644 --- a/pykd/module.cpp +++ b/pykd/module.cpp @@ -193,4 +193,16 @@ python::list Module::getTypedVarListByTypeName( ULONG64 listHeadAddress, const s /////////////////////////////////////////////////////////////////////////////////// +SymbolPtr Module::getSymbolByVa( ULONG64 offset, ULONG symTag, LONG* displacment ) +{ + offset = addr64(offset); + + if ( offset < m_base || offset > getEnd() ) + throw DbgException( "address is out of the module space" ); + + return getSymSession()->findByRva( (ULONG)(offset - m_base ), symTag, displacment ); +} + +/////////////////////////////////////////////////////////////////////////////////// + }; // end of namespace pykd diff --git a/pykd/module.h b/pykd/module.h index 2b603b9..d317dc3 100644 --- a/pykd/module.h +++ b/pykd/module.h @@ -93,6 +93,8 @@ public: ULONG64 getSymbolSize( const std::string &symName ); + SymbolPtr getSymbolByVa( ULONG64 offset, ULONG symTag, LONG* displacemnt ); + std::string print(); private: diff --git a/pykd/pykd_2008.vcproj b/pykd/pykd_2008.vcproj index b7ea18b..05ce6fe 100644 --- a/pykd/pykd_2008.vcproj +++ b/pykd/pykd_2008.vcproj @@ -369,6 +369,10 @@ RelativePath=".\disasm.cpp" > + + @@ -467,6 +471,10 @@ RelativePath=".\disasmengine.h" > + + diff --git a/pykd/pymod.cpp b/pykd/pymod.cpp index 6d3bbbe..5c13dad 100644 --- a/pykd/pymod.cpp +++ b/pykd/pymod.cpp @@ -18,6 +18,7 @@ #include "cpureg.h" #include "disasm.h" #include "stkframe.h" +#include "localvar.h" using namespace pykd; @@ -44,8 +45,6 @@ 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 ) { python::scope().attr("version") = pykdVersion; @@ -58,6 +57,12 @@ BOOST_PYTHON_MODULE( pykd ) "Stop process debugging"); python::def( "killProcess", &terminateProcess, "Stop debugging and terminate current process" ); + python::def( "loadDump", &loadDump, + "Load crash dump"); + python::def( "isDumpAnalyzing", &isDumpAnalyzing, + "Check if it is a dump analyzing ( not living debuggee )" ); + python::def( "isKernelDebugging", &isKernelDebugging, + "Check if kernel dubugging is running" ); python::def( "go", &debugGo, "Go debugging" ); @@ -162,7 +167,7 @@ BOOST_PYTHON_MODULE( pykd ) // stack and local variables python::def( "getCurrentStack", &getCurrentStack, "Return a current stack as a list of stackFrame objects" ); - + python::def( "getLocals", &getLocals, "Get list of local variables" ); python::class_( "intBase", "intBase", python::no_init ) .def( python::init() ) @@ -318,6 +323,33 @@ BOOST_PYTHON_MODULE( pykd ) .def( "__str__", &StackFrame::print, "Return stacks frame as a string"); + //python::class_( + // "Context", "Context of thread (register values)", python::no_init ) + // .def( "ip", &ThreadContext::getIp, + // "Get instruction pointer register" ) + // .def( "retreg", &ThreadContext::getRetReg, + // "Get primary return value register" ) + // .def( "csp", &ThreadContext::getSp, + // "Get current stack pointer" ) + // .def( "get", &ThreadContext::getValue, + // "Get register value by ID (CV_REG_XXX)" ) + // .def( "get", &ThreadContext::getValueByName, + // "Get register value by name" ) + // .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, + // "Return tuple by index") + // .def("__getitem__", &ThreadContext::getValueByName, + // "Return register value by name" ) + // .def("__getattr__", &ThreadContext::getValueByName, + // "Return register value as a attribute of the Context" ) + // .def("__str__", &ThreadContext::print, + // "Return context 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/stkframe.cpp b/pykd/stkframe.cpp index e2b18f1..e3b43fb 100644 --- a/pykd/stkframe.cpp +++ b/pykd/stkframe.cpp @@ -5,6 +5,7 @@ #include "stdafx.h" #include "stkframe.h" #include "dbgengine.h" +#include "localvar.h" //////////////////////////////////////////////////////////////////////////////// @@ -40,6 +41,13 @@ std::string StackFrame::print() const //////////////////////////////////////////////////////////////////////////////// +python::dict StackFrame::getLocals() +{ + return getLocalsByFrame( *this ); +} + +//////////////////////////////////////////////////////////////////////////////// + python::list getCurrentStack() { ULONG frameCount = getStackTraceFrameCount(); @@ -62,6 +70,19 @@ python::list getCurrentStack() //////////////////////////////////////////////////////////////////////////////// +StackFrame getCurrentStackFrame() +{ + ULONG frameCount = getStackTraceFrameCount(); + + std::vector frames(frameCount); + + getStackTrace( &frames[0], frameCount ); + + return frames[0]; +} + +/////////////////////////////////////////////////////////////////////////////// + } // namespace pykd diff --git a/pykd/stkframe.h b/pykd/stkframe.h index 75501f1..3bd2c22 100644 --- a/pykd/stkframe.h +++ b/pykd/stkframe.h @@ -5,6 +5,7 @@ #pragma once #include "dbgengine.h" +#include "context.h" //////////////////////////////////////////////////////////////////////////////// @@ -17,7 +18,7 @@ class StackFrame public: StackFrame( const STACK_FRAME_DESC& desc ); -// python::dict getLocals(ContextPtr ctx = ContextPtr()); + python::dict getLocals(); std::string print() const; @@ -33,6 +34,8 @@ public: /////////////////////////////////////////////////////////////////////////////// +StackFrame getCurrentStackFrame(); + python::list getCurrentStack(); /////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/win/dbgeng.cpp b/pykd/win/dbgeng.cpp index 03095df..8f345a1 100644 --- a/pykd/win/dbgeng.cpp +++ b/pykd/win/dbgeng.cpp @@ -91,6 +91,58 @@ void terminateProcess( ULONG processId ) /////////////////////////////////////////////////////////////////////////////////// +void loadDump( const std::wstring &fileName ) +{ + PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate ); + + HRESULT hres; + + hres = g_dbgEng->client->OpenDumpFileWide( fileName.c_str(), NULL ); + if ( FAILED( hres ) ) + throw DbgException( "IDebugClient4::OpenDumpFileWide failed" ); + + hres = g_dbgEng->control->WaitForEvent(DEBUG_WAIT_DEFAULT, INFINITE); + if ( FAILED( hres ) ) + throw DbgException( "IDebugControl::WaitForEvent failed" ); + +} + +/////////////////////////////////////////////////////////////////////////////////// + +bool isDumpAnalyzing() +{ + PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate ); + + HRESULT hres; + ULONG debugClass, debugQualifier; + + hres = g_dbgEng->control->GetDebuggeeType( &debugClass, &debugQualifier ); + + if ( FAILED( hres ) ) + throw DbgException( "IDebugControl::GetDebuggeeType failed" ); + + return debugQualifier >= DEBUG_DUMP_SMALL; +} + +/////////////////////////////////////////////////////////////////////////////////// + +bool isKernelDebugging() +{ + PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate ); + + HRESULT hres; + ULONG debugClass, debugQualifier; + + hres = g_dbgEng->control->GetDebuggeeType( &debugClass, &debugQualifier ); + + if ( FAILED( hres ) ) + throw DbgException( "IDebugControl::GetDebuggeeType failed" ); + + return debugClass == DEBUG_CLASS_KERNEL; +} + +/////////////////////////////////////////////////////////////////////////////////// + void debugGo() { PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate ); diff --git a/test/scripts/pykdtest.py b/test/scripts/pykdtest.py index 4248fe3..cf0d271 100644 --- a/test/scripts/pykdtest.py +++ b/test/scripts/pykdtest.py @@ -48,9 +48,7 @@ if __name__ == "__main__": target.module.reload(); pykd.go() - - unittest.TextTestRunner(stream=sys.stdout, verbosity=2).run(getTestSuite( "typedvar.TypedVarTest.testPrint" ) ) - + unittest.TextTestRunner(stream=sys.stdout, verbosity=2).run( getTestSuite() ) pykd.killProcess( processId )