2021-09-20 18:20:01 +02:00

730 lines
30 KiB
C#

/*
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 <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using dnSpy.Debugger.DotNet.Metadata.Impl;
namespace dnSpy.Debugger.DotNet.Metadata {
/// <summary>
/// A .NET module
/// </summary>
public abstract class DmdModule : DmdObject, IDmdCustomAttributeProvider {
/// <summary>
/// Dummy abstract method to make sure no-one outside this assembly can create their own <see cref="DmdModule"/>
/// </summary>
private protected abstract void YouCantDeriveFromThisClass();
/// <summary>
/// Returns the fully qualified name
/// </summary>
/// <param name="isInMemory">true if the module is in memory</param>
/// <param name="isDynamic">true if it's a dynamic module</param>
/// <param name="fullyQualifiedName">Module filename or null</param>
/// <returns></returns>
public static string GetFullyQualifiedName(bool isInMemory, bool isDynamic, string? fullyQualifiedName) {
if (isDynamic)
return "<In Memory Module>";
if (isInMemory)
return "<Unknown>";
return fullyQualifiedName ?? string.Empty;
}
/// <summary>
/// Gets the AppDomain
/// </summary>
public abstract DmdAppDomain AppDomain { get; }
/// <summary>
/// Gets the fully qualified name
/// </summary>
public abstract string FullyQualifiedName { get; }
/// <summary>
/// true if this is the corlib module
/// </summary>
public bool IsCorLib => this == AppDomain.CorLib?.ManifestModule;
/// <summary>
/// Gets all types in this module
/// </summary>
/// <returns></returns>
public abstract DmdType[] GetTypes();
/// <summary>
/// Gets all types that exist in the ExportedType table. This includes types that have been
/// forwarded to other assemblies.
/// </summary>
/// <returns></returns>
public abstract DmdType[] GetExportedTypes();
/// <summary>
/// Gets the module version ID
/// </summary>
public abstract Guid ModuleVersionId { get; }
/// <summary>
/// Gets the metadata token
/// </summary>
public abstract int MetadataToken { get; }
/// <summary>
/// Gets the global type
/// </summary>
public abstract DmdType GlobalType { get; }
/// <summary>
/// Gets the metadata stream version
/// </summary>
public abstract int MDStreamVersion { get; }
/// <summary>
/// Gets the metadata name of the module
/// </summary>
public abstract string ScopeName { get; set; }
/// <summary>
/// Gets a dynamic module's version number. It gets incremented each time a new type gets added to the dynamic module.
/// </summary>
public abstract int DynamicModuleVersion { get; }
/// <summary>
/// Gets the module name
/// </summary>
public string Name {
get {
var fqn = FullyQualifiedName;
// Don't use Path.GetFileName() since fqn could contain invalid characters
int index = fqn.LastIndexOfAny(dirSepChars);
if (index >= 0)
fqn = fqn.Substring(index + 1);
if (fqn.EndsWith(".ni.dll", StringComparison.OrdinalIgnoreCase))
fqn = fqn.Substring(0, fqn.Length - ".ni.dll".Length) + fqn.Substring(fqn.Length - ".dll".Length);
else if (fqn.EndsWith(".ni.exe", StringComparison.OrdinalIgnoreCase))
fqn = fqn.Substring(0, fqn.Length - ".ni.exe".Length) + fqn.Substring(fqn.Length - ".exe".Length);
return fqn;
}
}
static readonly char[] dirSepChars = new char[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar };
/// <summary>
/// Gets the assembly
/// </summary>
public abstract DmdAssembly Assembly { get; }
/// <summary>
/// true if it's a dynamic module (types can be added at runtime)
/// </summary>
public abstract bool IsDynamic { get; }
/// <summary>
/// true if it's an in-memory module (eg. loaded from a <see cref="byte"/> array)
/// </summary>
public abstract bool IsInMemory { get; }
/// <summary>
/// true if it's a synthetic module; it's not loaded in the debugged process
/// </summary>
public abstract bool IsSynthetic { get; }
/// <summary>
/// Gets the custom attributes
/// </summary>
public ReadOnlyCollection<DmdCustomAttributeData> CustomAttributes => GetCustomAttributesData();
/// <summary>
/// Gets the custom attributes
/// </summary>
/// <returns></returns>
public abstract ReadOnlyCollection<DmdCustomAttributeData> GetCustomAttributesData();
/// <summary>
/// Checks if a custom attribute is present
/// </summary>
/// <param name="attributeTypeFullName">Full name of the custom attribute type</param>
/// <param name="inherit">true to check custom attributes in all base classes</param>
/// <returns></returns>
public bool IsDefined(string attributeTypeFullName, bool inherit) => CustomAttributesHelper.IsDefined(GetCustomAttributesData(), attributeTypeFullName);
/// <summary>
/// Checks if a custom attribute is present
/// </summary>
/// <param name="attributeType">Custom attribute type</param>
/// <param name="inherit">true to check custom attributes in all base classes</param>
/// <returns></returns>
public bool IsDefined(DmdType? attributeType, bool inherit) => CustomAttributesHelper.IsDefined(GetCustomAttributesData(), attributeType);
/// <summary>
/// Checks if a custom attribute is present
/// </summary>
/// <param name="attributeType">Custom attribute type</param>
/// <param name="inherit">true to check custom attributes in all base classes</param>
/// <returns></returns>
public bool IsDefined(Type attributeType, bool inherit) => CustomAttributesHelper.IsDefined(GetCustomAttributesData(), DmdTypeUtilities.ToDmdType(attributeType, AppDomain));
/// <summary>
/// Finds a custom attribute
/// </summary>
/// <param name="attributeTypeFullName">Full name of the custom attribute type</param>
/// <param name="inherit">true to check custom attributes in all base classes</param>
/// <returns></returns>
public DmdCustomAttributeData? FindCustomAttribute(string attributeTypeFullName, bool inherit) => CustomAttributesHelper.Find(GetCustomAttributesData(), attributeTypeFullName);
/// <summary>
/// Finds a custom attribute
/// </summary>
/// <param name="attributeType">Custom attribute type</param>
/// <param name="inherit">true to check custom attributes in all base classes</param>
/// <returns></returns>
public DmdCustomAttributeData? FindCustomAttribute(DmdType? attributeType, bool inherit) => CustomAttributesHelper.Find(GetCustomAttributesData(), attributeType);
/// <summary>
/// Finds a custom attribute
/// </summary>
/// <param name="attributeType">Custom attribute type</param>
/// <param name="inherit">true to check custom attributes in all base classes</param>
/// <returns></returns>
public DmdCustomAttributeData? FindCustomAttribute(Type attributeType, bool inherit) => CustomAttributesHelper.Find(GetCustomAttributesData(), DmdTypeUtilities.ToDmdType(attributeType, AppDomain));
/// <summary>
/// Resolves a method
/// </summary>
/// <param name="metadataToken">Token</param>
/// <returns></returns>
public DmdMethodBase? ResolveMethod(int metadataToken) => ResolveMethod(metadataToken, (IList<DmdType>?)null, null);
/// <summary>
/// Resolves a method
/// </summary>
/// <param name="metadataToken">Token</param>
/// <param name="options">Resolve options</param>
/// <returns></returns>
public DmdMethodBase? ResolveMethod(int metadataToken, DmdResolveOptions options) => ResolveMethod(metadataToken, (IList<DmdType>?)null, null, options);
/// <summary>
/// Resolves a method
/// </summary>
/// <param name="metadataToken">Token</param>
/// <param name="genericTypeArguments">Generic type arguments or null</param>
/// <param name="genericMethodArguments">Generic method arguments or null</param>
/// <returns></returns>
public DmdMethodBase ResolveMethod(int metadataToken, IList<DmdType>? genericTypeArguments, IList<DmdType>? genericMethodArguments) =>
ResolveMethod(metadataToken, genericTypeArguments, genericMethodArguments, DmdResolveOptions.ThrowOnError)!;
/// <summary>
/// Resolves a method
/// </summary>
/// <param name="metadataToken">Token</param>
/// <param name="genericTypeArguments">Generic type arguments or null</param>
/// <param name="genericMethodArguments">Generic method arguments or null</param>
/// <returns></returns>
public DmdMethodBase ResolveMethod(int metadataToken, IList<Type>? genericTypeArguments, IList<Type>? genericMethodArguments) =>
ResolveMethod(metadataToken, genericTypeArguments, genericMethodArguments, DmdResolveOptions.ThrowOnError)!;
/// <summary>
/// Resolves a method
/// </summary>
/// <param name="metadataToken">Token</param>
/// <param name="genericTypeArguments">Generic type arguments or null</param>
/// <param name="genericMethodArguments">Generic method arguments or null</param>
/// <param name="options">Resolve options</param>
/// <returns></returns>
public abstract DmdMethodBase? ResolveMethod(int metadataToken, IList<DmdType>? genericTypeArguments, IList<DmdType>? genericMethodArguments, DmdResolveOptions options);
/// <summary>
/// Resolves a method
/// </summary>
/// <param name="metadataToken">Token</param>
/// <param name="genericTypeArguments">Generic type arguments or null</param>
/// <param name="genericMethodArguments">Generic method arguments or null</param>
/// <param name="options">Resolve options</param>
/// <returns></returns>
public DmdMethodBase? ResolveMethod(int metadataToken, IList<Type>? genericTypeArguments, IList<Type>? genericMethodArguments, DmdResolveOptions options) =>
ResolveMethod(metadataToken, genericTypeArguments.ToDmdType(AppDomain), genericMethodArguments.ToDmdType(AppDomain), options);
/// <summary>
/// Resolves a field
/// </summary>
/// <param name="metadataToken">Token</param>
/// <returns></returns>
public DmdFieldInfo? ResolveField(int metadataToken) => ResolveField(metadataToken, (IList<DmdType>?)null, null);
/// <summary>
/// Resolves a field
/// </summary>
/// <param name="metadataToken">Token</param>
/// <param name="options">Resolve options</param>
/// <returns></returns>
public DmdFieldInfo? ResolveField(int metadataToken, DmdResolveOptions options) => ResolveField(metadataToken, (IList<DmdType>?)null, null, options);
/// <summary>
/// Resolves a field
/// </summary>
/// <param name="metadataToken">Token</param>
/// <param name="genericTypeArguments">Generic type arguments or null</param>
/// <param name="genericMethodArguments">Generic method arguments or null</param>
/// <returns></returns>
public DmdFieldInfo ResolveField(int metadataToken, IList<DmdType>? genericTypeArguments, IList<DmdType>? genericMethodArguments) =>
ResolveField(metadataToken, genericTypeArguments, genericMethodArguments, DmdResolveOptions.ThrowOnError)!;
/// <summary>
/// Resolves a field
/// </summary>
/// <param name="metadataToken">Token</param>
/// <param name="genericTypeArguments">Generic type arguments or null</param>
/// <param name="genericMethodArguments">Generic method arguments or null</param>
/// <returns></returns>
public DmdFieldInfo ResolveField(int metadataToken, IList<Type>? genericTypeArguments, IList<Type>? genericMethodArguments) =>
ResolveField(metadataToken, genericTypeArguments, genericMethodArguments, DmdResolveOptions.ThrowOnError)!;
/// <summary>
/// Resolves a field
/// </summary>
/// <param name="metadataToken">Token</param>
/// <param name="genericTypeArguments">Generic type arguments or null</param>
/// <param name="genericMethodArguments">Generic method arguments or null</param>
/// <param name="options">Resolve options</param>
/// <returns></returns>
public abstract DmdFieldInfo? ResolveField(int metadataToken, IList<DmdType>? genericTypeArguments, IList<DmdType>? genericMethodArguments, DmdResolveOptions options);
/// <summary>
/// Resolves a field
/// </summary>
/// <param name="metadataToken">Token</param>
/// <param name="genericTypeArguments">Generic type arguments or null</param>
/// <param name="genericMethodArguments">Generic method arguments or null</param>
/// <param name="options">Resolve options</param>
/// <returns></returns>
public DmdFieldInfo? ResolveField(int metadataToken, IList<Type>? genericTypeArguments, IList<Type>? genericMethodArguments, DmdResolveOptions options) =>
ResolveField(metadataToken, genericTypeArguments.ToDmdType(AppDomain), genericMethodArguments.ToDmdType(AppDomain), options);
/// <summary>
/// Resolves a type
/// </summary>
/// <param name="metadataToken">Token</param>
/// <returns></returns>
public DmdType? ResolveType(int metadataToken) => ResolveType(metadataToken, (IList<DmdType>?)null, null);
/// <summary>
/// Resolves a type
/// </summary>
/// <param name="metadataToken">Token</param>
/// <param name="options">Resolve options</param>
/// <returns></returns>
public DmdType? ResolveType(int metadataToken, DmdResolveOptions options) => ResolveType(metadataToken, (IList<DmdType>?)null, null, options);
/// <summary>
/// Resolves a type
/// </summary>
/// <param name="metadataToken">Token</param>
/// <param name="genericTypeArguments">Generic type arguments or null</param>
/// <param name="genericMethodArguments">Generic method arguments or null</param>
/// <returns></returns>
public DmdType ResolveType(int metadataToken, IList<DmdType>? genericTypeArguments, IList<DmdType>? genericMethodArguments) =>
ResolveType(metadataToken, genericTypeArguments, genericMethodArguments, DmdResolveOptions.ThrowOnError)!;
/// <summary>
/// Resolves a type
/// </summary>
/// <param name="metadataToken">Token</param>
/// <param name="genericTypeArguments">Generic type arguments or null</param>
/// <param name="genericMethodArguments">Generic method arguments or null</param>
/// <returns></returns>
public DmdType ResolveType(int metadataToken, IList<Type>? genericTypeArguments, IList<Type>? genericMethodArguments) =>
ResolveType(metadataToken, genericTypeArguments, genericMethodArguments, DmdResolveOptions.ThrowOnError)!;
/// <summary>
/// Resolves a type
/// </summary>
/// <param name="metadataToken">Token</param>
/// <param name="genericTypeArguments">Generic type arguments or null</param>
/// <param name="genericMethodArguments">Generic method arguments or null</param>
/// <param name="options">Resolve options</param>
/// <returns></returns>
public abstract DmdType? ResolveType(int metadataToken, IList<DmdType>? genericTypeArguments, IList<DmdType>? genericMethodArguments, DmdResolveOptions options);
/// <summary>
/// Resolves a type
/// </summary>
/// <param name="metadataToken">Token</param>
/// <param name="genericTypeArguments">Generic type arguments or null</param>
/// <param name="genericMethodArguments">Generic method arguments or null</param>
/// <param name="options">Resolve options</param>
/// <returns></returns>
public DmdType? ResolveType(int metadataToken, IList<Type>? genericTypeArguments, IList<Type>? genericMethodArguments, DmdResolveOptions options) =>
ResolveType(metadataToken, genericTypeArguments.ToDmdType(AppDomain), genericMethodArguments.ToDmdType(AppDomain), options);
/// <summary>
/// Resolves a member
/// </summary>
/// <param name="metadataToken">Token</param>
/// <returns></returns>
public DmdMemberInfo? ResolveMember(int metadataToken) => ResolveMember(metadataToken, (IList<DmdType>?)null, null);
/// <summary>
/// Resolves a member
/// </summary>
/// <param name="metadataToken">Token</param>
/// <param name="options">Resolve options</param>
/// <returns></returns>
public DmdMemberInfo? ResolveMember(int metadataToken, DmdResolveOptions options) => ResolveMember(metadataToken, (IList<DmdType>?)null, null, options);
/// <summary>
/// Resolves a member
/// </summary>
/// <param name="metadataToken">Token</param>
/// <param name="genericTypeArguments">Generic type arguments or null</param>
/// <param name="genericMethodArguments">Generic method arguments or null</param>
/// <returns></returns>
public DmdMemberInfo ResolveMember(int metadataToken, IList<DmdType>? genericTypeArguments, IList<DmdType>? genericMethodArguments) =>
ResolveMember(metadataToken, genericTypeArguments, genericMethodArguments, DmdResolveOptions.ThrowOnError)!;
/// <summary>
/// Resolves a member
/// </summary>
/// <param name="metadataToken">Token</param>
/// <param name="genericTypeArguments">Generic type arguments or null</param>
/// <param name="genericMethodArguments">Generic method arguments or null</param>
/// <returns></returns>
public DmdMemberInfo ResolveMember(int metadataToken, IList<Type>? genericTypeArguments, IList<Type>? genericMethodArguments) =>
ResolveMember(metadataToken, genericTypeArguments.ToDmdType(AppDomain), genericMethodArguments.ToDmdType(AppDomain), DmdResolveOptions.ThrowOnError)!;
/// <summary>
/// Resolves a member
/// </summary>
/// <param name="metadataToken">Token</param>
/// <param name="genericTypeArguments">Generic type arguments or null</param>
/// <param name="genericMethodArguments">Generic method arguments or null</param>
/// <param name="options">Resolve options</param>
/// <returns></returns>
public abstract DmdMemberInfo? ResolveMember(int metadataToken, IList<DmdType>? genericTypeArguments, IList<DmdType>? genericMethodArguments, DmdResolveOptions options);
/// <summary>
/// Resolves a member
/// </summary>
/// <param name="metadataToken">Token</param>
/// <param name="genericTypeArguments">Generic type arguments or null</param>
/// <param name="genericMethodArguments">Generic method arguments or null</param>
/// <param name="options">Resolve options</param>
/// <returns></returns>
public DmdMemberInfo? ResolveMember(int metadataToken, IList<Type>? genericTypeArguments, IList<Type>? genericMethodArguments, DmdResolveOptions options) =>
ResolveMember(metadataToken, genericTypeArguments.ToDmdType(AppDomain), genericMethodArguments.ToDmdType(AppDomain), options);
/// <summary>
/// Resolves a method signature
/// </summary>
/// <param name="metadataToken">StandaloneSig token from a method body</param>
/// <param name="genericTypeArguments">Generic type arguments or null</param>
/// <param name="genericMethodArguments">Generic method arguments or null</param>
/// <returns></returns>
public DmdMethodSignature ResolveMethodSignature(int metadataToken, IList<DmdType>? genericTypeArguments, IList<DmdType>? genericMethodArguments) =>
ResolveMethodSignature(metadataToken, genericTypeArguments, genericMethodArguments, DmdResolveOptions.ThrowOnError)!;
/// <summary>
/// Resolves a method signature
/// </summary>
/// <param name="metadataToken">StandaloneSig token from a method body</param>
/// <param name="genericTypeArguments">Generic type arguments or null</param>
/// <param name="genericMethodArguments">Generic method arguments or null</param>
/// <returns></returns>
public DmdMethodSignature ResolveMethodSignature(int metadataToken, IList<Type>? genericTypeArguments, IList<Type>? genericMethodArguments) =>
ResolveMethodSignature(metadataToken, genericTypeArguments.ToDmdType(AppDomain), genericMethodArguments.ToDmdType(AppDomain), DmdResolveOptions.ThrowOnError)!;
/// <summary>
/// Resolves a method signature
/// </summary>
/// <param name="metadataToken">StandaloneSig token from a method body</param>
/// <param name="genericTypeArguments">Generic type arguments or null</param>
/// <param name="genericMethodArguments">Generic method arguments or null</param>
/// <param name="options">Resolve options</param>
/// <returns></returns>
public abstract DmdMethodSignature? ResolveMethodSignature(int metadataToken, IList<DmdType>? genericTypeArguments, IList<DmdType>? genericMethodArguments, DmdResolveOptions options);
/// <summary>
/// Resolves a method signature
/// </summary>
/// <param name="metadataToken">StandaloneSig token from a method body</param>
/// <param name="genericTypeArguments">Generic type arguments or null</param>
/// <param name="genericMethodArguments">Generic method arguments or null</param>
/// <param name="options">Resolve options</param>
/// <returns></returns>
public DmdMethodSignature? ResolveMethodSignature(int metadataToken, IList<Type>? genericTypeArguments, IList<Type>? genericMethodArguments, DmdResolveOptions options) =>
ResolveMethodSignature(metadataToken, genericTypeArguments.ToDmdType(AppDomain), genericMethodArguments.ToDmdType(AppDomain), options);
/// <summary>
/// Resolves a signature
/// </summary>
/// <param name="metadataToken">Token</param>
/// <returns></returns>
public abstract byte[]? ResolveSignature(int metadataToken);
/// <summary>
/// Resolves a string
/// </summary>
/// <param name="metadataToken">String token (<c>0x70xxxxxx</c>)</param>
/// <returns></returns>
public abstract string ResolveString(int metadataToken);
/// <summary>
/// Gets PE information
/// </summary>
/// <param name="peKind">PE Kind</param>
/// <param name="machine">Machine</param>
public abstract void GetPEKind(out DmdPortableExecutableKinds peKind, out DmdImageFileMachine machine);
/// <summary>
/// Gets a type
/// </summary>
/// <param name="type">Type</param>
/// <returns></returns>
public DmdType? GetType(Type type) => GetType(type, DmdGetTypeOptions.None);
/// <summary>
/// Gets a type and throws if it couldn't be found
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public DmdType GetTypeThrow(Type type) => GetType(type, DmdGetTypeOptions.ThrowOnError)!;
/// <summary>
/// Gets a type
/// </summary>
/// <param name="type">Type</param>
/// <param name="options">Options</param>
/// <returns></returns>
public DmdType? GetType(Type type, DmdGetTypeOptions options) {
if (type is null)
throw new ArgumentNullException(nameof(type));
var fullname = type.FullName ?? throw new ArgumentException();
return GetType(fullname, options);
}
/// <summary>
/// Gets a type
/// </summary>
/// <param name="className">Name of type</param>
/// <param name="ignoreCase">true to ignore case</param>
/// <returns></returns>
public DmdType? GetType(string className, bool ignoreCase) => GetType(className, ignoreCase ? DmdGetTypeOptions.IgnoreCase : 0);
/// <summary>
/// Gets a type
/// </summary>
/// <param name="className">Name of type</param>
/// <returns></returns>
public DmdType? GetType(string className) => GetType(className, DmdGetTypeOptions.None);
/// <summary>
/// Gets a type and throws if it couldn't be found
/// </summary>
/// <param name="className">Name of type</param>
/// <returns></returns>
public DmdType GetTypeThrow(string className) => GetType(className, DmdGetTypeOptions.ThrowOnError)!;
/// <summary>
/// Gets a type
/// </summary>
/// <param name="className">Name of type</param>
/// <param name="throwOnError">true to throw if the type couldn't be found</param>
/// <param name="ignoreCase">true to ignore case</param>
/// <returns></returns>
public DmdType? GetType(string className, bool throwOnError, bool ignoreCase) =>
GetType(className, (throwOnError ? DmdGetTypeOptions.ThrowOnError : 0) | (ignoreCase ? DmdGetTypeOptions.IgnoreCase : 0));
/// <summary>
/// Gets a type
/// </summary>
/// <param name="typeName">Full name of the type (<see cref="DmdType.FullName"/>)</param>
/// <param name="options">Options</param>
/// <returns></returns>
public abstract DmdType? GetType(string typeName, DmdGetTypeOptions options);
/// <summary>
/// Gets all global public static and instance fields
/// </summary>
/// <returns></returns>
public DmdFieldInfo[] GetFields() => GetFields(DmdBindingFlags.Instance | DmdBindingFlags.Static | DmdBindingFlags.Public);
/// <summary>
/// Gets all global fields
/// </summary>
/// <param name="bindingFlags">Binding attributes</param>
/// <returns></returns>
public DmdFieldInfo[] GetFields(DmdBindingFlags bindingFlags) => GlobalType.GetFields(bindingFlags);
/// <summary>
/// Gets a global public static or instance field
/// </summary>
/// <param name="name">Field name</param>
/// <returns></returns>
public DmdFieldInfo? GetField(string name) => GetField(name, DmdBindingFlags.Instance | DmdBindingFlags.Static | DmdBindingFlags.Public);
/// <summary>
/// Gets a global field
/// </summary>
/// <param name="name">Field name</param>
/// <param name="bindingAttr">Binding attributes</param>
/// <returns></returns>
public DmdFieldInfo? GetField(string name, DmdBindingFlags bindingAttr) => GlobalType.GetField(name, bindingAttr);
/// <summary>
/// Gets all global public static or instance methods
/// </summary>
/// <returns></returns>
public DmdMethodInfo[] GetMethods() => GetMethods(DmdBindingFlags.Instance | DmdBindingFlags.Static | DmdBindingFlags.Public);
/// <summary>
/// Gets global methods
/// </summary>
/// <param name="bindingFlags">Binding attributes</param>
/// <returns></returns>
public DmdMethodInfo[] GetMethods(DmdBindingFlags bindingFlags) => GlobalType.GetMethods(bindingFlags);
/// <summary>
/// Gets a global method
/// </summary>
/// <param name="name">Method name</param>
/// <param name="bindingAttr">Binding attributes</param>
/// <param name="callConvention">Calling convention</param>
/// <param name="types">Method parameter types or null</param>
/// <returns></returns>
public DmdMethodInfo? GetMethod(string name, DmdBindingFlags bindingAttr, DmdCallingConventions callConvention, IList<DmdType>? types) {
if (types is null)
return GlobalType.GetMethod(name, bindingAttr);
return GlobalType.GetMethod(name, bindingAttr, callConvention, types);
}
/// <summary>
/// Gets a global method
/// </summary>
/// <param name="name">Method name</param>
/// <param name="bindingAttr">Binding attributes</param>
/// <param name="callConvention">Calling convention</param>
/// <param name="types">Method parameter types or null</param>
/// <returns></returns>
public DmdMethodInfo? GetMethod(string name, DmdBindingFlags bindingAttr, DmdCallingConventions callConvention, IList<Type>? types) =>
GetMethod(name, bindingAttr, callConvention, types.ToDmdType(AppDomain));
/// <summary>
/// Gets a global public static or instance method
/// </summary>
/// <param name="name">Method name</param>
/// <param name="types">Method parameter types</param>
/// <returns></returns>
public DmdMethodInfo? GetMethod(string name, IList<DmdType> types) => GetMethod(name, DmdBindingFlags.Instance | DmdBindingFlags.Static | DmdBindingFlags.Public, DmdCallingConventions.Any, types);
/// <summary>
/// Gets a global public static or instance method
/// </summary>
/// <param name="name">Method name</param>
/// <param name="types">Method parameter types</param>
/// <returns></returns>
public DmdMethodInfo? GetMethod(string name, IList<Type> types) => GetMethod(name, DmdBindingFlags.Instance | DmdBindingFlags.Static | DmdBindingFlags.Public, DmdCallingConventions.Any, types.ToDmdType(AppDomain));
/// <summary>
/// Gets a global public static or instance method
/// </summary>
/// <param name="name">Method name</param>
/// <returns></returns>
public DmdMethodInfo? GetMethod(string name) => GetMethod(name, DmdBindingFlags.Instance | DmdBindingFlags.Static | DmdBindingFlags.Public, DmdCallingConventions.Any, (IList<DmdType>?)null);
/// <summary>
/// Gets all referenced assemblies
/// </summary>
/// <returns></returns>
public abstract DmdReadOnlyAssemblyName[] GetReferencedAssemblies();
/// <summary>
/// Reads memory. Returns false if data couldn't be read.
/// </summary>
/// <param name="rva">RVA of data</param>
/// <param name="destination">Destination address</param>
/// <param name="size">Number of bytes to read</param>
/// <returns></returns>
public abstract unsafe bool ReadMemory(uint rva, void* destination, int size);
/// <summary>
/// Reads memory. Returns false if data couldn't be read.
/// </summary>
/// <param name="rva">RVA of data</param>
/// <param name="destination">Destination buffer</param>
/// <param name="destinationIndex">Destination index</param>
/// <param name="size">Number of bytes to read</param>
/// <returns></returns>
public unsafe bool ReadMemory(uint rva, byte[] destination, int destinationIndex, int size) {
if (destination is null)
throw new ArgumentNullException(nameof(destination));
if ((uint)destinationIndex > (uint)destination.Length)
throw new ArgumentOutOfRangeException(nameof(destinationIndex));
if (size < 0)
throw new ArgumentOutOfRangeException(nameof(size));
if ((uint)(destinationIndex + size) > (uint)destination.Length)
throw new ArgumentOutOfRangeException(nameof(destinationIndex));
if (size == 0)
return true;
fixed (void* p = &destination[destinationIndex])
return ReadMemory(rva, p, size);
}
/// <summary>
/// Reads memory. Returns null if data couldn't be read.
/// </summary>
/// <param name="rva">RVA of data</param>
/// <param name="size">Number of bytes to read</param>
/// <returns></returns>
public byte[]? ReadMemory(uint rva, int size) {
if (size == 0)
return Array.Empty<byte>();
var res = new byte[size];
if (!ReadMemory(rva, res, 0, size))
return null;
return res;
}
/// <summary>
/// Returns the metadata name (<see cref="ScopeName"/>)
/// </summary>
/// <returns></returns>
public sealed override string ToString() => ScopeName;
}
/// <summary>
/// Type/member resolve options
/// </summary>
[Flags]
public enum DmdResolveOptions {
/// <summary>
/// No bit is set
/// </summary>
None = 0,
/// <summary>
/// Throw if the type or member couldn't be resolved
/// </summary>
ThrowOnError = 0x00000001,
/// <summary>
/// Don't try to resolve type refs, field refs, method refs
/// </summary>
NoTryResolveRefs = 0x00000002,
}
}