From bba6f842edbc3a10cb79d5eca7e0ce57257cd8aa Mon Sep 17 00:00:00 2001 From: "SND\\EreTIk_cp" Date: Mon, 10 Dec 2012 09:39:22 +0000 Subject: [PATCH] [0.2.x] + getStackTraceWow64 implementation git-svn-id: https://pykd.svn.codeplex.com/svn@81742 9b283d60-5439-405e-af05-b73fd8c4d996 --- pykd/dbgmem.h | 1 + pykd/pymod.cpp | 5 +- pykd/win/dbgeng.cpp | 133 +++++++++++++++++++++++++++++++++++++++++--- pykd/win/memory.cpp | 12 +++- 4 files changed, 139 insertions(+), 12 deletions(-) diff --git a/pykd/dbgmem.h b/pykd/dbgmem.h index d798ad7..b5c37e0 100644 --- a/pykd/dbgmem.h +++ b/pykd/dbgmem.h @@ -8,6 +8,7 @@ ULONG64 addr64( ULONG64 offset ); ULONG64 addr64NoSafe( ULONG64 addr ); void readMemory( ULONG64 offset, PVOID buffer, ULONG length, bool phyAddr = FALSE, ULONG *readed = NULL ); bool readMemoryUnsafe( ULONG64 offset, PVOID buffer, ULONG length, bool phyAddr = FALSE, ULONG *readed = NULL ); +bool readMemoryUnsafeNoSafe( ULONG64 offset, PVOID buffer, ULONG length, bool phyAddr = FALSE, ULONG *readed = NULL ); bool isVaValid( ULONG64 addr ); bool compareMemory( ULONG64 addr1, ULONG64 addr2, ULONG length, bool phyAddr = FALSE ); diff --git a/pykd/pymod.cpp b/pykd/pymod.cpp index fb14efc..61fce00 100644 --- a/pykd/pymod.cpp +++ b/pykd/pymod.cpp @@ -37,6 +37,7 @@ static const std::string pykdVersion = PYKD_VERSION_BUILD_STR //////////////////////////////////////////////////////////////////////////////// +BOOST_PYTHON_FUNCTION_OVERLOADS( detachProcess_, detachProcess, 0, 1 ); BOOST_PYTHON_FUNCTION_OVERLOADS( dprint_, dprint, 1, 2 ); BOOST_PYTHON_FUNCTION_OVERLOADS( dprintln_, dprintln, 1, 2 ); @@ -90,8 +91,8 @@ BOOST_PYTHON_MODULE( pykd ) "Start process for debugging"); python::def( "attachProcess", &attachProcess, "Attach debugger to a exsisting process" ); - python::def( "detachProcess", &detachProcess, - "Stop process debugging"); + python::def( "detachProcess", &detachProcess, detachProcess_( boost::python::args( "pid" ), + "Stop process debugging") ); python::def( "killProcess", &terminateProcess, "Stop debugging and terminate current process" ); python::def( "loadDump", &loadDump, diff --git a/pykd/win/dbgeng.cpp b/pykd/win/dbgeng.cpp index 814a18a..eaacc27 100644 --- a/pykd/win/dbgeng.cpp +++ b/pykd/win/dbgeng.cpp @@ -726,16 +726,25 @@ ULONG64 getRegInstructionPointer() /////////////////////////////////////////////////////////////////////////////// -void getStackTrace(std::vector &frames) +static void buildStacksFrames( + std::vector &frames, + ULONG64 frameOffset = 0, + ULONG64 stackOffset = 0, + ULONG64 instructionOffset = 0) { - PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate ); - - HRESULT hres; ULONG filledFrames = 1024; std::vector dbgFrames(filledFrames); - hres = g_dbgEng->control->GetStackTrace( 0, 0, 0, &dbgFrames[0], filledFrames, &filledFrames); - if ( FAILED( hres ) ) - throw DbgException( "IDebugControl::GetStackTrace failed" ); + + HRESULT hres = + g_dbgEng->control->GetStackTrace( + frameOffset, + stackOffset, + instructionOffset, + &dbgFrames[0], + filledFrames, + &filledFrames); + if (S_OK != hres) + throw DbgException( "IDebugControl::GetStackTrace", hres ); frames.resize(filledFrames); for ( ULONG i = 0; i < filledFrames; ++i ) @@ -750,11 +759,121 @@ void getStackTrace(std::vector &frames) /////////////////////////////////////////////////////////////////////////////// +void getStackTrace(std::vector &frames) +{ + PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate ); + + frames.resize(0); + + buildStacksFrames(frames); +} + +/////////////////////////////////////////////////////////////////////////////// + +static void ReadWow64Context(WOW64_CONTEXT &Context) +{ + // + // *** undoc *** + // !wow64exts.r + // http://www.woodmann.com/forum/archive/index.php/t-11162.html + // http://www.nynaeve.net/Code/GetThreadWow64Context.cpp + // + + ULONG64 teb64Address; + HRESULT hres = g_dbgEng->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; + + bool readRes; + readRes = + readMemoryUnsafeNoSafe( + teb64Address + teb64ToTlsOffset + (sizeof(ULONG64) * WOW64_TLS_CPURESERVED), + &cpuAreaAddress, + sizeof(cpuAreaAddress), + false, + &readedBytes); + if (!readRes || readedBytes != sizeof(cpuAreaAddress)) + throw DbgException( "IDebugDataSpaces::ReadVirtual", hres); + + // CPU Area is: + // +00 unknown ULONG + // +04 WOW64_CONTEXT struct + static const ULONG cpuAreaToWow64ContextOffset = sizeof(ULONG); + readRes = + readMemoryUnsafeNoSafe( + cpuAreaAddress + cpuAreaToWow64ContextOffset, + &Context, + sizeof(Context), + false, + &readedBytes); + if (!readRes || readedBytes != sizeof(Context)) + throw DbgException( "IDebugDataSpaces::ReadVirtual", hres); +} + +/////////////////////////////////////////////////////////////////////////////// + +class AutoRevertEffectiveProcessorType +{ +public: + AutoRevertEffectiveProcessorType() + : m_processType(IMAGE_FILE_MACHINE_UNKNOWN) + { + } + + ~AutoRevertEffectiveProcessorType() + { + if (IMAGE_FILE_MACHINE_UNKNOWN != m_processType) + BOOST_VERIFY(S_OK == g_dbgEng->control->SetEffectiveProcessorType(m_processType)); + } + + void to(ULONG processType) { m_processType = processType; } +private: + ULONG m_processType; +}; + +/////////////////////////////////////////////////////////////////////////////// + void getStackTraceWow64(std::vector &frames) { PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate ); frames.resize(0); + + ULONG processorType; + HRESULT hres = g_dbgEng->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" ); + + hres = g_dbgEng->control->GetEffectiveProcessorType(&processorType); + if (S_OK != hres) + throw DbgException( "IDebugControl::GetEffectiveProcessorType", hres ); + + AutoRevertEffectiveProcessorType autoRevertEffectiveProcessorType; + if (IMAGE_FILE_MACHINE_I386 != processorType) + { + if (IMAGE_FILE_MACHINE_AMD64 != processorType) + throw DbgException( "Only for WOW64 processor mode" ); + + hres = g_dbgEng->control->SetEffectiveProcessorType(IMAGE_FILE_MACHINE_I386); + if (S_OK != hres) + throw DbgException( "IDebugControl::SetEffectiveProcessorType", hres ); + + autoRevertEffectiveProcessorType.to(IMAGE_FILE_MACHINE_AMD64); + } + + WOW64_CONTEXT Context; + ReadWow64Context(Context); + + buildStacksFrames(frames, Context.Ebp, Context.Esp, Context.Eip); } /////////////////////////////////////////////////////////////////////////////// diff --git a/pykd/win/memory.cpp b/pykd/win/memory.cpp index b123dc4..aa9e4ab 100644 --- a/pykd/win/memory.cpp +++ b/pykd/win/memory.cpp @@ -95,10 +95,8 @@ void readMemory( ULONG64 offset, PVOID buffer, ULONG length, bool phyAddr, ULONG /////////////////////////////////////////////////////////////////////////////////// -bool readMemoryUnsafe( ULONG64 offset, PVOID buffer, ULONG length, bool phyAddr, ULONG *readed ) +bool readMemoryUnsafeNoSafe( ULONG64 offset, PVOID buffer, ULONG length, bool phyAddr, ULONG *readed ) { - PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate ); - HRESULT hres; if ( phyAddr == false ) { @@ -122,6 +120,14 @@ bool readMemoryUnsafe( ULONG64 offset, PVOID buffer, ULONG length, bool phyAddr, /////////////////////////////////////////////////////////////////////////////////// +bool readMemoryUnsafe( ULONG64 offset, PVOID buffer, ULONG length, bool phyAddr, ULONG *readed ) +{ + PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate ); + return readMemoryUnsafeNoSafe(offset, buffer, length, phyAddr, readed); +} + +/////////////////////////////////////////////////////////////////////////////////// + std::string loadCStr( ULONG64 offset ) { PyThread_StateRestore pyThreadRestore( g_dbgEng->pystate );