Skip to content

Commit

Permalink
[cdac] Pass a delegate into Target (#105043)
Browse files Browse the repository at this point in the history
  • Loading branch information
jkoritzinsky authored Jul 18, 2024
1 parent a5c0dec commit d79cd32
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 28 deletions.
8 changes: 7 additions & 1 deletion src/native/managed/cdacreader/src/Entrypoints.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,13 @@ internal static class Entrypoints
private static unsafe int Init(ulong descriptor, delegate* unmanaged<ulong, byte*, uint, void*, int> readFromTarget, void* readContext, IntPtr* handle)
{
// TODO: [cdac] Better error code/details
if (!Target.TryCreate(descriptor, readFromTarget, readContext, out Target? target))
if (!Target.TryCreate(descriptor, (address, buffer) =>
{
fixed (byte* bufferPtr = buffer)
{
return readFromTarget(address, bufferPtr, (uint)buffer.Length, readContext);
}
}, out Target? target))
return -1;

GCHandle gcHandle = GCHandle.Alloc(target);
Expand Down
24 changes: 7 additions & 17 deletions src/native/managed/cdacreader/src/Target.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,11 @@ private readonly struct Configuration
internal DataCache ProcessedData { get; }
internal Helpers.Metadata Metadata { get; }

public static bool TryCreate(ulong contractDescriptor, delegate* unmanaged<ulong, byte*, uint, void*, int> readFromTarget, void* readContext, out Target? target)
public delegate int ReadFromTargetDelegate(ulong address, Span<byte> bufferToFill);

public static bool TryCreate(ulong contractDescriptor, ReadFromTargetDelegate readFromTarget, out Target? target)
{
Reader reader = new Reader(readFromTarget, readContext);
Reader reader = new Reader(readFromTarget);
if (TryReadContractDescriptor(contractDescriptor, reader, out Configuration config, out ContractDescriptorParser.ContractDescriptor? descriptor, out TargetPointer[] pointerData))
{
target = new Target(config, descriptor!, pointerData, reader);
Expand Down Expand Up @@ -458,26 +460,14 @@ public bool TryGet<T>(ulong address, [NotNullWhen(true)] out T? data)
}
}

private sealed class Reader
private readonly struct Reader(ReadFromTargetDelegate readFromTarget)
{
private readonly delegate* unmanaged<ulong, byte*, uint, void*, int> _readFromTarget;
private readonly void* _context;

public Reader(delegate* unmanaged<ulong, byte*, uint, void*, int> readFromTarget, void* context)
{
_readFromTarget = readFromTarget;
_context = context;
}

public int ReadFromTarget(ulong address, Span<byte> buffer)
{
fixed (byte* bufferPtr = buffer)
{
return _readFromTarget(address, bufferPtr, (uint)buffer.Length, _context);
}
return readFromTarget(address, buffer);
}

public int ReadFromTarget(ulong address, byte* buffer, uint bytesToRead)
=> _readFromTarget(address, buffer, bytesToRead, _context);
=> readFromTarget(address, new Span<byte>(buffer, checked((int)bytesToRead)));
}
}
16 changes: 6 additions & 10 deletions src/native/managed/cdacreader/tests/MockMemorySpace.cs
Original file line number Diff line number Diff line change
Expand Up @@ -159,20 +159,16 @@ public static ReadContext CreateContext(ReadOnlySpan<byte> descriptor, ReadOnlyS

public static bool TryCreateTarget(ReadContext* context, out Target? target)
{
return Target.TryCreate(ContractDescriptorAddr, &ReadFromTarget, context, out target);
return Target.TryCreate(ContractDescriptorAddr, (address, buffer) => ReadFromTarget(address, buffer, context), out target);
}

[UnmanagedCallersOnly]
private static int ReadFromTarget(ulong address, byte* buffer, uint length, void* context)
private static int ReadFromTarget(ulong address, Span<byte> span, ReadContext* readContext)
{
ReadContext* readContext = (ReadContext*)context;
var span = new Span<byte>(buffer, (int)length);

// Populate the span with the requested portion of the contract descriptor
if (address >= ContractDescriptorAddr && address <= ContractDescriptorAddr + (ulong)readContext->ContractDescriptorLength - length)
if (address >= ContractDescriptorAddr && address <= ContractDescriptorAddr + (ulong)readContext->ContractDescriptorLength - (uint)span.Length)
{
ulong offset = address - ContractDescriptorAddr;
new ReadOnlySpan<byte>(readContext->ContractDescriptor + offset, (int)length).CopyTo(span);
new ReadOnlySpan<byte>(readContext->ContractDescriptor + offset, span.Length).CopyTo(span);
return 0;
}

Expand All @@ -184,10 +180,10 @@ private static int ReadFromTarget(ulong address, byte* buffer, uint length, void
}

// Populate the span with the requested portion of the pointer data
if (address >= ContractPointerDataAddr && address <= ContractPointerDataAddr + (ulong)readContext->PointerDataLength - length)
if (address >= ContractPointerDataAddr && address <= ContractPointerDataAddr + (ulong)readContext->PointerDataLength - (uint)span.Length)
{
ulong offset = address - ContractPointerDataAddr;
new ReadOnlySpan<byte>(readContext->PointerData + offset, (int)length).CopyTo(span);
new ReadOnlySpan<byte>(readContext->PointerData + offset, span.Length).CopyTo(span);
return 0;
}

Expand Down

0 comments on commit d79cd32

Please sign in to comment.