/* Copyright (C) 2014-2019 de4dot@gmail.com This file is part of dnSpy dnSpy is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. dnSpy is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with dnSpy. If not, see . */ using System; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using dnSpy.Contracts.Debugger.Engine.Evaluation; using dnSpy.Contracts.Debugger.Evaluation; using dnSpy.Debugger.DotNet.Metadata; namespace dnSpy.Contracts.Debugger.DotNet.Evaluation { /// /// Result of evaluating an expression. All values are automatically closed when the runtime continues /// but they implement and should be disposed of earlier if possible. /// public abstract class DbgDotNetValue : IDisposable { /// /// Gets the type of the value /// public abstract DmdType Type { get; } /// /// true if this is a null value /// public virtual bool IsNull => false; /// /// Gets the referenced value if it's a by-ref or a pointer /// /// public virtual DbgDotNetValueResult LoadIndirect() => DbgDotNetValueResult.CreateError(PredefinedEvaluationErrorMessages.InternalDebuggerError); /// /// Writes to the referenced value (by-ref or pointer). The return value is null or an error message. /// /// Evaluation info /// Value to store: A or a primitive number or a string or arrays of primitive numbers / strings /// public virtual string? StoreIndirect(DbgEvaluationInfo evalInfo, object? value) => PredefinedEvaluationErrorMessages.InternalDebuggerError; /// /// Gets the number of elements of the array /// /// Total number of elements in the array /// public virtual bool GetArrayCount(out uint elementCount) { elementCount = 0; return false; } /// /// Gets array information if it's an array or returns false /// /// Total number of elements in the array /// Dimension base indexes and lengths /// public virtual bool GetArrayInfo(out uint elementCount, [NotNullWhen(true)] out DbgDotNetArrayDimensionInfo[]? dimensionInfos) { elementCount = 0; dimensionInfos = null; return false; } /// /// Gets the address of the element at in the array or null if it's not supported. /// This method can be called even if it's a multi-dimensional array. /// /// Zero-based index of the element /// public virtual DbgDotNetValueResult? GetArrayElementAddressAt(uint index) => null; /// /// Gets the element at in the array. This method can be called even if it's /// a multi-dimensional array. /// /// Zero-based index of the element /// public virtual DbgDotNetValueResult GetArrayElementAt(uint index) => DbgDotNetValueResult.CreateError(PredefinedEvaluationErrorMessages.InternalDebuggerError); /// /// Stores a value at in the array. This method can be called even if it's /// a multi-dimensional array. /// The return value is null or an error message. /// /// Evaluation info /// Zero-based index of the element /// Value to store: A or a primitive number or a string or arrays of primitive numbers / strings /// public virtual string? SetArrayElementAt(DbgEvaluationInfo evalInfo, uint index, object? value) => PredefinedEvaluationErrorMessages.InternalDebuggerError; /// /// Boxes the value type, returns null on failure /// /// Evaluation info /// public virtual DbgDotNetValueResult? Box(DbgEvaluationInfo evalInfo) => null; /// /// Gets the address of the value or null if there's no address available. /// The returned address gets invalid when the runtime continues. /// /// If true and if it's a supported type (eg. a simple type such as integers, /// floating point values, strings or byte arrays) the returned object contains the address of the actual /// value, else the returned address and length covers the whole object including vtable, method table or other /// special data. /// public virtual DbgRawAddressValue? GetRawAddressValue(bool onlyDataAddress) => null; /// /// Gets the raw value /// /// public virtual DbgDotNetRawValue GetRawValue() => new DbgDotNetRawValue(DbgSimpleValueType.Other); /// /// Returns the instance or null if it's unknown /// /// public virtual IDbgDotNetRuntime? TryGetDotNetRuntime() => null; /// /// Called when its owner () gets closed /// public virtual void Dispose() { } } /// /// Contains base index and length of an array dimension /// public readonly struct DbgDotNetArrayDimensionInfo { /// /// Base index /// public int BaseIndex { get; } /// /// Number of elements in this dimension /// public uint Length { get; } /// /// Constructor /// /// Base index /// Number of elements in this dimension public DbgDotNetArrayDimensionInfo(int baseIndex, uint length) { BaseIndex = baseIndex; Length = length; } } /// /// Raw value /// public readonly struct DbgDotNetRawValue { /// /// Type of the value /// public DbgSimpleValueType ValueType { get; } /// /// true if is valid /// public bool HasRawValue { get; } /// /// The value. It's only valid if is true. A null value is a valid value. /// If it's an enum value, it's stored as the enum's underlying type (eg. ) /// public object? RawValue { get; } /// /// Constructor /// /// Type public DbgDotNetRawValue(DbgSimpleValueType valueType) { Debug.Assert(valueType == DbgSimpleValueType.Other || valueType == DbgSimpleValueType.Void); ValueType = valueType; HasRawValue = false; RawValue = null; } /// /// Constructor /// /// Type /// Value public DbgDotNetRawValue(DbgSimpleValueType valueType, object? rawValue) { Debug.Assert(valueType != DbgSimpleValueType.Void); ValueType = valueType; HasRawValue = true; RawValue = rawValue; } } }