Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions src/coreclr/debug/daccess/dacdbiimpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6861,11 +6861,11 @@ HRESULT STDMETHODCALLTYPE DacDbiInterfaceImpl::IsValidObject(CORDB_ADDRESS obj,
return hr;
}

HRESULT STDMETHODCALLTYPE DacDbiInterfaceImpl::CreateRefWalk(OUT RefWalkHandle * pHandle, BOOL walkStacks, BOOL walkFQ, UINT32 handleWalkMask)
HRESULT STDMETHODCALLTYPE DacDbiInterfaceImpl::CreateRefWalk(OUT RefWalkHandle * pHandle, BOOL walkStacks, UINT32 handleWalkMask)
{
DD_ENTER_MAY_THROW;

DacRefWalker *walker = new (nothrow) DacRefWalker(this, walkStacks, walkFQ, handleWalkMask, TRUE);
DacRefWalker *walker = new (nothrow) DacRefWalker(this, walkStacks, handleWalkMask, TRUE);

if (walker == NULL)
return E_OUTOFMEMORY;
Expand Down Expand Up @@ -7506,8 +7506,8 @@ HRESULT STDMETHODCALLTYPE DacDbiInterfaceImpl::GetGenericArgTokenIndex(VMPTR_Met
return S_OK;
}

DacRefWalker::DacRefWalker(ClrDataAccess *dac, BOOL walkStacks, BOOL walkFQ, UINT32 handleMask, BOOL resolvePointers)
: mDac(dac), mWalkStacks(walkStacks), mWalkFQ(walkFQ), mHandleMask(handleMask), mStackWalker(NULL),
DacRefWalker::DacRefWalker(ClrDataAccess *dac, BOOL walkStacks, UINT32 handleMask, BOOL resolvePointers)
: mDac(dac), mWalkStacks(walkStacks), mHandleMask(handleMask), mStackWalker(NULL),
mResolvePointers(resolvePointers), mHandleWalker(NULL), mFQStart(PTR_NULL), mFQEnd(PTR_NULL), mFQCurr(PTR_NULL)
{
}
Expand Down
6 changes: 3 additions & 3 deletions src/coreclr/debug/daccess/dacdbiimpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ class DacDbiInterfaceImpl :

HRESULT STDMETHODCALLTYPE IsValidObject(CORDB_ADDRESS obj, OUT BOOL * pResult);

HRESULT STDMETHODCALLTYPE CreateRefWalk(RefWalkHandle * pHandle, BOOL walkStacks, BOOL walkFQ, UINT32 handleWalkMask);
HRESULT STDMETHODCALLTYPE CreateRefWalk(RefWalkHandle * pHandle, BOOL walkStacks, UINT32 handleWalkMask);
HRESULT STDMETHODCALLTYPE DeleteRefWalk(RefWalkHandle handle);
HRESULT STDMETHODCALLTYPE WalkRefs(RefWalkHandle handle, ULONG count, OUT DacGcReference * objects, OUT ULONG *pFetched);

Expand Down Expand Up @@ -964,7 +964,7 @@ class DDHolder
class DacRefWalker
{
public:
DacRefWalker(ClrDataAccess *dac, BOOL walkStacks, BOOL walkFQ, UINT32 handleMask, BOOL resolvePointers);
DacRefWalker(ClrDataAccess *dac, BOOL walkStacks, UINT32 handleMask, BOOL resolvePointers);
~DacRefWalker();

HRESULT Init();
Expand All @@ -977,7 +977,7 @@ class DacRefWalker

private:
ClrDataAccess *mDac;
BOOL mWalkStacks, mWalkFQ;
BOOL mWalkStacks;
UINT32 mHandleMask;

// Stacks
Expand Down
6 changes: 3 additions & 3 deletions src/coreclr/debug/di/process.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2552,13 +2552,13 @@ HRESULT CordbProcess::GetTypeForObject(CORDB_ADDRESS addr, CordbType **ppType, C
// CordbRefEnum
// ******************************************
CordbRefEnum::CordbRefEnum(CordbProcess *proc, BOOL walkWeakRefs)
: CordbBase(proc, 0, enumCordbHeap), mRefHandle(0), mEnumStacksFQ(TRUE),
: CordbBase(proc, 0, enumCordbHeap), mRefHandle(0), mEnumStacks(TRUE),
mHandleMask((UINT32)(walkWeakRefs ? CorHandleAll : CorHandleStrongOnly))
{
}

CordbRefEnum::CordbRefEnum(CordbProcess *proc, CorGCReferenceType types)
: CordbBase(proc, 0, enumCordbHeap), mRefHandle(0), mEnumStacksFQ(FALSE),
: CordbBase(proc, 0, enumCordbHeap), mRefHandle(0), mEnumStacks(FALSE),
mHandleMask((UINT32)types)
{
}
Expand Down Expand Up @@ -2657,7 +2657,7 @@ HRESULT CordbRefEnum::Next(ULONG celt, COR_GC_REFERENCE refs[], ULONG *pceltFetc
EX_TRY
{
if (!mRefHandle)
hr = process->GetDAC()->CreateRefWalk(&mRefHandle, mEnumStacksFQ, mEnumStacksFQ, mHandleMask);
hr = process->GetDAC()->CreateRefWalk(&mRefHandle, mEnumStacks, mHandleMask);

if (SUCCEEDED(hr))
{
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/debug/di/rspriv.h
Original file line number Diff line number Diff line change
Expand Up @@ -10618,7 +10618,7 @@ class CordbRefEnum : public CordbBase, public ICorDebugGCReferenceEnum

private:
RefWalkHandle mRefHandle;
BOOL mEnumStacksFQ;
BOOL mEnumStacks;
UINT32 mHandleMask;
};

Expand Down
3 changes: 1 addition & 2 deletions src/coreclr/debug/inc/dacdbiinterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -2012,13 +2012,12 @@ IDacDbiInterface : public IUnknown
// Parameters:
// pHandle - out - the reference walk handle to create
// walkStacks - in - whether or not to report stack references
// walkFQ - in - whether or not to report references from the finalizer queue
// handleWalkMask - in - the types of handles report (see CorGCReferenceType, cordebug.idl)
// Returns:
// An HRESULT indicating whether it succeeded or failed.
// Exceptions:
// Returns an HRESULT indicating success or failure.
virtual HRESULT STDMETHODCALLTYPE CreateRefWalk(OUT RefWalkHandle * pHandle, BOOL walkStacks, BOOL walkFQ, UINT32 handleWalkMask) = 0;
virtual HRESULT STDMETHODCALLTYPE CreateRefWalk(OUT RefWalkHandle * pHandle, BOOL walkStacks, UINT32 handleWalkMask) = 0;

// Deletes a reference walk.
// Parameters:
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/inc/dacdbi.idl
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ interface IDacDbiInterface : IUnknown
HRESULT IsValidObject([in] CORDB_ADDRESS obj, [out] BOOL * pResult);

// Reference Walking
HRESULT CreateRefWalk([out] RefWalkHandle * pHandle, [in] BOOL walkStacks, [in] BOOL walkFQ, [in] UINT32 handleWalkMask);
HRESULT CreateRefWalk([out] RefWalkHandle * pHandle, [in] BOOL walkStacks, [in] UINT32 handleWalkMask);
HRESULT DeleteRefWalk([in] RefWalkHandle handle);
HRESULT WalkRefs([in] RefWalkHandle handle, [in] ULONG count, [out] struct DacGcReference * refs, [out] ULONG * pFetched);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public enum StackWalkState
public class StackReferenceData
{
public bool HasRegisterInformation { get; init; }
public bool IsInteriorPointer { get; init; }
public int Register { get; init; }
Comment on lines 37 to 41
public int Offset { get; init; }
public TargetPointer Address { get; init; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public void RecordDeferredFrame(TargetPointer frameAddress)
StackRefs.Add(new StackRefData
{
HasRegisterInformation = false,
IsInteriorPointer = false,
Register = 0,
Offset = 0,
Address = 0,
Expand Down Expand Up @@ -71,6 +72,7 @@ public void GCEnumCallback(TargetPointer pObject, GcScanFlags flags, GcScanSlotL
StackRefData data = new()
{
HasRegisterInformation = true,
IsInteriorPointer = flags.HasFlag(GcScanFlags.GC_CALL_INTERIOR),
Register = loc.Reg,
Offset = loc.RegOffset,
Address = addr,
Expand Down Expand Up @@ -109,6 +111,7 @@ public void GCReportCallback(TargetPointer ppObj, GcScanFlags flags)
StackRefData data = new()
{
HasRegisterInformation = false,
IsInteriorPointer = flags.HasFlag(GcScanFlags.GC_CALL_INTERIOR),
Register = 0,
Offset = 0,
Address = ppObj,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public enum SourceTypes
}

public bool HasRegisterInformation { get; set; }
public bool IsInteriorPointer { get; set; }
public int Register { get; set; }
public int Offset { get; set; }
public TargetPointer Address { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,7 @@ IReadOnlyList<StackReferenceData> IStackWalk.WalkStackReferences(ThreadData thre
return scanContext.StackRefs.Select(r => new StackReferenceData
{
HasRegisterInformation = r.HasRegisterInformation,
IsInteriorPointer = r.IsInteriorPointer,
Register = r.Register,
Offset = r.Offset,
Address = r.Address,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3531,14 +3531,150 @@ public int IsValidObject(ulong obj, Interop.BOOL* pResult)
return hr;
}

public int CreateRefWalk(nuint* pHandle, Interop.BOOL walkStacks, Interop.BOOL walkFQ, uint handleWalkMask)
=> LegacyFallbackHelper.CanFallback() && _legacy is not null ? _legacy.CreateRefWalk(pHandle, walkStacks, walkFQ, handleWalkMask) : HResults.E_NOTIMPL;
public int CreateRefWalk(nuint* pHandle, Interop.BOOL walkStacks, CorGCReferenceType handleWalkMask)
{
int hr = HResults.S_OK;
RefWalk? walk = null;
try
{
if (pHandle is null)
throw new NullReferenceException(nameof(pHandle));
walk = new RefWalk(_target, walkStacks != Interop.BOOL.FALSE, handleWalkMask);
*pHandle = (nuint)((IEnum<DacGcReference>)walk).GetHandle();
Comment on lines +3540 to +3543
}
Comment thread
rcj1 marked this conversation as resolved.
catch (System.Exception ex)
{
hr = ex.HResult;
}
Comment on lines +3536 to +3548
#if DEBUG
if (_legacy is not null)
{
nuint legacyHandle = 0;
int hrLocal = _legacy.CreateRefWalk(&legacyHandle, walkStacks, handleWalkMask);
Debug.ValidateHResult(hr, hrLocal);
if (hrLocal == HResults.S_OK && walk is not null)
walk.LegacyHandle = legacyHandle;
else if (hrLocal == HResults.S_OK)
_legacy.DeleteRefWalk(legacyHandle);
}
#endif
return hr;
}

public int DeleteRefWalk(nuint handle)
=> LegacyFallbackHelper.CanFallback() && _legacy is not null ? _legacy.DeleteRefWalk(handle) : HResults.E_NOTIMPL;
{
if (handle == 0)
return HResults.S_OK;

int hr = HResults.S_OK;
nuint legacyHandle = 0;
try
{
GCHandle gcHandle = GCHandle.FromIntPtr((nint)handle);
if (gcHandle.Target is not RefWalk walk)
throw new ArgumentException("Handle does not reference a valid RefWalk instance.", nameof(handle));
legacyHandle = walk.LegacyHandle;
((IEnum<DacGcReference>)walk).Dispose();
gcHandle.Free();
}
catch (System.Exception ex)
{
hr = ex.HResult;
}
#if DEBUG
if (_legacy is not null && legacyHandle != 0)
{
int hrLocal = _legacy.DeleteRefWalk(legacyHandle);
Debug.ValidateHResult(hr, hrLocal);
}
#endif
return hr;
}

public int WalkRefs(nuint handle, uint count, nint refs, uint* pFetched)
=> LegacyFallbackHelper.CanFallback() && _legacy is not null ? _legacy.WalkRefs(handle, count, refs, pFetched) : HResults.E_NOTIMPL;
// Should be called repeatedly until it returns S_FALSE.
public int WalkRefs(nuint handle, uint count, [In, MarshalUsing(CountElementName = "count"), Out] DacGcReference[] refs, uint* pFetched)
{
RefWalk walk;
try
{
if (pFetched is null)
throw new NullReferenceException(nameof(pFetched));
if (handle == 0)
throw new ArgumentException("Handle is invalid.", nameof(handle));
GCHandle gcHandle = GCHandle.FromIntPtr((nint)handle);
if (gcHandle.Target is not RefWalk rw)
throw new ArgumentException("Handle does not reference a valid RefWalk instance.", nameof(handle));
walk = rw;
*pFetched = 0;
Comment on lines +3600 to +3608
}
catch (System.Exception ex)
{
return ex.HResult;
}
Comment on lines +3594 to +3613

int hr = HResults.S_OK;
uint i = 0;
try
{
while (i < count && walk.Enumerator.MoveNext())
refs[i++] = walk.Enumerator.Current;

// A clean batch reports S_FALSE iff we couldn't fill the caller's request.
if (i < count)
hr = HResults.S_FALSE;
}
catch (System.Exception ex)
{
hr = ex.HResult;
}

*pFetched = i;

#if DEBUG
if (_legacy is not null && walk.LegacyHandle != 0 && count > 0)
{
// Parity check covers the handle prefix only.
DacGcReference[] legacyRefs = new DacGcReference[(int)count];
uint legacyFetched = 0;
int hrLocal = _legacy.WalkRefs(walk.LegacyHandle, count, legacyRefs, &legacyFetched);
Debug.ValidateHResult(hr, hrLocal);

uint cdacHandlePrefix = CountHandlePrefix(refs, i);
uint legacyHandlePrefix = CountHandlePrefix(legacyRefs, legacyFetched);
Debug.Assert(
cdacHandlePrefix == legacyHandlePrefix,
$"cDAC handle-prefix count {cdacHandlePrefix}, legacy {legacyHandlePrefix}");

uint compare = Math.Min(cdacHandlePrefix, legacyHandlePrefix);
for (uint j = 0; j < compare; j++)
{
Debug.Assert(refs[j].dwType == legacyRefs[j].dwType,
$"refs[{j}].dwType cDAC={refs[j].dwType:X}, legacy={legacyRefs[j].dwType:X}");
Debug.Assert(refs[j].vmDomain == legacyRefs[j].vmDomain,
$"refs[{j}].vmDomain cDAC=0x{refs[j].vmDomain:X}, legacy=0x{legacyRefs[j].vmDomain:X}");
Debug.Assert(refs[j].objHnd == legacyRefs[j].objHnd,
$"refs[{j}].objHnd cDAC=0x{refs[j].objHnd:X}, legacy=0x{legacyRefs[j].objHnd:X}");
Debug.Assert(refs[j].i64ExtraData == legacyRefs[j].i64ExtraData,
$"refs[{j}].i64ExtraData cDAC=0x{refs[j].i64ExtraData:X}, legacy=0x{legacyRefs[j].i64ExtraData:X}");
}
}

static uint CountHandlePrefix(DacGcReference[] buffer, uint length)
{
for (uint j = 0; j < length; j++)
{
CorGCReferenceType dwType = buffer[j].dwType;
if (dwType == CorGCReferenceType.CorReferenceStack)
{
return j;
}
}
return length;
}
#endif

return hr;
}

public int GetTypeID(ulong obj, COR_TYPEID* pType)
{
Expand Down
Loading
Loading