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: RSRegSetCommon.cpp
8 // Common cross-platform behavior of reg sets.
9 // Platform specific stuff is in CordbRegisterSet.cpp located in
10 // the platform sub-dir.
12 //*****************************************************************************
14 #include "primitives.h"
16 /* ------------------------------------------------------------------------- *
17 * Common (cross-platform) Register-Set stuff
18 * ------------------------------------------------------------------------- */
21 CordbRegisterSet::CordbRegisterSet(
22 DebuggerREGDISPLAY * pRegDisplay,
23 CordbThread * pThread,
26 bool fTakeOwnershipOfDRD /*= false*/)
27 : CordbBase(pThread->GetProcess(), 0, enumCordbRegisterSet)
29 _ASSERTE( pRegDisplay != NULL );
30 _ASSERTE( pThread != NULL );
34 m_quickUnwind = fQuickUnwind;
36 m_fTakeOwnershipOfDRD = fTakeOwnershipOfDRD;
38 // Add to our parent thread's neuter list.
43 pThread->GetRefreshStackNeuterList()->Add(GetProcess(), this);
46 SetUnrecoverableIfFailed(GetProcess(), hr);
49 void CordbRegisterSet::Neuter()
52 if (m_fTakeOwnershipOfDRD)
61 CordbRegisterSet::~CordbRegisterSet()
63 _ASSERTE(this->IsNeutered());
67 HRESULT CordbRegisterSet::QueryInterface(REFIID riid, void **ppInterface)
70 // This is an exception to the rule that a QI for a higher version API should fail if
71 // the debugger does not support that version of the API. The reasoning is that
72 // while higher versions of other APIs support enhanced functionality and are not
73 // required, this particular API is required on IA64. An example scenario is when an
74 // Everett debuggger is ported to Whidbey and the user wants to use the debugger on IA64.
75 // The user should not be required to implement the ICorDebugManagedCallback2 API, as would
76 // be the case if we make the versioning check like other higher version APIs.
78 if (riid == IID_ICorDebugRegisterSet)
80 *ppInterface = static_cast<ICorDebugRegisterSet*>(this);
82 else if (riid == IID_ICorDebugRegisterSet2)
84 *ppInterface = static_cast<ICorDebugRegisterSet2*>(this);
86 else if (riid == IID_IUnknown)
88 *ppInterface = static_cast<IUnknown*>(static_cast<ICorDebugRegisterSet*>(this));
100 //-----------------------------------------------------------------------------
101 // This is just a convenience function to convert a regdisplay into a Context.
102 // Since a context has more info than a regdisplay, the conversion isn't perfect
103 // and the context can't be fully accurate.
106 // contextSize - sizeof incoming context buffer in bytes
107 // context - buffer to copy this regdisplay's OS CONTEXT structure into.
109 // Returns S_OK on success.
110 //-----------------------------------------------------------------------------
111 HRESULT CordbRegisterSet::GetThreadContext(ULONG32 contextSize, BYTE context[])
113 PUBLIC_REENTRANT_API_ENTRY(this);
114 FAIL_IF_NEUTERED(this);
115 ATT_REQUIRE_STOPPED_MAY_FAIL(GetProcess());
120 _ASSERTE( m_thread != NULL );
121 if( contextSize < sizeof( DT_CONTEXT ))
123 ThrowHR(E_INVALIDARG);
126 ValidateOrThrow(context);
128 DT_CONTEXT *pInputContext = reinterpret_cast<DT_CONTEXT *> (context);
130 // Just to be safe, zero out the buffer we got in while preserving the ContextFlags.
131 // On X64 the ContextFlags field is not the first 4 bytes of the DT_CONTEXT.
132 DWORD dwContextFlags = pInputContext->ContextFlags;
133 ZeroMemory(context, contextSize);
134 pInputContext->ContextFlags = dwContextFlags;
136 // Augment the leafmost (active) register w/ information from the current context.
137 DT_CONTEXT * pLeafContext = NULL;
142 // This may fail, but it is not a disastrous failure in this case. All we care is whether
143 // pLeafContext is updated to a non-NULL value.
144 m_thread->GetManagedContext( &pLeafContext);
149 EX_END_CATCH(SwallowAllExceptions)
151 if (pLeafContext != NULL)
153 // @todo - shouldn't this be a context-flags sensitive copy?
154 memmove( pInputContext, pLeafContext, sizeof( DT_CONTEXT) );
159 // Now update the registers based on the current frame.
160 // This is a very platform specific action.
161 InternalCopyRDToContext(pInputContext);
163 EX_CATCH_HRESULT(hr);
167 //-----------------------------------------------------------------------------
168 // Helpers to impl IRegSet2 on top of original IRegSet.
169 // These are useful on platforms that don't need IRegSet2 (like x86 + amd64).
170 // See CorDebug.idl for details.
173 // regCount - size of pAvailable buffer in bytes
174 // pAvailable - buffer to hold bitvector of available registers.
175 // On success, bit at position CorDebugRegister is 1 iff that
176 // register is available.
177 // Returns S_OK on success.
178 //-----------------------------------------------------------------------------
179 HRESULT CordbRegisterSet::GetRegistersAvailableAdapter(
183 // Defer to call on v1.0 interface
186 if (regCount < sizeof(ULONG64))
191 _ASSERTE(pAvailable != NULL);
194 hr = this->GetRegistersAvailable(&availRegs);
200 // Nor marshal our 64-bit value into the outgoing byte array.
201 for(int iBit = 0; iBit < (int) sizeof(availRegs) * 8; iBit++)
203 ULONG64 test = SETBITULONG64(iBit);
204 if (availRegs & test)
206 SET_BIT_MASK(pAvailable, iBit);
210 RESET_BIT_MASK(pAvailable, iBit);
216 //-----------------------------------------------------------------------------
217 // Helpers to impl IRegSet2 on top of original IRegSet.
218 // These are useful on platforms that don't need IRegSet2 (like x86 + amd64).
219 // See CorDebug.idl for details.
222 // maskCount - size of mask buffer in bytes.
223 // mask - input buffer specifying registers to request
224 // regCount - size of regBuffer in bytes
225 // regBuffer - output buffer, regBuffer[n] = value of register at n-th active
227 // Returns S_OK on success.
228 //-----------------------------------------------------------------------------
230 // mask input requrest registers, which get written to regCount buffer.
231 HRESULT CordbRegisterSet::GetRegistersAdapter(
232 ULONG32 maskCount, BYTE mask[],
233 ULONG32 regCount, CORDB_REGISTER regBuffer[])
235 // Convert input mask to orig mask.
236 ULONG64 maskOrig = 0;
238 for(UINT iBit = 0; iBit < maskCount * 8; iBit++)
240 if (IS_SET_BIT_MASK(mask, iBit))
242 maskOrig |= SETBITULONG64(iBit);
246 return this->GetRegisters(maskOrig,
247 regCount, regBuffer);