// // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2015 Jb Evain // Copyright (c) 2008 - 2011 Novell, Inc. // // Licensed under the MIT/X11 license. // using MonoFN.Cecil.Cil; using MonoFN.Cecil.Metadata; using MonoFN.Collections.Generic; using System; using System.Collections.Generic; using System.Threading; namespace MonoFN.Cecil { internal struct Range { public uint Start; public uint Length; public Range(uint index, uint length) { Start = index; Length = length; } } internal sealed class MetadataSystem { internal AssemblyNameReference[] AssemblyReferences; internal ModuleReference[] ModuleReferences; internal TypeDefinition[] Types; internal TypeReference[] TypeReferences; internal FieldDefinition[] Fields; internal MethodDefinition[] Methods; internal MemberReference[] MemberReferences; internal Dictionary> NestedTypes; internal Dictionary ReverseNestedTypes; internal Dictionary>> Interfaces; internal Dictionary> ClassLayouts; internal Dictionary FieldLayouts; internal Dictionary FieldRVAs; internal Dictionary FieldMarshals; internal Dictionary> Constants; internal Dictionary> Overrides; internal Dictionary CustomAttributes; internal Dictionary SecurityDeclarations; internal Dictionary Events; internal Dictionary Properties; internal Dictionary> Semantics; internal Dictionary> PInvokes; internal Dictionary GenericParameters; internal Dictionary>> GenericConstraints; internal Document[] Documents; internal Dictionary>> LocalScopes; internal ImportDebugInformation[] ImportScopes; internal Dictionary StateMachineMethods; internal Dictionary[]> CustomDebugInformations; private static Dictionary> primitive_value_types; private static void InitializePrimitives() { Dictionary> types = new(18, StringComparer.Ordinal) { { "Void", new(ElementType.Void, false) }, { "Boolean", new(ElementType.Boolean, true) }, { "Char", new(ElementType.Char, true) }, { "SByte", new(ElementType.I1, true) }, { "Byte", new(ElementType.U1, true) }, { "Int16", new(ElementType.I2, true) }, { "UInt16", new(ElementType.U2, true) }, { "Int32", new(ElementType.I4, true) }, { "UInt32", new(ElementType.U4, true) }, { "Int64", new(ElementType.I8, true) }, { "UInt64", new(ElementType.U8, true) }, { "Single", new(ElementType.R4, true) }, { "Double", new(ElementType.R8, true) }, { "String", new(ElementType.String, false) }, { "TypedReference", new(ElementType.TypedByRef, false) }, { "IntPtr", new(ElementType.I, true) }, { "UIntPtr", new(ElementType.U, true) }, { "Object", new(ElementType.Object, false) } }; Interlocked.CompareExchange(ref primitive_value_types, types, null); } public static void TryProcessPrimitiveTypeReference(TypeReference type) { if (type.Namespace != "System") return; IMetadataScope scope = type.scope; if (scope == null || scope.MetadataScopeType != MetadataScopeType.AssemblyNameReference) return; Row primitive_data; if (!TryGetPrimitiveData(type, out primitive_data)) return; type.etype = primitive_data.Col1; type.IsValueType = primitive_data.Col2; } public static bool TryGetPrimitiveElementType(TypeDefinition type, out ElementType etype) { etype = ElementType.None; if (type.Namespace != "System") return false; Row primitive_data; if (TryGetPrimitiveData(type, out primitive_data)) { etype = primitive_data.Col1; return true; } return false; } private static bool TryGetPrimitiveData(TypeReference type, out Row primitive_data) { if (primitive_value_types == null) InitializePrimitives(); return primitive_value_types.TryGetValue(type.Name, out primitive_data); } public void Clear() { if (NestedTypes != null) NestedTypes = new(capacity: 0); if (ReverseNestedTypes != null) ReverseNestedTypes = new(capacity: 0); if (Interfaces != null) Interfaces = new(capacity: 0); if (ClassLayouts != null) ClassLayouts = new(capacity: 0); if (FieldLayouts != null) FieldLayouts = new(capacity: 0); if (FieldRVAs != null) FieldRVAs = new(capacity: 0); if (FieldMarshals != null) FieldMarshals = new(capacity: 0); if (Constants != null) Constants = new(capacity: 0); if (Overrides != null) Overrides = new(capacity: 0); if (CustomAttributes != null) CustomAttributes = new(capacity: 0); if (SecurityDeclarations != null) SecurityDeclarations = new(capacity: 0); if (Events != null) Events = new(capacity: 0); if (Properties != null) Properties = new(capacity: 0); if (Semantics != null) Semantics = new(capacity: 0); if (PInvokes != null) PInvokes = new(capacity: 0); if (GenericParameters != null) GenericParameters = new(capacity: 0); if (GenericConstraints != null) GenericConstraints = new(capacity: 0); Documents = Empty.Array; ImportScopes = Empty.Array; if (LocalScopes != null) LocalScopes = new(capacity: 0); if (StateMachineMethods != null) StateMachineMethods = new(capacity: 0); } public AssemblyNameReference GetAssemblyNameReference(uint rid) { if (rid < 1 || rid > AssemblyReferences.Length) return null; return AssemblyReferences[rid - 1]; } public TypeDefinition GetTypeDefinition(uint rid) { if (rid < 1 || rid > Types.Length) return null; return Types[rid - 1]; } public void AddTypeDefinition(TypeDefinition type) { Types[type.token.RID - 1] = type; } public TypeReference GetTypeReference(uint rid) { if (rid < 1 || rid > TypeReferences.Length) return null; return TypeReferences[rid - 1]; } public void AddTypeReference(TypeReference type) { TypeReferences[type.token.RID - 1] = type; } public FieldDefinition GetFieldDefinition(uint rid) { if (rid < 1 || rid > Fields.Length) return null; return Fields[rid - 1]; } public void AddFieldDefinition(FieldDefinition field) { Fields[field.token.RID - 1] = field; } public MethodDefinition GetMethodDefinition(uint rid) { if (rid < 1 || rid > Methods.Length) return null; return Methods[rid - 1]; } public void AddMethodDefinition(MethodDefinition method) { Methods[method.token.RID - 1] = method; } public MemberReference GetMemberReference(uint rid) { if (rid < 1 || rid > MemberReferences.Length) return null; return MemberReferences[rid - 1]; } public void AddMemberReference(MemberReference member) { MemberReferences[member.token.RID - 1] = member; } public bool TryGetNestedTypeMapping(TypeDefinition type, out Collection mapping) { return NestedTypes.TryGetValue(type.token.RID, out mapping); } public void SetNestedTypeMapping(uint type_rid, Collection mapping) { NestedTypes[type_rid] = mapping; } public void RemoveNestedTypeMapping(TypeDefinition type) { NestedTypes.Remove(type.token.RID); } public bool TryGetReverseNestedTypeMapping(TypeDefinition type, out uint declaring) { return ReverseNestedTypes.TryGetValue(type.token.RID, out declaring); } public void SetReverseNestedTypeMapping(uint nested, uint declaring) { ReverseNestedTypes[nested] = declaring; } public void RemoveReverseNestedTypeMapping(TypeDefinition type) { ReverseNestedTypes.Remove(type.token.RID); } public bool TryGetInterfaceMapping(TypeDefinition type, out Collection> mapping) { return Interfaces.TryGetValue(type.token.RID, out mapping); } public void SetInterfaceMapping(uint type_rid, Collection> mapping) { Interfaces[type_rid] = mapping; } public void RemoveInterfaceMapping(TypeDefinition type) { Interfaces.Remove(type.token.RID); } public void AddPropertiesRange(uint type_rid, Range range) { Properties.Add(type_rid, range); } public bool TryGetPropertiesRange(TypeDefinition type, out Range range) { return Properties.TryGetValue(type.token.RID, out range); } public void RemovePropertiesRange(TypeDefinition type) { Properties.Remove(type.token.RID); } public void AddEventsRange(uint type_rid, Range range) { Events.Add(type_rid, range); } public bool TryGetEventsRange(TypeDefinition type, out Range range) { return Events.TryGetValue(type.token.RID, out range); } public void RemoveEventsRange(TypeDefinition type) { Events.Remove(type.token.RID); } public bool TryGetGenericParameterRanges(IGenericParameterProvider owner, out Range[] ranges) { return GenericParameters.TryGetValue(owner.MetadataToken, out ranges); } public void RemoveGenericParameterRange(IGenericParameterProvider owner) { GenericParameters.Remove(owner.MetadataToken); } public bool TryGetCustomAttributeRanges(ICustomAttributeProvider owner, out Range[] ranges) { return CustomAttributes.TryGetValue(owner.MetadataToken, out ranges); } public void RemoveCustomAttributeRange(ICustomAttributeProvider owner) { CustomAttributes.Remove(owner.MetadataToken); } public bool TryGetSecurityDeclarationRanges(ISecurityDeclarationProvider owner, out Range[] ranges) { return SecurityDeclarations.TryGetValue(owner.MetadataToken, out ranges); } public void RemoveSecurityDeclarationRange(ISecurityDeclarationProvider owner) { SecurityDeclarations.Remove(owner.MetadataToken); } public bool TryGetGenericConstraintMapping(GenericParameter generic_parameter, out Collection> mapping) { return GenericConstraints.TryGetValue(generic_parameter.token.RID, out mapping); } public void SetGenericConstraintMapping(uint gp_rid, Collection> mapping) { GenericConstraints[gp_rid] = mapping; } public void RemoveGenericConstraintMapping(GenericParameter generic_parameter) { GenericConstraints.Remove(generic_parameter.token.RID); } public bool TryGetOverrideMapping(MethodDefinition method, out Collection mapping) { return Overrides.TryGetValue(method.token.RID, out mapping); } public void SetOverrideMapping(uint rid, Collection mapping) { Overrides[rid] = mapping; } public void RemoveOverrideMapping(MethodDefinition method) { Overrides.Remove(method.token.RID); } public Document GetDocument(uint rid) { if (rid < 1 || rid > Documents.Length) return null; return Documents[rid - 1]; } public bool TryGetLocalScopes(MethodDefinition method, out Collection> scopes) { return LocalScopes.TryGetValue(method.MetadataToken.RID, out scopes); } public void SetLocalScopes(uint method_rid, Collection> records) { LocalScopes[method_rid] = records; } public ImportDebugInformation GetImportScope(uint rid) { if (rid < 1 || rid > ImportScopes.Length) return null; return ImportScopes[rid - 1]; } public bool TryGetStateMachineKickOffMethod(MethodDefinition method, out uint rid) { return StateMachineMethods.TryGetValue(method.MetadataToken.RID, out rid); } public TypeDefinition GetFieldDeclaringType(uint field_rid) { return BinaryRangeSearch(Types, field_rid, true); } public TypeDefinition GetMethodDeclaringType(uint method_rid) { return BinaryRangeSearch(Types, method_rid, false); } private static TypeDefinition BinaryRangeSearch(TypeDefinition[] types, uint rid, bool field) { int min = 0; int max = types.Length - 1; while (min <= max) { int mid = min + (max - min) / 2; TypeDefinition type = types[mid]; Range range = field ? type.fields_range : type.methods_range; if (rid < range.Start) max = mid - 1; else if (rid >= range.Start + range.Length) min = mid + 1; else return type; } return null; } } }