Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Various fixes #390

Merged
merged 6 commits into from
Dec 8, 2019
Merged
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
6 changes: 1 addition & 5 deletions src/Microsoft.Diagnostics.Runtime.Tests/src/Helpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -106,11 +106,7 @@ public static ClrStackFrame GetFrame(this ClrThread thread, string functionName)
public static string TestWorkingDirectory
{
get => _userSetWorkingPath ?? _workingPath.Value;
set
{
Debug.Assert(!_workingPath.IsValueCreated);
_userSetWorkingPath = value;
}
set => _userSetWorkingPath = value;
}

private static string _userSetWorkingPath;
Expand Down
4 changes: 2 additions & 2 deletions src/Microsoft.Diagnostics.Runtime.Utilities/GCRoot/GCRoot.cs
Original file line number Diff line number Diff line change
Expand Up @@ -344,8 +344,8 @@ Stack<ClrObject> GetRefs(
out LinkedListNode<ClrObject> end)
{
// These asserts slow debug down by a lot, but it's important to ensure consistency in retail.
//Debug.Assert(obj.Type != null);
//Debug.Assert(obj.Type == _heap.GetObjectType(obj.Address));
//DebugOnly.Assert(obj.Type != null);
//DebugOnly.Assert(obj.Type == _heap.GetObjectType(obj.Address));

Stack<ClrObject> result = null;

Expand Down
76 changes: 45 additions & 31 deletions src/Microsoft.Diagnostics.Runtime/src/Builders/RuntimeBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
using System;
using System.Buffers;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Reflection;
Expand Down Expand Up @@ -499,51 +498,66 @@ private IEnumerable<ClrHandle> EnumerateHandleTable(ClrRuntime runtime, HandleDa
{
CheckDisposed();

// TODO: Use smarter handle enum overload in _sos
Dictionary<ulong, ClrAppDomain> domains = new Dictionary<ulong, ClrAppDomain>();
if (runtime.SharedDomain != null)
domains[runtime.SharedDomain.Address] = runtime.SharedDomain;

if (runtime.SystemDomain != null)
domains[runtime.SystemDomain.Address] = runtime.SystemDomain;

foreach (ClrAppDomain domain in runtime.AppDomains)
{
// Don't use .ToDictionary in case we have bad data
domains[domain.Address] = domain;
}

using SOSHandleEnum? handleEnum = _sos.EnumerateHandles();
if (handleEnum is null)
yield break;

ClrHeap heap = runtime.Heap;
ClrAppDomain? domain = heap.Runtime.AppDomains.Count > 0 ? heap.Runtime.AppDomains[0] : null;

int fetched;
while ((fetched = handleEnum.ReadHandles(handles)) != 0)
{
for (int i = 0; i < fetched; i++)
{
ulong obj = DataReader.ReadPointerUnsafe(handles[i].Handle);
ulong mt = 0;
if (obj != 0)
mt = DataReader.ReadPointerUnsafe(obj);
ulong objAddress = DataReader.ReadPointerUnsafe(handles[i].Handle);
ClrObject clrObj = heap.GetObject(objAddress);

if (mt != 0)
if (!clrObj.IsNull)
{
ClrType? type = GetOrCreateType(mt, obj);
ClrType? dependent = null;
if (handles[i].Type == (int)ClrHandleKind.Dependent && handles[i].Secondary != 0)
if (domain == null || domain.Address != handles[i].AppDomain)
domain = GetOrCreateAppDomain(null, handles[i].AppDomain);

ClrHandleKind handleKind = (ClrHandleKind)handles[i].Type;
switch (handleKind)
{
ulong dmt = DataReader.ReadPointerUnsafe(handles[i].Secondary);
default:
yield return new ClrmdHandle(domain, handles[i].Handle, clrObj, handleKind);
break;

if (dmt != 0)
dependent = GetOrCreateType(dmt, handles[i].Secondary);
}
case ClrHandleKind.Dependent:
ClrObject dependent = heap.GetObject(handles[i].Secondary);
yield return new ClrmdDependentHandle(domain, handles[i].Handle, clrObj, dependent);
break;

domains.TryGetValue(handles[i].AppDomain, out ClrAppDomain domain);
case ClrHandleKind.RefCount:
uint refCount = 0;

if (handles[i].IsPegged != 0)
refCount = handles[i].JupiterRefCount;

if (refCount < handles[i].RefCount)
refCount = handles[i].RefCount;

if (!clrObj.IsNull)
{
ComCallWrapper? ccw = clrObj.Type?.GetCCWData(objAddress);
if (ccw != null && refCount < ccw.RefCount)
{
refCount = (uint)ccw.RefCount;
}
else
{
RuntimeCallableWrapper? rcw = clrObj.Type?.GetRCWData(objAddress);
if (rcw != null && refCount < rcw.RefCount)
refCount = (uint)rcw.RefCount;
}
}

yield return new ClrmdRefCountHandle(domain, handles[i].Handle, clrObj, refCount);
break;

ClrObject clrObj = type != null ? new ClrObject(obj, type) : default;
ClrHandle handle = new ClrHandle(in handles[i], clrObj, domain, dependent);
yield return handle;
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public ClrException(IExceptionHelpers helpers, ClrThread? thread, ClrObject obj)
_object = obj;
Thread = thread;

Debug.Assert(obj.IsException);
DebugOnly.Assert(obj.IsException);
}

/// <summary>
Expand Down
67 changes: 8 additions & 59 deletions src/Microsoft.Diagnostics.Runtime/src/Common/ClrHandle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,39 +9,39 @@ namespace Microsoft.Diagnostics.Runtime
/// <summary>
/// Represents a Clr handle in the target process.
/// </summary>
public sealed class ClrHandle : IClrRoot
public abstract class ClrHandle : IClrRoot
{
/// <summary>
/// The address of the handle itself. That is, *ulong == Object.
/// </summary>
public ulong Address { get; }
public abstract ulong Address { get; }

/// <summary>
/// The Object the handle roots.
/// </summary>
public ClrObject Object { get; }
public abstract ClrObject Object { get; }

/// <summary>
/// Gets the type of handle.
/// </summary>
public ClrHandleKind HandleKind { get; }
public abstract ClrHandleKind HandleKind { get; }

/// <summary>
/// If this handle is a RefCount handle, this returns the reference count.
/// RefCount handles with a RefCount > 0 are strong.
/// NOTE: v2 CLR CANNOT determine the RefCount. We always set the RefCount
/// to 1 in a v2 query since a strong RefCount handle is the common case.
/// </summary>
public uint RefCount { get; }
public abstract uint ReferenceCount { get; }

/// <summary>
/// The dependent handle target if this is a dependent handle.
/// </summary>
public ClrObject Dependent { get; }
public abstract ClrObject Dependent { get; }

/// The AppDomain the handle resides in.
/// </summary>
public ClrAppDomain AppDomain { get; }
public abstract ClrAppDomain AppDomain { get; }

/// <summary>
/// ToString override.
Expand All @@ -52,57 +52,6 @@ public override string ToString()
return HandleKind + " " + (Object.Type?.Name ?? string.Empty);
}

public ClrHandle(ulong address, ClrObject obj, ClrHandleKind handleKind, uint refCount, ClrObject dependent, ClrAppDomain domain)
{
Address = address;
Object = obj;
AppDomain = domain;
HandleKind = handleKind;
RefCount = refCount;
Dependent = dependent;
}

public ClrHandle(in HandleData handleData, ClrObject obj, ClrAppDomain domain, ClrType? dependentSecondary)
{
Address = handleData.Handle;

Object = obj;

uint refCount = 0;

if (handleData.Type == (int)ClrHandleKind.RefCount)
{
if (handleData.IsPegged != 0)
refCount = handleData.JupiterRefCount;

if (refCount < handleData.RefCount)
refCount = handleData.RefCount;

if (!obj.IsNull)
{
ComCallWrapper? ccw = obj.Type?.GetCCWData(obj);
if (ccw != null && refCount < ccw.RefCount)
{
refCount = (uint)ccw.RefCount;
}
else
{
RuntimeCallableWrapper? rcw = obj.Type?.GetRCWData(obj);
if (rcw != null && refCount < rcw.RefCount)
refCount = (uint)rcw.RefCount;
}
}

RefCount = refCount;
}

HandleKind = (ClrHandleKind)handleData.Type;
AppDomain = domain;

if (HandleKind == ClrHandleKind.Dependent)
Dependent = new ClrObject(handleData.Secondary, dependentSecondary);
}

/// <summary>
/// Whether the handle is strong (roots the object) or not.
/// </summary>
Expand All @@ -113,7 +62,7 @@ public bool IsStrong
switch (HandleKind)
{
case ClrHandleKind.RefCount:
return RefCount > 0;
return ReferenceCount > 0;

case ClrHandleKind.WeakLong:
case ClrHandleKind.WeakShort:
Expand Down
4 changes: 2 additions & 2 deletions src/Microsoft.Diagnostics.Runtime/src/Common/ClrObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ public ClrObject(ulong address, ClrType? type)
Address = address;
Type = type;

Debug.Assert(address == 0 || type != null);
Debug.Assert(address == 0 || (type != null && type.Heap.GetObjectType(address) == type));
DebugOnly.Assert(address == 0 || type != null);
DebugOnly.Assert(address == 0 || (type != null && type.Heap.GetObjectType(address) == type));
}

/// <summary>
Expand Down
13 changes: 2 additions & 11 deletions src/Microsoft.Diagnostics.Runtime/src/Common/ClrType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -153,15 +153,6 @@ public abstract class ClrType
/// </summary>
public abstract IReadOnlyList<ClrMethod> Methods { get; }

/// <summary>
/// When you enumerate a object, the offset within the object is returned. This offset might represent
/// nested fields (obj.Field1.Field2). GetFieldOffset returns the first of these field (Field1),
/// and 'remaining' offset with the type of Field1 (which must be a struct type). Calling
/// GetFieldForOffset repeatedly until the childFieldOffset is 0 will retrieve the whole chain.
/// </summary>
/// <returns>true if successful. Will fail if it 'this' is an array type.</returns>
public abstract bool GetFieldForOffset(int fieldOffset, bool inner, out ClrInstanceField? childField, out int childFieldOffset);

/// <summary>
/// Returns the field given by <paramref name="name"/>, case sensitive. Returns <see langword="null" /> if no such field name exists (or on error).
/// </summary>
Expand Down Expand Up @@ -219,9 +210,9 @@ public abstract class ClrType
public abstract object? GetArrayElementValue(ulong objRef, int index);

/// <summary>
/// Returns the base size of the object.
/// Returns the static size of objects of this type when they are created on the CLR heap.
/// </summary>
public abstract int BaseSize { get; }
public abstract int StaticSize { get; }

/// <summary>
/// Returns the size of elements of this object.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ internal ClrValueClass(ulong address, ClrType type, bool interior)
Type = type;
_interior = interior;

Debug.Assert(type.IsValueClass);
DebugOnly.Assert(type.IsValueClass);
}

/// <summary>
Expand Down
2 changes: 1 addition & 1 deletion src/Microsoft.Diagnostics.Runtime/src/Common/GCDesc.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public GCDesc(byte[] data)

public IEnumerable<(ulong, int)> WalkObject(ulong addr, ulong size, Func<ulong, ulong> readPointer)
{
Debug.Assert(size >= (ulong)IntPtr.Size);
DebugOnly.Assert(size >= (ulong)IntPtr.Size);

int series = GetNumSeries();
int highest = GetHighestSeries();
Expand Down
4 changes: 2 additions & 2 deletions src/Microsoft.Diagnostics.Runtime/src/Common/MemoryReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public bool ReadDword(ulong addr, out uint value)
return MisalignedRead(addr, out value);

// If MoveToPage succeeds, we MUST be on the right page.
Debug.Assert(addr >= _currPageStart);
DebugOnly.Assert(addr >= _currPageStart);

// However, the amount of data requested may fall off of the page. In that case,
// fall back to MisalignedRead.
Expand Down Expand Up @@ -108,7 +108,7 @@ public bool ReadPtr(ulong addr, out ulong value)
return MisalignedRead(addr, out value);

// If MoveToPage succeeds, we MUST be on the right page.
Debug.Assert(addr >= _currPageStart);
DebugOnly.Assert(addr >= _currPageStart);

// However, the amount of data requested may fall off of the page. In that case,
// fall back to MisalignedRead.
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ public int ReadVirtual(IntPtr self, ulong address, IntPtr buffer, int bytesReque
PEImage? peimage = _dataTarget.LoadPEImage(filePath);
if (peimage != null)
{
Debug.Assert(peimage.IsValid);
DebugOnly.Assert(peimage.IsValid);
int rva = checked((int)(address - info.ImageBase));
bytesRead = peimage.Read(rva, span);
return S_OK;
Expand Down Expand Up @@ -262,7 +262,7 @@ public unsafe int GetMetadata(
if (peimage is null || peimage.OptionalHeader is null)
return E_FAIL;

Debug.Assert(peimage.IsValid);
DebugOnly.Assert(peimage.IsValid);

uint rva = mdRva;
uint size = bufferSize;
Expand Down
Loading