summaryrefslogtreecommitdiff
path: root/src/debug
diff options
context:
space:
mode:
Diffstat (limited to 'src/debug')
-rw-r--r--src/debug/daccess/daccess.cpp18
-rw-r--r--src/debug/daccess/daccess.targets6
-rw-r--r--src/debug/daccess/dacdbiimpl.cpp35
-rw-r--r--src/debug/daccess/dacdbiimpl.h10
-rw-r--r--src/debug/daccess/dacfn.cpp4
-rw-r--r--src/debug/daccess/enummem.cpp11
-rw-r--r--src/debug/daccess/fntableaccess.cpp5
-rw-r--r--src/debug/daccess/fntableaccess.h3
-rw-r--r--src/debug/daccess/nidump.cpp21
-rw-r--r--src/debug/daccess/request.cpp78
-rw-r--r--src/debug/daccess/request_svr.cpp4
-rw-r--r--src/debug/di/breakpoint.cpp2
-rw-r--r--src/debug/di/module.cpp377
-rw-r--r--src/debug/di/process.cpp14
-rw-r--r--src/debug/di/rsenumerator.hpp6
-rw-r--r--src/debug/di/rsmain.cpp2
-rw-r--r--src/debug/di/rspriv.h86
-rw-r--r--src/debug/di/rspriv.inl2
-rw-r--r--src/debug/di/rsthread.cpp11
-rw-r--r--src/debug/di/rstype.cpp122
-rw-r--r--src/debug/ee/controller.cpp6
-rw-r--r--src/debug/ee/controller.h14
-rw-r--r--src/debug/ee/debugger.cpp13
-rw-r--r--src/debug/ee/debugger.h4
-rw-r--r--src/debug/ee/functioninfo.cpp43
-rw-r--r--src/debug/ee/i386/dbghelpers.S70
-rw-r--r--src/debug/ee/wks/CMakeLists.txt4
-rw-r--r--src/debug/ildbsymlib/symwrite.h3
-rw-r--r--src/debug/inc/common.h24
-rw-r--r--src/debug/inc/dacdbiinterface.h27
-rw-r--r--src/debug/shared/dbgtransportsession.cpp36
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)&param, 0,
&handleType, 1,
- mGenerationFilter, GCHeap::GetMaxGeneration(), 0);
+ mGenerationFilter, GCHeapUtilities::GetMaxGeneration(), 0);
else
HndEnumHandles(hTable, &handleType, 1, callback, (LPARAM)&param, 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);
}