Skip to content
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
Original file line number Diff line number Diff line change
@@ -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.

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.Marshalling;

namespace Microsoft.Diagnostics.DataContractReader.Legacy;

[GeneratedComClass]
public sealed unsafe partial class ClrDataAppDomain : IXCLRDataAppDomain
{
private readonly TargetPointer _appDomain;
private readonly IXCLRDataAppDomain? _legacyImpl;

public TargetPointer Address => _appDomain;

public ClrDataAppDomain(TargetPointer appDomain, IXCLRDataAppDomain? legacyImpl)
{
_appDomain = appDomain;
_legacyImpl = legacyImpl;
}

int IXCLRDataAppDomain.GetProcess(/*IXCLRDataProcess*/ void** process)
=> _legacyImpl is not null ? _legacyImpl.GetProcess(process) : HResults.E_NOTIMPL;

int IXCLRDataAppDomain.GetName(uint bufLen, uint* nameLen, char* name)
=> _legacyImpl is not null ? _legacyImpl.GetName(bufLen, nameLen, name) : HResults.E_NOTIMPL;

int IXCLRDataAppDomain.GetUniqueID(ulong* id)
=> _legacyImpl is not null ? _legacyImpl.GetUniqueID(id) : HResults.E_NOTIMPL;

int IXCLRDataAppDomain.GetFlags(uint* flags)
=> _legacyImpl is not null ? _legacyImpl.GetFlags(flags) : HResults.E_NOTIMPL;

int IXCLRDataAppDomain.IsSameObject(IXCLRDataAppDomain* appDomain)
{
int hr = HResults.S_FALSE;
try
{
StrategyBasedComWrappers cw = new();
object obj = cw.GetOrCreateObjectForComInstance((nint)appDomain, CreateObjectFlags.None);
if (obj is ClrDataAppDomain other)
{
hr = _appDomain == other._appDomain ? HResults.S_OK : HResults.S_FALSE;
}
}
catch (Exception ex)
{
hr = ex.HResult;
}

#if DEBUG
if (_legacyImpl is not null)
{
int hrLocal = _legacyImpl.IsSameObject(appDomain);
Debug.Assert(hrLocal == hr, $"cDAC: {hr}, DAC: {hrLocal}");
}
#endif

return hr;
}

int IXCLRDataAppDomain.GetManagedObject(/*IXCLRDataValue*/ void** value)
=> _legacyImpl is not null ? _legacyImpl.GetManagedObject(value) : HResults.E_NOTIMPL;

int IXCLRDataAppDomain.Request(uint reqCode, uint inBufferSize, byte* inBuffer, uint outBufferSize, byte* outBuffer)
=> _legacyImpl is not null ? _legacyImpl.Request(reqCode, inBufferSize, inBuffer, outBufferSize, outBuffer) : HResults.E_NOTIMPL;
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ int IXCLRDataFrame.GetContext(
[Out, MarshalUsing(CountElementName = nameof(contextBufSize))] byte[] contextBuf)
=> _legacyImpl is not null ? _legacyImpl.GetContext(contextFlags, contextBufSize, contextSize, contextBuf) : HResults.E_NOTIMPL;

int IXCLRDataFrame.GetAppDomain(void** appDomain)
int IXCLRDataFrame.GetAppDomain(/*IXCLRDataAppDomain*/ void** appDomain)
=> _legacyImpl is not null ? _legacyImpl.GetAppDomain(appDomain) : HResults.E_NOTIMPL;

int IXCLRDataFrame.GetNumArguments(uint* numArgs)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,33 @@ public ClrDataTask(TargetPointer address, Target target, IXCLRDataTask? legacyIm

int IXCLRDataTask.GetProcess(/*IXCLRDataProcess*/ void** process)
=> _legacyImpl is not null ? _legacyImpl.GetProcess(process) : HResults.E_NOTIMPL;
int IXCLRDataTask.GetCurrentAppDomain(/*IXCLRDataAppDomain*/ void** appDomain)
=> _legacyImpl is not null ? _legacyImpl.GetCurrentAppDomain(appDomain) : HResults.E_NOTIMPL;
int IXCLRDataTask.GetCurrentAppDomain(out IXCLRDataAppDomain? appDomain)
{
int hr = HResults.S_OK, hrLocal = HResults.S_OK;
appDomain = null;
IXCLRDataAppDomain? legacyAppDomain = null;

if (_legacyImpl is not null)
{
hrLocal = _legacyImpl.GetCurrentAppDomain(out legacyAppDomain);
}
try
{
TargetPointer currentAppDomain = _target.ReadPointer(_target.ReadGlobalPointer(Constants.Globals.AppDomain));
appDomain = new ClrDataAppDomain(currentAppDomain, legacyAppDomain);
}
catch (System.Exception ex)
{
hr = ex.HResult;
}
#if DEBUG
if (_legacyImpl is not null)
{
System.Diagnostics.Debug.Assert(hrLocal == hr, $"cDAC: {hr:x}, DAC: {hrLocal:x}");
}
#endif
return hr;
}
int IXCLRDataTask.GetUniqueID(ulong* id)
=> _legacyImpl is not null ? _legacyImpl.GetUniqueID(id) : HResults.E_NOTIMPL;
int IXCLRDataTask.GetFlags(uint* flags)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,7 @@ public unsafe partial interface IXCLRDataTask
int GetProcess(/*IXCLRDataProcess*/ void** process);

[PreserveSig]
int GetCurrentAppDomain(/*IXCLRDataAppDomain*/ void** appDomain);
int GetCurrentAppDomain(out IXCLRDataAppDomain? appDomain);

[PreserveSig]
int GetUniqueID(ulong* id);
Expand Down Expand Up @@ -595,7 +595,7 @@ public unsafe partial interface IXCLRDataAppDomain
[PreserveSig]
int GetFlags(uint* flags);
[PreserveSig]
int IsSameObject(/*IXCLRDataAppDomain*/ void* appDomain);
int IsSameObject(IXCLRDataAppDomain* appDomain);
[PreserveSig]
int GetManagedObject(/*IXCLRDataValue*/ void** value);
[PreserveSig]
Expand Down
45 changes: 45 additions & 0 deletions src/native/managed/cdac/tests/ClrDataTaskTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using Microsoft.Diagnostics.DataContractReader.Legacy;
using Xunit;

namespace Microsoft.Diagnostics.DataContractReader.Tests;

public unsafe class ClrDataTaskTests
{
[Theory]
[ClassData(typeof(MockTarget.StdArch))]
public void GetCurrentAppDomain(MockTarget.Architecture arch)
{
TargetTestHelpers helpers = new(arch);
MockMemorySpace.Builder builder = new(helpers);

ulong globalPtrAddr = 0x1000;
ulong expectedAppDomain = 0x2000;

byte[] ptrData = new byte[helpers.PointerSize];
helpers.WritePointer(ptrData, expectedAppDomain);
builder.AddHeapFragment(new MockMemorySpace.HeapFragment
{
Address = globalPtrAddr,
Data = ptrData,
Name = "AppDomainGlobalPointer"
});

var target = new TestPlaceholderTarget(
arch,
builder.GetMemoryContext().ReadFromTarget,
globals: [(Constants.Globals.AppDomain, globalPtrAddr)]);

TargetPointer taskAddress = new TargetPointer(0x5000);
IXCLRDataTask task = new ClrDataTask(taskAddress, target, legacyImpl: null);
int hr = task.GetCurrentAppDomain(out IXCLRDataAppDomain? appDomain);

Assert.Equal(HResults.S_OK, hr);
Assert.NotNull(appDomain);
ClrDataAppDomain clrAppDomain = Assert.IsType<ClrDataAppDomain>(appDomain);
Assert.Equal(new TargetPointer(expectedAppDomain), clrAppDomain.Address);
}
}
Loading