// Implement public interface HRESULT CordbAppDomain::GetModuleFromMetaDataInterface( IUnknown *pIMetaData, ICorDebugModule **ppModule) { PUBLIC_API_ENTRY(this); FAIL_IF_NEUTERED(this); VALIDATE_POINTER_TO_OBJECT(pIMetaData, IUnknown *); VALIDATE_POINTER_TO_OBJECT(ppModule, ICorDebugModule **); HRESULT hr = S_OK; ATT_REQUIRE_STOPPED_MAY_FAIL(GetProcess()); *ppModule = NULL; EX_TRY { CordbModule * pModule = GetModuleFromMetaDataInterface(pIMetaData); _ASSERTE(pModule != NULL); // thrown on error *ppModule = static_cast<ICorDebugModule*> (pModule); pModule->ExternalAddRef(); } EX_CATCH_HRESULT(hr); return hr; }
HRESULT CordbAppDomain::EnumerateSteppers(ICorDebugStepperEnum **ppSteppers) { PUBLIC_API_ENTRY(this); FAIL_IF_NEUTERED(this); ATT_REQUIRE_STOPPED_MAY_FAIL(GetProcess()); VALIDATE_POINTER_TO_OBJECT(ppSteppers,ICorDebugStepperEnum **); HRESULT hr = S_OK; EX_TRY { // // !!! m_steppers may be modified while user is enumerating, // if steppers complete (if process is running) // RSInitHolder<CordbHashTableEnum> pEnum; CordbHashTableEnum::BuildOrThrow( GetProcess(), GetProcess()->GetContinueNeuterList(), // ownership &(m_pProcess->m_steppers), IID_ICorDebugStepperEnum, pEnum.GetAddr()); pEnum.TransferOwnershipExternal(ppSteppers); } EX_CATCH_HRESULT(hr); return hr; }
HRESULT CordbRegisterSet::GetRegisters(ULONG64 mask, ULONG32 regCount, CORDB_REGISTER regBuffer[]) { PUBLIC_REENTRANT_API_ENTRY(this); FAIL_IF_NEUTERED(this); ATT_REQUIRE_STOPPED_MAY_FAIL(GetProcess()); UINT iRegister = 0; VALIDATE_POINTER_TO_OBJECT_ARRAY(regBuffer, CORDB_REGISTER, regCount, true, true); // @ARMTODO: floating point support for (int i = REGISTER_INSTRUCTION_POINTER; i <= REGISTER_ARM_LR && iRegister < regCount; i++) { if (mask & SETBITULONG64(i)) { switch (i) { case REGISTER_INSTRUCTION_POINTER: regBuffer[iRegister++] = m_rd->PC; break; case REGISTER_STACK_POINTER: regBuffer[iRegister++] = m_rd->SP; break; case REGISTER_ARM_R0: regBuffer[iRegister++] = m_rd->R0; break; case REGISTER_ARM_R1: regBuffer[iRegister++] = m_rd->R1; break; case REGISTER_ARM_R2: regBuffer[iRegister++] = m_rd->R2; break; case REGISTER_ARM_R3: regBuffer[iRegister++] = m_rd->R3; break; case REGISTER_ARM_R4: regBuffer[iRegister++] = m_rd->R4; break; case REGISTER_ARM_R5: regBuffer[iRegister++] = m_rd->R5; break; case REGISTER_ARM_R6: regBuffer[iRegister++] = m_rd->R6; break; case REGISTER_ARM_R7: regBuffer[iRegister++] = m_rd->R7; break; case REGISTER_ARM_R8: regBuffer[iRegister++] = m_rd->R8; break; case REGISTER_ARM_R9: regBuffer[iRegister++] = m_rd->R9; break; case REGISTER_ARM_R10: regBuffer[iRegister++] = m_rd->R10; break; case REGISTER_ARM_R11: regBuffer[iRegister++] = m_rd->R11; break; case REGISTER_ARM_R12: regBuffer[iRegister++] = m_rd->R12; break; case REGISTER_ARM_LR: regBuffer[iRegister++] = m_rd->LR; break; } } } _ASSERTE (iRegister <= regCount); return S_OK; }
HRESULT CordbAppDomain::Attach() { PUBLIC_API_ENTRY(this); FAIL_IF_NEUTERED(this); ATT_REQUIRE_STOPPED_MAY_FAIL(m_pProcess); return S_OK; }
//----------------------------------------------------------------------------- // Get the full associated XML for the MDA. This may be empty. // This could be a potentially expensive operation if the xml stream is large. // See the MDA documentation for the schema for this XML stream. // See CopyOutString for parameter details. //----------------------------------------------------------------------------- HRESULT CordbMDA::GetXML(ULONG32 cchName, ULONG32 * pcchName, WCHAR szName[]) { PUBLIC_API_ENTRY(this); FAIL_IF_NEUTERED(this); ATT_REQUIRE_STOPPED_MAY_FAIL(GetProcess()); return CopyOutString(m_szXml, cchName, pcchName, szName); }
HRESULT CordbAppDomain::SetAllThreadsDebugState(CorDebugThreadState state, ICorDebugThread *pExceptThisThread) { PUBLIC_API_ENTRY(this); FAIL_IF_NEUTERED(this); ATT_REQUIRE_STOPPED_MAY_FAIL(GetProcess()); return m_pProcess->SetAllThreadsDebugState(state, pExceptThisThread); }
//----------------------------------------------------------------------------- // Thread that the MDA is fired on. We use the os tid instead of an ICDThread in case an MDA is fired on a // native thread (or a managed thread that hasn't yet entered managed code and so we don't have a ICDThread // object for it yet) //----------------------------------------------------------------------------- HRESULT CordbMDA::GetOSThreadId(DWORD * pOsTid) { PUBLIC_API_ENTRY(this); FAIL_IF_NEUTERED(this); ATT_REQUIRE_STOPPED_MAY_FAIL(GetProcess()); if (pOsTid == NULL) { return E_INVALIDARG; } *pOsTid = this->m_dwOSTID; return S_OK; }
//----------------------------------------------------------------------------- // Get flags for this MDA object. //----------------------------------------------------------------------------- HRESULT CordbMDA::GetFlags(CorDebugMDAFlags * pFlags) { PUBLIC_API_ENTRY(this); FAIL_IF_NEUTERED(this); ATT_REQUIRE_STOPPED_MAY_FAIL(GetProcess()); if (pFlags == NULL) { return E_INVALIDARG; } *pFlags = this->m_flags; return S_OK; }
HRESULT CordbRegisterSet::GetRegisters(ULONG64 mask, ULONG32 regCount, CORDB_REGISTER regBuffer[]) { PUBLIC_REENTRANT_API_ENTRY(this); FAIL_IF_NEUTERED(this); ATT_REQUIRE_STOPPED_MAY_FAIL(GetProcess()); UINT iRegister = 0; VALIDATE_POINTER_TO_OBJECT_ARRAY(regBuffer, CORDB_REGISTER, regCount, true, true); // @ARM64TODO: floating point support for (int i = REGISTER_ARM64_X0; i <= REGISTER_ARM64_PC && iRegister < regCount; i++) { if (mask & SETBITULONG64(i)) { if ((i >= REGISTER_ARM64_X0) && (i <= REGISTER_ARM64_X28)) { regBuffer[iRegister++] = m_rd->X[i - REGISTER_ARM64_X0]; continue; } switch (i) { case REGISTER_ARM64_PC: regBuffer[iRegister++] = m_rd->PC; break; case REGISTER_ARM64_SP: regBuffer[iRegister++] = m_rd->SP; break; case REGISTER_ARM64_FP: regBuffer[iRegister++] = m_rd->FP; break; case REGISTER_ARM64_LR: regBuffer[iRegister++] = m_rd->LR; break; default: _ASSERTE(false); break; } } } _ASSERTE (iRegister <= regCount); return S_OK; }
HRESULT CordbAppDomain::EnumerateBreakpoints(ICorDebugBreakpointEnum **ppBreakpoints) { PUBLIC_API_ENTRY(this); FAIL_IF_NEUTERED(this); ATT_REQUIRE_STOPPED_MAY_FAIL(GetProcess()); VALIDATE_POINTER_TO_OBJECT(ppBreakpoints, ICorDebugBreakpointEnum **); HRESULT hr = S_OK; EX_TRY { RSInitHolder<CordbHashTableEnum> pEnum; CordbHashTableEnum::BuildOrThrow( this, GetProcess()->GetContinueNeuterList(), // ownership &m_breakpoints, IID_ICorDebugBreakpointEnum, pEnum.GetAddr()); pEnum.TransferOwnershipExternal(ppBreakpoints); } EX_CATCH_HRESULT(hr); return hr; }
//----------------------------------------------------------------------------- // Get a ICorDebugValue for a static field on this class. // // Parameters: // fieldDef - metadata token for field on this class. Can not be from an // inherited class. // pFrame - frame used to resolve Thread-static, AppDomain-static, etc. // ppValue - OUT: gets value of the field. // // Returns: // S_OK on success. // CORDBG_E_STATIC_VAR_NOT_AVAILABLE //----------------------------------------------------------------------------- HRESULT CordbClass::GetStaticFieldValue(mdFieldDef fieldDef, ICorDebugFrame *pFrame, ICorDebugValue **ppValue) { PUBLIC_REENTRANT_API_ENTRY(this); FAIL_IF_NEUTERED(this); VALIDATE_POINTER_TO_OBJECT(ppValue, ICorDebugValue **); ATT_REQUIRE_STOPPED_MAY_FAIL(GetProcess()); HRESULT hr = S_OK; *ppValue = NULL; BOOL fEnCHangingField = FALSE; IMetaDataImport * pImport = NULL; EX_TRY { pImport = GetModule()->GetMetaDataImporter(); // throws // Validate the token. if (!pImport->IsValidToken(fieldDef) || (TypeFromToken(fieldDef) != mdtFieldDef)) { ThrowHR(E_INVALIDARG); } // Make sure we have enough info about the class. Init(); // Uninstantiated generics (eg, Foo<T>) don't have static data. Must use instantiated (eg Foo<int>) // But all CordbClass instances are uninstantiated. So this should fail for all generic types. // Normally, debuggers should be using ICorDebugType instead. // Though in the forward compat case, they'll hit this. if (HasTypeParams()) { ThrowHR(CORDBG_E_STATIC_VAR_NOT_AVAILABLE); } // Lookup the field given its metadata token. FieldData *pFieldData; hr = GetFieldInfo(fieldDef, &pFieldData); // This field was added by EnC, need to use EnC specific code path if (hr == CORDBG_E_ENC_HANGING_FIELD) { // Static fields added with EnC hang off the EnCFieldDesc hr = GetEnCHangingField(fieldDef, &pFieldData, NULL); if (SUCCEEDED(hr)) { fEnCHangingField = TRUE; } // Note: the FieldOffset in pFieldData has been cooked to produce // the correct address of the field in the syncBlock. // @todo: extend Debugger_IPCEFieldData so we don't have to cook the offset here } IfFailThrow(hr); { Instantiation emptyInst; hr = CordbClass::GetStaticFieldValue2(GetModule(), pFieldData, fEnCHangingField, &emptyInst, pFrame, ppValue); // Let hr fall through } } EX_CATCH_HRESULT(hr); // Translate Failure HRs. if (pImport != NULL) { hr = CordbClass::PostProcessUnavailableHRESULT(hr, pImport, fieldDef); } return hr; }