You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

760 lines
26 KiB

7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
  1. using System;
  2. using System.Collections.Immutable;
  3. using System.IO;
  4. using System.IO.MemoryMappedFiles;
  5. using System.Reflection;
  6. using System.Reflection.Metadata;
  7. using System.Reflection.Metadata.Ecma335;
  8. using System.Reflection.PortableExecutable;
  9. using ICSharpCode.Decompiler.Metadata;
  10. using ICSharpCode.Decompiler.TypeSystem;
  11. using ICSharpCode.Decompiler.Util;
  12. using SRM = System.Reflection.Metadata;
  13. namespace ICSharpCode.Decompiler
  14. {
  15. public static partial class SRMExtensions
  16. {
  17. public static bool HasFlag(this TypeDefinition typeDefinition, TypeAttributes attribute)
  18. => (typeDefinition.Attributes & attribute) == attribute;
  19. public static bool HasFlag(this MethodDefinition methodDefinition, MethodAttributes attribute)
  20. => (methodDefinition.Attributes & attribute) == attribute;
  21. public static bool HasFlag(this FieldDefinition fieldDefinition, FieldAttributes attribute)
  22. => (fieldDefinition.Attributes & attribute) == attribute;
  23. public static bool HasFlag(this PropertyDefinition propertyDefinition, PropertyAttributes attribute)
  24. => (propertyDefinition.Attributes & attribute) == attribute;
  25. public static bool HasFlag(this EventDefinition eventDefinition, EventAttributes attribute)
  26. => (eventDefinition.Attributes & attribute) == attribute;
  27. public static bool IsTypeKind(this HandleKind kind) =>
  28. kind == HandleKind.TypeDefinition || kind == HandleKind.TypeReference
  29. || kind == HandleKind.TypeSpecification;
  30. public static bool IsMemberKind(this HandleKind kind) =>
  31. kind == HandleKind.MethodDefinition || kind == HandleKind.PropertyDefinition
  32. || kind == HandleKind.FieldDefinition || kind == HandleKind.EventDefinition
  33. || kind == HandleKind.MemberReference || kind == HandleKind.MethodSpecification;
  34. public static bool IsEntityHandle(this Handle handle) =>
  35. handle.IsNil || (byte)handle.Kind < 112;
  36. public static bool IsValueType(this TypeDefinitionHandle handle, MetadataReader reader)
  37. {
  38. return reader.GetTypeDefinition(handle).IsValueType(reader);
  39. }
  40. public static bool IsValueType(this TypeDefinition typeDefinition, MetadataReader reader)
  41. {
  42. EntityHandle baseType = typeDefinition.GetBaseTypeOrNil();
  43. if (baseType.IsNil)
  44. return false;
  45. if (baseType.IsKnownType(reader, KnownTypeCode.Enum))
  46. return true;
  47. if (!baseType.IsKnownType(reader, KnownTypeCode.ValueType))
  48. return false;
  49. var thisType = typeDefinition.GetFullTypeName(reader);
  50. return !thisType.IsKnownType(KnownTypeCode.Enum);
  51. }
  52. public static bool IsEnum(this TypeDefinitionHandle handle, MetadataReader reader)
  53. {
  54. return reader.GetTypeDefinition(handle).IsEnum(reader);
  55. }
  56. public static bool IsEnum(this TypeDefinition typeDefinition, MetadataReader reader)
  57. {
  58. EntityHandle baseType = typeDefinition.GetBaseTypeOrNil();
  59. if (baseType.IsNil)
  60. return false;
  61. return baseType.IsKnownType(reader, KnownTypeCode.Enum);
  62. }
  63. public static bool IsEnum(this TypeDefinitionHandle handle, MetadataReader reader,
  64. out PrimitiveTypeCode underlyingType)
  65. {
  66. return reader.GetTypeDefinition(handle).IsEnum(reader, out underlyingType);
  67. }
  68. public static bool IsEnum(this TypeDefinition typeDefinition, MetadataReader reader,
  69. out PrimitiveTypeCode underlyingType)
  70. {
  71. underlyingType = 0;
  72. EntityHandle baseType = typeDefinition.GetBaseTypeOrNil();
  73. if (baseType.IsNil)
  74. return false;
  75. if (!baseType.IsKnownType(reader, KnownTypeCode.Enum))
  76. return false;
  77. foreach (var handle in typeDefinition.GetFields())
  78. {
  79. var field = reader.GetFieldDefinition(handle);
  80. if ((field.Attributes & FieldAttributes.Static) != 0)
  81. continue;
  82. var blob = reader.GetBlobReader(field.Signature);
  83. if (blob.ReadSignatureHeader().Kind != SignatureKind.Field)
  84. return false;
  85. underlyingType = (PrimitiveTypeCode)blob.ReadByte();
  86. return true;
  87. }
  88. return false;
  89. }
  90. public static bool IsDelegate(this TypeDefinitionHandle handle, MetadataReader reader)
  91. {
  92. return reader.GetTypeDefinition(handle).IsDelegate(reader);
  93. }
  94. public static bool IsDelegate(this TypeDefinition typeDefinition, MetadataReader reader)
  95. {
  96. var baseType = typeDefinition.GetBaseTypeOrNil();
  97. return !baseType.IsNil && baseType.IsKnownType(reader, KnownTypeCode.MulticastDelegate);
  98. }
  99. public static bool HasBody(this MethodDefinition methodDefinition)
  100. {
  101. const MethodAttributes noBodyAttrs = MethodAttributes.Abstract | MethodAttributes.PinvokeImpl;
  102. const MethodImplAttributes noBodyImplAttrs = MethodImplAttributes.InternalCall
  103. | MethodImplAttributes.Native | MethodImplAttributes.Unmanaged | MethodImplAttributes.Runtime;
  104. return (methodDefinition.Attributes & noBodyAttrs) == 0 &&
  105. (methodDefinition.ImplAttributes & noBodyImplAttrs) == 0 &&
  106. methodDefinition.RelativeVirtualAddress > 0;
  107. }
  108. public static int GetCodeSize(this MethodBodyBlock body)
  109. {
  110. if (body == null)
  111. throw new ArgumentNullException(nameof(body));
  112. return body.GetILReader().Length;
  113. }
  114. public static MethodDefinitionHandle GetAny(this PropertyAccessors accessors)
  115. {
  116. if (!accessors.Getter.IsNil)
  117. return accessors.Getter;
  118. return accessors.Setter;
  119. }
  120. public static MethodDefinitionHandle GetAny(this EventAccessors accessors)
  121. {
  122. if (!accessors.Adder.IsNil)
  123. return accessors.Adder;
  124. if (!accessors.Remover.IsNil)
  125. return accessors.Remover;
  126. return accessors.Raiser;
  127. }
  128. public static EntityHandle GetGenericType(this in TypeSpecification ts, MetadataReader metadata)
  129. {
  130. if (ts.Signature.IsNil)
  131. return default;
  132. // Do a quick scan using BlobReader
  133. var signature = metadata.GetBlobReader(ts.Signature);
  134. // When dealing with FSM implementations, we can safely assume that if it's a type spec,
  135. // it must be a generic type instance.
  136. if (signature.ReadByte() != (byte)SignatureTypeCode.GenericTypeInstance)
  137. return default;
  138. // Skip over the rawTypeKind: value type or class
  139. var rawTypeKind = signature.ReadCompressedInteger();
  140. if (rawTypeKind < 17 || rawTypeKind > 18)
  141. return default;
  142. // Only read the generic type, ignore the type arguments
  143. return signature.ReadTypeHandle();
  144. }
  145. public static EntityHandle GetDeclaringType(this EntityHandle entity, MetadataReader metadata)
  146. {
  147. switch (entity.Kind)
  148. {
  149. case HandleKind.TypeDefinition:
  150. var td = metadata.GetTypeDefinition((TypeDefinitionHandle)entity);
  151. return td.GetDeclaringType();
  152. case HandleKind.TypeReference:
  153. var tr = metadata.GetTypeReference((TypeReferenceHandle)entity);
  154. return tr.GetDeclaringType();
  155. case HandleKind.TypeSpecification:
  156. var ts = metadata.GetTypeSpecification((TypeSpecificationHandle)entity);
  157. return ts.GetGenericType(metadata).GetDeclaringType(metadata);
  158. case HandleKind.FieldDefinition:
  159. var fd = metadata.GetFieldDefinition((FieldDefinitionHandle)entity);
  160. return fd.GetDeclaringType();
  161. case HandleKind.MethodDefinition:
  162. var md = metadata.GetMethodDefinition((MethodDefinitionHandle)entity);
  163. return md.GetDeclaringType();
  164. case HandleKind.MemberReference:
  165. var mr = metadata.GetMemberReference((MemberReferenceHandle)entity);
  166. return mr.Parent;
  167. case HandleKind.EventDefinition:
  168. var ed = metadata.GetEventDefinition((EventDefinitionHandle)entity);
  169. return metadata.GetMethodDefinition(ed.GetAccessors().GetAny()).GetDeclaringType();
  170. case HandleKind.PropertyDefinition:
  171. var pd = metadata.GetPropertyDefinition((PropertyDefinitionHandle)entity);
  172. return metadata.GetMethodDefinition(pd.GetAccessors().GetAny()).GetDeclaringType();
  173. case HandleKind.MethodSpecification:
  174. var ms = metadata.GetMethodSpecification((MethodSpecificationHandle)entity);
  175. return ms.Method.GetDeclaringType(metadata);
  176. default:
  177. throw new ArgumentOutOfRangeException();
  178. }
  179. }
  180. public static TypeReferenceHandle GetDeclaringType(this in TypeReference tr)
  181. {
  182. switch (tr.ResolutionScope.Kind)
  183. {
  184. case HandleKind.TypeReference:
  185. return (TypeReferenceHandle)tr.ResolutionScope;
  186. default:
  187. return default(TypeReferenceHandle);
  188. }
  189. }
  190. public static FullTypeName GetFullTypeName(this EntityHandle handle, MetadataReader reader)
  191. {
  192. if (handle.IsNil)
  193. throw new ArgumentNullException(nameof(handle));
  194. switch (handle.Kind)
  195. {
  196. case HandleKind.TypeDefinition:
  197. return ((TypeDefinitionHandle)handle).GetFullTypeName(reader);
  198. case HandleKind.TypeReference:
  199. return ((TypeReferenceHandle)handle).GetFullTypeName(reader);
  200. case HandleKind.TypeSpecification:
  201. return ((TypeSpecificationHandle)handle).GetFullTypeName(reader);
  202. default:
  203. throw new ArgumentOutOfRangeException();
  204. }
  205. }
  206. public static bool IsKnownType(this EntityHandle handle, MetadataReader reader,
  207. KnownTypeCode knownType)
  208. {
  209. return IsKnownType(handle, reader, KnownTypeReference.Get(knownType).TypeName);
  210. }
  211. internal static bool IsKnownType(this EntityHandle handle, MetadataReader reader,
  212. KnownAttribute knownType)
  213. {
  214. return IsKnownType(handle, reader, knownType.GetTypeName());
  215. }
  216. private static bool IsKnownType(EntityHandle handle, MetadataReader reader, TopLevelTypeName knownType)
  217. {
  218. if (handle.IsNil)
  219. return false;
  220. StringHandle nameHandle, namespaceHandle;
  221. try
  222. {
  223. switch (handle.Kind)
  224. {
  225. case HandleKind.TypeReference:
  226. var tr = reader.GetTypeReference((TypeReferenceHandle)handle);
  227. // ignore exported and nested types
  228. if (tr.ResolutionScope.IsNil || tr.ResolutionScope.Kind == HandleKind.TypeReference)
  229. return false;
  230. nameHandle = tr.Name;
  231. namespaceHandle = tr.Namespace;
  232. break;
  233. case HandleKind.TypeDefinition:
  234. var td = reader.GetTypeDefinition((TypeDefinitionHandle)handle);
  235. if (td.IsNested)
  236. return false;
  237. nameHandle = td.Name;
  238. namespaceHandle = td.Namespace;
  239. break;
  240. case HandleKind.TypeSpecification:
  241. var ts = reader.GetTypeSpecification((TypeSpecificationHandle)handle);
  242. var blob = reader.GetBlobReader(ts.Signature);
  243. return SignatureIsKnownType(reader, knownType, ref blob);
  244. default:
  245. return false;
  246. }
  247. }
  248. catch (BadImageFormatException)
  249. {
  250. // ignore bad metadata when trying to resolve ResolutionScope et al.
  251. return false;
  252. }
  253. if (knownType.TypeParameterCount == 0)
  254. {
  255. if (!reader.StringComparer.Equals(nameHandle, knownType.Name))
  256. return false;
  257. }
  258. else
  259. {
  260. string name = reader.GetString(nameHandle);
  261. name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(name, out int typeParameterCount);
  262. if (typeParameterCount != knownType.TypeParameterCount || name != knownType.Name)
  263. return false;
  264. }
  265. if (namespaceHandle.IsNil)
  266. {
  267. return knownType.Namespace.Length == 0;
  268. }
  269. else
  270. {
  271. return reader.StringComparer.Equals(namespaceHandle, knownType.Namespace);
  272. }
  273. }
  274. private static bool SignatureIsKnownType(MetadataReader reader, TopLevelTypeName knownType, ref BlobReader blob)
  275. {
  276. if (!blob.TryReadCompressedInteger(out int typeCode))
  277. return false;
  278. switch (typeCode)
  279. {
  280. case 0x1: // ELEMENT_TYPE_VOID
  281. return knownType.IsKnownType(KnownTypeCode.Void);
  282. case 0x2: // ELEMENT_TYPE_BOOLEAN
  283. return knownType.IsKnownType(KnownTypeCode.Boolean);
  284. case 0x3: // ELEMENT_TYPE_CHAR
  285. return knownType.IsKnownType(KnownTypeCode.Char);
  286. case 0x4: // ELEMENT_TYPE_I1
  287. return knownType.IsKnownType(KnownTypeCode.SByte);
  288. case 0x5: // ELEMENT_TYPE_U1
  289. return knownType.IsKnownType(KnownTypeCode.Byte);
  290. case 0x6: // ELEMENT_TYPE_I2
  291. return knownType.IsKnownType(KnownTypeCode.Int16);
  292. case 0x7: // ELEMENT_TYPE_U2
  293. return knownType.IsKnownType(KnownTypeCode.UInt16);
  294. case 0x8: // ELEMENT_TYPE_I4
  295. return knownType.IsKnownType(KnownTypeCode.Int32);
  296. case 0x9: // ELEMENT_TYPE_U4
  297. return knownType.IsKnownType(KnownTypeCode.UInt32);
  298. case 0xA: // ELEMENT_TYPE_I8
  299. return knownType.IsKnownType(KnownTypeCode.Int64);
  300. case 0xB: // ELEMENT_TYPE_U8
  301. return knownType.IsKnownType(KnownTypeCode.UInt64);
  302. case 0xC: // ELEMENT_TYPE_R4
  303. return knownType.IsKnownType(KnownTypeCode.Single);
  304. case 0xD: // ELEMENT_TYPE_R8
  305. return knownType.IsKnownType(KnownTypeCode.Double);
  306. case 0xE: // ELEMENT_TYPE_STRING
  307. return knownType.IsKnownType(KnownTypeCode.String);
  308. case 0x16: // ELEMENT_TYPE_TYPEDBYREF
  309. return knownType.IsKnownType(KnownTypeCode.TypedReference);
  310. case 0x18: // ELEMENT_TYPE_I
  311. return knownType.IsKnownType(KnownTypeCode.IntPtr);
  312. case 0x19: // ELEMENT_TYPE_U
  313. return knownType.IsKnownType(KnownTypeCode.UIntPtr);
  314. case 0x1C: // ELEMENT_TYPE_OBJECT
  315. return knownType.IsKnownType(KnownTypeCode.Object);
  316. case 0xF: // ELEMENT_TYPE_PTR
  317. case 0x10: // ELEMENT_TYPE_BYREF
  318. case 0x45: // ELEMENT_TYPE_PINNED
  319. case 0x1D: // ELEMENT_TYPE_SZARRAY
  320. case 0x1B: // ELEMENT_TYPE_FNPTR
  321. case 0x14: // ELEMENT_TYPE_ARRAY
  322. return false;
  323. case 0x1F: // ELEMENT_TYPE_CMOD_REQD
  324. case 0x20: // ELEMENT_TYPE_CMOD_OPT
  325. // modifier
  326. blob.ReadTypeHandle(); // skip modifier
  327. return SignatureIsKnownType(reader, knownType, ref blob);
  328. case 0x15: // ELEMENT_TYPE_GENERICINST
  329. // generic type
  330. return SignatureIsKnownType(reader, knownType, ref blob);
  331. case 0x13: // ELEMENT_TYPE_VAR
  332. case 0x1E: // ELEMENT_TYPE_MVAR
  333. // index
  334. return false;
  335. case 0x11: // ELEMENT_TYPE_VALUETYPE
  336. case 0x12: // ELEMENT_TYPE_CLASS
  337. return IsKnownType(blob.ReadTypeHandle(), reader, knownType);
  338. default:
  339. return false;
  340. }
  341. }
  342. public static FullTypeName GetFullTypeName(this TypeSpecificationHandle handle, MetadataReader reader)
  343. {
  344. if (handle.IsNil)
  345. throw new ArgumentNullException(nameof(handle));
  346. var ts = reader.GetTypeSpecification(handle);
  347. return ts.DecodeSignature(new Metadata.FullTypeNameSignatureDecoder(reader), default(Unit));
  348. }
  349. public static FullTypeName GetFullTypeName(this TypeReferenceHandle handle, MetadataReader reader)
  350. {
  351. if (handle.IsNil)
  352. throw new ArgumentNullException(nameof(handle));
  353. var tr = reader.GetTypeReference(handle);
  354. string name;
  355. try
  356. {
  357. name = reader.GetString(tr.Name);
  358. }
  359. catch (BadImageFormatException)
  360. {
  361. name = $"TR{reader.GetToken(handle):x8}";
  362. }
  363. name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(
  364. name, out var typeParameterCount);
  365. TypeReferenceHandle declaringTypeHandle;
  366. try
  367. {
  368. declaringTypeHandle = tr.GetDeclaringType();
  369. }
  370. catch (BadImageFormatException)
  371. {
  372. declaringTypeHandle = default;
  373. }
  374. if (declaringTypeHandle.IsNil)
  375. {
  376. string ns;
  377. try
  378. {
  379. ns = tr.Namespace.IsNil ? "" : reader.GetString(tr.Namespace);
  380. }
  381. catch (BadImageFormatException)
  382. {
  383. ns = "";
  384. }
  385. return new FullTypeName(new TopLevelTypeName(ns, name, typeParameterCount));
  386. }
  387. else
  388. {
  389. return declaringTypeHandle.GetFullTypeName(reader).NestedType(name, typeParameterCount);
  390. }
  391. }
  392. public static FullTypeName GetFullTypeName(this TypeDefinitionHandle handle, MetadataReader reader)
  393. {
  394. if (handle.IsNil)
  395. throw new ArgumentNullException(nameof(handle));
  396. return reader.GetTypeDefinition(handle).GetFullTypeName(reader);
  397. }
  398. public static FullTypeName GetFullTypeName(this TypeDefinition td, MetadataReader reader)
  399. {
  400. TypeDefinitionHandle declaringTypeHandle;
  401. string name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(
  402. reader.GetString(td.Name), out var typeParameterCount);
  403. if ((declaringTypeHandle = td.GetDeclaringType()).IsNil)
  404. {
  405. string @namespace = td.Namespace.IsNil ? "" : reader.GetString(td.Namespace);
  406. return new FullTypeName(new TopLevelTypeName(@namespace, name, typeParameterCount));
  407. }
  408. else
  409. {
  410. return declaringTypeHandle.GetFullTypeName(reader).NestedType(name, typeParameterCount);
  411. }
  412. }
  413. public static FullTypeName GetFullTypeName(this ExportedType type, MetadataReader metadata)
  414. {
  415. string name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(
  416. metadata.GetString(type.Name), out int typeParameterCount);
  417. if (type.Implementation.Kind == HandleKind.ExportedType)
  418. {
  419. var outerType = metadata.GetExportedType((ExportedTypeHandle)type.Implementation);
  420. return outerType.GetFullTypeName(metadata).NestedType(name, typeParameterCount);
  421. }
  422. else
  423. {
  424. string ns = type.Namespace.IsNil ? "" : metadata.GetString(type.Namespace);
  425. return new TopLevelTypeName(ns, name, typeParameterCount);
  426. }
  427. }
  428. public static bool IsAnonymousType(this TypeDefinition type, MetadataReader metadata)
  429. {
  430. string name = metadata.GetString(type.Name);
  431. if (type.Namespace.IsNil && type.HasGeneratedName(metadata)
  432. && (name.Contains("AnonType") || name.Contains("AnonymousType")))
  433. {
  434. return type.IsCompilerGenerated(metadata);
  435. }
  436. return false;
  437. }
  438. #region HasGeneratedName
  439. public static bool IsGeneratedName(this StringHandle handle, MetadataReader metadata)
  440. {
  441. return !handle.IsNil
  442. && (metadata.GetString(handle).StartsWith("<", StringComparison.Ordinal)
  443. || metadata.GetString(handle).Contains("$"));
  444. }
  445. public static bool HasGeneratedName(this MethodDefinitionHandle handle, MetadataReader metadata)
  446. {
  447. return metadata.GetMethodDefinition(handle).Name.IsGeneratedName(metadata);
  448. }
  449. public static bool HasGeneratedName(this TypeDefinitionHandle handle, MetadataReader metadata)
  450. {
  451. return metadata.GetTypeDefinition(handle).Name.IsGeneratedName(metadata);
  452. }
  453. public static bool HasGeneratedName(this TypeDefinition type, MetadataReader metadata)
  454. {
  455. return type.Name.IsGeneratedName(metadata);
  456. }
  457. public static bool HasGeneratedName(this FieldDefinitionHandle handle, MetadataReader metadata)
  458. {
  459. return metadata.GetFieldDefinition(handle).Name.IsGeneratedName(metadata);
  460. }
  461. #endregion
  462. #region IsCompilerGenerated
  463. public static bool IsCompilerGenerated(this MethodDefinitionHandle handle, MetadataReader metadata)
  464. {
  465. return metadata.GetMethodDefinition(handle).IsCompilerGenerated(metadata);
  466. }
  467. public static bool IsCompilerGeneratedOrIsInCompilerGeneratedClass(this MethodDefinitionHandle handle,
  468. MetadataReader metadata)
  469. {
  470. MethodDefinition method = metadata.GetMethodDefinition(handle);
  471. if (method.IsCompilerGenerated(metadata))
  472. return true;
  473. TypeDefinitionHandle declaringTypeHandle = method.GetDeclaringType();
  474. if (!declaringTypeHandle.IsNil && declaringTypeHandle.IsCompilerGenerated(metadata))
  475. return true;
  476. return false;
  477. }
  478. public static bool IsCompilerGeneratedOrIsInCompilerGeneratedClass(this TypeDefinitionHandle handle,
  479. MetadataReader metadata)
  480. {
  481. TypeDefinition type = metadata.GetTypeDefinition(handle);
  482. if (type.IsCompilerGenerated(metadata))
  483. return true;
  484. TypeDefinitionHandle declaringTypeHandle = type.GetDeclaringType();
  485. if (!declaringTypeHandle.IsNil && declaringTypeHandle.IsCompilerGenerated(metadata))
  486. return true;
  487. return false;
  488. }
  489. public static bool IsCompilerGenerated(this MethodDefinition method, MetadataReader metadata)
  490. {
  491. return method.GetCustomAttributes().HasKnownAttribute(metadata, KnownAttribute.CompilerGenerated);
  492. }
  493. public static bool IsCompilerGenerated(this FieldDefinitionHandle handle, MetadataReader metadata)
  494. {
  495. return metadata.GetFieldDefinition(handle).IsCompilerGenerated(metadata);
  496. }
  497. public static bool IsCompilerGenerated(this FieldDefinition field, MetadataReader metadata)
  498. {
  499. return field.GetCustomAttributes().HasKnownAttribute(metadata, KnownAttribute.CompilerGenerated);
  500. }
  501. public static bool IsCompilerGenerated(this TypeDefinitionHandle handle, MetadataReader metadata)
  502. {
  503. return metadata.GetTypeDefinition(handle).IsCompilerGenerated(metadata);
  504. }
  505. public static bool IsCompilerGenerated(this TypeDefinition type, MetadataReader metadata)
  506. {
  507. return type.GetCustomAttributes().HasKnownAttribute(metadata, KnownAttribute.CompilerGenerated);
  508. }
  509. #endregion
  510. #region Attribute extensions
  511. /// <summary>
  512. /// Gets the type of the attribute.
  513. /// </summary>
  514. public static EntityHandle GetAttributeType(this SRM.CustomAttribute attribute, MetadataReader reader)
  515. {
  516. switch (attribute.Constructor.Kind)
  517. {
  518. case HandleKind.MethodDefinition:
  519. var md = reader.GetMethodDefinition((MethodDefinitionHandle)attribute.Constructor);
  520. return md.GetDeclaringType();
  521. case HandleKind.MemberReference:
  522. var mr = reader.GetMemberReference((MemberReferenceHandle)attribute.Constructor);
  523. return mr.Parent;
  524. default:
  525. throw new BadImageFormatException("Unexpected token kind for attribute constructor: "
  526. + attribute.Constructor.Kind);
  527. }
  528. }
  529. public static bool HasKnownAttribute(this CustomAttributeHandleCollection customAttributes,
  530. MetadataReader metadata, KnownAttribute type)
  531. {
  532. foreach (var handle in customAttributes)
  533. {
  534. var customAttribute = metadata.GetCustomAttribute(handle);
  535. if (customAttribute.IsKnownAttribute(metadata, type))
  536. return true;
  537. }
  538. return false;
  539. }
  540. internal static bool IsKnownAttribute(this SRM.CustomAttribute attr, MetadataReader metadata,
  541. KnownAttribute attrType)
  542. {
  543. return attr.GetAttributeType(metadata).IsKnownType(metadata, attrType);
  544. }
  545. public static Nullability? GetNullableContext(this CustomAttributeHandleCollection customAttributes,
  546. MetadataReader metadata)
  547. {
  548. foreach (var handle in customAttributes)
  549. {
  550. var customAttribute = metadata.GetCustomAttribute(handle);
  551. if (customAttribute.IsKnownAttribute(metadata, KnownAttribute.NullableContext))
  552. {
  553. // Decode
  554. CustomAttributeValue<IType> value;
  555. try
  556. {
  557. value = customAttribute.DecodeValue(
  558. Metadata.MetadataExtensions.MinimalAttributeTypeProvider);
  559. }
  560. catch (BadImageFormatException)
  561. {
  562. continue;
  563. }
  564. catch (Metadata.EnumUnderlyingTypeResolveException)
  565. {
  566. continue;
  567. }
  568. if (value.FixedArguments.Length == 1 && value.FixedArguments[0].Value is byte b && b <= 2)
  569. {
  570. return (Nullability)b;
  571. }
  572. }
  573. }
  574. return null;
  575. }
  576. #endregion
  577. public static unsafe BlobReader GetInitialValue(this FieldDefinition field, MetadataFile pefile,
  578. ICompilation typeSystem)
  579. {
  580. if (!field.HasFlag(FieldAttributes.HasFieldRVA))
  581. return default;
  582. int rva = field.GetRelativeVirtualAddress();
  583. if (rva == 0)
  584. return default;
  585. int size = field.DecodeSignature(new FieldValueSizeDecoder(typeSystem), default);
  586. var sectionData = pefile.GetSectionData(rva);
  587. if (sectionData.Length == 0 && size != 0)
  588. throw new BadImageFormatException($"Field data (rva=0x{rva:x}) could not be found"
  589. + "in any section!");
  590. if (size < 0 || size > sectionData.Length)
  591. throw new BadImageFormatException($"Invalid size {size} for field data!");
  592. return sectionData.GetReader(0, size);
  593. }
  594. sealed class FieldValueSizeDecoder : ISignatureTypeProvider<int, GenericContext>
  595. {
  596. readonly MetadataModule module;
  597. readonly int pointerSize;
  598. public FieldValueSizeDecoder(ICompilation typeSystem = null)
  599. {
  600. this.module = (MetadataModule)typeSystem?.MainModule;
  601. if (module?.MetadataFile is not PEFile pefile)
  602. this.pointerSize = IntPtr.Size;
  603. else
  604. this.pointerSize = pefile.Reader.PEHeaders.PEHeader.Magic == PEMagic.PE32 ? 4 : 8;
  605. }
  606. public int GetArrayType(int elementType, ArrayShape shape) =>
  607. GetPrimitiveType(PrimitiveTypeCode.Object);
  608. public int GetSZArrayType(int elementType) => GetPrimitiveType(PrimitiveTypeCode.Object);
  609. public int GetByReferenceType(int elementType) => pointerSize;
  610. public int GetFunctionPointerType(MethodSignature<int> signature) => pointerSize;
  611. public int GetGenericInstantiation(int genericType, ImmutableArray<int> typeArguments)
  612. => genericType;
  613. public int GetGenericMethodParameter(GenericContext genericContext, int index) => 0;
  614. public int GetGenericTypeParameter(GenericContext genericContext, int index) => 0;
  615. public int GetModifiedType(int modifier, int unmodifiedType, bool isRequired) => unmodifiedType;
  616. public int GetPinnedType(int elementType) => elementType;
  617. public int GetPointerType(int elementType) => pointerSize;
  618. public int GetPrimitiveType(PrimitiveTypeCode typeCode)
  619. {
  620. switch (typeCode)
  621. {
  622. case PrimitiveTypeCode.Boolean:
  623. case PrimitiveTypeCode.Byte:
  624. case PrimitiveTypeCode.SByte:
  625. return 1;
  626. case PrimitiveTypeCode.Char:
  627. case PrimitiveTypeCode.Int16:
  628. case PrimitiveTypeCode.UInt16:
  629. return 2;
  630. case PrimitiveTypeCode.Int32:
  631. case PrimitiveTypeCode.UInt32:
  632. case PrimitiveTypeCode.Single:
  633. return 4;
  634. case PrimitiveTypeCode.Int64:
  635. case PrimitiveTypeCode.UInt64:
  636. case PrimitiveTypeCode.Double:
  637. return 8;
  638. case PrimitiveTypeCode.IntPtr:
  639. case PrimitiveTypeCode.UIntPtr:
  640. return pointerSize;
  641. default:
  642. return 0;
  643. }
  644. }
  645. public int GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle,
  646. byte rawTypeKind)
  647. {
  648. var td = reader.GetTypeDefinition(handle);
  649. return td.GetLayout().Size;
  650. }
  651. public int GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle,
  652. byte rawTypeKind)
  653. {
  654. var typeDef = module?.ResolveType(handle, new GenericContext()).GetDefinition();
  655. if (typeDef == null || typeDef.MetadataToken.IsNil)
  656. return 0;
  657. reader = typeDef.ParentModule.MetadataFile.Metadata;
  658. var td = reader.GetTypeDefinition((TypeDefinitionHandle)typeDef.MetadataToken);
  659. return td.GetLayout().Size;
  660. }
  661. public int GetTypeFromSpecification(MetadataReader reader, GenericContext genericContext,
  662. TypeSpecificationHandle handle, byte rawTypeKind)
  663. {
  664. return reader.GetTypeSpecification(handle).DecodeSignature(this, genericContext);
  665. }
  666. }
  667. public static EntityHandle GetBaseTypeOrNil(this TypeDefinition definition)
  668. {
  669. try
  670. {
  671. return definition.BaseType;
  672. }
  673. catch (BadImageFormatException)
  674. {
  675. return default;
  676. }
  677. }
  678. public static string ToILSyntax(this SignatureCallingConvention callConv)
  679. {
  680. return callConv switch {
  681. SignatureCallingConvention.Default => "default",
  682. SignatureCallingConvention.CDecl => "unmanaged cdecl",
  683. SignatureCallingConvention.StdCall => "unmanaged stdcall",
  684. SignatureCallingConvention.ThisCall => "unmanaged thiscall",
  685. SignatureCallingConvention.FastCall => "unmanaged fastcall",
  686. SignatureCallingConvention.VarArgs => "vararg",
  687. SignatureCallingConvention.Unmanaged => "unmanaged",
  688. _ => callConv.ToString().ToLowerInvariant()
  689. };
  690. }
  691. public static UnmanagedMemoryStream AsStream(this MemoryMappedViewAccessor view)
  692. {
  693. long size = checked((long)view.SafeMemoryMappedViewHandle.ByteLength);
  694. return new UnmanagedMemoryStream(view.SafeMemoryMappedViewHandle, 0, size);
  695. }
  696. }
  697. }