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