using System;
using System.Collections.Immutable;
using System.IO;
using System.IO.MemoryMappedFiles;
using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.Reflection.PortableExecutable;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Util;
using SRM = System.Reflection.Metadata;
namespace ICSharpCode.Decompiler
{
public static partial class SRMExtensions
{
public static bool HasFlag(this TypeDefinition typeDefinition, TypeAttributes attribute)
=> (typeDefinition.Attributes & attribute) == attribute;
public static bool HasFlag(this MethodDefinition methodDefinition, MethodAttributes attribute)
=> (methodDefinition.Attributes & attribute) == attribute;
public static bool HasFlag(this FieldDefinition fieldDefinition, FieldAttributes attribute)
=> (fieldDefinition.Attributes & attribute) == attribute;
public static bool HasFlag(this PropertyDefinition propertyDefinition, PropertyAttributes attribute)
=> (propertyDefinition.Attributes & attribute) == attribute;
public static bool HasFlag(this EventDefinition eventDefinition, EventAttributes attribute)
=> (eventDefinition.Attributes & attribute) == attribute;
public static bool IsTypeKind(this HandleKind kind) =>
kind == HandleKind.TypeDefinition || kind == HandleKind.TypeReference
|| kind == HandleKind.TypeSpecification;
public static bool IsMemberKind(this HandleKind kind) =>
kind == HandleKind.MethodDefinition || kind == HandleKind.PropertyDefinition
|| kind == HandleKind.FieldDefinition || kind == HandleKind.EventDefinition
|| kind == HandleKind.MemberReference || kind == HandleKind.MethodSpecification;
public static bool IsEntityHandle(this Handle handle) =>
handle.IsNil || (byte)handle.Kind < 112;
public static bool IsValueType(this TypeDefinitionHandle handle, MetadataReader reader)
{
return reader.GetTypeDefinition(handle).IsValueType(reader);
}
public static bool IsValueType(this TypeDefinition typeDefinition, MetadataReader reader)
{
EntityHandle baseType = typeDefinition.GetBaseTypeOrNil();
if (baseType.IsNil)
return false;
if (baseType.IsKnownType(reader, KnownTypeCode.Enum))
return true;
if (!baseType.IsKnownType(reader, KnownTypeCode.ValueType))
return false;
var thisType = typeDefinition.GetFullTypeName(reader);
return !thisType.IsKnownType(KnownTypeCode.Enum);
}
public static bool IsEnum(this TypeDefinitionHandle handle, MetadataReader reader)
{
return reader.GetTypeDefinition(handle).IsEnum(reader);
}
public static bool IsEnum(this TypeDefinition typeDefinition, MetadataReader reader)
{
EntityHandle baseType = typeDefinition.GetBaseTypeOrNil();
if (baseType.IsNil)
return false;
return baseType.IsKnownType(reader, KnownTypeCode.Enum);
}
public static bool IsEnum(this TypeDefinitionHandle handle, MetadataReader reader,
out PrimitiveTypeCode underlyingType)
{
return reader.GetTypeDefinition(handle).IsEnum(reader, out underlyingType);
}
public static bool IsEnum(this TypeDefinition typeDefinition, MetadataReader reader,
out PrimitiveTypeCode underlyingType)
{
underlyingType = 0;
EntityHandle baseType = typeDefinition.GetBaseTypeOrNil();
if (baseType.IsNil)
return false;
if (!baseType.IsKnownType(reader, KnownTypeCode.Enum))
return false;
foreach (var handle in typeDefinition.GetFields())
{
var field = reader.GetFieldDefinition(handle);
if ((field.Attributes & FieldAttributes.Static) != 0)
continue;
var blob = reader.GetBlobReader(field.Signature);
if (blob.ReadSignatureHeader().Kind != SignatureKind.Field)
return false;
underlyingType = (PrimitiveTypeCode)blob.ReadByte();
return true;
}
return false;
}
public static bool IsDelegate(this TypeDefinitionHandle handle, MetadataReader reader)
{
return reader.GetTypeDefinition(handle).IsDelegate(reader);
}
public static bool IsDelegate(this TypeDefinition typeDefinition, MetadataReader reader)
{
var baseType = typeDefinition.GetBaseTypeOrNil();
return !baseType.IsNil && baseType.IsKnownType(reader, KnownTypeCode.MulticastDelegate);
}
public static bool HasBody(this MethodDefinition methodDefinition)
{
const MethodAttributes noBodyAttrs = MethodAttributes.Abstract | MethodAttributes.PinvokeImpl;
const MethodImplAttributes noBodyImplAttrs = MethodImplAttributes.InternalCall
| MethodImplAttributes.Native | MethodImplAttributes.Unmanaged | MethodImplAttributes.Runtime;
return (methodDefinition.Attributes & noBodyAttrs) == 0 &&
(methodDefinition.ImplAttributes & noBodyImplAttrs) == 0 &&
methodDefinition.RelativeVirtualAddress > 0;
}
public static int GetCodeSize(this MethodBodyBlock body)
{
if (body == null)
throw new ArgumentNullException(nameof(body));
return body.GetILReader().Length;
}
public static MethodDefinitionHandle GetAny(this PropertyAccessors accessors)
{
if (!accessors.Getter.IsNil)
return accessors.Getter;
return accessors.Setter;
}
public static MethodDefinitionHandle GetAny(this EventAccessors accessors)
{
if (!accessors.Adder.IsNil)
return accessors.Adder;
if (!accessors.Remover.IsNil)
return accessors.Remover;
return accessors.Raiser;
}
public static EntityHandle GetGenericType(this in TypeSpecification ts, MetadataReader metadata)
{
if (ts.Signature.IsNil)
return default;
// Do a quick scan using BlobReader
var signature = metadata.GetBlobReader(ts.Signature);
// When dealing with FSM implementations, we can safely assume that if it's a type spec,
// it must be a generic type instance.
if (signature.ReadByte() != (byte)SignatureTypeCode.GenericTypeInstance)
return default;
// Skip over the rawTypeKind: value type or class
var rawTypeKind = signature.ReadCompressedInteger();
if (rawTypeKind < 17 || rawTypeKind > 18)
return default;
// Only read the generic type, ignore the type arguments
return signature.ReadTypeHandle();
}
public static EntityHandle GetDeclaringType(this EntityHandle entity, MetadataReader metadata)
{
switch (entity.Kind)
{
case HandleKind.TypeDefinition:
var td = metadata.GetTypeDefinition((TypeDefinitionHandle)entity);
return td.GetDeclaringType();
case HandleKind.TypeReference:
var tr = metadata.GetTypeReference((TypeReferenceHandle)entity);
return tr.GetDeclaringType();
case HandleKind.TypeSpecification:
var ts = metadata.GetTypeSpecification((TypeSpecificationHandle)entity);
return ts.GetGenericType(metadata).GetDeclaringType(metadata);
case HandleKind.FieldDefinition:
var fd = metadata.GetFieldDefinition((FieldDefinitionHandle)entity);
return fd.GetDeclaringType();
case HandleKind.MethodDefinition:
var md = metadata.GetMethodDefinition((MethodDefinitionHandle)entity);
return md.GetDeclaringType();
case HandleKind.MemberReference:
var mr = metadata.GetMemberReference((MemberReferenceHandle)entity);
return mr.Parent;
case HandleKind.EventDefinition:
var ed = metadata.GetEventDefinition((EventDefinitionHandle)entity);
return metadata.GetMethodDefinition(ed.GetAccessors().GetAny()).GetDeclaringType();
case HandleKind.PropertyDefinition:
var pd = metadata.GetPropertyDefinition((PropertyDefinitionHandle)entity);
return metadata.GetMethodDefinition(pd.GetAccessors().GetAny()).GetDeclaringType();
case HandleKind.MethodSpecification:
var ms = metadata.GetMethodSpecification((MethodSpecificationHandle)entity);
return ms.Method.GetDeclaringType(metadata);
default:
throw new ArgumentOutOfRangeException();
}
}
public static TypeReferenceHandle GetDeclaringType(this in TypeReference tr)
{
switch (tr.ResolutionScope.Kind)
{
case HandleKind.TypeReference:
return (TypeReferenceHandle)tr.ResolutionScope;
default:
return default(TypeReferenceHandle);
}
}
public static FullTypeName GetFullTypeName(this EntityHandle handle, MetadataReader reader)
{
if (handle.IsNil)
throw new ArgumentNullException(nameof(handle));
switch (handle.Kind)
{
case HandleKind.TypeDefinition:
return ((TypeDefinitionHandle)handle).GetFullTypeName(reader);
case HandleKind.TypeReference:
return ((TypeReferenceHandle)handle).GetFullTypeName(reader);
case HandleKind.TypeSpecification:
return ((TypeSpecificationHandle)handle).GetFullTypeName(reader);
default:
throw new ArgumentOutOfRangeException();
}
}
public static bool IsKnownType(this EntityHandle handle, MetadataReader reader,
KnownTypeCode knownType)
{
return IsKnownType(handle, reader, KnownTypeReference.Get(knownType).TypeName);
}
internal static bool IsKnownType(this EntityHandle handle, MetadataReader reader,
KnownAttribute knownType)
{
return IsKnownType(handle, reader, knownType.GetTypeName());
}
private static bool IsKnownType(EntityHandle handle, MetadataReader reader, TopLevelTypeName knownType)
{
if (handle.IsNil)
return false;
StringHandle nameHandle, namespaceHandle;
try
{
switch (handle.Kind)
{
case HandleKind.TypeReference:
var tr = reader.GetTypeReference((TypeReferenceHandle)handle);
// ignore exported and nested types
if (tr.ResolutionScope.IsNil || tr.ResolutionScope.Kind == HandleKind.TypeReference)
return false;
nameHandle = tr.Name;
namespaceHandle = tr.Namespace;
break;
case HandleKind.TypeDefinition:
var td = reader.GetTypeDefinition((TypeDefinitionHandle)handle);
if (td.IsNested)
return false;
nameHandle = td.Name;
namespaceHandle = td.Namespace;
break;
case HandleKind.TypeSpecification:
var ts = reader.GetTypeSpecification((TypeSpecificationHandle)handle);
var blob = reader.GetBlobReader(ts.Signature);
return SignatureIsKnownType(reader, knownType, ref blob);
default:
return false;
}
}
catch (BadImageFormatException)
{
// ignore bad metadata when trying to resolve ResolutionScope et al.
return false;
}
if (knownType.TypeParameterCount == 0)
{
if (!reader.StringComparer.Equals(nameHandle, knownType.Name))
return false;
}
else
{
string name = reader.GetString(nameHandle);
name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(name, out int typeParameterCount);
if (typeParameterCount != knownType.TypeParameterCount || name != knownType.Name)
return false;
}
if (namespaceHandle.IsNil)
{
return knownType.Namespace.Length == 0;
}
else
{
return reader.StringComparer.Equals(namespaceHandle, knownType.Namespace);
}
}
private static bool SignatureIsKnownType(MetadataReader reader, TopLevelTypeName knownType, ref BlobReader blob)
{
if (!blob.TryReadCompressedInteger(out int typeCode))
return false;
switch (typeCode)
{
case 0x1: // ELEMENT_TYPE_VOID
return knownType.IsKnownType(KnownTypeCode.Void);
case 0x2: // ELEMENT_TYPE_BOOLEAN
return knownType.IsKnownType(KnownTypeCode.Boolean);
case 0x3: // ELEMENT_TYPE_CHAR
return knownType.IsKnownType(KnownTypeCode.Char);
case 0x4: // ELEMENT_TYPE_I1
return knownType.IsKnownType(KnownTypeCode.SByte);
case 0x5: // ELEMENT_TYPE_U1
return knownType.IsKnownType(KnownTypeCode.Byte);
case 0x6: // ELEMENT_TYPE_I2
return knownType.IsKnownType(KnownTypeCode.Int16);
case 0x7: // ELEMENT_TYPE_U2
return knownType.IsKnownType(KnownTypeCode.UInt16);
case 0x8: // ELEMENT_TYPE_I4
return knownType.IsKnownType(KnownTypeCode.Int32);
case 0x9: // ELEMENT_TYPE_U4
return knownType.IsKnownType(KnownTypeCode.UInt32);
case 0xA: // ELEMENT_TYPE_I8
return knownType.IsKnownType(KnownTypeCode.Int64);
case 0xB: // ELEMENT_TYPE_U8
return knownType.IsKnownType(KnownTypeCode.UInt64);
case 0xC: // ELEMENT_TYPE_R4
return knownType.IsKnownType(KnownTypeCode.Single);
case 0xD: // ELEMENT_TYPE_R8
return knownType.IsKnownType(KnownTypeCode.Double);
case 0xE: // ELEMENT_TYPE_STRING
return knownType.IsKnownType(KnownTypeCode.String);
case 0x16: // ELEMENT_TYPE_TYPEDBYREF
return knownType.IsKnownType(KnownTypeCode.TypedReference);
case 0x18: // ELEMENT_TYPE_I
return knownType.IsKnownType(KnownTypeCode.IntPtr);
case 0x19: // ELEMENT_TYPE_U
return knownType.IsKnownType(KnownTypeCode.UIntPtr);
case 0x1C: // ELEMENT_TYPE_OBJECT
return knownType.IsKnownType(KnownTypeCode.Object);
case 0xF: // ELEMENT_TYPE_PTR
case 0x10: // ELEMENT_TYPE_BYREF
case 0x45: // ELEMENT_TYPE_PINNED
case 0x1D: // ELEMENT_TYPE_SZARRAY
case 0x1B: // ELEMENT_TYPE_FNPTR
case 0x14: // ELEMENT_TYPE_ARRAY
return false;
case 0x1F: // ELEMENT_TYPE_CMOD_REQD
case 0x20: // ELEMENT_TYPE_CMOD_OPT
// modifier
blob.ReadTypeHandle(); // skip modifier
return SignatureIsKnownType(reader, knownType, ref blob);
case 0x15: // ELEMENT_TYPE_GENERICINST
// generic type
return SignatureIsKnownType(reader, knownType, ref blob);
case 0x13: // ELEMENT_TYPE_VAR
case 0x1E: // ELEMENT_TYPE_MVAR
// index
return false;
case 0x11: // ELEMENT_TYPE_VALUETYPE
case 0x12: // ELEMENT_TYPE_CLASS
return IsKnownType(blob.ReadTypeHandle(), reader, knownType);
default:
return false;
}
}
public static FullTypeName GetFullTypeName(this TypeSpecificationHandle handle, MetadataReader reader)
{
if (handle.IsNil)
throw new ArgumentNullException(nameof(handle));
var ts = reader.GetTypeSpecification(handle);
return ts.DecodeSignature(new Metadata.FullTypeNameSignatureDecoder(reader), default(Unit));
}
public static FullTypeName GetFullTypeName(this TypeReferenceHandle handle, MetadataReader reader)
{
if (handle.IsNil)
throw new ArgumentNullException(nameof(handle));
var tr = reader.GetTypeReference(handle);
string name;
try
{
name = reader.GetString(tr.Name);
}
catch (BadImageFormatException)
{
name = $"TR{reader.GetToken(handle):x8}";
}
name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(
name, out var typeParameterCount);
TypeReferenceHandle declaringTypeHandle;
try
{
declaringTypeHandle = tr.GetDeclaringType();
}
catch (BadImageFormatException)
{
declaringTypeHandle = default;
}
if (declaringTypeHandle.IsNil)
{
string ns;
try
{
ns = tr.Namespace.IsNil ? "" : reader.GetString(tr.Namespace);
}
catch (BadImageFormatException)
{
ns = "";
}
return new FullTypeName(new TopLevelTypeName(ns, name, typeParameterCount));
}
else
{
return declaringTypeHandle.GetFullTypeName(reader).NestedType(name, typeParameterCount);
}
}
public static FullTypeName GetFullTypeName(this TypeDefinitionHandle handle, MetadataReader reader)
{
if (handle.IsNil)
throw new ArgumentNullException(nameof(handle));
return reader.GetTypeDefinition(handle).GetFullTypeName(reader);
}
public static FullTypeName GetFullTypeName(this TypeDefinition td, MetadataReader reader)
{
TypeDefinitionHandle declaringTypeHandle;
string name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(
reader.GetString(td.Name), out var typeParameterCount);
if ((declaringTypeHandle = td.GetDeclaringType()).IsNil)
{
string @namespace = td.Namespace.IsNil ? "" : reader.GetString(td.Namespace);
return new FullTypeName(new TopLevelTypeName(@namespace, name, typeParameterCount));
}
else
{
return declaringTypeHandle.GetFullTypeName(reader).NestedType(name, typeParameterCount);
}
}
public static FullTypeName GetFullTypeName(this ExportedType type, MetadataReader metadata)
{
string name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(
metadata.GetString(type.Name), out int typeParameterCount);
if (type.Implementation.Kind == HandleKind.ExportedType)
{
var outerType = metadata.GetExportedType((ExportedTypeHandle)type.Implementation);
return outerType.GetFullTypeName(metadata).NestedType(name, typeParameterCount);
}
else
{
string ns = type.Namespace.IsNil ? "" : metadata.GetString(type.Namespace);
return new TopLevelTypeName(ns, name, typeParameterCount);
}
}
public static bool IsAnonymousType(this TypeDefinition type, MetadataReader metadata)
{
string name = metadata.GetString(type.Name);
if (type.Namespace.IsNil && type.HasGeneratedName(metadata)
&& (name.Contains("AnonType") || name.Contains("AnonymousType")))
{
return type.IsCompilerGenerated(metadata);
}
return false;
}
#region HasGeneratedName
public static bool IsGeneratedName(this StringHandle handle, MetadataReader metadata)
{
return !handle.IsNil
&& (metadata.GetString(handle).StartsWith("<", StringComparison.Ordinal)
|| metadata.GetString(handle).Contains("$"));
}
public static bool HasGeneratedName(this MethodDefinitionHandle handle, MetadataReader metadata)
{
return metadata.GetMethodDefinition(handle).Name.IsGeneratedName(metadata);
}
public static bool HasGeneratedName(this TypeDefinitionHandle handle, MetadataReader metadata)
{
return metadata.GetTypeDefinition(handle).Name.IsGeneratedName(metadata);
}
public static bool HasGeneratedName(this TypeDefinition type, MetadataReader metadata)
{
return type.Name.IsGeneratedName(metadata);
}
public static bool HasGeneratedName(this FieldDefinitionHandle handle, MetadataReader metadata)
{
return metadata.GetFieldDefinition(handle).Name.IsGeneratedName(metadata);
}
#endregion
#region IsCompilerGenerated
public static bool IsCompilerGenerated(this MethodDefinitionHandle handle, MetadataReader metadata)
{
return metadata.GetMethodDefinition(handle).IsCompilerGenerated(metadata);
}
public static bool IsCompilerGeneratedOrIsInCompilerGeneratedClass(this MethodDefinitionHandle handle,
MetadataReader metadata)
{
MethodDefinition method = metadata.GetMethodDefinition(handle);
if (method.IsCompilerGenerated(metadata))
return true;
TypeDefinitionHandle declaringTypeHandle = method.GetDeclaringType();
if (!declaringTypeHandle.IsNil && declaringTypeHandle.IsCompilerGenerated(metadata))
return true;
return false;
}
public static bool IsCompilerGeneratedOrIsInCompilerGeneratedClass(this TypeDefinitionHandle handle,
MetadataReader metadata)
{
TypeDefinition type = metadata.GetTypeDefinition(handle);
if (type.IsCompilerGenerated(metadata))
return true;
TypeDefinitionHandle declaringTypeHandle = type.GetDeclaringType();
if (!declaringTypeHandle.IsNil && declaringTypeHandle.IsCompilerGenerated(metadata))
return true;
return false;
}
public static bool IsCompilerGenerated(this MethodDefinition method, MetadataReader metadata)
{
return method.GetCustomAttributes().HasKnownAttribute(metadata, KnownAttribute.CompilerGenerated);
}
public static bool IsCompilerGenerated(this FieldDefinitionHandle handle, MetadataReader metadata)
{
return metadata.GetFieldDefinition(handle).IsCompilerGenerated(metadata);
}
public static bool IsCompilerGenerated(this FieldDefinition field, MetadataReader metadata)
{
return field.GetCustomAttributes().HasKnownAttribute(metadata, KnownAttribute.CompilerGenerated);
}
public static bool IsCompilerGenerated(this TypeDefinitionHandle handle, MetadataReader metadata)
{
return metadata.GetTypeDefinition(handle).IsCompilerGenerated(metadata);
}
public static bool IsCompilerGenerated(this TypeDefinition type, MetadataReader metadata)
{
return type.GetCustomAttributes().HasKnownAttribute(metadata, KnownAttribute.CompilerGenerated);
}
#endregion
#region Attribute extensions
///
/// Gets the type of the attribute.
///
public static EntityHandle GetAttributeType(this SRM.CustomAttribute attribute, MetadataReader reader)
{
switch (attribute.Constructor.Kind)
{
case HandleKind.MethodDefinition:
var md = reader.GetMethodDefinition((MethodDefinitionHandle)attribute.Constructor);
return md.GetDeclaringType();
case HandleKind.MemberReference:
var mr = reader.GetMemberReference((MemberReferenceHandle)attribute.Constructor);
return mr.Parent;
default:
throw new BadImageFormatException("Unexpected token kind for attribute constructor: "
+ attribute.Constructor.Kind);
}
}
public static bool HasKnownAttribute(this CustomAttributeHandleCollection customAttributes,
MetadataReader metadata, KnownAttribute type)
{
foreach (var handle in customAttributes)
{
var customAttribute = metadata.GetCustomAttribute(handle);
if (customAttribute.IsKnownAttribute(metadata, type))
return true;
}
return false;
}
internal static bool IsKnownAttribute(this SRM.CustomAttribute attr, MetadataReader metadata,
KnownAttribute attrType)
{
return attr.GetAttributeType(metadata).IsKnownType(metadata, attrType);
}
public static Nullability? GetNullableContext(this CustomAttributeHandleCollection customAttributes,
MetadataReader metadata)
{
foreach (var handle in customAttributes)
{
var customAttribute = metadata.GetCustomAttribute(handle);
if (customAttribute.IsKnownAttribute(metadata, KnownAttribute.NullableContext))
{
// Decode
CustomAttributeValue value;
try
{
value = customAttribute.DecodeValue(
Metadata.MetadataExtensions.MinimalAttributeTypeProvider);
}
catch (BadImageFormatException)
{
continue;
}
catch (Metadata.EnumUnderlyingTypeResolveException)
{
continue;
}
if (value.FixedArguments.Length == 1 && value.FixedArguments[0].Value is byte b && b <= 2)
{
return (Nullability)b;
}
}
}
return null;
}
#endregion
public static unsafe BlobReader GetInitialValue(this FieldDefinition field, MetadataFile pefile,
ICompilation typeSystem)
{
if (!field.HasFlag(FieldAttributes.HasFieldRVA))
return default;
int rva = field.GetRelativeVirtualAddress();
if (rva == 0)
return default;
int size = field.DecodeSignature(new FieldValueSizeDecoder(typeSystem), default);
var sectionData = pefile.GetSectionData(rva);
if (sectionData.Length == 0 && size != 0)
throw new BadImageFormatException($"Field data (rva=0x{rva:x}) could not be found"
+ "in any section!");
if (size < 0 || size > sectionData.Length)
throw new BadImageFormatException($"Invalid size {size} for field data!");
return sectionData.GetReader(0, size);
}
sealed class FieldValueSizeDecoder : ISignatureTypeProvider
{
readonly MetadataModule module;
readonly int pointerSize;
public FieldValueSizeDecoder(ICompilation typeSystem = null)
{
this.module = (MetadataModule)typeSystem?.MainModule;
if (module?.MetadataFile is not PEFile pefile)
this.pointerSize = IntPtr.Size;
else
this.pointerSize = pefile.Reader.PEHeaders.PEHeader.Magic == PEMagic.PE32 ? 4 : 8;
}
public int GetArrayType(int elementType, ArrayShape shape) =>
GetPrimitiveType(PrimitiveTypeCode.Object);
public int GetSZArrayType(int elementType) => GetPrimitiveType(PrimitiveTypeCode.Object);
public int GetByReferenceType(int elementType) => pointerSize;
public int GetFunctionPointerType(MethodSignature signature) => pointerSize;
public int GetGenericInstantiation(int genericType, ImmutableArray typeArguments)
=> genericType;
public int GetGenericMethodParameter(GenericContext genericContext, int index) => 0;
public int GetGenericTypeParameter(GenericContext genericContext, int index) => 0;
public int GetModifiedType(int modifier, int unmodifiedType, bool isRequired) => unmodifiedType;
public int GetPinnedType(int elementType) => elementType;
public int GetPointerType(int elementType) => pointerSize;
public int GetPrimitiveType(PrimitiveTypeCode typeCode)
{
switch (typeCode)
{
case PrimitiveTypeCode.Boolean:
case PrimitiveTypeCode.Byte:
case PrimitiveTypeCode.SByte:
return 1;
case PrimitiveTypeCode.Char:
case PrimitiveTypeCode.Int16:
case PrimitiveTypeCode.UInt16:
return 2;
case PrimitiveTypeCode.Int32:
case PrimitiveTypeCode.UInt32:
case PrimitiveTypeCode.Single:
return 4;
case PrimitiveTypeCode.Int64:
case PrimitiveTypeCode.UInt64:
case PrimitiveTypeCode.Double:
return 8;
case PrimitiveTypeCode.IntPtr:
case PrimitiveTypeCode.UIntPtr:
return pointerSize;
default:
return 0;
}
}
public int GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle,
byte rawTypeKind)
{
var td = reader.GetTypeDefinition(handle);
return td.GetLayout().Size;
}
public int GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle,
byte rawTypeKind)
{
var typeDef = module?.ResolveType(handle, new GenericContext()).GetDefinition();
if (typeDef == null || typeDef.MetadataToken.IsNil)
return 0;
reader = typeDef.ParentModule.MetadataFile.Metadata;
var td = reader.GetTypeDefinition((TypeDefinitionHandle)typeDef.MetadataToken);
return td.GetLayout().Size;
}
public int GetTypeFromSpecification(MetadataReader reader, GenericContext genericContext,
TypeSpecificationHandle handle, byte rawTypeKind)
{
return reader.GetTypeSpecification(handle).DecodeSignature(this, genericContext);
}
}
public static EntityHandle GetBaseTypeOrNil(this TypeDefinition definition)
{
try
{
return definition.BaseType;
}
catch (BadImageFormatException)
{
return default;
}
}
public static string ToILSyntax(this SignatureCallingConvention callConv)
{
return callConv switch {
SignatureCallingConvention.Default => "default",
SignatureCallingConvention.CDecl => "unmanaged cdecl",
SignatureCallingConvention.StdCall => "unmanaged stdcall",
SignatureCallingConvention.ThisCall => "unmanaged thiscall",
SignatureCallingConvention.FastCall => "unmanaged fastcall",
SignatureCallingConvention.VarArgs => "vararg",
SignatureCallingConvention.Unmanaged => "unmanaged",
_ => callConv.ToString().ToLowerInvariant()
};
}
public static UnmanagedMemoryStream AsStream(this MemoryMappedViewAccessor view)
{
long size = checked((long)view.SafeMemoryMappedViewHandle.ByteLength);
return new UnmanagedMemoryStream(view.SafeMemoryMappedViewHandle, 0, size);
}
}
}