1 | // Licensed to the .NET Foundation under one or more agreements. |
2 | // The .NET Foundation licenses this file to you under the MIT license. |
3 | // See the LICENSE file in the project root for more information. |
4 | //***************************************************************************** |
5 | // File: reimpl.cpp |
6 | // |
7 | |
8 | // |
9 | // Data-access-specific reimplementations of standard code. |
10 | // |
11 | //***************************************************************************** |
12 | |
13 | #include "stdafx.h" |
14 | |
15 | // |
16 | // Get the Thread instance for a specific OS thread ID |
17 | // |
18 | // Arguments: |
19 | // osThread - the OS thread ID of interest. |
20 | // |
21 | // Return value: |
22 | // A Thread object marshalled from the target corresponding to the specified OS thread |
23 | // ID, or NULL if there is no such Thread. |
24 | // |
25 | // Notes: |
26 | // We used to accept a thread ID of '0' to mean "use the current thread", which was based on |
27 | // ICLRDataTarget::GetCurrentThreadID. But this is error-prone and not well-defined (many data targets |
28 | // don't implement that API). It's better to require explicit thread IDs to be passed down when they |
29 | // are needed. |
30 | // |
31 | Thread* __stdcall |
32 | DacGetThread(ULONG32 osThread) |
33 | { |
34 | _ASSERTE(osThread > 0); |
35 | |
36 | if (!g_dacImpl) |
37 | { |
38 | DacError(E_UNEXPECTED); |
39 | UNREACHABLE(); |
40 | } |
41 | |
42 | // Note that if we had access to TLS, we could get this at index gThreadTLSIndex for the specified |
43 | // thread. However, this is the only place we might want to use TLS, and it's not performance critical, |
44 | // so we haven't added TLS support to ICorDebugDataTarget (the legacy ICLRDataTarget interface has it though) |
45 | |
46 | // Scan the whole thread store to see if there's a matching thread. |
47 | |
48 | if (!ThreadStore::s_pThreadStore) |
49 | { |
50 | return NULL; |
51 | } |
52 | |
53 | Thread* thread = ThreadStore::s_pThreadStore->m_ThreadList.GetHead(); |
54 | while (thread) |
55 | { |
56 | if (thread->GetOSThreadId() == osThread) |
57 | { |
58 | return thread; |
59 | } |
60 | |
61 | thread = ThreadStore::s_pThreadStore->m_ThreadList.GetNext(thread); |
62 | } |
63 | |
64 | return NULL; |
65 | } |
66 | |
67 | EXTERN_C Thread* GetThread() |
68 | { |
69 | // In dac mode it's unlikely that the thread calling dac |
70 | // is actually the same "current thread" that the runtime cares |
71 | // about. Fail all queries of the current thread by |
72 | // the runtime code to catch any inadvertent usage. |
73 | // Enumerating the ThreadStore is the proper way to get access |
74 | // to specific Thread objects. |
75 | DacError(E_UNEXPECTED); |
76 | return NULL; |
77 | } |
78 | |
79 | BOOL |
80 | DacGetThreadContext(Thread* thread, T_CONTEXT* context) |
81 | { |
82 | SUPPORTS_DAC; |
83 | |
84 | if (!g_dacImpl) |
85 | { |
86 | DacError(E_UNEXPECTED); |
87 | UNREACHABLE(); |
88 | } |
89 | |
90 | // XXX Microsoft - How do you retrieve the context for |
91 | // a Thread that's not running? |
92 | if (!thread->GetOSThreadId() || |
93 | thread->GetOSThreadId() == 0xbaadf00d) |
94 | { |
95 | DacError(E_UNEXPECTED); |
96 | UNREACHABLE(); |
97 | } |
98 | |
99 | ULONG32 contextFlags; |
100 | |
101 | contextFlags = CONTEXT_ALL; |
102 | |
103 | HRESULT status = |
104 | g_dacImpl->m_pTarget-> |
105 | GetThreadContext(thread->GetOSThreadId(), contextFlags, |
106 | sizeof(*context), (PBYTE)context); |
107 | if (status != S_OK) |
108 | { |
109 | DacError(status); |
110 | UNREACHABLE(); |
111 | } |
112 | |
113 | return TRUE; |
114 | } |
115 | |
116 | |