diff options
Diffstat (limited to 'src/debug')
31 files changed, 855 insertions, 206 deletions
diff --git a/src/debug/daccess/daccess.cpp b/src/debug/daccess/daccess.cpp index ba3995b1f7..69167ab07e 100644 --- a/src/debug/daccess/daccess.cpp +++ b/src/debug/daccess/daccess.cpp @@ -5888,14 +5888,15 @@ ClrDataAccess::RawGetMethodName( LPCWSTR wszStubManagerName = pStubManager->GetStubManagerName(TO_TADDR(address)); _ASSERTE(wszStubManagerName != NULL); - HRESULT hr = StringCchPrintfW( + int result = _snwprintf_s( symbolBuf, bufLen, + _TRUNCATE, s_wszFormatNameWithStubManager, wszStubManagerName, // Arg 1 = stub name TO_TADDR(address)); // Arg 2 = stub hex address - if (hr == S_OK) + if (result != -1) { // Printf succeeded, so we have an exact char count to return if (symbolLen) @@ -5951,13 +5952,14 @@ NameFromMethodDesc: // XXX Microsoft - Should this case have a more specific name? static WCHAR s_wszFormatNameAddressOnly[] = W("CLRStub@%I64x"); - HRESULT hr = StringCchPrintfW( + int result = _snwprintf_s( symbolBuf, bufLen, + _TRUNCATE, s_wszFormatNameAddressOnly, TO_TADDR(address)); - if (hr == S_OK) + if (result != -1) { // Printf succeeded, so we have an exact char count to return if (symbolLen) @@ -7352,7 +7354,7 @@ Exit: //---------------------------------------------------------------------------- // -// IsExceptionFromManagedCode - report if pExceptionRecord points to a exception belonging to the current runtime +// IsExceptionFromManagedCode - report if pExceptionRecord points to an exception belonging to the current runtime // // Arguments: // pExceptionRecord - the exception record @@ -7974,7 +7976,7 @@ HRESULT DacHandleWalker::Init(ClrDataAccess *dac, UINT types[], UINT typeCount, { SUPPORTS_DAC; - if (gen < 0 || gen > (int)GCHeap::GetMaxGeneration()) + if (gen < 0 || gen > (int)GCHeapUtilities::GetMaxGeneration()) return E_INVALIDARG; mGenerationFilter = gen; @@ -8033,7 +8035,7 @@ bool DacHandleWalker::FetchMoreHandles(HANDLESCANPROC callback) int max_slots = 1; #ifdef FEATURE_SVR_GC - if (GCHeap::IsServerHeap()) + if (GCHeapUtilities::IsServerHeap()) max_slots = GCHeapCount(); #endif // FEATURE_SVR_GC @@ -8089,7 +8091,7 @@ bool DacHandleWalker::FetchMoreHandles(HANDLESCANPROC callback) HndScanHandlesForGC(hTable, callback, (LPARAM)¶m, 0, &handleType, 1, - mGenerationFilter, GCHeap::GetMaxGeneration(), 0); + mGenerationFilter, GCHeapUtilities::GetMaxGeneration(), 0); else HndEnumHandles(hTable, &handleType, 1, callback, (LPARAM)¶m, 0, FALSE); } diff --git a/src/debug/daccess/daccess.targets b/src/debug/daccess/daccess.targets index a7d9e41554..43da554f47 100644 --- a/src/debug/daccess/daccess.targets +++ b/src/debug/daccess/daccess.targets @@ -4,6 +4,12 @@ <!--from the original SOURCES/DIRS file by the KBC tool.--> <!--*****************************************************--> <!--Import the settings--> + <PropertyGroup> + <!-- Work around problems with loading System.Private.CoreLib.dll, --> + <!-- caused by inconsistent setting of UseLegacyCompiler and FeatureSpanOfT --> + <!-- between System.Private.CoreLib.dll and the runtime. --> + <UseLegacyCompiler>true</UseLegacyCompiler> + </PropertyGroup> <Import Project="$(_NTDRIVE)$(_NTROOT)\ndp\clr\clr.props" /> <Import Project="$(_NTDRIVE)$(_NTROOT)\ndp\clr\dac.props" /> <Import Project="..\SetDebugTargetLocal.props" /> diff --git a/src/debug/daccess/dacdbiimpl.cpp b/src/debug/daccess/dacdbiimpl.cpp index 9b17f4cd46..ae266e8a6f 100644 --- a/src/debug/daccess/dacdbiimpl.cpp +++ b/src/debug/daccess/dacdbiimpl.cpp @@ -90,7 +90,7 @@ IDacDbiInterface::IAllocator * g_pAllocator = NULL; // // Need a class to serve as a tag that we can use to overload New/Delete. -#define forDbi (*(forDbiWorker *)NULL) +forDbiWorker forDbi; void * operator new(size_t lenBytes, const forDbiWorker &) { @@ -2364,10 +2364,12 @@ TypeHandle DacDbiInterfaceImpl::FindLoadedFnptrType(DWORD numTypeArgs, TypeHandl // Lookup operations run the class loader in non-load mode. ENABLE_FORBID_GC_LOADER_USE_IN_THIS_SCOPE(); - // @dbgtodo : Do we need to worry about calling convention here? - return ClassLoader::LoadFnptrTypeThrowing(0, - numTypeArgs, - pInst, + // @dbgtodo : Do we need to worry about calling convention here? + // LoadFnptrTypeThrowing expects the count of arguments, not + // including return value, so we subtract 1 from numTypeArgs. + return ClassLoader::LoadFnptrTypeThrowing(0, + numTypeArgs - 1, + pInst, ClassLoader::DontLoadTypes); } // DacDbiInterfaceImpl::FindLoadedFnptrType @@ -6517,7 +6519,7 @@ HRESULT DacHeapWalker::Init(CORDB_ADDRESS start, CORDB_ADDRESS end) if (thread == NULL) continue; - alloc_context *ctx = thread->GetAllocContext(); + gc_alloc_context *ctx = thread->GetAllocContext(); if (ctx == NULL) continue; @@ -6533,7 +6535,7 @@ HRESULT DacHeapWalker::Init(CORDB_ADDRESS start, CORDB_ADDRESS end) } #ifdef FEATURE_SVR_GC - HRESULT hr = GCHeap::IsServerHeap() ? InitHeapDataSvr(mHeaps, mHeapCount) : InitHeapDataWks(mHeaps, mHeapCount); + HRESULT hr = GCHeapUtilities::IsServerHeap() ? InitHeapDataSvr(mHeaps, mHeapCount) : InitHeapDataWks(mHeaps, mHeapCount); #else HRESULT hr = InitHeapDataWks(mHeaps, mHeapCount); #endif @@ -6777,7 +6779,7 @@ HRESULT DacDbiInterfaceImpl::GetHeapSegments(OUT DacDbiArrayList<COR_SEGMENT> *p HeapData *heaps = 0; #ifdef FEATURE_SVR_GC - HRESULT hr = GCHeap::IsServerHeap() ? DacHeapWalker::InitHeapDataSvr(heaps, heapCount) : DacHeapWalker::InitHeapDataWks(heaps, heapCount); + HRESULT hr = GCHeapUtilities::IsServerHeap() ? DacHeapWalker::InitHeapDataSvr(heaps, heapCount) : DacHeapWalker::InitHeapDataWks(heaps, heapCount); #else HRESULT hr = DacHeapWalker::InitHeapDataWks(heaps, heapCount); #endif @@ -6987,6 +6989,21 @@ HRESULT DacDbiInterfaceImpl::GetTypeID(CORDB_ADDRESS dbgObj, COR_TYPEID *pID) return hr; } +HRESULT DacDbiInterfaceImpl::GetTypeIDForType(VMPTR_TypeHandle vmTypeHandle, COR_TYPEID *pID) +{ + DD_ENTER_MAY_THROW; + + _ASSERTE(pID != NULL); + _ASSERTE(!vmTypeHandle.IsNull()); + + TypeHandle th = TypeHandle::FromPtr(vmTypeHandle.GetDacPtr()); + PTR_MethodTable pMT = th.GetMethodTable(); + pID->token1 = pMT.GetAddr(); + _ASSERTE(pID->token1 != 0); + pID->token2 = 0; + return S_OK; +} + HRESULT DacDbiInterfaceImpl::GetObjectFields(COR_TYPEID id, ULONG32 celt, COR_FIELD *layout, ULONG32 *pceltFetched) { if (layout == NULL || pceltFetched == NULL) @@ -7171,7 +7188,7 @@ void DacDbiInterfaceImpl::GetGCHeapInformation(COR_HEAPINFO * pHeapInfo) pHeapInfo->areGCStructuresValid = GCScan::GetGcRuntimeStructuresValid(); #ifdef FEATURE_SVR_GC - if (GCHeap::IsServerHeap()) + if (GCHeapUtilities::IsServerHeap()) { pHeapInfo->gcType = CorDebugServerGC; pHeapInfo->numHeaps = DacGetNumHeaps(); diff --git a/src/debug/daccess/dacdbiimpl.h b/src/debug/daccess/dacdbiimpl.h index 56d7b0d1d7..a86072325c 100644 --- a/src/debug/daccess/dacdbiimpl.h +++ b/src/debug/daccess/dacdbiimpl.h @@ -138,11 +138,13 @@ public: HRESULT WalkRefs(RefWalkHandle handle, ULONG count, OUT DacGcReference * objects, OUT ULONG *pFetched); HRESULT GetTypeID(CORDB_ADDRESS obj, COR_TYPEID *pID); + + HRESULT GetTypeIDForType(VMPTR_TypeHandle vmTypeHandle, COR_TYPEID *pID); - HRESULT GetObjectFields(COR_TYPEID id, ULONG32 celt, COR_FIELD *layout, ULONG32 *pceltFetched); - HRESULT GetTypeLayout(COR_TYPEID id, COR_TYPE_LAYOUT *pLayout); - HRESULT GetArrayLayout(COR_TYPEID id, COR_ARRAY_LAYOUT *pLayout); - void GetGCHeapInformation(COR_HEAPINFO * pHeapInfo); + HRESULT GetObjectFields(COR_TYPEID id, ULONG32 celt, COR_FIELD *layout, ULONG32 *pceltFetched); + HRESULT GetTypeLayout(COR_TYPEID id, COR_TYPE_LAYOUT *pLayout); + HRESULT GetArrayLayout(COR_TYPEID id, COR_ARRAY_LAYOUT *pLayout); + void GetGCHeapInformation(COR_HEAPINFO * pHeapInfo); HRESULT GetPEFileMDInternalRW(VMPTR_PEFile vmPEFile, OUT TADDR* pAddrMDInternalRW); HRESULT GetReJitInfo(VMPTR_Module vmModule, mdMethodDef methodTk, OUT VMPTR_ReJitInfo* pReJitInfo); HRESULT GetReJitInfo(VMPTR_MethodDesc vmMethod, CORDB_ADDRESS codeStartAddress, OUT VMPTR_ReJitInfo* pReJitInfo); diff --git a/src/debug/daccess/dacfn.cpp b/src/debug/daccess/dacfn.cpp index 88d45993b3..d8bae7746f 100644 --- a/src/debug/daccess/dacfn.cpp +++ b/src/debug/daccess/dacfn.cpp @@ -217,7 +217,7 @@ DacWriteAll(TADDR addr, PVOID buffer, ULONG32 size, bool throwEx) return S_OK; } -#if defined(WIN64EXCEPTIONS) && defined(FEATURE_PAL) +#ifdef FEATURE_PAL HRESULT DacVirtualUnwind(DWORD threadId, PCONTEXT context, PT_KNONVOLATILE_CONTEXT_POINTERS contextPointers) { @@ -242,7 +242,7 @@ DacVirtualUnwind(DWORD threadId, PCONTEXT context, PT_KNONVOLATILE_CONTEXT_POINT return hr; } -#endif // defined(WIN64EXCEPTIONS) && defined(FEATURE_PAL) +#endif // FEATURE_PAL // DacAllocVirtual - Allocate memory from the target process // Note: this is only available to clients supporting the legacy diff --git a/src/debug/daccess/enummem.cpp b/src/debug/daccess/enummem.cpp index 068c2f2b13..d66af05769 100644 --- a/src/debug/daccess/enummem.cpp +++ b/src/debug/daccess/enummem.cpp @@ -250,9 +250,9 @@ HRESULT ClrDataAccess::EnumMemCLRStatic(IN CLRDataEnumMemoryFlags flags) ReportMem(m_globalBase + g_dacGlobals.SharedDomain__m_pSharedDomain, sizeof(SharedDomain)); - // We need GCHeap pointer to make EEVersion work + // We need IGCHeap pointer to make EEVersion work ReportMem(m_globalBase + g_dacGlobals.dac__g_pGCHeap, - sizeof(GCHeap *)); + sizeof(IGCHeap *)); // see synblk.cpp, the pointer is pointed to a static byte[] SyncBlockCache::s_pSyncBlockCache.EnumMem(); @@ -292,7 +292,9 @@ HRESULT ClrDataAccess::EnumMemCLRStatic(IN CLRDataEnumMemoryFlags flags) CATCH_ALL_EXCEPT_RETHROW_COR_E_OPERATIONCANCELLED( g_pValueTypeClass.EnumMem(); ) CATCH_ALL_EXCEPT_RETHROW_COR_E_OPERATIONCANCELLED( g_pEnumClass.EnumMem(); ) CATCH_ALL_EXCEPT_RETHROW_COR_E_OPERATIONCANCELLED( g_pThreadClass.EnumMem(); ) +#ifdef FEATURE_CER CATCH_ALL_EXCEPT_RETHROW_COR_E_OPERATIONCANCELLED( g_pCriticalFinalizerObjectClass.EnumMem(); ) +#endif CATCH_ALL_EXCEPT_RETHROW_COR_E_OPERATIONCANCELLED( g_pFreeObjectMethodTable.EnumMem(); ) CATCH_ALL_EXCEPT_RETHROW_COR_E_OPERATIONCANCELLED( g_pObjectCtorMD.EnumMem(); ) CATCH_ALL_EXCEPT_RETHROW_COR_E_OPERATIONCANCELLED( g_fHostConfig.EnumMem(); ) @@ -316,7 +318,7 @@ HRESULT ClrDataAccess::EnumMemCLRStatic(IN CLRDataEnumMemoryFlags flags) #ifdef FEATURE_SVR_GC CATCH_ALL_EXCEPT_RETHROW_COR_E_OPERATIONCANCELLED ( - GCHeap::gcHeapType.EnumMem(); + IGCHeap::gcHeapType.EnumMem(); ); #endif // FEATURE_SVR_GC @@ -796,10 +798,9 @@ HRESULT ClrDataAccess::EnumMemWalkStackHelper(CLRDataEnumMemoryFlags flags, currentSP = dac_cast<TADDR>(pThread->GetCachedStackLimit()) + sizeof(TADDR); // exhaust the frames using DAC api - bool frameHadContext; for (; status == S_OK; ) { - frameHadContext = false; + bool frameHadContext = false; status = pStackWalk->GetFrame(&pFrame); PCODE addr = NULL; if (status == S_OK && pFrame != NULL) diff --git a/src/debug/daccess/fntableaccess.cpp b/src/debug/daccess/fntableaccess.cpp index e7b96ec3e0..6dcd5844e4 100644 --- a/src/debug/daccess/fntableaccess.cpp +++ b/src/debug/daccess/fntableaccess.cpp @@ -11,6 +11,7 @@ #include "stdafx.h" +#ifndef FEATURE_PAL #ifndef _TARGET_X86_ // @@ -388,6 +389,7 @@ static NTSTATUS OutOfProcessFunctionTableCallback_Stub(IN ReadMemoryFunction #endif // DEBUGSUPPORT_STUBS_HAVE_UNWIND_INFO + BOOL ReadMemory(PVOID pUserContext, LPCVOID lpBaseAddress, PVOID lpBuffer, SIZE_T nSize, SIZE_T* lpNumberOfBytesRead) { HANDLE hProcess = (HANDLE)pUserContext; @@ -456,6 +458,5 @@ extern "C" NTSTATUS OutOfProcessFunctionTableCallbackEx() return STATUS_UNSUCCESSFUL; } - - #endif // !_TARGET_X86_ +#endif // !FEATURE_PAL
\ No newline at end of file diff --git a/src/debug/daccess/fntableaccess.h b/src/debug/daccess/fntableaccess.h index 0dbabdf8c9..b5ea5452f6 100644 --- a/src/debug/daccess/fntableaccess.h +++ b/src/debug/daccess/fntableaccess.h @@ -51,6 +51,9 @@ typedef struct _FakeHpRealCodeHdr LPVOID phdrDebugInfo; LPVOID phdrJitEHInfo; // changed from EE_ILEXCEPTION* LPVOID phdrJitGCInfo; // changed from BYTE* +#if defined (FEATURE_GDBJIT) + LPVOID pCalledMethods; +#endif LPVOID hdrMDesc; // changed from MethodDesc* DWORD nUnwindInfos; T_RUNTIME_FUNCTION unwindInfos[0]; diff --git a/src/debug/daccess/nidump.cpp b/src/debug/daccess/nidump.cpp index 32eab498d3..23e76c4fe4 100644 --- a/src/debug/daccess/nidump.cpp +++ b/src/debug/daccess/nidump.cpp @@ -1187,12 +1187,12 @@ NativeImageDumper::DumpNativeImage() mscorlib->fIsMscorlib = TRUE; _ASSERTE(mscorlib->fIsHardbound); } + + _ASSERTE(mscorlib != NULL); if( mscorlib->fIsHardbound ) { m_isMscorlibHardBound = true; } - - _ASSERTE(mscorlib != NULL); if( m_isMscorlibHardBound ) { //go through the module to the binder. @@ -3120,7 +3120,7 @@ void NativeImageDumper::DumpCompleteMethod(PTR_Module module, MethodIterator& mi #ifdef _TARGET_X86_ InfoHdr hdr; stringOutFn( "method info Block:\n" ); - curGCInfoPtr += gcDump.DumpInfoHdr(PTR_CBYTE(gcInfoToken.Info), &hdr, &methodSize, 0); + curGCInfoPtr += gcDump.DumpInfoHdr(curGCInfoPtr, &hdr, &methodSize, 0); stringOutFn( "\n" ); #endif @@ -4088,6 +4088,7 @@ void NativeImageDumper::DumpModule( PTR_Module module ) (int)(module->m_maxDynamicEntries * sizeof(*(module->m_pDynamicStaticsInfo)))); +#ifdef FEATURE_CER DisplayWriteFieldInt( m_dwReliabilityContract, module->m_dwReliabilityContract, Module, MODULE ); @@ -4105,6 +4106,7 @@ void NativeImageDumper::DumpModule( PTR_Module module ) offsetof(Module, m_pCerNgenRootTable), fieldsize(Module, m_pCerNgenRootTable) ); } +#endif _ASSERTE(module->m_debuggerSpecificData.m_pDynamicILCrst == NULL); @@ -4152,6 +4154,7 @@ bool NativeImageDumper::isPrecode(TADDR maybePrecode) return !!module->IsZappedPrecode(maybePrecode); } +#ifdef FEATURE_CER void NativeImageDumper::DumpNgenRootTable( PTR_CerNgenRootTable table, const char * name, unsigned offset, unsigned fieldSize ) @@ -4231,6 +4234,8 @@ void NativeImageDumper::DumpNgenRootTable( PTR_CerNgenRootTable table, DisplayEndStructure( MODULE ); //CERNgenRootTable } +#endif // FEATURE_CER + void NativeImageDumper::IterateTypeDefToMTCallback( TADDR mtTarget, TADDR flags, PTR_LookupMapBase map, @@ -9034,12 +9039,14 @@ NativeImageDumper::DumpEEClassForMethodTable( PTR_MethodTable mt ) DisplayWriteFieldInt( m_cbModuleDynamicID, pClassOptional->m_cbModuleDynamicID, EEClassOptionalFields, EECLASSES ); +#ifdef FEATURE_CER /* REVISIT_TODO Fri 10/14/2005 * Use the macros from ConstrainedExecutionRegion.cpp on this? */ DisplayWriteFieldUInt( m_dwReliabilityContract, clazz->GetReliabilityContract(), EEClassOptionalFields, EECLASSES ); +#endif DisplayWriteFieldEnumerated( m_SecProps, clazz->GetSecurityProperties()->dwFlags, EEClassOptionalFields, s_SecurityProperties, W("|"), @@ -9439,10 +9446,12 @@ void NativeImageDumper::DumpReadyToRunMethod(PCODE pEntryPoint, PTR_RUNTIME_FUNC g_holdStringOutData.Clear(); GCDump gcDump(GCINFO_VERSION); gcDump.gcPrintf = stringOutFn; -#if !defined(_TARGET_X86_) && defined(USE_GC_INFO_DECODER) UINT32 r2rversion = m_pReadyToRunHeader->MajorVersion; UINT32 gcInfoVersion = GCInfoToken::ReadyToRunVersionToGcInfoVersion(r2rversion); - GcInfoDecoder gcInfoDecoder({ curGCInfoPtr, gcInfoVersion }, DECODE_CODE_LENGTH); + GCInfoToken gcInfoToken = { curGCInfoPtr, gcInfoVersion }; + +#if !defined(_TARGET_X86_) && defined(USE_GC_INFO_DECODER) + GcInfoDecoder gcInfoDecoder(gcInfoToken, DECODE_CODE_LENGTH); methodSize = gcInfoDecoder.GetCodeLength(); #endif @@ -9541,8 +9550,10 @@ mdTypeRef NativeImageDumper::FindTypeRefForMT( PTR_MethodTable mt ) #undef GC_NOTRIGGER #if defined _DEBUG && defined _TARGET_X86_ +#ifdef _MSC_VER // disable FPO for checked build #pragma optimize("y", off) +#endif // _MSC_VER #endif #undef _ASSERTE diff --git a/src/debug/daccess/request.cpp b/src/debug/daccess/request.cpp index a30ec37eac..35ab5a0814 100644 --- a/src/debug/daccess/request.cpp +++ b/src/debug/daccess/request.cpp @@ -725,7 +725,7 @@ ClrDataAccess::GetHeapAllocData(unsigned int count, struct DacpGenerationAllocDa SOSDacEnter(); #if defined(FEATURE_SVR_GC) - if (GCHeap::IsServerHeap()) + if (GCHeapUtilities::IsServerHeap()) { hr = GetServerAllocData(count, data, pNeeded); } @@ -2809,7 +2809,7 @@ ClrDataAccess::GetGCHeapDetails(CLRDATA_ADDRESS heap, struct DacpGcHeapDetails * SOSDacEnter(); // doesn't make sense to call this on WKS mode - if (!GCHeap::IsServerHeap()) + if (!GCHeapUtilities::IsServerHeap()) hr = E_INVALIDARG; else #ifdef FEATURE_SVR_GC @@ -2884,7 +2884,7 @@ ClrDataAccess::GetHeapSegmentData(CLRDATA_ADDRESS seg, struct DacpHeapSegmentDat SOSDacEnter(); - if (GCHeap::IsServerHeap()) + if (GCHeapUtilities::IsServerHeap()) { #if !defined(FEATURE_SVR_GC) _ASSERTE(0); @@ -2924,7 +2924,7 @@ ClrDataAccess::GetGCHeapList(unsigned int count, CLRDATA_ADDRESS heaps[], unsign SOSDacEnter(); // make sure we called this in appropriate circumstances (i.e., we have multiple heaps) - if (GCHeap::IsServerHeap()) + if (GCHeapUtilities::IsServerHeap()) { #if !defined(FEATURE_SVR_GC) _ASSERTE(0); @@ -2960,45 +2960,49 @@ ClrDataAccess::GetGCHeapData(struct DacpGcHeapData *gcheapData) SOSDacEnter(); - // Now get the heap type. The first data member of the GCHeap class is the GC_HEAP_TYPE, which has - // three possible values: + // for server GC-capable builds only, we need to check and see if IGCHeap::gcHeapType + // is GC_HEAP_INVALID, in which case we fail. + // IGCHeap::gcHeapType doesn't exist on non-server-GC capable builds. +#ifdef FEATURE_SVR_GC + ULONG32 gcHeapValue = IGCHeap::gcHeapType; + + // GC_HEAP_TYPE has three possible values: // GC_HEAP_INVALID = 0, // GC_HEAP_WKS = 1, // GC_HEAP_SVR = 2 + // If we get something other than that, we probably read the wrong location. + _ASSERTE(gcHeapValue >= IGCHeap::GC_HEAP_INVALID && gcHeapValue <= IGCHeap::GC_HEAP_SVR); - TADDR gcHeapLocation = g_pGCHeap.GetAddrRaw (); // get the starting address of the global GCHeap instance - size_t gcHeapValue = 0; // this will hold the heap type - ULONG32 returned = 0; - - // @todo Microsoft: we should probably be capturing the HRESULT from ReadVirtual. We could - // provide a more informative error message. E_FAIL is a wretchedly vague thing to return. - hr = m_pTarget->ReadVirtual(gcHeapLocation, (PBYTE)&gcHeapValue, sizeof(gcHeapValue), &returned); - - //@todo Microsoft: We have an enumerated type, we probably should use the symbolic name // we have GC_HEAP_INVALID if gcHeapValue == 0, so we're done - if (SUCCEEDED(hr) && ((returned != sizeof(gcHeapValue)) || (gcHeapValue == 0))) + if (gcHeapValue == IGCHeap::GC_HEAP_INVALID) + { hr = E_FAIL; + goto cleanup; + } +#endif - if (SUCCEEDED(hr)) + // Now we can get other important information about the heap + gcheapData->g_max_generation = GCHeapUtilities::GetMaxGeneration(); + gcheapData->bServerMode = GCHeapUtilities::IsServerHeap(); + gcheapData->bGcStructuresValid = GCScan::GetGcRuntimeStructuresValid(); + if (GCHeapUtilities::IsServerHeap()) { - // Now we can get other important information about the heap - gcheapData->g_max_generation = GCHeap::GetMaxGeneration(); - gcheapData->bServerMode = GCHeap::IsServerHeap(); - gcheapData->bGcStructuresValid = GCScan::GetGcRuntimeStructuresValid(); - if (GCHeap::IsServerHeap()) - { #if !defined (FEATURE_SVR_GC) - _ASSERTE(0); - gcheapData->HeapCount = 1; + _ASSERTE(0); + gcheapData->HeapCount = 1; #else // !defined (FEATURE_SVR_GC) - gcheapData->HeapCount = GCHeapCount(); + gcheapData->HeapCount = GCHeapCount(); #endif // !defined (FEATURE_SVR_GC) - } - else - { - gcheapData->HeapCount = 1; - } } + else + { + gcheapData->HeapCount = 1; + } + +#ifdef FEATURE_SVR_GC +cleanup: + ; +#endif SOSDacLeave(); return hr; @@ -3014,7 +3018,7 @@ ClrDataAccess::GetOOMStaticData(struct DacpOomData *oomData) memset(oomData, 0, sizeof(DacpOomData)); - if (!GCHeap::IsServerHeap()) + if (!GCHeapUtilities::IsServerHeap()) { oom_history* pOOMInfo = &(WKS::gc_heap::oom_info); oomData->reason = pOOMInfo->reason; @@ -3043,7 +3047,7 @@ ClrDataAccess::GetOOMData(CLRDATA_ADDRESS oomAddr, struct DacpOomData *data) SOSDacEnter(); memset(data, 0, sizeof(DacpOomData)); - if (!GCHeap::IsServerHeap()) + if (!GCHeapUtilities::IsServerHeap()) hr = E_FAIL; // doesn't make sense to call this on WKS mode #ifdef FEATURE_SVR_GC @@ -3090,7 +3094,7 @@ ClrDataAccess::GetGCInterestingInfoStaticData(struct DacpGCInterestingInfoData * SOSDacEnter(); memset(data, 0, sizeof(DacpGCInterestingInfoData)); - if (!GCHeap::IsServerHeap()) + if (!GCHeapUtilities::IsServerHeap()) { for (int i = 0; i < NUM_GC_DATA_POINTS; i++) data->interestingDataPoints[i] = WKS::interesting_data_per_heap[i]; @@ -3123,7 +3127,7 @@ ClrDataAccess::GetGCInterestingInfoData(CLRDATA_ADDRESS interestingInfoAddr, str SOSDacEnter(); memset(data, 0, sizeof(DacpGCInterestingInfoData)); - if (!GCHeap::IsServerHeap()) + if (!GCHeapUtilities::IsServerHeap()) hr = E_FAIL; // doesn't make sense to call this on WKS mode #ifdef FEATURE_SVR_GC @@ -3149,7 +3153,7 @@ ClrDataAccess::GetHeapAnalyzeData(CLRDATA_ADDRESS addr, struct DacpGcHeapAnalyz SOSDacEnter(); - if (!GCHeap::IsServerHeap()) + if (!GCHeapUtilities::IsServerHeap()) hr = E_FAIL; // doesn't make sense to call this on WKS mode #ifdef FEATURE_SVR_GC @@ -3856,7 +3860,7 @@ ClrDataAccess::EnumWksGlobalMemoryRegions(CLRDataEnumMemoryFlags flags) // enumerating the generations from max (which is normally gen2) to max+1 gives you // the segment list for all the normal segements plus the large heap segment (max+1) // this is the convention in the GC so it is repeated here - for (ULONG i = GCHeap::GetMaxGeneration(); i <= GCHeap::GetMaxGeneration()+1; i++) + for (ULONG i = GCHeapUtilities::GetMaxGeneration(); i <= GCHeapUtilities::GetMaxGeneration()+1; i++) { __DPtr<WKS::heap_segment> seg = dac_cast<TADDR>(WKS::generation_table[i].start_segment); while (seg) diff --git a/src/debug/daccess/request_svr.cpp b/src/debug/daccess/request_svr.cpp index 429f30020f..1fe20e2b60 100644 --- a/src/debug/daccess/request_svr.cpp +++ b/src/debug/daccess/request_svr.cpp @@ -256,7 +256,7 @@ ClrDataAccess::EnumSvrGlobalMemoryRegions(CLRDataEnumMemoryFlags flags) // enumerating the generations from max (which is normally gen2) to max+1 gives you // the segment list for all the normal segements plus the large heap segment (max+1) // this is the convention in the GC so it is repeated here - for (ULONG i = GCHeap::GetMaxGeneration(); i <= GCHeap::GetMaxGeneration()+1; i++) + for (ULONG i = GCHeapUtilities::GetMaxGeneration(); i <= GCHeapUtilities::GetMaxGeneration()+1; i++) { __DPtr<SVR::heap_segment> seg = dac_cast<TADDR>(pHeap->generation_table[i].start_segment); while (seg) @@ -271,7 +271,7 @@ ClrDataAccess::EnumSvrGlobalMemoryRegions(CLRDataEnumMemoryFlags flags) DWORD DacGetNumHeaps() { - if (GCHeap::IsServerHeap()) + if (GCHeapUtilities::IsServerHeap()) return (DWORD)SVR::gc_heap::n_heaps; // workstation gc diff --git a/src/debug/di/breakpoint.cpp b/src/debug/di/breakpoint.cpp index 1e381a5f83..e3e4fb04a5 100644 --- a/src/debug/di/breakpoint.cpp +++ b/src/debug/di/breakpoint.cpp @@ -15,7 +15,7 @@ CordbBreakpoint::CordbBreakpoint(CordbProcess * pProcess, CordbBreakpointType bpType) : CordbBase(pProcess, 0, enumCordbBreakpoint), - m_active(false), m_type(bpType) + m_active(false), m_pAppDomain(NULL), m_type(bpType) { } diff --git a/src/debug/di/module.cpp b/src/debug/di/module.cpp index 6717e8575f..36cc6f5f9e 100644 --- a/src/debug/di/module.cpp +++ b/src/debug/di/module.cpp @@ -3755,7 +3755,269 @@ HRESULT FindNativeInfoInILVariableArray(DWORD return CORDBG_E_IL_VAR_NOT_AVAILABLE; } // FindNativeInfoInILVariableArray -//* ------------------------------------------------------------------------- * + +// * ------------------------------------------------------------------------- * +// * Variable Enum class +// * ------------------------------------------------------------------------- * +//----------------------------------------------------------------------------- +// CordbVariableHome constructor +// Arguments: +// Input: +// pCode - CordbNativeCode instance containing this variable home +// pNativeVarInfo - native location, lifetime, and index information for +// this variable +// isLocal - indicates whether the instance is a local variable, +// as opposed to an argument +// index - the argument or slot index +// Output: +// fields of the CordbVariableHome instance have been initialized +//----------------------------------------------------------------------------- +CordbVariableHome::CordbVariableHome(CordbNativeCode *pCode, + const ICorDebugInfo::NativeVarInfo nativeVarInfo, + BOOL isLocal, + ULONG index) : + CordbBase(pCode->GetModule()->GetProcess(), 0) +{ + _ASSERTE(pCode != NULL); + + m_pCode.Assign(pCode); + m_nativeVarInfo = nativeVarInfo; + m_isLocal = isLocal; + m_index = index; +} + +CordbVariableHome::~CordbVariableHome() +{ + _ASSERTE(this->IsNeutered()); +} + +void CordbVariableHome::Neuter() +{ + m_pCode.Clear(); + CordbBase::Neuter(); +} + +//----------------------------------------------------------------------------- +// Public method for IUnknown::QueryInterface. +// Has standard QI semantics. +//----------------------------------------------------------------------------- +HRESULT CordbVariableHome::QueryInterface(REFIID id, void **pInterface) +{ + if (id == IID_ICorDebugVariableHome) + { + *pInterface = static_cast<ICorDebugVariableHome *>(this); + } + else if (id == IID_IUnknown) + { + *pInterface = static_cast<IUnknown *>(static_cast<ICorDebugVariableHome *>(this)); + } + else + { + *pInterface = NULL; + return E_NOINTERFACE; + } + + ExternalAddRef(); + return S_OK; +} + +//----------------------------------------------------------------------------- +// CordbVariableHome::GetCode +// Public method to get the Code object containing this variable home. +// +// Parameters: +// ppCode - OUT: returns the Code object for this variable home. +// +// Returns: +// S_OK - on success. +//----------------------------------------------------------------------------- +HRESULT CordbVariableHome::GetCode(ICorDebugCode **ppCode) +{ + PUBLIC_REENTRANT_API_ENTRY(this); + FAIL_IF_NEUTERED(this); + VALIDATE_POINTER_TO_OBJECT(ppCode, ICorDebugCode **); + ATT_REQUIRE_STOPPED_MAY_FAIL(m_pCode->GetProcess()); + + HRESULT hr = m_pCode->QueryInterface(IID_ICorDebugCode, (LPVOID*)ppCode); + + return hr; +} + +//----------------------------------------------------------------------------- +// CordbVariableHome::GetSlotIndex +// Public method to get the slot index for this variable home. +// +// Parameters: +// pSlotIndex - OUT: returns the managed slot-index of this variable home. +// +// Returns: +// S_OK - on success +// E_FAIL - if the variable is not a local variable, but an argument +//----------------------------------------------------------------------------- +HRESULT CordbVariableHome::GetSlotIndex(ULONG32 *pSlotIndex) +{ + PUBLIC_REENTRANT_API_ENTRY(this); + FAIL_IF_NEUTERED(this); + VALIDATE_POINTER_TO_OBJECT(pSlotIndex, ULONG32 *); + ATT_REQUIRE_STOPPED_MAY_FAIL(m_pCode->GetProcess()); + + if (!m_isLocal) + { + return E_FAIL; + } + *pSlotIndex = m_index; + return S_OK; +} + +//----------------------------------------------------------------------------- +// CordbVariableHome::GetArgumentIndex +// Public method to get the slot index for this variable home. +// +// Parameters: +// pSlotIndex - OUT: returns the managed argument-index of this variable home. +// +// Returns: +// S_OK - on success +// E_FAIL - if the variable is not an argument, but a local variable +//----------------------------------------------------------------------------- +HRESULT CordbVariableHome::GetArgumentIndex(ULONG32 *pArgumentIndex) +{ + PUBLIC_REENTRANT_API_ENTRY(this); + FAIL_IF_NEUTERED(this); + VALIDATE_POINTER_TO_OBJECT(pArgumentIndex, ULONG32 *); + ATT_REQUIRE_STOPPED_MAY_FAIL(m_pCode->GetProcess()); + + if (m_isLocal) + { + return E_FAIL; + } + *pArgumentIndex = m_index; + return S_OK; +} + +//----------------------------------------------------------------------------- +// CordbVariableHome::GetLiveRange +// Public method to get the native range over which this variable is live. +// +// Parameters: +// pStartOffset - OUT: returns the logical offset at which the variable is +// first live +// pEndOffset - OUT: returns the logical offset immediately after that at +// which the variable is last live +// +// Returns: +// S_OK - on success +//----------------------------------------------------------------------------- +HRESULT CordbVariableHome::GetLiveRange(ULONG32 *pStartOffset, + ULONG32 *pEndOffset) +{ + PUBLIC_REENTRANT_API_ENTRY(this); + FAIL_IF_NEUTERED(this); + VALIDATE_POINTER_TO_OBJECT(pStartOffset, ULONG32 *); + VALIDATE_POINTER_TO_OBJECT(pEndOffset, ULONG32 *); + ATT_REQUIRE_STOPPED_MAY_FAIL(m_pCode->GetProcess()); + + *pStartOffset = m_nativeVarInfo.startOffset; + *pEndOffset = m_nativeVarInfo.endOffset; + return S_OK; +} + +//----------------------------------------------------------------------------- +// CordbVariableHome::GetLocationType +// Public method to get the type of native location for this variable home. +// +// Parameters: +// pLocationType - OUT: the type of native location +// +// Returns: +// S_OK - on success +//----------------------------------------------------------------------------- +HRESULT CordbVariableHome::GetLocationType(VariableLocationType *pLocationType) +{ + PUBLIC_REENTRANT_API_ENTRY(this); + FAIL_IF_NEUTERED(this); + VALIDATE_POINTER_TO_OBJECT(pLocationType, VariableLocationType *); + ATT_REQUIRE_STOPPED_MAY_FAIL(m_pCode->GetProcess()); + + switch (m_nativeVarInfo.loc.vlType) + { + case ICorDebugInfo::VLT_REG: + *pLocationType = VLT_REGISTER; + break; + case ICorDebugInfo::VLT_STK: + *pLocationType = VLT_REGISTER_RELATIVE; + break; + default: + *pLocationType = VLT_INVALID; + } + return S_OK; +} + +//----------------------------------------------------------------------------- +// CordbVariableHome::GetRegister +// Public method to get the register or base register for this variable hom. +// +// Parameters: +// pRegister - OUT: for VLT_REGISTER location types, gives the register. +// for VLT_REGISTER_RELATIVE location types, gives the base +// register. +// +// Returns: +// S_OK - on success +// E_FAIL - for VLT_INVALID location types +//----------------------------------------------------------------------------- +HRESULT CordbVariableHome::GetRegister(CorDebugRegister *pRegister) +{ + PUBLIC_REENTRANT_API_ENTRY(this); + FAIL_IF_NEUTERED(this); + VALIDATE_POINTER_TO_OBJECT(pRegister, CorDebugRegister *); + ATT_REQUIRE_STOPPED_MAY_FAIL(m_pCode->GetProcess()); + + switch (m_nativeVarInfo.loc.vlType) + { + case ICorDebugInfo::VLT_REG: + *pRegister = ConvertRegNumToCorDebugRegister(m_nativeVarInfo.loc.vlReg.vlrReg); + break; + case ICorDebugInfo::VLT_STK: + *pRegister = ConvertRegNumToCorDebugRegister(m_nativeVarInfo.loc.vlStk.vlsBaseReg); + break; + default: + return E_FAIL; + } + return S_OK; +} + +//----------------------------------------------------------------------------- +// CordbVariableHome::GetOffset +// Public method to get the offset from the base register for this variable home. +// +// Parameters: +// pOffset - OUT: gives the offset from the base register +// +// Returns: +// S_OK - on success +// E_FAIL - for location types other than VLT_REGISTER_RELATIVE +//----------------------------------------------------------------------------- +HRESULT CordbVariableHome::GetOffset(LONG *pOffset) +{ + PUBLIC_REENTRANT_API_ENTRY(this); + FAIL_IF_NEUTERED(this); + VALIDATE_POINTER_TO_OBJECT(pOffset, LONG *); + ATT_REQUIRE_STOPPED_MAY_FAIL(m_pCode->GetProcess()); + + switch (m_nativeVarInfo.loc.vlType) + { + case ICorDebugInfo::VLT_STK: + *pOffset = m_nativeVarInfo.loc.vlStk.vlsOffset; + break; + default: + return E_FAIL; + } + return S_OK; +} + + +// * ------------------------------------------------------------------------- * // * Native Code class // * ------------------------------------------------------------------------- */ @@ -3780,7 +4042,7 @@ CordbNativeCode::CordbNativeCode(CordbFunction * pFunction, m_fIsInstantiatedGeneric(fIsInstantiatedGeneric != FALSE) { _ASSERTE(GetVersion() >= CorDB_DEFAULT_ENC_FUNCTION_VERSION); - + for (CodeBlobRegion region = kHot; region < MAX_REGIONS; ++region) { m_rgCodeRegions[region] = pJitData->m_rgCodeRegions[region]; @@ -3805,6 +4067,10 @@ HRESULT CordbNativeCode::QueryInterface(REFIID id, void ** pInterface) { *pInterface = static_cast<ICorDebugCode3 *>(this); } + else if (id == IID_ICorDebugCode4) + { + *pInterface = static_cast<ICorDebugCode4 *>(this); + } else if (id == IID_IUnknown) { *pInterface = static_cast<IUnknown *>(static_cast<ICorDebugCode *>(this)); @@ -4111,6 +4377,113 @@ HRESULT CordbNativeCode::GetReturnValueLiveOffset(ULONG32 ILoffset, ULONG32 buff return hr; } +//----------------------------------------------------------------------------- +// CordbNativeCode::EnumerateVariableHomes +// Public method to get an enumeration of native variable homes. This may +// include multiple ICorDebugVariableHomes for the same slot or argument index +// if they have different homes at different points in the function. +// +// Parameters: +// ppEnum - OUT: returns the enum of variable homes. +// +// Returns: +// HRESULT for success or failure. +//----------------------------------------------------------------------------- +HRESULT CordbNativeCode::EnumerateVariableHomes(ICorDebugVariableHomeEnum **ppEnum) +{ + PUBLIC_REENTRANT_API_ENTRY(this); + FAIL_IF_NEUTERED(this); + VALIDATE_POINTER_TO_OBJECT(ppEnum, ICorDebugVariableHomeEnum **); + ATT_REQUIRE_STOPPED_MAY_FAIL(GetProcess()); + + HRESULT hr = S_OK; + + // Get the argument count + ULONG argCount = 0; + CordbFunction *func = GetFunction(); + _ASSERTE(func != NULL); + IfFailRet(func->GetSig(NULL, &argCount, NULL)); + +#ifdef _DEBUG + // Get the number of locals + ULONG localCount = 0; + EX_TRY + { + GetFunction()->GetILCode()->GetLocalVarSig(NULL, &localCount); + } + EX_CATCH_HRESULT(hr); + IfFailRet(hr); +#endif + + RSSmartPtr<CordbVariableHome> *rsHomes = NULL; + + EX_TRY + { + CordbProcess *pProcess = GetProcess(); + _ASSERTE(pProcess != NULL); + + const DacDbiArrayList<ICorDebugInfo::NativeVarInfo> *pOffsetInfoList = m_nativeVarData.GetOffsetInfoList(); + _ASSERTE(pOffsetInfoList != NULL); + DWORD countHomes = 0; + for (int i = 0; i < pOffsetInfoList->Count(); i++) + { + const ICorDebugInfo::NativeVarInfo *pNativeVarInfo = &((*pOffsetInfoList)[i]); + _ASSERTE(pNativeVarInfo != NULL); + + // The variable information list can include variables + // with special varNumbers representing, for instance, the + // parameter types for generic methods. Here we are only + // interested in local variables and arguments. + if (pNativeVarInfo->varNumber < (DWORD)ICorDebugInfo::MAX_ILNUM) + { + countHomes++; + } + } + rsHomes = new RSSmartPtr<CordbVariableHome>[countHomes]; + + DWORD varHomeInd = 0; + for (int i = 0; i < pOffsetInfoList->Count(); i++) + { + const ICorDebugInfo::NativeVarInfo *pNativeVarInfo = &((*pOffsetInfoList)[i]); + + // Again, only look for native var info representing local + // variables and arguments. + if (pNativeVarInfo->varNumber < (DWORD)ICorDebugInfo::MAX_ILNUM) + { + // determine whether this variable home represents and argument or local variable + BOOL isLocal = ((ULONG)pNativeVarInfo->varNumber >= argCount); + + // determine the argument-index or slot-index of this variable home + ULONG argOrSlotIndex; + if (isLocal) { + argOrSlotIndex = pNativeVarInfo->varNumber - argCount; + _ASSERTE(argOrSlotIndex < localCount); + } else { + argOrSlotIndex = pNativeVarInfo->varNumber; + } + + RSInitHolder<CordbVariableHome> pCVH(new CordbVariableHome(this, + (*pOffsetInfoList)[i], + isLocal, + argOrSlotIndex)); + pProcess->GetContinueNeuterList()->Add(pProcess, pCVH); + _ASSERTE(varHomeInd < countHomes); + rsHomes[varHomeInd].Assign(pCVH); + pCVH.ClearAndMarkDontNeuter(); + varHomeInd++; + } + } + + RSInitHolder<CordbVariableHomeEnumerator> pCDVHE( + new CordbVariableHomeEnumerator(GetProcess(), &rsHomes, countHomes)); + pProcess->GetContinueNeuterList()->Add(pProcess, pCDVHE); + pCDVHE.TransferOwnershipExternal(ppEnum); + } + EX_CATCH_HRESULT(hr); + + return hr; +} + int CordbNativeCode::GetCallInstructionLength(BYTE *ip, ULONG32 count) { #if defined(DBG_TARGET_ARM) diff --git a/src/debug/di/process.cpp b/src/debug/di/process.cpp index 44e4a0c667..a5496eee54 100644 --- a/src/debug/di/process.cpp +++ b/src/debug/di/process.cpp @@ -7334,6 +7334,7 @@ CordbUnmanagedThread *CordbProcess::HandleUnmanagedCreateThread(DWORD dwThreadId if (!SUCCEEDED(hr)) { delete ut; + ut = NULL; LOG((LF_CORDB, LL_INFO10000, "Failed adding unmanaged thread to process!\n")); CORDBSetUnrecoverableError(this, hr, 0); @@ -8119,7 +8120,9 @@ void CordbProcess::DispatchUnmanagedInBandEvent() break; // Get the thread for this event + _ASSERTE(pUnmanagedThread == NULL); pUnmanagedThread = pUnmanagedEvent->m_owner; + _ASSERTE(pUnmanagedThread != NULL); // We better not have dispatched it yet! _ASSERTE(!pUnmanagedEvent->IsDispatched()); @@ -8177,13 +8180,10 @@ void CordbProcess::DispatchUnmanagedInBandEvent() m_pShim->GetWin32EventThread()->DoDbgContinue(this, pUnmanagedEvent); // Release our reference to the unmanaged thread that we dispatched - if (pUnmanagedThread) - { - // This event should have been continued long ago... - _ASSERTE(!pUnmanagedThread->IBEvent()->IsEventWaitingForContinue()); - pUnmanagedThread->InternalRelease(); - pUnmanagedThread = NULL; - } + // This event should have been continued long ago... + _ASSERTE(!pUnmanagedThread->IBEvent()->IsEventWaitingForContinue()); + pUnmanagedThread->InternalRelease(); + pUnmanagedThread = NULL; } m_dispatchingUnmanagedEvent = false; diff --git a/src/debug/di/rsenumerator.hpp b/src/debug/di/rsenumerator.hpp index eb7a225a5d..84e6194c4d 100644 --- a/src/debug/di/rsenumerator.hpp +++ b/src/debug/di/rsenumerator.hpp @@ -99,8 +99,8 @@ CordbEnumerator<ElemType, ElemType **items, DWORD countItems) : CordbBase(pProcess, 0, enumCordbEnumerator), -m_nextIndex(0), -m_countItems(countItems) +m_countItems(countItems), +m_nextIndex(0) { _ASSERTE(items != NULL); m_items = *items; @@ -108,7 +108,7 @@ m_countItems(countItems) } // Destructor -template< typename ElemType, +template< typename ElemType, typename ElemPublicType, typename EnumInterfaceType, ElemPublicType (*GetPublicType)(ElemType)> diff --git a/src/debug/di/rsmain.cpp b/src/debug/di/rsmain.cpp index b5685750db..0f5778789f 100644 --- a/src/debug/di/rsmain.cpp +++ b/src/debug/di/rsmain.cpp @@ -40,6 +40,8 @@ RSDebuggingInfo g_RSDebuggingInfo_OutOfProc = {0 }; // set to NULL RSDebuggingInfo * g_pRSDebuggingInfo = &g_RSDebuggingInfo_OutOfProc; +// The following instances are used for invoking overloaded new/delete +forDbiWorker forDbi; #ifdef _DEBUG // For logs, we can print the string name for the debug codes. diff --git a/src/debug/di/rspriv.h b/src/debug/di/rspriv.h index 853767804a..18920add5d 100644 --- a/src/debug/di/rspriv.h +++ b/src/debug/di/rspriv.h @@ -85,6 +85,7 @@ class CordbJITILFrame; class CordbInternalFrame; class CordbContext; class CordbThread; +class CordbVariableHome; #ifdef FEATURE_INTEROP_DEBUGGING class CordbUnmanagedThread; @@ -176,7 +177,7 @@ private: USHORT m_usPort; }; -#define forDbi (*(forDbiWorker *)NULL) +extern forDbiWorker forDbi; // for dbi we just default to new, but we need to have these defined for both dac and dbi inline void * operator new(size_t lenBytes, const forDbiWorker &) @@ -1586,7 +1587,7 @@ template< typename ElemType, typename ElemPublicType, typename EnumInterfaceType, ElemPublicType (*GetPublicType)(ElemType)> -class CordbEnumerator : public CordbBase, EnumInterfaceType +class CordbEnumerator : public CordbBase, public EnumInterfaceType { private: // the list of items being enumerated over @@ -1680,6 +1681,11 @@ typedef CordbEnumerator<RsGuidToTypeMapping, ICorDebugGuidToTypeEnum, GuidToTypeMappingConvert > CordbGuidToTypeEnumerator; +typedef CordbEnumerator<RSSmartPtr<CordbVariableHome>, + ICorDebugVariableHome*, + ICorDebugVariableHomeEnum, + QueryInterfaceConvert<RSSmartPtr<CordbVariableHome>, ICorDebugVariableHome> > CordbVariableHomeEnumerator; + // ---------------------------------------------------------------------------- // Hash table for CordbBase objects. // - Uses Internal AddRef/Release (not external) @@ -2920,7 +2926,7 @@ class CordbProcess : public ICorDebugProcess4, public ICorDebugProcess5, public ICorDebugProcess7, - public ICorDebugProcess8, + public ICorDebugProcess8, public IDacDbiInterface::IAllocator, public IDacDbiInterface::IMetaDataLookup, public IProcessShimHooks @@ -4696,7 +4702,7 @@ public: // See definition of ICorDebugType for further invariants on types. // -class CordbType : public CordbBase, public ICorDebugType +class CordbType : public CordbBase, public ICorDebugType, public ICorDebugType2 { public: CordbType(CordbAppDomain *appdomain, CorElementType ty, unsigned int rank); @@ -4736,6 +4742,11 @@ public: COM_METHOD GetRank(ULONG32 *pnRank); //----------------------------------------------------------- + // ICorDebugType2 + //----------------------------------------------------------- + COM_METHOD GetTypeID(COR_TYPEID *pId); + + //----------------------------------------------------------- // Non-COM members //----------------------------------------------------------- @@ -5812,7 +5823,10 @@ private: * code, including an optional set of mappings from IL to offsets in the native Code. * ------------------------------------------------------------------------- */ -class CordbNativeCode : public CordbCode, public ICorDebugCode2, public ICorDebugCode3 +class CordbNativeCode : public CordbCode, + public ICorDebugCode2, + public ICorDebugCode3, + public ICorDebugCode4 { public: CordbNativeCode(CordbFunction * pFunction, @@ -5853,6 +5867,11 @@ public: //----------------------------------------------------------- + // ICorDebugCode4 + //----------------------------------------------------------- + COM_METHOD EnumerateVariableHomes(ICorDebugVariableHomeEnum **ppEnum); + + //----------------------------------------------------------- // Internal members //----------------------------------------------------------- @@ -8539,6 +8558,63 @@ private: typedef enum {kUnboxed, kBoxed} BoxedValue; #define EMPTY_BUFFER TargetBuffer(PTR_TO_CORDB_ADDRESS((void *)NULL), 0) +/* ------------------------------------------------------------------------- * + * Variable Home class + * ------------------------------------------------------------------------- */ +class CordbVariableHome : public CordbBase, public ICorDebugVariableHome +{ +public: + CordbVariableHome(CordbNativeCode *pCode, + const ICorDebugInfo::NativeVarInfo nativeVarInfo, + BOOL isLoc, + ULONG index); + ~CordbVariableHome(); + virtual void Neuter(); + +#ifdef _DEBUG + virtual const char * DbgGetName() { return "CordbVariableHome"; } +#endif + + //----------------------------------------------------------- + // IUnknown + //----------------------------------------------------------- + ULONG STDMETHODCALLTYPE AddRef() + { + return (BaseAddRef()); + } + ULONG STDMETHODCALLTYPE Release() + { + return (BaseRelease()); + } + + COM_METHOD QueryInterface(REFIID riid, void **ppInterface); + + //----------------------------------------------------------- + // ICorDebugVariableHome + //----------------------------------------------------------- + + COM_METHOD GetCode(ICorDebugCode **ppCode); + + COM_METHOD GetSlotIndex(ULONG32 *pSlotIndex); + + COM_METHOD GetArgumentIndex(ULONG32* pArgumentIndex); + + COM_METHOD GetLiveRange(ULONG32* pStartOffset, + ULONG32 *pEndOffset); + + COM_METHOD GetLocationType(VariableLocationType *pLocationType); + + COM_METHOD GetRegister(CorDebugRegister *pRegister); + + COM_METHOD GetOffset(LONG *pOffset); +private: + RSSmartPtr<CordbNativeCode> m_pCode; + ICorDebugInfo::NativeVarInfo m_nativeVarInfo; + BOOL m_isLocal; + ULONG m_index; +}; + + // for an inheritance graph of the ICDValue types, // See file:./ICorDebugValueTypes.vsd for a diagram of the types. /* ------------------------------------------------------------------------- * * Value class diff --git a/src/debug/di/rspriv.inl b/src/debug/di/rspriv.inl index 00e4c233b6..5de99c6284 100644 --- a/src/debug/di/rspriv.inl +++ b/src/debug/di/rspriv.inl @@ -162,7 +162,7 @@ void CordbProcess::ForceDacFlush() { if (m_pDacPrimitives != NULL) { - STRESS_LOG1(LF_CORDB, LL_INFO1000, "Flush() - old counter: %d", m_flushCounter); + STRESS_LOG1(LF_CORDB, LL_INFO1000, "Flush() - old counter: %d\n", m_flushCounter); m_flushCounter++; HRESULT hr = S_OK; EX_TRY diff --git a/src/debug/di/rsthread.cpp b/src/debug/di/rsthread.cpp index ae9b43cd01..a4660be570 100644 --- a/src/debug/di/rsthread.cpp +++ b/src/debug/di/rsthread.cpp @@ -1493,7 +1493,7 @@ void CordbThread::Get32bitFPRegisters(CONTEXT * pContext) for (i = 0; i <= floatStackTop; i++) { - long double td; + double td = 0.0; __asm fstp td // copy out the double m_floatValues[i] = td; } @@ -4585,7 +4585,7 @@ void CordbUnmanagedThread::SaveRaiseExceptionEntryContext() LOG((LF_CORDB, LL_INFO1000, "CP::SREEC: failed to read exception information pointer.\n")); return; } -#elif +#else _ASSERTE(!"Implement this for your platform"); return; #endif @@ -8935,8 +8935,13 @@ HRESULT CordbJITILFrame::GetReturnValueForILOffsetImpl(ULONG32 ILoffset, ICorDeb bool found = false; ULONG32 currentOffset = m_nativeFrame->GetIPOffset(); for (ULONG32 i = 0; i < count; ++i) - if ((found = currentOffset == offsets[i])) + { + if (currentOffset == offsets[i]) + { + found = true; break; + } + } if (!found) return E_UNEXPECTED; diff --git a/src/debug/di/rstype.cpp b/src/debug/di/rstype.cpp index b183fdf39e..e537613412 100644 --- a/src/debug/di/rstype.cpp +++ b/src/debug/di/rstype.cpp @@ -276,6 +276,8 @@ HRESULT CordbType::QueryInterface(REFIID id, void **pInterface) { if (id == IID_ICorDebugType) *pInterface = static_cast<ICorDebugType*>(this); + else if (id == IID_ICorDebugType2) + *pInterface = static_cast<ICorDebugType2*>(this); else if (id == IID_IUnknown) *pInterface = static_cast<IUnknown*>(static_cast<ICorDebugType*>(this)); else @@ -2280,6 +2282,126 @@ HRESULT CordbType::GetBase(ICorDebugType ** ppType) return hr; } +//----------------------------------------------------------------------------- +// CordbType::GetTypeID +// Method to get the COR_TYPEID corresponding to this CordbType. +// +// Parameters: +// pId - OUT: gives the COR_TYPEID for this CordbType +// +// Returns: +// S_OK if succeeded. +// CORDBG_E_CLASS_NOT_LOADED if the type which this CordbType represents has +// not been loaded in the runtime. +// E_POINTER if pId is NULL +// CORDBG_E_UNSUPPORTED for unsupported types. +// +HRESULT CordbType::GetTypeID(COR_TYPEID *pId) +{ + LOG((LF_CORDB, LL_INFO1000, "GetTypeID\n")); + if (pId == NULL) + return E_POINTER; + + HRESULT hr = S_OK; + + PUBLIC_API_ENTRY(this); + RSLockHolder stopGoLock(GetProcess()->GetStopGoLock()); + RSLockHolder procLock(GetProcess()->GetProcessLock()); + + EX_TRY + { + hr = Init(FALSE); + IfFailThrow(hr); + + VMPTR_TypeHandle vmTypeHandle; + + CorElementType et = GetElementType(); + switch (et) + { + case ELEMENT_TYPE_OBJECT: + case ELEMENT_TYPE_VOID: + case ELEMENT_TYPE_BOOLEAN: + case ELEMENT_TYPE_CHAR: + case ELEMENT_TYPE_I1: + case ELEMENT_TYPE_U1: + case ELEMENT_TYPE_I2: + case ELEMENT_TYPE_U2: + case ELEMENT_TYPE_I4: + case ELEMENT_TYPE_U4: + case ELEMENT_TYPE_I8: + case ELEMENT_TYPE_U8: + case ELEMENT_TYPE_R4: + case ELEMENT_TYPE_R8: + case ELEMENT_TYPE_STRING: + case ELEMENT_TYPE_TYPEDBYREF: + case ELEMENT_TYPE_I: + case ELEMENT_TYPE_U: + { + mdTypeDef mdToken; + VMPTR_Module vmModule = VMPTR_Module::NullPtr(); + VMPTR_DomainFile vmDomainFile = VMPTR_DomainFile::NullPtr(); + + // get module and token of the simple type + GetProcess()->GetDAC()->GetSimpleType(GetAppDomain()->GetADToken(), + et, + &mdToken, + &vmModule, + &vmDomainFile); + + vmTypeHandle = GetProcess()->GetDAC()->GetTypeHandle(vmModule, mdToken); + } + break; + case ELEMENT_TYPE_ARRAY: + case ELEMENT_TYPE_SZARRAY: + { + LOG((LF_CORDB, LL_INFO1000, "GetTypeID: parameterized type\n")); + if (m_typeHandleExact.IsNull()) + { + hr = InitInstantiationTypeHandle(FALSE); + IfFailThrow(hr); + } + vmTypeHandle = m_typeHandleExact; + } + break; + case ELEMENT_TYPE_CLASS: + { + ICorDebugClass *pICDClass = NULL; + hr = GetClass(&pICDClass); + IfFailThrow(hr); + CordbClass *pClass = (CordbClass*)pICDClass; + _ASSERTE(pClass != NULL); + + if (pClass->HasTypeParams()) + { + vmTypeHandle = m_typeHandleExact; + } + else + { + mdTypeDef mdToken; + hr = pClass->GetToken(&mdToken); + IfFailThrow(hr); + + VMPTR_Module vmModule = GetModule(); + vmTypeHandle = GetProcess()->GetDAC()->GetTypeHandle(vmModule, mdToken); + } + } + break; + case ELEMENT_TYPE_PTR: + case ELEMENT_TYPE_BYREF: + case ELEMENT_TYPE_FNPTR: + IfFailThrow(CORDBG_E_UNSUPPORTED); + default: + _ASSERTE(!"unexpected element type!"); + IfFailThrow(CORDBG_E_UNSUPPORTED); + break; + } + + GetProcess()->GetDAC()->GetTypeIDForType(vmTypeHandle, pId); + } + EX_CATCH_HRESULT(hr); + + return hr; +} //----------------------------------------------------------------------------- // Get rich field information given a token. diff --git a/src/debug/ee/controller.cpp b/src/debug/ee/controller.cpp index 7f4d44568d..3a87fdf166 100644 --- a/src/debug/ee/controller.cpp +++ b/src/debug/ee/controller.cpp @@ -2824,6 +2824,8 @@ DPOSS_ACTION DebuggerController::DispatchPatchOrSingleStep(Thread *thread, CONTE CrstHolderWithState lockController(&g_criticalSection); + TADDR originalAddress = 0; + #ifdef EnC_SUPPORTED DebuggerControllerPatch *dcpEnCOriginal = NULL; @@ -2878,7 +2880,7 @@ DPOSS_ACTION DebuggerController::DispatchPatchOrSingleStep(Thread *thread, CONTE // If we setip, then that will change the address in the context. // Remeber the old address so that we can compare it to the context's ip and see if it changed. // If it did change, then don't dispatch our current event. - TADDR originalAddress = (TADDR) address; + originalAddress = (TADDR) address; #ifdef _DEBUG // If we do a SetIP after this point, the value of address will be garbage. Set it to a distictive pattern now, so @@ -4486,7 +4488,7 @@ void DebuggerPatchSkip::DebuggerDetachClean() // THIS FIX IS INCOMPLETE!It attempts to update the IP in the cases we can easily detect.However, // if a thread is in pre - emptive mode, and its filter context has been propagated to a VEH // context, then the filter context we get will be NULL and this fix will not work.Our belief is - // that this scenario is rare enough that it doesn’t justify the cost and risk associated with a + // that this scenario is rare enough that it doesnt justify the cost and risk associated with a // complete fix, in which we would have to either : // 1. Change the reference counting for DebuggerController and then change the exception handling // logic in the debuggee so that we can handle the debugger event after detach. diff --git a/src/debug/ee/controller.h b/src/debug/ee/controller.h index 6611e044e5..a314874b8d 100644 --- a/src/debug/ee/controller.h +++ b/src/debug/ee/controller.h @@ -227,23 +227,23 @@ public: LONG AddRef() { - InterlockedIncrement(&m_refCount); - _ASSERTE(m_refCount > 0); - return m_refCount; + LONG newRefCount = InterlockedIncrement(&m_refCount); + _ASSERTE(newRefCount > 0); + return newRefCount; } LONG Release() { - LONG result = InterlockedDecrement(&m_refCount); - _ASSERTE(m_refCount >= 0); + LONG newRefCount = InterlockedDecrement(&m_refCount); + _ASSERTE(newRefCount >= 0); - if (m_refCount == 0) + if (newRefCount == 0) { TRACE_FREE(this); DeleteInteropSafeExecutable(this); } - return result; + return newRefCount; } // "PatchBypass" must be the first field of this class for alignment to be correct. diff --git a/src/debug/ee/debugger.cpp b/src/debug/ee/debugger.cpp index a06811c817..2aed8bd820 100644 --- a/src/debug/ee/debugger.cpp +++ b/src/debug/ee/debugger.cpp @@ -75,6 +75,9 @@ SVAL_IMPL_INIT(BOOL, Debugger, s_fCanChangeNgenFlags, TRUE); bool g_EnableSIS = false; +// The following instances are used for invoking overloaded new/delete +InteropSafe interopsafe; +InteropSafeExecutable interopsafeEXEC; #ifndef DACCESS_COMPILE @@ -594,8 +597,8 @@ void DoAssertOnType(DebuggerIPCEventType event, int count) if (g_iDbgRuntimeCounter[event & 0x00ff] == count) { char tmpStr[256]; - sprintf(tmpStr, "%s == %d, break now!", - IPCENames::GetName(event), count); + _snprintf_s(tmpStr, _countof(tmpStr), _TRUNCATE, "%s == %d, break now!", + IPCENames::GetName(event), count); // fire the assertion DbgAssertDialog(__FILE__, __LINE__, tmpStr); @@ -608,8 +611,8 @@ void DoAssertOnType(DebuggerIPCEventType event, int count) if (g_iDbgDebuggerCounter[event & 0x00ff] == count) { char tmpStr[256]; - sprintf(tmpStr, "%s == %d, break now!", - IPCENames::GetName(event), count); + _snprintf_s(tmpStr, _countof(tmpStr), _TRUNCATE, "%s == %d, break now!", + IPCENames::GetName(event), count); // fire the assertion DbgAssertDialog(__FILE__, __LINE__, tmpStr); @@ -11907,7 +11910,7 @@ HRESULT Debugger::GetAndSendInterceptCommand(DebuggerIPCEvent *event) // // Save off this breakpoint, so that if the exception gets unwound before we hit - // the breakpoint - the exeception info can call back to remove it. + // the breakpoint - the exception info can call back to remove it. // pExState->GetDebuggerState()->SetDebuggerInterceptContext((void *)pBreakpoint); diff --git a/src/debug/ee/debugger.h b/src/debug/ee/debugger.h index 6368647946..9cdf546290 100644 --- a/src/debug/ee/debugger.h +++ b/src/debug/ee/debugger.h @@ -3512,10 +3512,10 @@ public: * ------------------------------------------------------------------------ */ class InteropSafe {}; -#define interopsafe (*(InteropSafe*)NULL) +extern InteropSafe interopsafe; class InteropSafeExecutable {}; -#define interopsafeEXEC (*(InteropSafeExecutable*)NULL) +extern InteropSafeExecutable interopsafeEXEC; #ifndef DACCESS_COMPILE inline void * __cdecl operator new(size_t n, const InteropSafe&) diff --git a/src/debug/ee/functioninfo.cpp b/src/debug/ee/functioninfo.cpp index 83c185cfc9..aa75b30407 100644 --- a/src/debug/ee/functioninfo.cpp +++ b/src/debug/ee/functioninfo.cpp @@ -890,7 +890,6 @@ DebuggerJitInfo::~DebuggerJitInfo() LOG((LF_CORDB,LL_EVERYTHING, "DJI::~DJI : deleted at 0x%p\n", this)); } - // Lazy initialize the Debugger-Jit-Info void DebuggerJitInfo::LazyInitBounds() { @@ -903,24 +902,22 @@ void DebuggerJitInfo::LazyInitBounds() PRECONDITION(!g_pDebugger->HasDebuggerDataLock()); } CONTRACTL_END; - //@todo: this method is not synchronized. Mei-chin's recent work should cover this one + LOG((LF_CORDB, LL_EVERYTHING, "DJI::LazyInitBounds: this=0x%x m_fAttemptInit %s\n", this, m_fAttemptInit == true ? "true": "false")); + // Only attempt lazy-init once - // new LOG message - LOG((LF_CORDB,LL_EVERYTHING, "DJI::LazyInitBounds: this=0x%x m_fAttemptInit %s\n", this, m_fAttemptInit == true? "true": "false")); if (m_fAttemptInit) { return; } - m_fAttemptInit = true; EX_TRY { - LOG((LF_CORDB,LL_EVERYTHING, "DJI::LazyInitBounds: this=0x%x Initing\n", this)); + LOG((LF_CORDB, LL_EVERYTHING, "DJI::LazyInitBounds: this=0x%x Initing\n", this)); + // Should have already been jitted _ASSERTE(this->m_jitComplete); MethodDesc * mdesc = this->m_fd; - DebugInfoRequest request; _ASSERTE(this->m_addrOfCode != NULL); // must have address to disambguate the Enc cases. @@ -928,7 +925,6 @@ void DebuggerJitInfo::LazyInitBounds() // Note the MethodDesc may not yet have the jitted info, so we'll also use the starting address we got in the jit complete callback. request.InitFromStartingAddr(mdesc, (PCODE)this->m_addrOfCode); - // Bounds info. ULONG32 cMap = 0; ICorDebugInfo::OffsetMapping *pMap = NULL; @@ -940,12 +936,26 @@ void DebuggerJitInfo::LazyInitBounds() InteropSafeNew, NULL, // allocator &cMap, &pMap, &cVars, &pVars); + LOG((LF_CORDB,LL_EVERYTHING, "DJI::LazyInitBounds: this=0x%x GetBoundariesAndVars success=0x%x\n", this, fSuccess)); - if (fSuccess) + + Debugger::DebuggerDataLockHolder debuggerDataLockHolder(g_pDebugger); + + if (!m_fAttemptInit) { - this->SetBoundaries(cMap, pMap); - this->SetVars(cVars, pVars); + if (fSuccess) + { + this->SetBoundaries(cMap, pMap); + this->SetVars(cVars, pVars); + } + m_fAttemptInit = true; } + else + { + DeleteInteropSafe(pMap); + DeleteInteropSafe(pVars); + } + // DebuggerDataLockHolder out of scope - release implied } EX_CATCH { @@ -963,10 +973,7 @@ void DebuggerJitInfo::SetVars(ULONG32 cVars, ICorDebugInfo::NativeVarInfo *pVars { LIMITED_METHOD_CONTRACT; - if (m_varNativeInfo) - { - return; - } + _ASSERTE(m_varNativeInfo == NULL); m_varNativeInfo = pVars; m_varNativeInfoCount = cVars; @@ -1020,15 +1027,11 @@ void DebuggerJitInfo::SetBoundaries(ULONG32 cMap, ICorDebugInfo::OffsetMapping * LOG((LF_CORDB,LL_EVERYTHING, "DJI::SetBoundaries: this=0x%x cMap=0x%x pMap=0x%x\n", this, cMap, pMap)); _ASSERTE((cMap == 0) == (pMap == NULL)); + _ASSERTE(m_sequenceMap == NULL); if (cMap == 0) return; - if (m_sequenceMap) - { - return; - } - ULONG ilLast = 0; #ifdef _DEBUG // We assume that the map is sorted by native offset diff --git a/src/debug/ee/i386/dbghelpers.S b/src/debug/ee/i386/dbghelpers.S new file mode 100644 index 0000000000..d0a11011ca --- /dev/null +++ b/src/debug/ee/i386/dbghelpers.S @@ -0,0 +1,70 @@ +// 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. + +.intel_syntax noprefix +#include "unixasmmacros.inc" + +//extern FuncEvalHijackWorker:proc + +// @dbgtodo- once we port Funceval, use the ExceptionHijack stub instead of this func-eval stub. +NESTED_ENTRY FuncEvalHijack, _TEXT, UnhandledExceptionHandlerUnix + push eax // the ptr to the DebuggerEval + call C_FUNC(FuncEvalHijackWorker) + jmp eax // return is the patch addresss to jmp to + +NESTED_END FuncEvalHijack, _TEXT + +// +// Flares for interop debugging. +// Flares are exceptions (breakpoints) at well known addresses which the RS +// listens for when interop debugging. +// + +// This exception is from managed code. +LEAF_ENTRY SignalHijackStartedFlare, _TEXT + int 3 + // make sure that the basic block is unique + test eax,1 + ret +LEAF_END SignalHijackStartedFlare, _TEXT + +// Start the handoff +LEAF_ENTRY ExceptionForRuntimeHandoffStartFlare, _TEXT + int 3 + // make sure that the basic block is unique + test eax,2 + ret +LEAF_END ExceptionForRuntimeHandoffStartFlare, _TEXT + +// Finish the handoff. +LEAF_ENTRY ExceptionForRuntimeHandoffCompleteFlare, _TEXT + int 3 + // make sure that the basic block is unique + test eax,3 + ret +LEAF_END ExceptionForRuntimeHandoffCompleteFlare, _TEXT + +// Signal execution return to unhijacked state +LEAF_ENTRY SignalHijackCompleteFlare, _TEXT + int 3 + // make sure that the basic block is unique + test eax,4 + ret +LEAF_END SignalHijackCompleteFlare, _TEXT + +// This exception is from unmanaged code. +LEAF_ENTRY ExceptionNotForRuntimeFlare, _TEXT + int 3 + // make sure that the basic block is unique + test eax,5 + ret +LEAF_END ExceptionNotForRuntimeFlare, _TEXT + +// The Runtime is synchronized. +LEAF_ENTRY NotifyRightSideOfSyncCompleteFlare, _TEXT + int 3 + // make sure that the basic block is unique + test eax,6 + ret +LEAF_END NotifyRightSideOfSyncCompleteFlare, _TEXT diff --git a/src/debug/ee/wks/CMakeLists.txt b/src/debug/ee/wks/CMakeLists.txt index a096cbfca7..2b1aff57a1 100644 --- a/src/debug/ee/wks/CMakeLists.txt +++ b/src/debug/ee/wks/CMakeLists.txt @@ -55,9 +55,7 @@ else () add_compile_options(-fPIC) -if(CLR_CMAKE_PLATFORM_ARCH_AMD64) - add_library_clr(cordbee_wks ${CORDBEE_SOURCES_WKS} ../${ARCH_SOURCES_DIR}/dbghelpers.S) -elseif(CLR_CMAKE_PLATFORM_ARCH_ARM) +if(CLR_CMAKE_PLATFORM_ARCH_AMD64 OR CLR_CMAKE_PLATFORM_ARCH_ARM OR CLR_CMAKE_PLATFORM_ARCH_I386) add_library_clr(cordbee_wks ${CORDBEE_SOURCES_WKS} ../${ARCH_SOURCES_DIR}/dbghelpers.S) elseif(CLR_CMAKE_PLATFORM_ARCH_ARM64) add_library_clr(cordbee_wks ${CORDBEE_SOURCES_WKS}) diff --git a/src/debug/ildbsymlib/symwrite.h b/src/debug/ildbsymlib/symwrite.h index 055b8ec21f..54ab11a9a2 100644 --- a/src/debug/ildbsymlib/symwrite.h +++ b/src/debug/ildbsymlib/symwrite.h @@ -839,7 +839,8 @@ public: { // Help mitigate the impact of buffer overflow // Fail fast with a null-reference AV - return *(static_cast<T*>(0)) ; + volatile char* nullPointer = nullptr; + *nullPointer; } return m_array[ i ]; } diff --git a/src/debug/inc/common.h b/src/debug/inc/common.h index 77fe27a4b3..3bbf0a6f08 100644 --- a/src/debug/inc/common.h +++ b/src/debug/inc/common.h @@ -295,29 +295,7 @@ inline CORDB_ADDRESS ALIGN_ADDRESS( CORDB_ADDRESS val, CORDB_ADDRESS alignment ) return result; } -// -// Whenever a structure is marshalled between different platforms, we need to ensure the -// layout is the same in both cases. We tell GCC to use the MSVC-style packing with -// the following attribute. The main thing this appears to control is whether -// 8-byte values are aligned at 4-bytes (GCC default) or 8-bytes (MSVC default). -// This attribute affects only the immediate struct it is applied to, you must also apply -// it to any nested structs if you want their layout affected as well. You also must -// apply this to unions embedded in other structures, since it can influence the starting -// alignment. -// -// Note that there doesn't appear to be any disadvantage to applying this a little -// more agressively than necessary, so we generally use it on all classes / structures -// defined in a file that defines marshalled data types (eg. DacDbiStructures.h) -// The -mms-bitfields compiler option also does this for the whole file, but we don't -// want to go changing the layout of, for example, structures defined in OS header files -// so we explicitly opt-in with this attribute. -// -#ifdef __GNUC__ -#define MSLAYOUT __attribute__((__ms_struct__)) -#else -#define MSLAYOUT -#endif - +#include "dacprivate.h" // for MSLAYOUT #include "dumpcommon.h" #endif //DEBUGGER_COMMON_H diff --git a/src/debug/inc/dacdbiinterface.h b/src/debug/inc/dacdbiinterface.h index fe58724fc5..569ccbaca7 100644 --- a/src/debug/inc/dacdbiinterface.h +++ b/src/debug/inc/dacdbiinterface.h @@ -32,7 +32,7 @@ template<class T> void DeleteDbiMemory(T *p); // Need a class to serve as a tag that we can use to overload New/Delete. class forDbiWorker {}; -#define forDbi (*(forDbiWorker *)NULL) +extern forDbiWorker forDbi; extern void * operator new(size_t lenBytes, const forDbiWorker &); extern void * operator new[](size_t lenBytes, const forDbiWorker &); extern void operator delete(void *p, const forDbiWorker &); @@ -2508,17 +2508,20 @@ public: virtual HRESULT GetTypeID(CORDB_ADDRESS obj, COR_TYPEID * pType) = 0; - virtual - HRESULT GetObjectFields(COR_TYPEID id, ULONG32 celt, OUT COR_FIELD * layout, OUT ULONG32 * pceltFetched) = 0; - - virtual - HRESULT GetTypeLayout(COR_TYPEID id, COR_TYPE_LAYOUT * pLayout) = 0; - - virtual - HRESULT GetArrayLayout(COR_TYPEID id, COR_ARRAY_LAYOUT * pLayout) = 0; - - virtual - void GetGCHeapInformation(OUT COR_HEAPINFO * pHeapInfo) = 0; + virtual + HRESULT GetTypeIDForType(VMPTR_TypeHandle vmTypeHandle, COR_TYPEID *pId) = 0; + + virtual + HRESULT GetObjectFields(COR_TYPEID id, ULONG32 celt, OUT COR_FIELD * layout, OUT ULONG32 * pceltFetched) = 0; + + virtual + HRESULT GetTypeLayout(COR_TYPEID id, COR_TYPE_LAYOUT * pLayout) = 0; + + virtual + HRESULT GetArrayLayout(COR_TYPEID id, COR_ARRAY_LAYOUT * pLayout) = 0; + + virtual + void GetGCHeapInformation(OUT COR_HEAPINFO * pHeapInfo) = 0; // If a PEFile has an RW capable IMDInternalImport, this returns the address of the MDInternalRW // object which implements it. diff --git a/src/debug/shared/dbgtransportsession.cpp b/src/debug/shared/dbgtransportsession.cpp index 14b509aa9c..95fdf25457 100644 --- a/src/debug/shared/dbgtransportsession.cpp +++ b/src/debug/shared/dbgtransportsession.cpp @@ -1140,33 +1140,6 @@ DbgTransportSession::Message * DbgTransportSession::RemoveMessageFromSendQueue(D #ifndef RIGHT_SIDE_COMPILE -#ifdef FEATURE_PAL -__attribute__((noinline)) -__attribute__((optnone)) -static void -ProbeMemory(__in_ecount(cbBuffer) volatile PBYTE pbBuffer, DWORD cbBuffer, bool fWriteAccess) -{ - // Need an throw in this function to fool the C++ runtime into handling the - // possible h/w exception below. - if (pbBuffer == NULL) - { - throw PAL_SEHException(); - } - - // Simple one byte at a time probing - while (cbBuffer > 0) - { - volatile BYTE read = *pbBuffer; - if (fWriteAccess) - { - *pbBuffer = read; - } - ++pbBuffer; - --cbBuffer; - } -} -#endif // FEATURE_PAL - // Check read and optionally write memory access to the specified range of bytes. Used to check // ReadProcessMemory and WriteProcessMemory requests. HRESULT DbgTransportSession::CheckBufferAccess(__in_ecount(cbBuffer) PBYTE pbBuffer, DWORD cbBuffer, bool fWriteAccess) @@ -1220,14 +1193,7 @@ HRESULT DbgTransportSession::CheckBufferAccess(__in_ecount(cbBuffer) PBYTE pbBuf } while (cbBuffer > 0); #else - try - { - // Need to explicit h/w exception holder so to catch them in ProbeMemory - CatchHardwareExceptionHolder __catchHardwareException; - - ProbeMemory(pbBuffer, cbBuffer, fWriteAccess); - } - catch(...) + if (!PAL_ProbeMemory(pbBuffer, cbBuffer, fWriteAccess)) { return HRESULT_FROM_WIN32(ERROR_INVALID_ADDRESS); } |