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
@@ -1,9 +1,9 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

namespace Microsoft.Diagnostics.DataContractReader.Legacy;
namespace Microsoft.Diagnostics.DataContractReader;

internal static class CorDbgHResults
public static class CorDbgHResults
{
public const int CORDBG_E_READVIRTUAL_FAILURE = unchecked((int)0x80131c49);
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,21 +55,24 @@ public abstract class Target
/// Read a pointer from the target in target endianness
/// </summary>
/// <param name="address">Address to start reading from</param>
/// <returns>Pointer read from the target</returns>}
/// <returns>Pointer read from the target</returns>
/// <exception cref="VirtualReadException">Thrown when the read operation fails</exception>
public abstract TargetPointer ReadPointer(ulong address);

/// <summary>
/// Read a code pointer from the target in target endianness
/// </summary>
/// <param name="address">Address to start reading from</param>
/// <returns>Pointer read from the target</returns>}
/// <returns>Pointer read from the target</returns>
/// <exception cref="VirtualReadException">Thrown when the read operation fails</exception>
public abstract TargetCodePointer ReadCodePointer(ulong address);

/// <summary>
/// Read some bytes from the target
/// </summary>
/// <param name="address">The address where to start reading</param>
/// <param name="buffer">Destination to copy the bytes, the number of bytes to read is the span length</param>
/// <exception cref="VirtualReadException">Thrown when the read operation fails</exception>
public abstract void ReadBuffer(ulong address, Span<byte> buffer);

/// <summary>
Expand All @@ -83,21 +86,24 @@ public abstract class Target
/// Read a null-terminated UTF-8 string from the target
/// </summary>
/// <param name="address">Address to start reading from</param>
/// <returns>String read from the target</returns>}
/// <returns>String read from the target</returns>
/// <exception cref="VirtualReadException">Thrown when the read operation fails</exception>
public abstract string ReadUtf8String(ulong address);

/// <summary>
/// Read a null-terminated UTF-16 string from the target in target endianness
/// </summary>
/// <param name="address">Address to start reading from</param>
/// <returns>String read from the target</returns>}
/// <returns>String read from the target</returns>
/// <exception cref="VirtualReadException">Thrown when the read operation fails</exception>
public abstract string ReadUtf16String(ulong address);

/// <summary>
/// Read a native unsigned integer from the target in target endianness
/// </summary>
/// <param name="address">Address to start reading from</param>
/// <returns>Value read from the target</returns>
/// <exception cref="VirtualReadException">Thrown when the read operation fails</exception>
public abstract TargetNUInt ReadNUInt(ulong address);

/// <summary>
Expand Down Expand Up @@ -138,6 +144,7 @@ public abstract class Target
/// <typeparam name="T">Type of value to read</typeparam>
/// <param name="address">Address to start reading from</param>
/// <returns>Value read from the target</returns>
/// <exception cref="VirtualReadException">Thrown when the read operation fails</exception>
public abstract T Read<T>(ulong address) where T : unmanaged, IBinaryInteger<T>, IMinMaxValue<T>;

/// <summary>
Expand All @@ -154,8 +161,7 @@ public abstract class Target
/// <typeparam name="T">Type of value to write</typeparam>
/// <param name="address">Address to start writing to</param>
/// <param name="value">Value to write</param>
/// <returns>True if the write was successful, false otherwise</returns>
public abstract bool Write<T>(ulong address, T value) where T : unmanaged, IBinaryInteger<T>, IMinMaxValue<T>;
public abstract void Write<T>(ulong address, T value) where T : unmanaged, IBinaryInteger<T>, IMinMaxValue<T>;

/// <summary>
/// Read a target pointer from a span of bytes
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;

namespace Microsoft.Diagnostics.DataContractReader;

/// <summary>
/// Exception thrown when a virtual memory read operation fails.
/// </summary>
public class VirtualReadException : Exception
{
/// <summary>
/// Initializes a new instance of the <see cref="VirtualReadException"/> class.
/// </summary>
public VirtualReadException()
{
HResult = CorDbgHResults.CORDBG_E_READVIRTUAL_FAILURE;
}

/// <summary>
/// Initializes a new instance of the <see cref="VirtualReadException"/> class with a specified error message.
/// </summary>
/// <param name="message">The message that describes the error.</param>
public VirtualReadException(string message) : base(message)
{
HResult = CorDbgHResults.CORDBG_E_READVIRTUAL_FAILURE;
}

/// <summary>
/// Initializes a new instance of the <see cref="VirtualReadException"/> class with a specified error message and a reference to the inner exception that is the cause of this exception.
/// </summary>
/// <param name="message">The error message that explains the reason for the exception.</param>
/// <param name="innerException">The exception that is the cause of the current exception, or a null reference if no inner exception is specified.</param>
public VirtualReadException(string message, Exception innerException) : base(message, innerException)
{
HResult = CorDbgHResults.CORDBG_E_READVIRTUAL_FAILURE;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1181,9 +1181,8 @@ public uint UnwindOpSlots()

return new UnwindInfoHeader(unwindInfoAddress, headerValue);
}
catch (InvalidOperationException)
catch (VirtualReadException)
{
// InvalidOperationException thrown if failed to read memory
return null;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ private void FormatAsciiString(TargetPointer ptr, PaddingFormat paddingFormat, S
{
builder.Append(_target.ReadUtf8String(ptr).PadLeft(paddingFormat.Width, paddingFormat.FormatChar));
}
catch (InvalidOperationException)
catch (VirtualReadException)
{
builder.Append($"(#Could not read address of string at 0x{ptr.Value:x}#)");
}
Expand All @@ -124,7 +124,7 @@ private void FormatUtf16String(TargetPointer ptr, PaddingFormat paddingFormat, S
{
builder.Append(_target.ReadUtf16String(ptr).PadLeft(paddingFormat.Width, paddingFormat.FormatChar));
}
catch (InvalidOperationException)
catch (VirtualReadException)
{
builder.Append($"(#Could not read address of string at 0x{ptr.Value:x}#)");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ private ContractDescriptorTarget(Configuration config, ContractDescriptorParser.
if (global.Indirect)
{
if (global.NumericValue.Value >= (ulong)pointerData.Length)
throw new InvalidOperationException($"Invalid pointer data index {global.NumericValue.Value}.");
throw new VirtualReadException($"Invalid pointer data index {global.NumericValue.Value}.");

globalValues[name] = new GlobalValue
{
Expand Down Expand Up @@ -293,10 +293,11 @@ public override bool TryGetThreadContext(ulong threadId, uint contextFlags, Span
/// <typeparam name="T">Type of value to read</typeparam>
/// <param name="address">Address to start reading from</param>
/// <returns>Value read from the target</returns>
/// <exception cref="VirtualReadException">Thrown when the read operation fails</exception>
public override T Read<T>(ulong address)
{
if (!TryRead(address, _config.IsLittleEndian, _dataTargetDelegates, out T value))
throw new InvalidOperationException($"Failed to read {typeof(T)} at 0x{address:x8}.");
throw new VirtualReadException($"Failed to read {typeof(T)} at 0x{address:x8}.");

return value;
}
Expand Down Expand Up @@ -334,12 +335,10 @@ private static bool TryRead<T>(ulong address, bool isLittleEndian, DataTargetDel
/// </summary>
/// <typeparam name="T">Type of value to write</typeparam>
/// <param name="address">Address to start writing to</param>
/// <returns>True if the value is successfully written. Throws an InvalidOperationException otherwise.</returns>
public override bool Write<T>(ulong address, T value)
public override void Write<T>(ulong address, T value)
{
if (!TryWrite(address, _config.IsLittleEndian, _dataTargetDelegates, value))
throw new InvalidOperationException($"Failed to write {typeof(T)} at 0x{address:x8}.");
return true;
}

private static bool TryWrite<T>(ulong address, bool isLittleEndian, DataTargetDelegates dataTargetDelegates, T value) where T : unmanaged, IBinaryInteger<T>, IMinMaxValue<T>
Expand Down Expand Up @@ -375,7 +374,7 @@ private static T Read<T>(ReadOnlySpan<byte> bytes, bool isLittleEndian) where T
public override void ReadBuffer(ulong address, Span<byte> buffer)
{
if (!TryReadBuffer(address, buffer))
throw new InvalidOperationException($"Failed to read {buffer.Length} bytes at 0x{address:x8}.");
throw new VirtualReadException($"Failed to read {buffer.Length} bytes at 0x{address:x8}.");
}

private bool TryReadBuffer(ulong address, Span<byte> buffer)
Expand Down Expand Up @@ -404,11 +403,11 @@ private static bool IsSigned<T>() where T : struct, INumberBase<T>, IMinMaxValue
/// Read a pointer from the target in target endianness
/// </summary>
/// <param name="address">Address to start reading from</param>
/// <returns>Pointer read from the target</returns>}
/// <returns>Pointer read from the target</returns>
public override TargetPointer ReadPointer(ulong address)
{
if (!TryReadPointer(address, _config, _dataTargetDelegates, out TargetPointer pointer))
throw new InvalidOperationException($"Failed to read pointer at 0x{address:x8}.");
throw new VirtualReadException($"Failed to read pointer at 0x{address:x8}.");

return pointer;
}
Expand Down Expand Up @@ -436,7 +435,7 @@ public override TargetCodePointer ReadCodePointer(ulong address)
{
return new TargetCodePointer(Read<ulong>(address));
}
throw new InvalidOperationException($"Failed to read code pointer at 0x{address:x8} because CodePointer size is not 4 or 8");
throw new VirtualReadException($"Failed to read code pointer at 0x{address:x8} because CodePointer size is not 4 or 8");
}

public void ReadPointers(ulong address, Span<TargetPointer> buffer)
Expand All @@ -456,7 +455,7 @@ public void ReadPointers(ulong address, Span<TargetPointer> buffer)
/// Read a null-terminated UTF-8 string from the target
/// </summary>
/// <param name="address">Address to start reading from</param>
/// <returns>String read from the target</returns>}
/// <returns>String read from the target</returns>
public override string ReadUtf8String(ulong address)
{
// Read characters until we find the null terminator
Expand All @@ -481,7 +480,7 @@ public override string ReadUtf8String(ulong address)
/// Read a null-terminated UTF-16 string from the target in target endianness
/// </summary>
/// <param name="address">Address to start reading from</param>
/// <returns>String read from the target</returns>}
/// <returns>String read from the target</returns>
public override string ReadUtf16String(ulong address)
{
// Read characters until we find the null terminator
Expand Down Expand Up @@ -513,7 +512,7 @@ public override string ReadUtf16String(ulong address)
public override TargetNUInt ReadNUInt(ulong address)
{
if (!TryReadNUInt(address, _config, _dataTargetDelegates, out ulong value))
throw new InvalidOperationException($"Failed to read nuint at 0x{address:x8}.");
throw new VirtualReadException($"Failed to read nuint at 0x{address:x8}.");

return new TargetNUInt(value);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,10 +138,10 @@ int IXCLRDataModule.GetFileName(uint bufLen, uint* nameLen, char* name)
{
result = contract.GetPath(handle);
}
catch (InvalidOperationException)
catch (VirtualReadException)
{
// The memory for the path may not be enumerated - for example, in triage dumps
// In this case, GetPath will throw InvalidOperationException
// In this case, GetPath will throw VirtualReadException
}

if (string.IsNullOrEmpty(result))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -715,11 +715,6 @@ int ISOSDacInterface.GetJumpThunkTarget(void* ctx, ClrDataAddress* targetIP, Clr
hr = HResults.E_FAIL;
}
}
catch (InvalidOperationException)
{
// If the target read fails, expect HResult to be CORDBG_E_READVIRTUAL_FAILURE
hr = CorDbgHResults.CORDBG_E_READVIRTUAL_FAILURE;
}
catch (System.Exception ex)
{
hr = ex.HResult;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,8 +197,7 @@ public void WriteValue(MockTarget.Architecture arch)

bool success = builder.TryCreateTarget(out ContractDescriptorTarget? target);
Assert.True(success);
bool writeSuccess = target.Write<uint>(addr, expected);
Assert.True(writeSuccess);
target.Write<uint>(addr, expected);
Assert.Equal(expected, target.Read<uint>(addr));
}

Expand Down
10 changes: 5 additions & 5 deletions src/native/managed/cdac/tests/TestPlaceholderTarget.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public override TargetPointer ReadGlobalPointer(string name)
public override void ReadBuffer(ulong address, Span<byte> buffer)
{
if (_dataReader(address, buffer) < 0)
throw new InvalidOperationException($"Failed to read {buffer.Length} bytes at 0x{address:x8}.");
throw new VirtualReadException($"Failed to read {buffer.Length} bytes at 0x{address:x8}.");
}
public override void WriteBuffer(ulong address, Span<byte> buffer) => throw new NotImplementedException();

Expand Down Expand Up @@ -172,7 +172,7 @@ public override bool TryRead<T>(ulong address, out T value)
return true;
}

public override bool Write<T>(ulong address, T value) => throw new NotImplementedException();
public override void Write<T>(ulong address, T value) => throw new NotImplementedException();

#region subclass reader helpers

Expand Down Expand Up @@ -231,14 +231,14 @@ protected static bool IsSigned<T>() where T : struct, INumberBase<T>, IMinMaxVal
protected T DefaultRead<T>(ulong address) where T : unmanaged, IBinaryInteger<T>, IMinMaxValue<T>
{
if (!DefaultTryRead(address, out T value))
throw new InvalidOperationException($"Failed to read {typeof(T)} at 0x{address:x8}.");
throw new VirtualReadException($"Failed to read {typeof(T)} at 0x{address:x8}.");
return value;
}

protected TargetPointer DefaultReadPointer(ulong address)
{
if (!DefaultTryReadPointer(address, out TargetPointer pointer))
throw new InvalidOperationException($"Failed to read pointer at 0x{address:x8}.");
throw new VirtualReadException($"Failed to read pointer at 0x{address:x8}.");

return pointer;
}
Expand Down Expand Up @@ -275,7 +275,7 @@ protected bool DefaultTryReadNUInt(ulong address, out ulong value)
protected TargetNUInt DefaultReadNUInt(ulong address)
{
if (!DefaultTryReadNUInt(address, out ulong value))
throw new InvalidOperationException($"Failed to read nuint at 0x{address:x8}.");
throw new VirtualReadException($"Failed to read nuint at 0x{address:x8}.");

return new TargetNUInt(value);
}
Expand Down