PageRenderTime 23ms CodeModel.GetById 2ms app.highlight 16ms RepoModel.GetById 1ms app.codeStats 0ms

/Mono.Cecil/MetadataSystem.cs

http://github.com/jbevain/cecil
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}