//--------------------------------------------------------------------------------------- // // Ensure the AppDomain friendly name has been set. // // Return value: // S_OK on success, or a failure code if we couldn't read the name for some reason. // There shouldn't be any reason in practice for this to fail other than a corrupt // process image. // // Assumptions: // The AppDomain object has already been initialized to know about // it's corresponding VM appdomain. // InvalidateName is called whenever the name may have changed to prompt us to re-fetch. // //--------------------------------------------------------------------------------------- HRESULT CordbAppDomain::RefreshName() { if (m_strAppDomainName.IsSet()) { // If we already have a valid name, we're done. return S_OK; } // Use DAC to get the name. _ASSERTE(!m_vmAppDomain.IsNull()); IDacDbiInterface * pDac = NULL; HRESULT hr = S_OK; EX_TRY { pDac = m_pProcess->GetDAC(); #ifdef _DEBUG // For debug, double-check the cached value against getting the AD via an AppDomainId. VMPTR_AppDomain pAppDomain = pDac->GetAppDomainFromId(m_AppDomainId); _ASSERTE(m_vmAppDomain == pAppDomain); #endif // Get the actual string contents. pDac->GetAppDomainFullName(m_vmAppDomain, &m_strAppDomainName); // Now that m_strAppDomainName is set, don't fail without clearing it. } EX_CATCH_HRESULT(hr); _ASSERTE(SUCCEEDED(hr) == m_strAppDomainName.IsSet()); return hr; }
/* static */ HRESULT CordbClass::GetStaticFieldValue2(CordbModule * pModule, FieldData * pFieldData, BOOL fEnCHangingField, const Instantiation * pInst, ICorDebugFrame * pFrame, ICorDebugValue ** ppValue) { FAIL_IF_NEUTERED(pModule); INTERNAL_SYNC_API_ENTRY(pModule->GetProcess()); _ASSERTE((pModule->GetProcess()->GetShim() == NULL) || pModule->GetProcess()->GetSynchronized()); HRESULT hr = S_OK; if (!pFieldData->m_fFldIsStatic) { return CORDBG_E_FIELD_NOT_STATIC; } CORDB_ADDRESS pRmtStaticValue = NULL; CordbProcess * pProcess = pModule->GetProcess(); if (pFieldData->m_fFldIsCollectibleStatic) { EX_TRY { pRmtStaticValue = pProcess->GetDAC()->GetCollectibleTypeStaticAddress(pFieldData->m_vmFieldDesc, pModule->GetAppDomain()->GetADToken()); } EX_CATCH_HRESULT(hr); if(FAILED(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; }
// 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; }
template <class Type> List<Type>::~List() { HRESULT hr = S_OK; EX_TRY { RemoveAll(); } EX_CATCH_HRESULT(hr); }
STDAPI InternalDllGetClassObject( REFCLSID rclsid, REFIID riid, LPVOID FAR *ppv) { // @todo: this is called before the runtime is really started, so the contract's don't work. STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_SO_TOLERANT; HRESULT hr = CLASS_E_CLASSNOTAVAILABLE; BEGIN_SO_INTOLERANT_CODE_NO_THROW_CHECK_THREAD(return COR_E_STACKOVERFLOW); if (rclsid == CLSID_CorMetaDataDispenser || rclsid == CLSID_CorMetaDataDispenserRuntime || rclsid == CLSID_CorRuntimeHost || rclsid == CLSID_CLRRuntimeHost || rclsid == CLSID_TypeNameFactory #ifdef FEATURE_HOSTED_BINDER || rclsid == __uuidof(CLRPrivRuntime) #endif ) { hr = MetaDataDllGetClassObject(rclsid, riid, ppv); } #ifdef FEATURE_PROFAPI_ATTACH_DETACH else if (rclsid == CLSID_CLRProfiling) { hr = ICLRProfilingGetClassObject(rclsid, riid, ppv); } #endif // FEATURE_PROFAPI_ATTACH_DETACH #ifdef FEATURE_COMINTEROP else if (rclsid == CLSID_ComCallUnmarshal || rclsid == CLSID_ComCallUnmarshalV4) { // We still respond to the 1.0/1.1/2.0 CLSID so we don't break anyone who is instantiating // this (we could be called for CLSID_ComCallUnmarshal if the process is rollForward=true) hr = g_COMCallUnmarshal.QueryInterface(riid, ppv); } else if (rclsid == CLSID_CorSymBinder_SxS) { EX_TRY { // PDB format - use diasymreader.dll with COM activation InlineSString<_MAX_PATH> ssBuf; if (SUCCEEDED(GetHModuleDirectory(GetModuleInst(), ssBuf))) { hr = FakeCoCallDllGetClassObject(rclsid, ssBuf, riid, ppv, NULL ); } } EX_CATCH_HRESULT(hr); }
// Block and wait for the next debug event from the debuggee process. BOOL DbgTransportPipeline::WaitForDebugEvent(DEBUG_EVENT * pEvent, DWORD dwTimeout, CordbProcess * pProcess) { if (!IsTransportRunning()) { return FALSE; } // We need to wait for a debug event from the transport and the process termination event. // On Windows, process termination is communicated via a debug event as well, but that's not true for // the Mac debugging transport. DWORD cWaitSet = 2; HANDLE rghWaitSet[2]; rghWaitSet[0] = m_pTransport->GetDebugEventReadyEvent(); rghWaitSet[1] = m_hProcess; DWORD dwRet = ::WaitForMultipleObjectsEx(cWaitSet, rghWaitSet, FALSE, dwTimeout, FALSE); if (dwRet == WAIT_OBJECT_0) { // The Mac debugging transport actually transmits IPC events and not debug events. // We need to convert the IPC event to a debug event and pass it back to the caller. m_pTransport->GetNextEvent(m_pIPCEvent, CorDBIPC_BUFFER_SIZE); pEvent->dwProcessId = m_pIPCEvent->processId; _ASSERTE(m_dwProcessId == m_pIPCEvent->processId); // We are supposed to return a thread ID in the DEBUG_EVENT back to our caller. // However, we don't actually store the thread ID in the DebuggerIPCEvent anymore. Instead, // we just get a VMPTR_Thread, and so we need to find the thread ID associated with the VMPTR_Thread. pEvent->dwThreadId = 0; HRESULT hr = S_OK; EX_TRY { if (!m_pIPCEvent->vmThread.IsNull()) { pEvent->dwThreadId = pProcess->GetDAC()->TryGetVolatileOSThreadID(m_pIPCEvent->vmThread); } } EX_CATCH_HRESULT(hr); if (FAILED(hr)) { return FALSE; } // The Windows implementation stores the target address of the IPC event in the debug event. // We can do that for Mac debugging, but that would require the caller to do another cross-machine // ReadProcessMemory(). Since we have all the data in-proc already, we just store a local address. // // @dbgtodo Mac - We are using -1 as a dummy base address right now. // Currently Mac remote debugging doesn't really support multi-instance. InitEventForDebuggerNotification(pEvent, PTR_TO_CORDB_ADDRESS(reinterpret_cast<LPVOID>(-1)), m_pIPCEvent); return TRUE; }
DWORD GetFileVersionInfoSizeW_NoThrow( LPCWSTR lptstrFilename, /* Filename of version stamped file */ LPDWORD lpdwHandle ) { WRAPPER_NO_CONTRACT; HRESULT hr=S_OK; DWORD dwRet=0; EX_TRY { dwRet=GetFileVersionInfoSize( (LPWSTR)lptstrFilename, lpdwHandle ); } EX_CATCH_HRESULT(hr); if (hr!=S_OK) SetLastError(hr); return dwRet; }
BOOL VerQueryValueW_NoThrow( const LPVOID pBlock, LPCWSTR lpSubBlock, LPVOID * lplpBuffer, PUINT puLen ) { WRAPPER_NO_CONTRACT; HRESULT hr=S_OK; BOOL bRet=FALSE; EX_TRY { bRet=VerQueryValueW( pBlock, (LPWSTR)lpSubBlock,lplpBuffer,puLen ); } EX_CATCH_HRESULT(hr); if (hr!=S_OK) SetLastError(hr); return bRet; }
BOOL GetFileVersionInfoW_NoThrow( LPCWSTR lptstrFilename, /* Filename of version stamped file */ DWORD dwHandle, /* Information from GetFileVersionSize */ DWORD dwLen, /* Length of buffer for info */ LPVOID lpData ) { WRAPPER_NO_CONTRACT; HRESULT hr=S_OK; BOOL bRet=FALSE; EX_TRY { bRet=GetFileVersionInfo( (LPWSTR)lptstrFilename, dwHandle,dwLen,lpData ); } EX_CATCH_HRESULT(hr); if (hr!=S_OK) SetLastError(hr); return bRet; }
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; }
LPSTR FillSymbolSearchPath(CQuickBytes &qb) { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_GC_NOTRIGGER; STATIC_CONTRACT_CANNOT_TAKE_LOCK; SCAN_IGNORE_FAULT; // Faults from Wsz funcs are handled. LPSTR retval; HRESULT hr = S_OK; EX_TRY { retval = FillSymbolSearchPathThrows(qb); } EX_CATCH_HRESULT(hr); if (hr != S_OK) { SetLastError(hr); retval = NULL; } return retval; }
//----------------------------------------------------------------------------- // 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; }