/*
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 dnSpy.Contracts.Debugger.CallStack;
using dnSpy.Contracts.Debugger.DotNet.Disassembly;
using dnSpy.Contracts.Debugger.Evaluation;
using dnSpy.Contracts.Disassembly;
using dnSpy.Contracts.Metadata;
using dnSpy.Debugger.DotNet.Metadata;
namespace dnSpy.Contracts.Debugger.DotNet.Evaluation {
///
/// Implemented by a .NET engine, see
///
public interface IDbgDotNetRuntime {
///
/// Gets the dispatcher
///
DbgDotNetDispatcher Dispatcher { get; }
///
/// Gets the feature flags
///
DbgDotNetRuntimeFeatures Features { get; }
///
/// Gets the module id
///
/// Module
///
ModuleId GetModuleId(DbgModule module);
///
/// Gets the module data or
///
/// Module
///
DbgDotNetRawModuleBytes GetRawModuleBytes(DbgModule module);
///
/// Translates a method token from the original dynamic module's metadata to the saved module metadata used by the expression compiler
///
/// Module
/// Method token
/// New method token
/// New method body local variables signature token
///
bool TryGetMethodToken(DbgModule module, int methodToken, out int metadataMethodToken, out int metadataLocalVarSigTok);
///
/// Gets the current method or null if it's not a normal IL frame
///
/// Evaluation info
///
DmdMethodBase? GetFrameMethod(DbgEvaluationInfo evalInfo);
///
/// Loads the address of an instance or a static field or returns null if it's not supported
///
/// Evaluation info
/// Instance object or null if it's a static field
/// Field
///
DbgDotNetValue? LoadFieldAddress(DbgEvaluationInfo evalInfo, DbgDotNetValue? obj, DmdFieldInfo field);
///
/// Loads an instance or a static field
///
/// Evaluation info
/// Instance object or null if it's a static field
/// Field
///
DbgDotNetValueResult LoadField(DbgEvaluationInfo evalInfo, DbgDotNetValue? obj, DmdFieldInfo field);
///
/// Stores a value in a field. Returns null or an error message
///
/// Evaluation info
/// Instance object or null if it's a static field
/// Field
/// Value to store: A or a primitive number or a string or arrays of primitive numbers / strings
///
string? StoreField(DbgEvaluationInfo evalInfo, DbgDotNetValue? obj, DmdFieldInfo field, object? value);
///
/// Calls an instance or a static method
///
/// Evaluation info
/// Instance object or null if it's a static method
/// Method
/// Arguments: A or a primitive number or a string or arrays of primitive numbers / strings
/// Invoke options
///
DbgDotNetValueResult Call(DbgEvaluationInfo evalInfo, DbgDotNetValue? obj, DmdMethodBase method, object?[] arguments, DbgDotNetInvokeOptions invokeOptions);
///
/// Creates a new instance of a type by calling its constructor
///
/// Evaluation info
/// Constructor
/// Arguments: A or a primitive number or a string or arrays of primitive numbers / strings
/// Invoke options
///
DbgDotNetValueResult CreateInstance(DbgEvaluationInfo evalInfo, DmdConstructorInfo ctor, object?[] arguments, DbgDotNetInvokeOptions invokeOptions);
///
/// Creates a new instance of a type. All fields are initialized to 0 or null. The constructor isn't called.
///
/// Evaluation info
/// Type to create
///
DbgDotNetValueResult CreateInstanceNoConstructor(DbgEvaluationInfo evalInfo, DmdType type);
///
/// Creates an SZ array
///
/// Evaluation info
/// Element type
/// Length of the array
///
DbgDotNetValueResult CreateSZArray(DbgEvaluationInfo evalInfo, DmdType elementType, int length);
///
/// Creates a multi-dimensional array
///
/// Evaluation info
/// Element type
/// Dimension infos
///
DbgDotNetValueResult CreateArray(DbgEvaluationInfo evalInfo, DmdType elementType, DbgDotNetArrayDimensionInfo[] dimensionInfos);
///
/// Gets aliases
///
/// Evaluation info
///
DbgDotNetAliasInfo[] GetAliases(DbgEvaluationInfo evalInfo);
///
/// Gets all exceptions
///
/// Evaluation info
///
DbgDotNetExceptionInfo[] GetExceptions(DbgEvaluationInfo evalInfo);
///
/// Gets all return values
///
/// Evaluation info
///
DbgDotNetReturnValueInfo[] GetReturnValues(DbgEvaluationInfo evalInfo);
///
/// Gets an exception or null
///
/// Evaluation info
/// Exception id, eg.
///
DbgDotNetValue? GetException(DbgEvaluationInfo evalInfo, uint id);
///
/// Gets a stowed exception or null
///
/// Evaluation info
/// Stowed exception id, eg.
///
DbgDotNetValue? GetStowedException(DbgEvaluationInfo evalInfo, uint id);
///
/// Gets a return value or null
///
/// Evaluation info
/// Return value id, eg.
///
DbgDotNetValue? GetReturnValue(DbgEvaluationInfo evalInfo, uint id);
///
/// Gets a local value
///
/// Evaluation info
/// Metadata index of local
///
DbgDotNetValueResult GetLocalValue(DbgEvaluationInfo evalInfo, uint index);
///
/// Gets a parameter value
///
/// Evaluation info
/// Metadata index of parameter
///
DbgDotNetValueResult GetParameterValue(DbgEvaluationInfo evalInfo, uint index);
///
/// Writes a new local value. Returns an error message or null.
///
/// Evaluation info
/// Metadata index of parameter
/// Type of the local
/// New value: A or a primitive number or a string or arrays of primitive numbers / strings
///
string? SetLocalValue(DbgEvaluationInfo evalInfo, uint index, DmdType targetType, object? value);
///
/// Writes a new parameter value. Returns an error message or null.
///
/// Evaluation info
/// Metadata index of parameter
/// Type of the parameter
/// New value: A or a primitive number or a string or arrays of primitive numbers / strings
///
string? SetParameterValue(DbgEvaluationInfo evalInfo, uint index, DmdType targetType, object? value);
///
/// Gets the address of a local value or null if it's not supported
///
/// Evaluation info
/// Metadata index of local
/// Type of the local
///
DbgDotNetValue? GetLocalValueAddress(DbgEvaluationInfo evalInfo, uint index, DmdType targetType);
///
/// Gets the address of a parameter value or null if it's not supported
///
/// Evaluation info
/// Metadata index of local
/// Type of the parameter
///
DbgDotNetValue? GetParameterValueAddress(DbgEvaluationInfo evalInfo, uint index, DmdType targetType);
///
/// Creates a simple value (a primitive number or a string, or arrays of those types)
///
/// Evaluation info
/// A or a primitive number or a string or arrays of primitive numbers / strings
///
DbgDotNetValueResult CreateValue(DbgEvaluationInfo evalInfo, object? value);
///
/// Boxes the value type
///
/// Evaluation info
/// Value to box
///
DbgDotNetValueResult Box(DbgEvaluationInfo evalInfo, object? value);
///
/// Returns true if it's possible to create an object id
///
/// Value created by this runtime
///
bool CanCreateObjectId(DbgDotNetValue value);
///
/// Creates an object id or returns null
///
/// Value created by this runtime
/// Unique id
///
DbgDotNetObjectId? CreateObjectId(DbgDotNetValue value, uint id);
///
/// Checks if an object id and a value refer to the same data
///
/// Object id created by this class
/// Value created by this runtime
///
bool Equals(DbgDotNetObjectId objectId, DbgDotNetValue value);
///
/// Gets the hash code of an object id
///
/// Object id created by this class
///
int GetHashCode(DbgDotNetObjectId objectId);
///
/// Gets the hash code of a value created by this runtime
///
/// Value created by this runtime
///
int GetHashCode(DbgDotNetValue value);
///
/// Gets an object ID's value or null if there was an error
///
/// Evaluation info
/// Object id created by this class
///
DbgDotNetValue? GetValue(DbgEvaluationInfo evalInfo, DbgDotNetObjectId objectId);
///
/// Checks if two values are equal. Returns null if it's unknown.
///
/// Value #1
/// Value #2
///
bool? Equals(DbgDotNetValue a, DbgDotNetValue b);
///
/// Tries to get the native code
///
/// Frame
/// Updated with the native code if successful
///
bool TryGetNativeCode(DbgStackFrame frame, out DbgDotNetNativeCode nativeCode);
///
/// Tries to get the native code
///
/// Method
/// Updated with the native code if successful
///
bool TryGetNativeCode(DmdMethodBase method, out DbgDotNetNativeCode nativeCode);
///
/// Tries to get a symbol
///
/// Address
/// Updated with the symbol if successful
///
bool TryGetSymbol(ulong address, out SymbolResolverResult result);
}
///
/// Invoke options
///
[Flags]
public enum DbgDotNetInvokeOptions {
///
/// No bit is set
///
None = 0,
///
/// Non-virtual call
///
NonVirtual = 0x00000001,
}
///
/// .NET runtime features
///
[Flags]
public enum DbgDotNetRuntimeFeatures {
///
/// No bit is set
///
None = 0,
///
/// Object IDs are supported
///
ObjectIds = 0x00000001,
///
/// Calling generic methods isn't supported
///
NoGenericMethods = 0x00000002,
///
/// and
/// isn't supported for pointers.
///
NoDereferencePointers = 0x00000004,
///
/// Async step with object ids isn't supported
///
NoAsyncStepObjectId = 0x00000008,
///
/// It's possible to get the native code of jitted managed methods
///
NativeMethodBodies = 0x00000010,
}
///
/// Constants
///
public static class DbgDotNetRuntimeConstants {
///
/// Exception ID
///
public const uint ExceptionId = 1;
///
/// Stowed exception ID
///
public const uint StowedExceptionId = 1;
///
/// ID of last return value
///
public const uint LastReturnValueId = 0;
}
///
/// Contains .NET module data information
///
public readonly struct DbgDotNetRawModuleBytes {
///
/// No .NET module data is available
///
public static readonly DbgDotNetRawModuleBytes None = default;
///
/// true if it's file layout, false if it's memory layout
///
public bool IsFileLayout { get; }
///
/// Raw bytes of the .NET module
///
public byte[] RawBytes { get; }
///
/// Constructor
///
/// Raw bytes of the .NET module
/// true if it's file layout, false if it's memory layout
public DbgDotNetRawModuleBytes(byte[] rawBytes, bool isFileLayout) {
IsFileLayout = isFileLayout;
RawBytes = rawBytes ?? throw new ArgumentNullException(nameof(rawBytes));
}
}
}