/*++ Function: GetThreadContext See MSDN doc. --*/ BOOL CONTEXT_GetThreadContext( DWORD dwProcessId, pthread_t self, LPCONTEXT lpContext) { BOOL ret = FALSE; if (lpContext == NULL) { ERROR("Invalid lpContext parameter value\n"); SetLastError(ERROR_NOACCESS); goto EXIT; } /* How to consider the case when self is different from the current thread of its owner process. Machine registers values could be retreived by a ptrace(pid, ...) call or from the "/proc/%pid/reg" file content. Unfortunately, these two methods only depend on process ID, not on thread ID. */ if (dwProcessId == GetCurrentProcessId()) { if (self != pthread_self()) { DWORD flags; // There aren't any APIs for this. We can potentially get the // context of another thread by using per-thread signals, but // on FreeBSD signal handlers that are called as a result // of signals raised via pthread_kill don't get a valid // sigcontext or ucontext_t. But we need this to return TRUE // to avoid an assertion in the CLR in code that manages to // cope reasonably well without a valid thread context. // Given that, we'll zero out our structure and return TRUE. ERROR("GetThreadContext on a thread other than the current " "thread is returning TRUE\n"); flags = lpContext->ContextFlags; memset(lpContext, 0, sizeof(*lpContext)); lpContext->ContextFlags = flags; ret = TRUE; goto EXIT; } } if (lpContext->ContextFlags & (CONTEXT_CONTROL | CONTEXT_INTEGER) & CONTEXT_AREA_MASK) { if (CONTEXT_GetRegisters(dwProcessId, lpContext) == FALSE) { SetLastError(ERROR_INTERNAL_ERROR); goto EXIT; } } ret = TRUE; EXIT: return ret; }
/*++ Function: GetThreadContext See MSDN doc. --*/ BOOL CONTEXT_GetThreadContext( HANDLE hThread, LPCONTEXT lpContext) { BOOL ret = FALSE; DWORD processId; #if HAVE_GETCONTEXT ucontext_t registers; #elif HAVE_BSD_REGS_T struct reg registers; #endif // HAVE_BSD_REGS_T if (lpContext == NULL) { ERROR("Invalid lpContext parameter value\n"); SetLastError(ERROR_NOACCESS); goto EXIT; } /* How to consider the case when hThread is different from the current thread of its owner process. Machine registers values could be retreived by a ptrace(pid, ...) call or from the "/proc/%pid/reg" file content. Unfortunately, these two methods only depend on process ID, not on thread ID. */ if (!(processId = THREADGetThreadProcessId(hThread))) { ERROR("Couldn't retrieve the process owner of hThread:%p\n", hThread); SetLastError(ERROR_INTERNAL_ERROR); goto EXIT; } if (processId == GetCurrentProcessId()) { THREAD *thread; thread = (THREAD *) HMGRLockHandle2(hThread, HOBJ_THREAD); if ((thread == NULL) || (thread->dwThreadId != GetCurrentThreadId())) { DWORD flags; // There aren't any APIs for this. We can potentially get the // context of another thread by using per-thread signals, but // on FreeBSD signal handlers that are called as a result // of signals raised via pthread_kill don't get a valid // sigcontext or ucontext_t. But we need this to return TRUE // to avoid an assertion in the CLR in code that manages to // cope reasonably well without a valid thread context. // Given that, we'll zero out our structure and return TRUE. ERROR("GetThreadContext on a thread other than the current " "thread is returning TRUE\n"); flags = lpContext->ContextFlags; memset(lpContext, 0, sizeof(*lpContext)); lpContext->ContextFlags = flags; HMGRUnlockHandle(hThread, &(thread->objHeader)); ret = TRUE; goto EXIT; } HMGRUnlockHandle(hThread, &(thread->objHeader)); } if (lpContext->ContextFlags & (CONTEXT_CONTROL | CONTEXT_INTEGER)) { if (CONTEXT_GetRegisters(processId, ®isters) == FALSE) { SetLastError(ERROR_INTERNAL_ERROR); goto EXIT; } if (lpContext->ContextFlags & CONTEXT_CONTROL) { #if HAVE_GETCONTEXT lpContext->Ebp = registers.uc_mcontext.gregs[REG_EBP]; lpContext->Eip = registers.uc_mcontext.gregs[REG_EIP]; lpContext->SegCs = registers.uc_mcontext.gregs[REG_CS]; lpContext->EFlags = registers.uc_mcontext.gregs[REG_EFL]; lpContext->Esp = registers.uc_mcontext.gregs[REG_ESP]; lpContext->SegSs = registers.uc_mcontext.gregs[REG_SS]; #elif HAVE_BSD_REGS_T lpContext->Ebp = registers.r_ebp; lpContext->Eip = registers.r_eip; lpContext->SegCs = registers.r_cs; lpContext->EFlags = registers.r_eflags; lpContext->Esp = registers.r_esp; lpContext->SegSs = registers.r_ss; #endif // HAVE_BSD_REGS_T } if (lpContext->ContextFlags & CONTEXT_INTEGER) { #if HAVE_GETCONTEXT lpContext->Edi = registers.uc_mcontext.gregs[REG_EDI]; lpContext->Esi = registers.uc_mcontext.gregs[REG_ESI]; lpContext->Ebx = registers.uc_mcontext.gregs[REG_EBX]; lpContext->Edx = registers.uc_mcontext.gregs[REG_EDX]; lpContext->Ecx = registers.uc_mcontext.gregs[REG_ECX]; lpContext->Eax = registers.uc_mcontext.gregs[REG_EAX]; #elif HAVE_BSD_REGS_T lpContext->Edi = registers.r_edi; lpContext->Esi = registers.r_esi; lpContext->Ebx = registers.r_ebx; lpContext->Edx = registers.r_edx; lpContext->Ecx = registers.r_ecx; lpContext->Eax = registers.r_eax; #endif // HAVE_BSD_REGS_T } } ret = TRUE; EXIT: return ret; }