// // 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 { struct Range { public uint Start; public uint Length; public Range (uint index, uint length) { this.Start = index; this.Length = length; } } 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; static Dictionary> primitive_value_types; static void InitializePrimitives () { var types = new Dictionary> (18, StringComparer.Ordinal) { { "Void", new Row (ElementType.Void, false) }, { "Boolean", new Row (ElementType.Boolean, true) }, { "Char", new Row (ElementType.Char, true) }, { "SByte", new Row (ElementType.I1, true) }, { "Byte", new Row (ElementType.U1, true) }, { "Int16", new Row (ElementType.I2, true) }, { "UInt16", new Row (ElementType.U2, true) }, { "Int32", new Row (ElementType.I4, true) }, { "UInt32", new Row (ElementType.U4, true) }, { "Int64", new Row (ElementType.I8, true) }, { "UInt64", new Row (ElementType.U8, true) }, { "Single", new Row (ElementType.R4, true) }, { "Double", new Row (ElementType.R8, true) }, { "String", new Row (ElementType.String, false) }, { "TypedReference", new Row (ElementType.TypedByRef, false) }, { "IntPtr", new Row (ElementType.I, true) }, { "UIntPtr", new Row (ElementType.U, true) }, { "Object", new Row (ElementType.Object, false) }, }; Interlocked.CompareExchange (ref primitive_value_types, types, null); } public static void TryProcessPrimitiveTypeReference (TypeReference type) { if (type.Namespace != "System") return; var 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; } 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 Dictionary> (capacity: 0); if (ReverseNestedTypes != null) ReverseNestedTypes = new Dictionary (capacity: 0); if (Interfaces != null) Interfaces = new Dictionary>> (capacity: 0); if (ClassLayouts != null) ClassLayouts = new Dictionary> (capacity: 0); if (FieldLayouts != null) FieldLayouts = new Dictionary (capacity: 0); if (FieldRVAs != null) FieldRVAs = new Dictionary (capacity: 0); if (FieldMarshals != null) FieldMarshals = new Dictionary (capacity: 0); if (Constants != null) Constants = new Dictionary> (capacity: 0); if (Overrides != null) Overrides = new Dictionary> (capacity: 0); if (CustomAttributes != null) CustomAttributes = new Dictionary (capacity: 0); if (SecurityDeclarations != null) SecurityDeclarations = new Dictionary (capacity: 0); if (Events != null) Events = new Dictionary (capacity: 0); if (Properties != null) Properties = new Dictionary (capacity: 0); if (Semantics != null) Semantics = new Dictionary> (capacity: 0); if (PInvokes != null) PInvokes = new Dictionary> (capacity: 0); if (GenericParameters != null) GenericParameters = new Dictionary (capacity: 0); if (GenericConstraints != null) GenericConstraints = new Dictionary>> (capacity: 0); Documents = Empty.Array; ImportScopes = Empty.Array; if (LocalScopes != null) LocalScopes = new Dictionary>> (capacity: 0); if (StateMachineMethods != null) StateMachineMethods = new Dictionary (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); } 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); var type = types [mid]; var 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; } } }