/* * MyGetThreadContext - get the context for a specific thread */ BOOL MyGetThreadContext( thread_info *ti, MYCONTEXT *pc ) { #ifdef WOW BOOL rc; if( ( ti->is_wow || ti->is_dos ) && UseVDMStuff ) { #if defined( MD_x86 ) VDMCONTEXT vc; vc.ContextFlags = VDMCONTEXT_TO_USE; rc = pVDMGetThreadContext( &DebugEvent, &vc ); /* * VDMCONTEXT and CONTEXT are the same on an x86 machine. * If we were ever to try to port this to NT running on a RISC, * they would be different, and this memcpy would be total crap. */ memcpy( pc, &vc, sizeof( MYCONTEXT ) ); /* * Sometimes crap is in the high word of EIP, ESP or EBP. We * check if CS or SS is a 32-bit selector, and if they are not, * we zero out the high word of EIP, ESP or EBP as appropriate */ if( !IsBigSel( pc->SegCs ) ) { pc->Eip = (DWORD)(WORD)pc->Eip; } if( !IsBigSel( pc->SegSs ) ) { pc->Esp = (DWORD)(WORD)pc->Esp; pc->Ebp = (DWORD)(WORD)pc->Ebp; } #elif defined( MD_axp ) | defined( MD_ppc ) rc = 0; #else #error MyGetThreadContext not configured #endif return( rc ); } else { pc->ContextFlags = MYCONTEXT_TO_USE; return( GetThreadContext( ti->thread_handle, pc ) ); } #else #if 1 pc->ContextFlags = MYCONTEXT_TO_USE; #if defined( MD_x64 ) return( Wow64GetThreadContext( ti->thread_handle, pc ) ); #else return( GetThreadContext( ti->thread_handle, pc ) ); #endif #else #if defined( MD_x64 ) if( ti->is_wow ) { pc->ContextFlags = WOW64CONTEXT_TO_USE; return( Wow64GetThreadContext( ti->thread_handle, pc ) ); } #endif pc->ContextFlags = MYCONTEXT_TO_USE; return( GetThreadContext( ti->thread_handle, pc ) ); #endif #endif }
static int adjbkpt(struct ps_prochandle *P, int wow) { CONTEXT ct; #if __amd64__ WOW64_CONTEXT ct32; if (wow) { ZeroMemory(&ct32, sizeof(PWOW64_CONTEXT)); ct32.ContextFlags = CONTEXT_CONTROL; if (Wow64GetThreadContext(P->thandle, &ct32) == 0) { return -1; } ct32.Eip--; if (Wow64SetThreadContext(P->thandle, &ct32) == 0) { return -1; } return 0; } #endif ZeroMemory(&ct, sizeof(CONTEXT)); ct.ContextFlags = CONTEXT_CONTROL; if (GetThreadContext(P->thandle, &ct) == 0) { return -1; } #if __i386__ ct.Eip--; #else ct.Rip--; #endif if (SetThreadContext(P->thandle, &ct) == 0) { return -1; } return 0; }
Pdb::Context Pdb::ReadContext(HANDLE hThread) { DR_LOG("ReadContext"); Context r; #ifdef CPU_64 if(win64) { CONTEXT ctx; ctx.ContextFlags = CONTEXT_FULL; if(!GetThreadContext(hThread, &ctx)) Error("GetThreadContext failed"); memcpy(&r.context64, &ctx, sizeof(CONTEXT)); } else { WOW64_CONTEXT ctx; ctx.ContextFlags = WOW64_CONTEXT_FULL; if(!Wow64GetThreadContext(hThread, &ctx)) Error("Wow64GetThreadContext failed"); memcpy(&r.context32, &ctx, sizeof(WOW64_CONTEXT)); } #else CONTEXT ctx; ctx.ContextFlags = CONTEXT_FULL; if(!GetThreadContext(hThread, &ctx)) Error("GetThreadContext failed"); memcpy(&r.context32, &ctx, sizeof(CONTEXT)); #endif return r; }
HL_API bool hl_debug_write_register( int pid, int thread, int reg, void *value, bool is64 ) { # if defined(HL_WIN) # ifdef HL_64 if( !is64 ) { WOW64_CONTEXT c; c.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS; if( !Wow64GetThreadContext(OpenTID(thread),&c) ) return false; if( reg == 3 ) c.EFlags = (int)(int_val)value; else *GetContextReg32(&c,reg) = (DWORD)(int_val)value; return (bool)Wow64SetThreadContext(OpenTID(thread),&c); } # else if( is64 ) return false; # endif CONTEXT c; c.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS; if( !GetThreadContext(OpenTID(thread),&c) ) return false; if( reg == 3 ) c.EFlags = (int)(int_val)value; else *GetContextReg(&c,reg) = (REGDATA)value; return (bool)SetThreadContext(OpenTID(thread),&c); # elif defined(USE_PTRACE) return ptrace(PTRACE_POKEUSER,thread,get_reg(reg),value) >= 0; # else return false; # endif }
HL_API void *hl_debug_read_register( int pid, int thread, int reg, bool is64 ) { # if defined(HL_WIN) # ifdef HL_64 if( !is64 ) { WOW64_CONTEXT c; c.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS; if( !Wow64GetThreadContext(OpenTID(thread),&c) ) return NULL; if( reg == 3 ) return (void*)(int_val)c.EFlags; return (void*)(int_val)*GetContextReg32(&c,reg); } # else if( is64 ) return NULL; # endif CONTEXT c; c.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS; if( !GetThreadContext(OpenTID(thread),&c) ) return NULL; if( reg == 3 ) return (void*)(int_val)c.EFlags; return (void*)*GetContextReg(&c,reg); # elif defined(USE_PTRACE) return (void*)ptrace(PTRACE_PEEKUSER,thread,get_reg(reg),0); # else return NULL; # endif }
void ReadCallstackX86( HANDLE hProcess, HANDLE hThread, std::list<FrameX86>& stack ) { const int MaxStackDepth = 10000; FrameX86 frame = { 0 }; #if _WIN64 WOW64_CONTEXT context = { 0 }; #else CONTEXT context = { 0 }; #endif #if _WIN64 context.ContextFlags = WOW64_CONTEXT_CONTROL; #else context.ContextFlags = CONTEXT_CONTROL; #endif #if _WIN64 Wow64GetThreadContext( hThread, &context ); #else GetThreadContext( hThread, &context ); #endif DWORD nextAddr = context.Ebp; DWORD retAddr = context.Eip; for ( int i = 0; i < MaxStackDepth; i++ ) { frame.Eip = retAddr; frame.Ebp = nextAddr; stack.push_back( frame ); if ( nextAddr == 0 ) break; BOOL bRet = FALSE; SIZE_T bytesRead = 0; bRet = ReadProcessMemory( hProcess, (void*) (nextAddr+sizeof nextAddr), &retAddr, sizeof retAddr, &bytesRead ); if ( !bRet ) break; bRet = ReadProcessMemory( hProcess, (void*) nextAddr, &nextAddr, sizeof nextAddr, &bytesRead ); if ( !bRet ) break; } }
static BOOL getThreadContext(HANDLE hProcess, HANDLE hThread, PCONTEXT pContext) { ZeroMemory(pContext, sizeof *pContext); BOOL bWow64 = FALSE; if (HAVE_WIN64) { IsWow64Process(hProcess, &bWow64); } BOOL bSuccess; if (bWow64) { PWOW64_CONTEXT pWow64Context = reinterpret_cast<PWOW64_CONTEXT>(pContext); static_assert(sizeof *pContext >= sizeof *pWow64Context, "WOW64_CONTEXT should fit in CONTEXT"); pWow64Context->ContextFlags = WOW64_CONTEXT_ALL; bSuccess = Wow64GetThreadContext(hThread, pWow64Context); } else { pContext->ContextFlags = CONTEXT_ALL; bSuccess = GetThreadContext(hThread, pContext); } return bSuccess; }