diff --git a/pykd/context.cpp b/pykd/context.cpp index 719b92d..6ca19cf 100644 --- a/pykd/context.cpp +++ b/pykd/context.cpp @@ -10,7 +10,46 @@ ///////////////////////////////////////////////////////////////////////////////// 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; +} + //////////////////////////////////////////////////////////////////////////////// namespace I386 { @@ -27,34 +66,7 @@ void ThreadContext::getI386Context() if (S_OK != hres) throw DbgException( "IDebugAdvanced2::GetThreadContext", hres ); - m_regValues[CV_REG_DR0] = Context.Dr0; - m_regValues[CV_REG_DR1] = Context.Dr1; - m_regValues[CV_REG_DR2] = Context.Dr2; - m_regValues[CV_REG_DR3] = Context.Dr3; - m_regValues[CV_REG_DR6] = Context.Dr6; - m_regValues[CV_REG_DR7] = Context.Dr7; - - m_regValues[CV_REG_GS] = Context.SegGs; - m_regValues[CV_REG_FS] = Context.SegFs; - m_regValues[CV_REG_ES] = Context.SegEs; - m_regValues[CV_REG_DS] = Context.SegDs; - - m_regValues[CV_REG_EDI] = Context.Edi; - m_regValues[CV_REG_ESI] = Context.Esi; - m_regValues[CV_REG_EBX] = Context.Ebx; - m_regValues[CV_REG_EDX] = Context.Edx; - m_regValues[CV_REG_ECX] = Context.Ecx; - m_regValues[CV_REG_EAX] = Context.Eax; - - m_regValues[CV_REG_EBP] = Context.Ebp; - - m_regValues[CV_REG_ESP] = Context.Esp; - m_regValues[CV_REG_SS] = Context.SegSs; - - m_regValues[CV_REG_EIP] = Context.Eip; - m_regValues[CV_REG_CS] = Context.SegCs; - - m_regValues[CV_REG_EFLAGS] = Context.EFlags; + FillRegistersFromContext32(m_regValues, Context); } ///////////////////////////////////////////////////////////////////////////////// @@ -136,6 +148,81 @@ ThreadContext::ThreadContext( IDebugClient4 *client ) : ///////////////////////////////////////////////////////////////////////////////// +ThreadContext::ThreadContext( + IDebugClient4 *client, + ULONG processorType +) : pykd::DbgObject(client) + , m_processorType(processorType) +{ +} + +///////////////////////////////////////////////////////////////////////////////// + +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 = + ptrContext->m_dataSpaces->ReadVirtual( + 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 = + ptrContext->m_dataSpaces->ReadVirtual( + 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; diff --git a/pykd/context.h b/pykd/context.h index 40d9b41..f16f255 100644 --- a/pykd/context.h +++ b/pykd/context.h @@ -26,7 +26,10 @@ std::string processorToStr(ULONG processorMode); class ThreadContext : private DbgObject { public: + typedef std::map RegValues; + ThreadContext( IDebugClient4 *client ); + static ContextPtr getWow64Context( IDebugClient4 *client ); // get register value by ID ULONG64 getValue(ULONG cvRegId) const; @@ -58,7 +61,11 @@ public: std::string print() const; -private: +protected: + ThreadContext( + IDebugClient4 *client, + ULONG processorType + ); // query i386 registers void getI386Context(); @@ -72,7 +79,6 @@ private: void __declspec(noreturn) throwUnsupportedProcessor(PCSTR szFunction) const; private: - typedef std::map RegValues; RegValues m_regValues; ULONG m_processorType; diff --git a/pykd/dbgclient.h b/pykd/dbgclient.h index cc51ea1..376ee6d 100644 --- a/pykd/dbgclient.h +++ b/pykd/dbgclient.h @@ -254,6 +254,9 @@ public: ContextPtr getThreadContext() { return ContextPtr( new ThreadContext(m_client) ); } + ContextPtr getThreadWow64Context() { + return ThreadContext::getWow64Context(m_client); + } python::dict getLocals( ContextPtr ctx = ContextPtr( reinterpret_cast(0) ) @@ -472,6 +475,10 @@ inline ContextPtr getThreadContext() { return g_dbgClient->getThreadContext(); } +inline ContextPtr getThreadWow64Context() { + return g_dbgClient->getThreadWow64Context(); +} + inline python::dict getLocals( ContextPtr ctx = ContextPtr() ) diff --git a/pykd/pymod.cpp b/pykd/pymod.cpp index c18288e..9e87344 100644 --- a/pykd/pymod.cpp +++ b/pykd/pymod.cpp @@ -322,6 +322,9 @@ BOOST_PYTHON_MODULE( pykd ) "Get the page size for the currently executing processor context" ) .def( "getContext", &DebugClient::getThreadContext, "Get context of current thread (register values)" ) + .def( "getWow64Context", &DebugClient::getThreadWow64Context, + "Get WOW64-context of current thread (register values)\n" + "!wow64exts.r analog") .def( "getLocals", &DebugClient::getLocals, DebugClient_getLocals( python::args( "ctx" ), "Get list of local variables" ) ) .def( "setBp", &DebugClient::setSoftwareBp, DebugClient_setSoftwareBp( python::args( "offset", "callback" ), @@ -523,6 +526,9 @@ BOOST_PYTHON_MODULE( pykd ) "Get the page size for the currently executing processor context" ); python::def( "getContext", &getThreadContext, "Get context of current thread (register values)" ); + python::def( "getWow64Context", &getThreadWow64Context, + "Get WOW64-context of current thread (register values)\n" + "!wow64exts.r analog" ); python::def( "getLocals", &getLocals, getLocals_( python::args( "ctx" ), "Get list of local variables" ) ); python::def( "setBp", &setSoftwareBp, setSoftwareBp_( python::args( "offset", "callback" ), @@ -719,7 +725,6 @@ BOOST_PYTHON_MODULE( pykd ) .def("__str__", &ThreadContext::print, "Return context as a string" ); - python::class_ >( "cpuReg", "CPU regsiter class", boost::python::no_init ) .def( "name", &CpuReg::name, "The name of the regsiter" )