示例#1
0
/*++
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;
}
示例#2
0
文件: context.c 项目: ArildF/masters
/*++
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, &registers) == 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;
}