summaryrefslogtreecommitdiff
path: root/src/debug/daccess/reimpl.cpp
blob: d1198eea7b891e5d2179eff51d7bd3b6deadba70 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
//*****************************************************************************
// File: reimpl.cpp
// 

//
// Data-access-specific reimplementations of standard code.
//
//*****************************************************************************

#include "stdafx.h"

//
// Get the Thread instance for a specific OS thread ID
// 
// Arguments:
//     osThread - the OS thread ID of interest.  
//     
// Return value:
//     A Thread object marshalled from the target corresponding to the specified OS thread
//     ID, or NULL if there is no such Thread.
//     
// Notes:
//     We used to accept a thread ID of '0' to mean "use the current thread", which was based on
//     ICLRDataTarget::GetCurrentThreadID.  But this is error-prone and not well-defined (many data targets
//     don't implement that API).  It's better to require explicit thread IDs to be passed down when they
//     are needed.
//     
Thread* __stdcall
DacGetThread(ULONG32 osThread)
{
    _ASSERTE(osThread > 0);

    if (!g_dacImpl)
    {
        DacError(E_UNEXPECTED);
        UNREACHABLE();
    }

    // Note that if we had access to TLS, we could get this at index gThreadTLSIndex for the specified
    // thread.  However, this is the only place we might want to use TLS, and it's not performance critical,
    // so we haven't added TLS support to ICorDebugDataTarget (the legacy ICLRDataTarget interface has it though)

    // Scan the whole thread store to see if there's a matching thread.

    if (!ThreadStore::s_pThreadStore)
    {
        return NULL;
    }

    Thread* thread = ThreadStore::s_pThreadStore->m_ThreadList.GetHead();
    while (thread)
    {
        if (thread->GetOSThreadId() == osThread)
        {
            return thread;
        }

        thread = ThreadStore::s_pThreadStore->m_ThreadList.GetNext(thread);
    }

    return NULL;
}

EXTERN_C Thread* GetThread()
{
    // In dac mode it's unlikely that the thread calling dac
    // is actually the same "current thread" that the runtime cares
    // about.  Fail all queries of the current thread by
    // the runtime code to catch any inadvertent usage.
    // Enumerating the ThreadStore is the proper way to get access 
    // to specific Thread objects.
    DacError(E_UNEXPECTED);
    return NULL;
}

BOOL
DacGetThreadContext(Thread* thread, T_CONTEXT* context)
{
    SUPPORTS_DAC;

    if (!g_dacImpl)
    {
        DacError(E_UNEXPECTED);
        UNREACHABLE();
    }

    // XXX Microsoft - How do you retrieve the context for
    // a Thread that's not running?
    if (!thread->GetOSThreadId() ||
        thread->GetOSThreadId() == 0xbaadf00d)
    {
        DacError(E_UNEXPECTED);
        UNREACHABLE();
    }

    ULONG32 contextFlags;

    contextFlags = CONTEXT_ALL; 

    HRESULT status =
        g_dacImpl->m_pTarget->
        GetThreadContext(thread->GetOSThreadId(), contextFlags, 
                         sizeof(*context), (PBYTE)context);
    if (status != S_OK)
    {
        DacError(status);
        UNREACHABLE();
    }

    return TRUE;
}