/Mono.Cecil/MetadataSystem.cs
C# | 432 lines | 342 code | 81 blank | 9 comment | 70 complexity | dcac970755c6cb3d599f03514fb9fb62 MD5 | raw file
1// 2// Author: 3// Jb Evain (jbevain@gmail.com) 4// 5// Copyright (c) 2008 - 2015 Jb Evain 6// Copyright (c) 2008 - 2011 Novell, Inc. 7// 8// Licensed under the MIT/X11 license. 9// 10 11using System; 12using System.Collections.Generic; 13using System.Runtime.CompilerServices; 14using System.Threading; 15using Mono.Cecil.Cil; 16using Mono.Cecil.Metadata; 17using Mono.Collections.Generic; 18 19namespace Mono.Cecil { 20 21 struct Range { 22 public uint Start; 23 public uint Length; 24 25 public Range (uint index, uint length) 26 { 27 this.Start = index; 28 this.Length = length; 29 } 30 } 31 32 sealed class MetadataSystem { 33 34 internal AssemblyNameReference [] AssemblyReferences; 35 internal ModuleReference [] ModuleReferences; 36 37 internal TypeDefinition [] Types; 38 internal TypeReference [] TypeReferences; 39 40 internal FieldDefinition [] Fields; 41 internal MethodDefinition [] Methods; 42 internal MemberReference [] MemberReferences; 43 44 internal Dictionary<uint, Collection<uint>> NestedTypes; 45 internal Dictionary<uint, uint> ReverseNestedTypes; 46 internal Dictionary<uint, Collection<Row<uint, MetadataToken>>> Interfaces; 47 internal Dictionary<uint, Row<ushort, uint>> ClassLayouts; 48 internal Dictionary<uint, uint> FieldLayouts; 49 internal Dictionary<uint, uint> FieldRVAs; 50 internal Dictionary<MetadataToken, uint> FieldMarshals; 51 internal Dictionary<MetadataToken, Row<ElementType, uint>> Constants; 52 internal Dictionary<uint, Collection<MetadataToken>> Overrides; 53 internal Dictionary<MetadataToken, Range []> CustomAttributes; 54 internal Dictionary<MetadataToken, Range []> SecurityDeclarations; 55 internal Dictionary<uint, Range> Events; 56 internal Dictionary<uint, Range> Properties; 57 internal Dictionary<uint, Row<MethodSemanticsAttributes, MetadataToken>> Semantics; 58 internal Dictionary<uint, Row<PInvokeAttributes, uint, uint>> PInvokes; 59 internal Dictionary<MetadataToken, Range []> GenericParameters; 60 internal Dictionary<uint, Collection<Row<uint, MetadataToken>>> GenericConstraints; 61 62 internal Document [] Documents; 63 internal Dictionary<uint, Collection<Row<uint, Range, Range, uint, uint, uint>>> LocalScopes; 64 internal ImportDebugInformation [] ImportScopes; 65 internal Dictionary<uint, uint> StateMachineMethods; 66 internal Dictionary<MetadataToken, Row<Guid, uint, uint> []> CustomDebugInformations; 67 68 static Dictionary<string, Row<ElementType, bool>> primitive_value_types; 69 70 static void InitializePrimitives () 71 { 72 var types = new Dictionary<string, Row<ElementType, bool>> (18, StringComparer.Ordinal) { 73 { "Void", new Row<ElementType, bool> (ElementType.Void, false) }, 74 { "Boolean", new Row<ElementType, bool> (ElementType.Boolean, true) }, 75 { "Char", new Row<ElementType, bool> (ElementType.Char, true) }, 76 { "SByte", new Row<ElementType, bool> (ElementType.I1, true) }, 77 { "Byte", new Row<ElementType, bool> (ElementType.U1, true) }, 78 { "Int16", new Row<ElementType, bool> (ElementType.I2, true) }, 79 { "UInt16", new Row<ElementType, bool> (ElementType.U2, true) }, 80 { "Int32", new Row<ElementType, bool> (ElementType.I4, true) }, 81 { "UInt32", new Row<ElementType, bool> (ElementType.U4, true) }, 82 { "Int64", new Row<ElementType, bool> (ElementType.I8, true) }, 83 { "UInt64", new Row<ElementType, bool> (ElementType.U8, true) }, 84 { "Single", new Row<ElementType, bool> (ElementType.R4, true) }, 85 { "Double", new Row<ElementType, bool> (ElementType.R8, true) }, 86 { "String", new Row<ElementType, bool> (ElementType.String, false) }, 87 { "TypedReference", new Row<ElementType, bool> (ElementType.TypedByRef, false) }, 88 { "IntPtr", new Row<ElementType, bool> (ElementType.I, true) }, 89 { "UIntPtr", new Row<ElementType, bool> (ElementType.U, true) }, 90 { "Object", new Row<ElementType, bool> (ElementType.Object, false) }, 91 }; 92 93 Interlocked.CompareExchange (ref primitive_value_types, types, null); 94 } 95 96 public static void TryProcessPrimitiveTypeReference (TypeReference type) 97 { 98 if (type.Namespace != "System") 99 return; 100 101 var scope = type.scope; 102 if (scope == null || scope.MetadataScopeType != MetadataScopeType.AssemblyNameReference) 103 return; 104 105 Row<ElementType, bool> primitive_data; 106 if (!TryGetPrimitiveData (type, out primitive_data)) 107 return; 108 109 type.etype = primitive_data.Col1; 110 type.IsValueType = primitive_data.Col2; 111 } 112 113 public static bool TryGetPrimitiveElementType (TypeDefinition type, out ElementType etype) 114 { 115 etype = ElementType.None; 116 117 if (type.Namespace != "System") 118 return false; 119 120 Row<ElementType, bool> primitive_data; 121 if (TryGetPrimitiveData (type, out primitive_data)) { 122 etype = primitive_data.Col1; 123 return true; 124 } 125 126 return false; 127 } 128 129 static bool TryGetPrimitiveData (TypeReference type, out Row<ElementType, bool> primitive_data) 130 { 131 if (primitive_value_types == null) 132 InitializePrimitives (); 133 134 return primitive_value_types.TryGetValue (type.Name, out primitive_data); 135 } 136 137 public void Clear () 138 { 139 if (NestedTypes != null) NestedTypes = new Dictionary<uint, Collection<uint>> (capacity: 0); 140 if (ReverseNestedTypes != null) ReverseNestedTypes = new Dictionary<uint, uint> (capacity: 0); 141 if (Interfaces != null) Interfaces = new Dictionary<uint, Collection<Row<uint, MetadataToken>>> (capacity: 0); 142 if (ClassLayouts != null) ClassLayouts = new Dictionary<uint, Row<ushort, uint>> (capacity: 0); 143 if (FieldLayouts != null) FieldLayouts = new Dictionary<uint, uint> (capacity: 0); 144 if (FieldRVAs != null) FieldRVAs = new Dictionary<uint, uint> (capacity: 0); 145 if (FieldMarshals != null) FieldMarshals = new Dictionary<MetadataToken, uint> (capacity: 0); 146 if (Constants != null) Constants = new Dictionary<MetadataToken, Row<ElementType, uint>> (capacity: 0); 147 if (Overrides != null) Overrides = new Dictionary<uint, Collection<MetadataToken>> (capacity: 0); 148 if (CustomAttributes != null) CustomAttributes = new Dictionary<MetadataToken, Range []> (capacity: 0); 149 if (SecurityDeclarations != null) SecurityDeclarations = new Dictionary<MetadataToken, Range []> (capacity: 0); 150 if (Events != null) Events = new Dictionary<uint, Range> (capacity: 0); 151 if (Properties != null) Properties = new Dictionary<uint, Range> (capacity: 0); 152 if (Semantics != null) Semantics = new Dictionary<uint, Row<MethodSemanticsAttributes, MetadataToken>> (capacity: 0); 153 if (PInvokes != null) PInvokes = new Dictionary<uint, Row<PInvokeAttributes, uint, uint>> (capacity: 0); 154 if (GenericParameters != null) GenericParameters = new Dictionary<MetadataToken, Range []> (capacity: 0); 155 if (GenericConstraints != null) GenericConstraints = new Dictionary<uint, Collection<Row<uint, MetadataToken>>> (capacity: 0); 156 157 Documents = Empty<Document>.Array; 158 ImportScopes = Empty<ImportDebugInformation>.Array; 159 if (LocalScopes != null) LocalScopes = new Dictionary<uint, Collection<Row<uint, Range, Range, uint, uint, uint>>> (capacity: 0); 160 if (StateMachineMethods != null) StateMachineMethods = new Dictionary<uint, uint> (capacity: 0); 161 } 162 163 public AssemblyNameReference GetAssemblyNameReference (uint rid) 164 { 165 if (rid < 1 || rid > AssemblyReferences.Length) 166 return null; 167 168 return AssemblyReferences [rid - 1]; 169 } 170 171 public TypeDefinition GetTypeDefinition (uint rid) 172 { 173 if (rid < 1 || rid > Types.Length) 174 return null; 175 176 return Types [rid - 1]; 177 } 178 179 public void AddTypeDefinition (TypeDefinition type) 180 { 181 Types [type.token.RID - 1] = type; 182 } 183 184 public TypeReference GetTypeReference (uint rid) 185 { 186 if (rid < 1 || rid > TypeReferences.Length) 187 return null; 188 189 return TypeReferences [rid - 1]; 190 } 191 192 public void AddTypeReference (TypeReference type) 193 { 194 TypeReferences [type.token.RID - 1] = type; 195 } 196 197 public FieldDefinition GetFieldDefinition (uint rid) 198 { 199 if (rid < 1 || rid > Fields.Length) 200 return null; 201 202 return Fields [rid - 1]; 203 } 204 205 public void AddFieldDefinition (FieldDefinition field) 206 { 207 Fields [field.token.RID - 1] = field; 208 } 209 210 public MethodDefinition GetMethodDefinition (uint rid) 211 { 212 if (rid < 1 || rid > Methods.Length) 213 return null; 214 215 return Methods [rid - 1]; 216 } 217 218 public void AddMethodDefinition (MethodDefinition method) 219 { 220 Methods [method.token.RID - 1] = method; 221 } 222 223 public MemberReference GetMemberReference (uint rid) 224 { 225 if (rid < 1 || rid > MemberReferences.Length) 226 return null; 227 228 return MemberReferences [rid - 1]; 229 } 230 231 public void AddMemberReference (MemberReference member) 232 { 233 MemberReferences [member.token.RID - 1] = member; 234 } 235 236 public bool TryGetNestedTypeMapping (TypeDefinition type, out Collection<uint> mapping) 237 { 238 return NestedTypes.TryGetValue (type.token.RID, out mapping); 239 } 240 241 public void SetNestedTypeMapping (uint type_rid, Collection<uint> mapping) 242 { 243 NestedTypes [type_rid] = mapping; 244 } 245 246 public void RemoveNestedTypeMapping (TypeDefinition type) 247 { 248 NestedTypes.Remove (type.token.RID); 249 } 250 251 public bool TryGetReverseNestedTypeMapping (TypeDefinition type, out uint declaring) 252 { 253 return ReverseNestedTypes.TryGetValue (type.token.RID, out declaring); 254 } 255 256 public void SetReverseNestedTypeMapping (uint nested, uint declaring) 257 { 258 ReverseNestedTypes [nested] = declaring; 259 } 260 261 public void RemoveReverseNestedTypeMapping (TypeDefinition type) 262 { 263 ReverseNestedTypes.Remove (type.token.RID); 264 } 265 266 public bool TryGetInterfaceMapping (TypeDefinition type, out Collection<Row<uint, MetadataToken>> mapping) 267 { 268 return Interfaces.TryGetValue (type.token.RID, out mapping); 269 } 270 271 public void SetInterfaceMapping (uint type_rid, Collection<Row<uint, MetadataToken>> mapping) 272 { 273 Interfaces [type_rid] = mapping; 274 } 275 276 public void RemoveInterfaceMapping (TypeDefinition type) 277 { 278 Interfaces.Remove (type.token.RID); 279 } 280 281 public void AddPropertiesRange (uint type_rid, Range range) 282 { 283 Properties.Add (type_rid, range); 284 } 285 286 public bool TryGetPropertiesRange (TypeDefinition type, out Range range) 287 { 288 return Properties.TryGetValue (type.token.RID, out range); 289 } 290 291 public void RemovePropertiesRange (TypeDefinition type) 292 { 293 Properties.Remove (type.token.RID); 294 } 295 296 public void AddEventsRange (uint type_rid, Range range) 297 { 298 Events.Add (type_rid, range); 299 } 300 301 public bool TryGetEventsRange (TypeDefinition type, out Range range) 302 { 303 return Events.TryGetValue (type.token.RID, out range); 304 } 305 306 public void RemoveEventsRange (TypeDefinition type) 307 { 308 Events.Remove (type.token.RID); 309 } 310 311 public bool TryGetGenericParameterRanges (IGenericParameterProvider owner, out Range [] ranges) 312 { 313 return GenericParameters.TryGetValue (owner.MetadataToken, out ranges); 314 } 315 316 public void RemoveGenericParameterRange (IGenericParameterProvider owner) 317 { 318 GenericParameters.Remove (owner.MetadataToken); 319 } 320 321 public bool TryGetCustomAttributeRanges (ICustomAttributeProvider owner, out Range [] ranges) 322 { 323 return CustomAttributes.TryGetValue (owner.MetadataToken, out ranges); 324 } 325 326 public void RemoveCustomAttributeRange (ICustomAttributeProvider owner) 327 { 328 CustomAttributes.Remove (owner.MetadataToken); 329 } 330 331 public bool TryGetSecurityDeclarationRanges (ISecurityDeclarationProvider owner, out Range [] ranges) 332 { 333 return SecurityDeclarations.TryGetValue (owner.MetadataToken, out ranges); 334 } 335 336 public void RemoveSecurityDeclarationRange (ISecurityDeclarationProvider owner) 337 { 338 SecurityDeclarations.Remove (owner.MetadataToken); 339 } 340 341 public bool TryGetGenericConstraintMapping (GenericParameter generic_parameter, out Collection<Row<uint, MetadataToken>> mapping) 342 { 343 return GenericConstraints.TryGetValue (generic_parameter.token.RID, out mapping); 344 } 345 346 public void SetGenericConstraintMapping (uint gp_rid, Collection<Row<uint, MetadataToken>> mapping) 347 { 348 GenericConstraints [gp_rid] = mapping; 349 } 350 351 public void RemoveGenericConstraintMapping (GenericParameter generic_parameter) 352 { 353 GenericConstraints.Remove (generic_parameter.token.RID); 354 } 355 356 public bool TryGetOverrideMapping (MethodDefinition method, out Collection<MetadataToken> mapping) 357 { 358 return Overrides.TryGetValue (method.token.RID, out mapping); 359 } 360 361 public void SetOverrideMapping (uint rid, Collection<MetadataToken> mapping) 362 { 363 Overrides [rid] = mapping; 364 } 365 366 public void RemoveOverrideMapping (MethodDefinition method) 367 { 368 Overrides.Remove (method.token.RID); 369 } 370 371 public Document GetDocument (uint rid) 372 { 373 if (rid < 1 || rid > Documents.Length) 374 return null; 375 376 return Documents [rid - 1]; 377 } 378 379 public bool TryGetLocalScopes (MethodDefinition method, out Collection<Row<uint, Range, Range, uint, uint, uint>> scopes) 380 { 381 return LocalScopes.TryGetValue (method.MetadataToken.RID, out scopes); 382 } 383 384 public void SetLocalScopes (uint method_rid, Collection<Row<uint, Range, Range, uint, uint, uint>> records) 385 { 386 LocalScopes [method_rid] = records; 387 } 388 389 public ImportDebugInformation GetImportScope (uint rid) 390 { 391 if (rid < 1 || rid > ImportScopes.Length) 392 return null; 393 394 return ImportScopes [rid - 1]; 395 } 396 397 public bool TryGetStateMachineKickOffMethod (MethodDefinition method, out uint rid) 398 { 399 return StateMachineMethods.TryGetValue (method.MetadataToken.RID, out rid); 400 } 401 402 public TypeDefinition GetFieldDeclaringType (uint field_rid) 403 { 404 return BinaryRangeSearch (Types, field_rid, true); 405 } 406 407 public TypeDefinition GetMethodDeclaringType (uint method_rid) 408 { 409 return BinaryRangeSearch (Types, method_rid, false); 410 } 411 412 static TypeDefinition BinaryRangeSearch (TypeDefinition [] types, uint rid, bool field) 413 { 414 int min = 0; 415 int max = types.Length - 1; 416 while (min <= max) { 417 int mid = min + ((max - min) / 2); 418 var type = types [mid]; 419 var range = field ? type.fields_range : type.methods_range; 420 421 if (rid < range.Start) 422 max = mid - 1; 423 else if (rid >= range.Start + range.Length) 424 min = mid + 1; 425 else 426 return type; 427 } 428 429 return null; 430 } 431 } 432}