PageRenderTime 60ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/Mono.Cecil/AssemblyWriter.cs

http://github.com/jbevain/cecil
C# | 3334 lines | 2662 code | 659 blank | 13 comment | 387 complexity | c49fef0cb35b6db20b02f33df08c51b7 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.IO;
  13. using System.IO.Compression;
  14. using System.Text;
  15. using System.Security.Cryptography;
  16. using Mono;
  17. using Mono.Collections.Generic;
  18. using Mono.Cecil.Cil;
  19. using Mono.Cecil.Metadata;
  20. using Mono.Cecil.PE;
  21. using RVA = System.UInt32;
  22. using RID = System.UInt32;
  23. using CodedRID = System.UInt32;
  24. using StringIndex = System.UInt32;
  25. using BlobIndex = System.UInt32;
  26. using GuidIndex = System.UInt32;
  27. namespace Mono.Cecil {
  28. using ModuleRow = Row<StringIndex, GuidIndex>;
  29. using TypeRefRow = Row<CodedRID, StringIndex, StringIndex>;
  30. using TypeDefRow = Row<TypeAttributes, StringIndex, StringIndex, CodedRID, RID, RID>;
  31. using FieldRow = Row<FieldAttributes, StringIndex, BlobIndex>;
  32. using MethodRow = Row<RVA, MethodImplAttributes, MethodAttributes, StringIndex, BlobIndex, RID>;
  33. using ParamRow = Row<ParameterAttributes, ushort, StringIndex>;
  34. using InterfaceImplRow = Row<uint, CodedRID>;
  35. using MemberRefRow = Row<CodedRID, StringIndex, BlobIndex>;
  36. using ConstantRow = Row<ElementType, CodedRID, BlobIndex>;
  37. using CustomAttributeRow = Row<CodedRID, CodedRID, BlobIndex>;
  38. using FieldMarshalRow = Row<CodedRID, BlobIndex>;
  39. using DeclSecurityRow = Row<SecurityAction, CodedRID, BlobIndex>;
  40. using ClassLayoutRow = Row<ushort, uint, RID>;
  41. using FieldLayoutRow = Row<uint, RID>;
  42. using EventMapRow = Row<RID, RID>;
  43. using EventRow = Row<EventAttributes, StringIndex, CodedRID>;
  44. using PropertyMapRow = Row<RID, RID>;
  45. using PropertyRow = Row<PropertyAttributes, StringIndex, BlobIndex>;
  46. using MethodSemanticsRow = Row<MethodSemanticsAttributes, RID, CodedRID>;
  47. using MethodImplRow = Row<RID, CodedRID, CodedRID>;
  48. using ImplMapRow = Row<PInvokeAttributes, CodedRID, StringIndex, RID>;
  49. using FieldRVARow = Row<RVA, RID>;
  50. using AssemblyRow = Row<AssemblyHashAlgorithm, ushort, ushort, ushort, ushort, AssemblyAttributes, uint, uint, uint>;
  51. using AssemblyRefRow = Row<ushort, ushort, ushort, ushort, AssemblyAttributes, uint, uint, uint, uint>;
  52. using FileRow = Row<FileAttributes, StringIndex, BlobIndex>;
  53. using ExportedTypeRow = Row<TypeAttributes, uint, StringIndex, StringIndex, CodedRID>;
  54. using ManifestResourceRow = Row<uint, ManifestResourceAttributes, StringIndex, CodedRID>;
  55. using NestedClassRow = Row<RID, RID>;
  56. using GenericParamRow = Row<ushort, GenericParameterAttributes, CodedRID, StringIndex>;
  57. using MethodSpecRow = Row<CodedRID, BlobIndex>;
  58. using GenericParamConstraintRow = Row<RID, CodedRID>;
  59. using DocumentRow = Row<BlobIndex, GuidIndex, BlobIndex, GuidIndex>;
  60. using MethodDebugInformationRow = Row<RID, BlobIndex>;
  61. using LocalScopeRow = Row<RID, RID, RID, RID, uint, uint>;
  62. using LocalVariableRow = Row<VariableAttributes, ushort, StringIndex>;
  63. using LocalConstantRow = Row<StringIndex, BlobIndex>;
  64. using ImportScopeRow = Row<RID, BlobIndex>;
  65. using StateMachineMethodRow = Row<RID, RID>;
  66. using CustomDebugInformationRow = Row<CodedRID, GuidIndex, BlobIndex>;
  67. static class ModuleWriter {
  68. public static void WriteModule (ModuleDefinition module, Disposable<Stream> stream, WriterParameters parameters)
  69. {
  70. using (stream)
  71. Write (module, stream, parameters);
  72. }
  73. static void Write (ModuleDefinition module, Disposable<Stream> stream, WriterParameters parameters)
  74. {
  75. if ((module.Attributes & ModuleAttributes.ILOnly) == 0)
  76. throw new NotSupportedException ("Writing mixed-mode assemblies is not supported");
  77. if (module.HasImage && module.ReadingMode == ReadingMode.Deferred) {
  78. var immediate_reader = new ImmediateModuleReader (module.Image);
  79. immediate_reader.ReadModule (module, resolve_attributes: false);
  80. immediate_reader.ReadSymbols (module);
  81. }
  82. module.MetadataSystem.Clear ();
  83. if (module.symbol_reader != null)
  84. module.symbol_reader.Dispose ();
  85. var name = module.assembly != null ? module.assembly.Name : null;
  86. var fq_name = stream.value.GetFileName ();
  87. var timestamp = parameters.Timestamp ?? module.timestamp;
  88. var symbol_writer_provider = parameters.SymbolWriterProvider;
  89. if (symbol_writer_provider == null && parameters.WriteSymbols)
  90. symbol_writer_provider = new DefaultSymbolWriterProvider ();
  91. if (parameters.HasStrongNameKey && name != null) {
  92. name.PublicKey = CryptoService.GetPublicKey (parameters);
  93. module.Attributes |= ModuleAttributes.StrongNameSigned;
  94. }
  95. if (parameters.DeterministicMvid)
  96. module.Mvid = Guid.Empty;
  97. var metadata = new MetadataBuilder (module, fq_name, timestamp, symbol_writer_provider);
  98. try {
  99. module.metadata_builder = metadata;
  100. using (var symbol_writer = GetSymbolWriter (module, fq_name, symbol_writer_provider, parameters)) {
  101. metadata.SetSymbolWriter (symbol_writer);
  102. BuildMetadata (module, metadata);
  103. if (parameters.DeterministicMvid)
  104. metadata.ComputeDeterministicMvid ();
  105. var writer = ImageWriter.CreateWriter (module, metadata, stream);
  106. stream.value.SetLength (0);
  107. writer.WriteImage ();
  108. if (parameters.HasStrongNameKey)
  109. CryptoService.StrongName (stream.value, writer, parameters);
  110. }
  111. } finally {
  112. module.metadata_builder = null;
  113. }
  114. }
  115. static void BuildMetadata (ModuleDefinition module, MetadataBuilder metadata)
  116. {
  117. if (!module.HasImage) {
  118. metadata.BuildMetadata ();
  119. return;
  120. }
  121. module.Read (metadata, (builder, _) => {
  122. builder.BuildMetadata ();
  123. return builder;
  124. });
  125. }
  126. static ISymbolWriter GetSymbolWriter (ModuleDefinition module, string fq_name, ISymbolWriterProvider symbol_writer_provider, WriterParameters parameters)
  127. {
  128. if (symbol_writer_provider == null)
  129. return null;
  130. if (parameters.SymbolStream != null)
  131. return symbol_writer_provider.GetSymbolWriter (module, parameters.SymbolStream);
  132. return symbol_writer_provider.GetSymbolWriter (module, fq_name);
  133. }
  134. }
  135. abstract class MetadataTable {
  136. public abstract int Length { get; }
  137. public bool IsLarge {
  138. get { return Length > ushort.MaxValue; }
  139. }
  140. public abstract void Write (TableHeapBuffer buffer);
  141. public abstract void Sort ();
  142. }
  143. abstract class OneRowTable<TRow> : MetadataTable where TRow : struct {
  144. internal TRow row;
  145. public sealed override int Length {
  146. get { return 1; }
  147. }
  148. public sealed override void Sort ()
  149. {
  150. }
  151. }
  152. abstract class MetadataTable<TRow> : MetadataTable where TRow : struct {
  153. internal TRow [] rows = new TRow [2];
  154. internal int length;
  155. public sealed override int Length {
  156. get { return length; }
  157. }
  158. public int AddRow (TRow row)
  159. {
  160. if (rows.Length == length)
  161. Grow ();
  162. rows [length++] = row;
  163. return length;
  164. }
  165. void Grow ()
  166. {
  167. var rows = new TRow [this.rows.Length * 2];
  168. Array.Copy (this.rows, rows, this.rows.Length);
  169. this.rows = rows;
  170. }
  171. public override void Sort ()
  172. {
  173. }
  174. }
  175. abstract class SortedTable<TRow> : MetadataTable<TRow>, IComparer<TRow> where TRow : struct {
  176. public sealed override void Sort ()
  177. {
  178. MergeSort<TRow>.Sort (rows, 0, this.length, this);
  179. }
  180. protected static int Compare (uint x, uint y)
  181. {
  182. return x == y ? 0 : x > y ? 1 : -1;
  183. }
  184. public abstract int Compare (TRow x, TRow y);
  185. }
  186. sealed class ModuleTable : OneRowTable<ModuleRow> {
  187. public override void Write (TableHeapBuffer buffer)
  188. {
  189. buffer.WriteUInt16 (0); // Generation
  190. buffer.WriteString (row.Col1); // Name
  191. buffer.WriteGuid (row.Col2); // Mvid
  192. buffer.WriteUInt16 (0); // EncId
  193. buffer.WriteUInt16 (0); // EncBaseId
  194. }
  195. }
  196. sealed class TypeRefTable : MetadataTable<TypeRefRow> {
  197. public override void Write (TableHeapBuffer buffer)
  198. {
  199. for (int i = 0; i < length; i++) {
  200. buffer.WriteCodedRID (
  201. rows [i].Col1, CodedIndex.ResolutionScope); // Scope
  202. buffer.WriteString (rows [i].Col2); // Name
  203. buffer.WriteString (rows [i].Col3); // Namespace
  204. }
  205. }
  206. }
  207. sealed class TypeDefTable : MetadataTable<TypeDefRow> {
  208. public override void Write (TableHeapBuffer buffer)
  209. {
  210. for (int i = 0; i < length; i++) {
  211. buffer.WriteUInt32 ((uint) rows [i].Col1); // Attributes
  212. buffer.WriteString (rows [i].Col2); // Name
  213. buffer.WriteString (rows [i].Col3); // Namespace
  214. buffer.WriteCodedRID (
  215. rows [i].Col4, CodedIndex.TypeDefOrRef); // Extends
  216. buffer.WriteRID (rows [i].Col5, Table.Field); // FieldList
  217. buffer.WriteRID (rows [i].Col6, Table.Method); // MethodList
  218. }
  219. }
  220. }
  221. sealed class FieldTable : MetadataTable<FieldRow> {
  222. public override void Write (TableHeapBuffer buffer)
  223. {
  224. for (int i = 0; i < length; i++) {
  225. buffer.WriteUInt16 ((ushort) rows [i].Col1); // Attributes
  226. buffer.WriteString (rows [i].Col2); // Name
  227. buffer.WriteBlob (rows [i].Col3); // Signature
  228. }
  229. }
  230. }
  231. sealed class MethodTable : MetadataTable<MethodRow> {
  232. public override void Write (TableHeapBuffer buffer)
  233. {
  234. for (int i = 0; i < length; i++) {
  235. buffer.WriteUInt32 (rows [i].Col1); // RVA
  236. buffer.WriteUInt16 ((ushort) rows [i].Col2); // ImplFlags
  237. buffer.WriteUInt16 ((ushort) rows [i].Col3); // Flags
  238. buffer.WriteString (rows [i].Col4); // Name
  239. buffer.WriteBlob (rows [i].Col5); // Signature
  240. buffer.WriteRID (rows [i].Col6, Table.Param); // ParamList
  241. }
  242. }
  243. }
  244. sealed class ParamTable : MetadataTable<ParamRow> {
  245. public override void Write (TableHeapBuffer buffer)
  246. {
  247. for (int i = 0; i < length; i++) {
  248. buffer.WriteUInt16 ((ushort) rows [i].Col1); // Attributes
  249. buffer.WriteUInt16 (rows [i].Col2); // Sequence
  250. buffer.WriteString (rows [i].Col3); // Name
  251. }
  252. }
  253. }
  254. sealed class InterfaceImplTable : MetadataTable<InterfaceImplRow> {
  255. public override void Write (TableHeapBuffer buffer)
  256. {
  257. for (int i = 0; i < length; i++) {
  258. buffer.WriteRID (rows [i].Col1, Table.TypeDef); // Class
  259. buffer.WriteCodedRID (rows [i].Col2, CodedIndex.TypeDefOrRef); // Interface
  260. }
  261. }
  262. /*public override int Compare (InterfaceImplRow x, InterfaceImplRow y)
  263. {
  264. return (int) (x.Col1 == y.Col1 ? y.Col2 - x.Col2 : x.Col1 - y.Col1);
  265. }*/
  266. }
  267. sealed class MemberRefTable : MetadataTable<MemberRefRow> {
  268. public override void Write (TableHeapBuffer buffer)
  269. {
  270. for (int i = 0; i < length; i++) {
  271. buffer.WriteCodedRID (rows [i].Col1, CodedIndex.MemberRefParent);
  272. buffer.WriteString (rows [i].Col2);
  273. buffer.WriteBlob (rows [i].Col3);
  274. }
  275. }
  276. }
  277. sealed class ConstantTable : SortedTable<ConstantRow> {
  278. public override void Write (TableHeapBuffer buffer)
  279. {
  280. for (int i = 0; i < length; i++) {
  281. buffer.WriteUInt16 ((ushort) rows [i].Col1);
  282. buffer.WriteCodedRID (rows [i].Col2, CodedIndex.HasConstant);
  283. buffer.WriteBlob (rows [i].Col3);
  284. }
  285. }
  286. public override int Compare (ConstantRow x, ConstantRow y)
  287. {
  288. return Compare (x.Col2, y.Col2);
  289. }
  290. }
  291. sealed class CustomAttributeTable : SortedTable<CustomAttributeRow> {
  292. public override void Write (TableHeapBuffer buffer)
  293. {
  294. for (int i = 0; i < length; i++) {
  295. buffer.WriteCodedRID (rows [i].Col1, CodedIndex.HasCustomAttribute); // Parent
  296. buffer.WriteCodedRID (rows [i].Col2, CodedIndex.CustomAttributeType); // Type
  297. buffer.WriteBlob (rows [i].Col3);
  298. }
  299. }
  300. public override int Compare (CustomAttributeRow x, CustomAttributeRow y)
  301. {
  302. return Compare (x.Col1, y.Col1);
  303. }
  304. }
  305. sealed class FieldMarshalTable : SortedTable<FieldMarshalRow> {
  306. public override void Write (TableHeapBuffer buffer)
  307. {
  308. for (int i = 0; i < length; i++) {
  309. buffer.WriteCodedRID (rows [i].Col1, CodedIndex.HasFieldMarshal);
  310. buffer.WriteBlob (rows [i].Col2);
  311. }
  312. }
  313. public override int Compare (FieldMarshalRow x, FieldMarshalRow y)
  314. {
  315. return Compare (x.Col1, y.Col1);
  316. }
  317. }
  318. sealed class DeclSecurityTable : SortedTable<DeclSecurityRow> {
  319. public override void Write (TableHeapBuffer buffer)
  320. {
  321. for (int i = 0; i < length; i++) {
  322. buffer.WriteUInt16 ((ushort) rows [i].Col1);
  323. buffer.WriteCodedRID (rows [i].Col2, CodedIndex.HasDeclSecurity);
  324. buffer.WriteBlob (rows [i].Col3);
  325. }
  326. }
  327. public override int Compare (DeclSecurityRow x, DeclSecurityRow y)
  328. {
  329. return Compare (x.Col2, y.Col2);
  330. }
  331. }
  332. sealed class ClassLayoutTable : SortedTable<ClassLayoutRow> {
  333. public override void Write (TableHeapBuffer buffer)
  334. {
  335. for (int i = 0; i < length; i++) {
  336. buffer.WriteUInt16 (rows [i].Col1); // PackingSize
  337. buffer.WriteUInt32 (rows [i].Col2); // ClassSize
  338. buffer.WriteRID (rows [i].Col3, Table.TypeDef); // Parent
  339. }
  340. }
  341. public override int Compare (ClassLayoutRow x, ClassLayoutRow y)
  342. {
  343. return Compare (x.Col3, y.Col3);
  344. }
  345. }
  346. sealed class FieldLayoutTable : SortedTable<FieldLayoutRow> {
  347. public override void Write (TableHeapBuffer buffer)
  348. {
  349. for (int i = 0; i < length; i++) {
  350. buffer.WriteUInt32 (rows [i].Col1); // Offset
  351. buffer.WriteRID (rows [i].Col2, Table.Field); // Parent
  352. }
  353. }
  354. public override int Compare (FieldLayoutRow x, FieldLayoutRow y)
  355. {
  356. return Compare (x.Col2, y.Col2);
  357. }
  358. }
  359. sealed class StandAloneSigTable : MetadataTable<uint> {
  360. public override void Write (TableHeapBuffer buffer)
  361. {
  362. for (int i = 0; i < length; i++)
  363. buffer.WriteBlob (rows [i]);
  364. }
  365. }
  366. sealed class EventMapTable : MetadataTable<EventMapRow> {
  367. public override void Write (TableHeapBuffer buffer)
  368. {
  369. for (int i = 0; i < length; i++) {
  370. buffer.WriteRID (rows [i].Col1, Table.TypeDef); // Parent
  371. buffer.WriteRID (rows [i].Col2, Table.Event); // EventList
  372. }
  373. }
  374. }
  375. sealed class EventTable : MetadataTable<EventRow> {
  376. public override void Write (TableHeapBuffer buffer)
  377. {
  378. for (int i = 0; i < length; i++) {
  379. buffer.WriteUInt16 ((ushort) rows [i].Col1); // Flags
  380. buffer.WriteString (rows [i].Col2); // Name
  381. buffer.WriteCodedRID (rows [i].Col3, CodedIndex.TypeDefOrRef); // EventType
  382. }
  383. }
  384. }
  385. sealed class PropertyMapTable : MetadataTable<PropertyMapRow> {
  386. public override void Write (TableHeapBuffer buffer)
  387. {
  388. for (int i = 0; i < length; i++) {
  389. buffer.WriteRID (rows [i].Col1, Table.TypeDef); // Parent
  390. buffer.WriteRID (rows [i].Col2, Table.Property); // PropertyList
  391. }
  392. }
  393. }
  394. sealed class PropertyTable : MetadataTable<PropertyRow> {
  395. public override void Write (TableHeapBuffer buffer)
  396. {
  397. for (int i = 0; i < length; i++) {
  398. buffer.WriteUInt16 ((ushort) rows [i].Col1); // Flags
  399. buffer.WriteString (rows [i].Col2); // Name
  400. buffer.WriteBlob (rows [i].Col3); // Type
  401. }
  402. }
  403. }
  404. sealed class MethodSemanticsTable : SortedTable<MethodSemanticsRow> {
  405. public override void Write (TableHeapBuffer buffer)
  406. {
  407. for (int i = 0; i < length; i++) {
  408. buffer.WriteUInt16 ((ushort) rows [i].Col1); // Flags
  409. buffer.WriteRID (rows [i].Col2, Table.Method); // Method
  410. buffer.WriteCodedRID (rows [i].Col3, CodedIndex.HasSemantics); // Association
  411. }
  412. }
  413. public override int Compare (MethodSemanticsRow x, MethodSemanticsRow y)
  414. {
  415. return Compare (x.Col3, y.Col3);
  416. }
  417. }
  418. sealed class MethodImplTable : MetadataTable<MethodImplRow> {
  419. public override void Write (TableHeapBuffer buffer)
  420. {
  421. for (int i = 0; i < length; i++) {
  422. buffer.WriteRID (rows [i].Col1, Table.TypeDef); // Class
  423. buffer.WriteCodedRID (rows [i].Col2, CodedIndex.MethodDefOrRef); // MethodBody
  424. buffer.WriteCodedRID (rows [i].Col3, CodedIndex.MethodDefOrRef); // MethodDeclaration
  425. }
  426. }
  427. }
  428. sealed class ModuleRefTable : MetadataTable<uint> {
  429. public override void Write (TableHeapBuffer buffer)
  430. {
  431. for (int i = 0; i < length; i++)
  432. buffer.WriteString (rows [i]); // Name
  433. }
  434. }
  435. sealed class TypeSpecTable : MetadataTable<uint> {
  436. public override void Write (TableHeapBuffer buffer)
  437. {
  438. for (int i = 0; i < length; i++)
  439. buffer.WriteBlob (rows [i]); // Signature
  440. }
  441. }
  442. sealed class ImplMapTable : SortedTable<ImplMapRow> {
  443. public override void Write (TableHeapBuffer buffer)
  444. {
  445. for (int i = 0; i < length; i++) {
  446. buffer.WriteUInt16 ((ushort) rows [i].Col1); // Flags
  447. buffer.WriteCodedRID (rows [i].Col2, CodedIndex.MemberForwarded); // MemberForwarded
  448. buffer.WriteString (rows [i].Col3); // ImportName
  449. buffer.WriteRID (rows [i].Col4, Table.ModuleRef); // ImportScope
  450. }
  451. }
  452. public override int Compare (ImplMapRow x, ImplMapRow y)
  453. {
  454. return Compare (x.Col2, y.Col2);
  455. }
  456. }
  457. sealed class FieldRVATable : SortedTable<FieldRVARow> {
  458. internal int position;
  459. public override void Write (TableHeapBuffer buffer)
  460. {
  461. position = buffer.position;
  462. for (int i = 0; i < length; i++) {
  463. buffer.WriteUInt32 (rows [i].Col1); // RVA
  464. buffer.WriteRID (rows [i].Col2, Table.Field); // Field
  465. }
  466. }
  467. public override int Compare (FieldRVARow x, FieldRVARow y)
  468. {
  469. return Compare (x.Col2, y.Col2);
  470. }
  471. }
  472. sealed class AssemblyTable : OneRowTable<AssemblyRow> {
  473. public override void Write (TableHeapBuffer buffer)
  474. {
  475. buffer.WriteUInt32 ((uint) row.Col1); // AssemblyHashAlgorithm
  476. buffer.WriteUInt16 (row.Col2); // MajorVersion
  477. buffer.WriteUInt16 (row.Col3); // MinorVersion
  478. buffer.WriteUInt16 (row.Col4); // Build
  479. buffer.WriteUInt16 (row.Col5); // Revision
  480. buffer.WriteUInt32 ((uint) row.Col6); // Flags
  481. buffer.WriteBlob (row.Col7); // PublicKey
  482. buffer.WriteString (row.Col8); // Name
  483. buffer.WriteString (row.Col9); // Culture
  484. }
  485. }
  486. sealed class AssemblyRefTable : MetadataTable<AssemblyRefRow> {
  487. public override void Write (TableHeapBuffer buffer)
  488. {
  489. for (int i = 0; i < length; i++) {
  490. buffer.WriteUInt16 (rows [i].Col1); // MajorVersion
  491. buffer.WriteUInt16 (rows [i].Col2); // MinorVersion
  492. buffer.WriteUInt16 (rows [i].Col3); // Build
  493. buffer.WriteUInt16 (rows [i].Col4); // Revision
  494. buffer.WriteUInt32 ((uint) rows [i].Col5); // Flags
  495. buffer.WriteBlob (rows [i].Col6); // PublicKeyOrToken
  496. buffer.WriteString (rows [i].Col7); // Name
  497. buffer.WriteString (rows [i].Col8); // Culture
  498. buffer.WriteBlob (rows [i].Col9); // Hash
  499. }
  500. }
  501. }
  502. sealed class FileTable : MetadataTable<FileRow> {
  503. public override void Write (TableHeapBuffer buffer)
  504. {
  505. for (int i = 0; i < length; i++) {
  506. buffer.WriteUInt32 ((uint) rows [i].Col1);
  507. buffer.WriteString (rows [i].Col2);
  508. buffer.WriteBlob (rows [i].Col3);
  509. }
  510. }
  511. }
  512. sealed class ExportedTypeTable : MetadataTable<ExportedTypeRow> {
  513. public override void Write (TableHeapBuffer buffer)
  514. {
  515. for (int i = 0; i < length; i++) {
  516. buffer.WriteUInt32 ((uint) rows [i].Col1);
  517. buffer.WriteUInt32 (rows [i].Col2);
  518. buffer.WriteString (rows [i].Col3);
  519. buffer.WriteString (rows [i].Col4);
  520. buffer.WriteCodedRID (rows [i].Col5, CodedIndex.Implementation);
  521. }
  522. }
  523. }
  524. sealed class ManifestResourceTable : MetadataTable<ManifestResourceRow> {
  525. public override void Write (TableHeapBuffer buffer)
  526. {
  527. for (int i = 0; i < length; i++) {
  528. buffer.WriteUInt32 (rows [i].Col1);
  529. buffer.WriteUInt32 ((uint) rows [i].Col2);
  530. buffer.WriteString (rows [i].Col3);
  531. buffer.WriteCodedRID (rows [i].Col4, CodedIndex.Implementation);
  532. }
  533. }
  534. }
  535. sealed class NestedClassTable : SortedTable<NestedClassRow> {
  536. public override void Write (TableHeapBuffer buffer)
  537. {
  538. for (int i = 0; i < length; i++) {
  539. buffer.WriteRID (rows [i].Col1, Table.TypeDef); // NestedClass
  540. buffer.WriteRID (rows [i].Col2, Table.TypeDef); // EnclosingClass
  541. }
  542. }
  543. public override int Compare (NestedClassRow x, NestedClassRow y)
  544. {
  545. return Compare (x.Col1, y.Col1);
  546. }
  547. }
  548. sealed class GenericParamTable : MetadataTable<GenericParamRow> {
  549. public override void Write (TableHeapBuffer buffer)
  550. {
  551. for (int i = 0; i < length; i++) {
  552. buffer.WriteUInt16 (rows [i].Col1); // Number
  553. buffer.WriteUInt16 ((ushort) rows [i].Col2); // Flags
  554. buffer.WriteCodedRID (rows [i].Col3, CodedIndex.TypeOrMethodDef); // Owner
  555. buffer.WriteString (rows [i].Col4); // Name
  556. }
  557. }
  558. }
  559. sealed class MethodSpecTable : MetadataTable<MethodSpecRow> {
  560. public override void Write (TableHeapBuffer buffer)
  561. {
  562. for (int i = 0; i < length; i++) {
  563. buffer.WriteCodedRID (rows [i].Col1, CodedIndex.MethodDefOrRef); // Method
  564. buffer.WriteBlob (rows [i].Col2); // Instantiation
  565. }
  566. }
  567. }
  568. sealed class GenericParamConstraintTable : MetadataTable<GenericParamConstraintRow> {
  569. public override void Write (TableHeapBuffer buffer)
  570. {
  571. for (int i = 0; i < length; i++) {
  572. buffer.WriteRID (rows [i].Col1, Table.GenericParam); // Owner
  573. buffer.WriteCodedRID (rows [i].Col2, CodedIndex.TypeDefOrRef); // Constraint
  574. }
  575. }
  576. }
  577. sealed class DocumentTable : MetadataTable<DocumentRow> {
  578. public override void Write (TableHeapBuffer buffer)
  579. {
  580. for (int i = 0; i < length; i++) {
  581. buffer.WriteBlob (rows [i].Col1); // Name
  582. buffer.WriteGuid (rows [i].Col2); // HashAlgorithm
  583. buffer.WriteBlob (rows [i].Col3); // Hash
  584. buffer.WriteGuid (rows [i].Col4); // Language
  585. }
  586. }
  587. }
  588. sealed class MethodDebugInformationTable : MetadataTable<MethodDebugInformationRow> {
  589. public override void Write (TableHeapBuffer buffer)
  590. {
  591. for (int i = 0; i < length; i++) {
  592. buffer.WriteRID (rows [i].Col1, Table.Document); // Document
  593. buffer.WriteBlob (rows [i].Col2); // SequencePoints
  594. }
  595. }
  596. }
  597. sealed class LocalScopeTable : MetadataTable<LocalScopeRow> {
  598. public override void Write (TableHeapBuffer buffer)
  599. {
  600. for (int i = 0; i < length; i++) {
  601. buffer.WriteRID (rows [i].Col1, Table.Method); // Method
  602. buffer.WriteRID (rows [i].Col2, Table.ImportScope); // ImportScope
  603. buffer.WriteRID (rows [i].Col3, Table.LocalVariable); // VariableList
  604. buffer.WriteRID (rows [i].Col4, Table.LocalConstant); // ConstantList
  605. buffer.WriteUInt32 (rows [i].Col5); // StartOffset
  606. buffer.WriteUInt32 (rows [i].Col6); // Length
  607. }
  608. }
  609. }
  610. sealed class LocalVariableTable : MetadataTable<LocalVariableRow> {
  611. public override void Write (TableHeapBuffer buffer)
  612. {
  613. for (int i = 0; i < length; i++) {
  614. buffer.WriteUInt16 ((ushort) rows [i].Col1); // Attributes
  615. buffer.WriteUInt16 (rows [i].Col2); // Index
  616. buffer.WriteString (rows [i].Col3); // Name
  617. }
  618. }
  619. }
  620. sealed class LocalConstantTable : MetadataTable<LocalConstantRow> {
  621. public override void Write (TableHeapBuffer buffer)
  622. {
  623. for (int i = 0; i < length; i++) {
  624. buffer.WriteString (rows [i].Col1); // Name
  625. buffer.WriteBlob (rows [i].Col2); // Signature
  626. }
  627. }
  628. }
  629. sealed class ImportScopeTable : MetadataTable<ImportScopeRow> {
  630. public override void Write (TableHeapBuffer buffer)
  631. {
  632. for (int i = 0; i < length; i++) {
  633. buffer.WriteRID (rows [i].Col1, Table.ImportScope); // Parent
  634. buffer.WriteBlob (rows [i].Col2); // Imports
  635. }
  636. }
  637. }
  638. sealed class StateMachineMethodTable : MetadataTable<StateMachineMethodRow> {
  639. public override void Write (TableHeapBuffer buffer)
  640. {
  641. for (int i = 0; i < length; i++) {
  642. buffer.WriteRID (rows [i].Col1, Table.Method); // MoveNextMethod
  643. buffer.WriteRID (rows [i].Col2, Table.Method); // KickoffMethod
  644. }
  645. }
  646. }
  647. sealed class CustomDebugInformationTable : SortedTable<CustomDebugInformationRow> {
  648. public override void Write (TableHeapBuffer buffer)
  649. {
  650. for (int i = 0; i < length; i++) {
  651. buffer.WriteCodedRID (rows [i].Col1, CodedIndex.HasCustomDebugInformation); // Parent
  652. buffer.WriteGuid (rows [i].Col2); // Kind
  653. buffer.WriteBlob (rows [i].Col3); // Value
  654. }
  655. }
  656. public override int Compare (CustomDebugInformationRow x, CustomDebugInformationRow y)
  657. {
  658. return Compare(x.Col1, y.Col1);
  659. }
  660. }
  661. sealed class MetadataBuilder {
  662. readonly internal ModuleDefinition module;
  663. readonly internal ISymbolWriterProvider symbol_writer_provider;
  664. internal ISymbolWriter symbol_writer;
  665. readonly internal TextMap text_map;
  666. readonly internal string fq_name;
  667. readonly internal uint timestamp;
  668. readonly Dictionary<TypeRefRow, MetadataToken> type_ref_map;
  669. readonly Dictionary<uint, MetadataToken> type_spec_map;
  670. readonly Dictionary<MemberRefRow, MetadataToken> member_ref_map;
  671. readonly Dictionary<MethodSpecRow, MetadataToken> method_spec_map;
  672. readonly Collection<GenericParameter> generic_parameters;
  673. readonly internal CodeWriter code;
  674. readonly internal DataBuffer data;
  675. readonly internal ResourceBuffer resources;
  676. readonly internal StringHeapBuffer string_heap;
  677. readonly internal GuidHeapBuffer guid_heap;
  678. readonly internal UserStringHeapBuffer user_string_heap;
  679. readonly internal BlobHeapBuffer blob_heap;
  680. readonly internal TableHeapBuffer table_heap;
  681. readonly internal PdbHeapBuffer pdb_heap;
  682. internal MetadataToken entry_point;
  683. internal RID type_rid = 1;
  684. internal RID field_rid = 1;
  685. internal RID method_rid = 1;
  686. internal RID param_rid = 1;
  687. internal RID property_rid = 1;
  688. internal RID event_rid = 1;
  689. internal RID local_variable_rid = 1;
  690. internal RID local_constant_rid = 1;
  691. readonly TypeRefTable type_ref_table;
  692. readonly TypeDefTable type_def_table;
  693. readonly FieldTable field_table;
  694. readonly MethodTable method_table;
  695. readonly ParamTable param_table;
  696. readonly InterfaceImplTable iface_impl_table;
  697. readonly MemberRefTable member_ref_table;
  698. readonly ConstantTable constant_table;
  699. readonly CustomAttributeTable custom_attribute_table;
  700. readonly DeclSecurityTable declsec_table;
  701. readonly StandAloneSigTable standalone_sig_table;
  702. readonly EventMapTable event_map_table;
  703. readonly EventTable event_table;
  704. readonly PropertyMapTable property_map_table;
  705. readonly PropertyTable property_table;
  706. readonly TypeSpecTable typespec_table;
  707. readonly MethodSpecTable method_spec_table;
  708. internal MetadataBuilder metadata_builder;
  709. readonly DocumentTable document_table;
  710. readonly MethodDebugInformationTable method_debug_information_table;
  711. readonly LocalScopeTable local_scope_table;
  712. readonly LocalVariableTable local_variable_table;
  713. readonly LocalConstantTable local_constant_table;
  714. readonly ImportScopeTable import_scope_table;
  715. readonly StateMachineMethodTable state_machine_method_table;
  716. readonly CustomDebugInformationTable custom_debug_information_table;
  717. readonly Dictionary<ImportScopeRow, MetadataToken> import_scope_map;
  718. readonly Dictionary<string, MetadataToken> document_map;
  719. public MetadataBuilder (ModuleDefinition module, string fq_name, uint timestamp, ISymbolWriterProvider symbol_writer_provider)
  720. {
  721. this.module = module;
  722. this.text_map = CreateTextMap ();
  723. this.fq_name = fq_name;
  724. this.timestamp = timestamp;
  725. this.symbol_writer_provider = symbol_writer_provider;
  726. this.code = new CodeWriter (this);
  727. this.data = new DataBuffer ();
  728. this.resources = new ResourceBuffer ();
  729. this.string_heap = new StringHeapBuffer ();
  730. this.guid_heap = new GuidHeapBuffer ();
  731. this.user_string_heap = new UserStringHeapBuffer ();
  732. this.blob_heap = new BlobHeapBuffer ();
  733. this.table_heap = new TableHeapBuffer (module, this);
  734. this.type_ref_table = GetTable<TypeRefTable> (Table.TypeRef);
  735. this.type_def_table = GetTable<TypeDefTable> (Table.TypeDef);
  736. this.field_table = GetTable<FieldTable> (Table.Field);
  737. this.method_table = GetTable<MethodTable> (Table.Method);
  738. this.param_table = GetTable<ParamTable> (Table.Param);
  739. this.iface_impl_table = GetTable<InterfaceImplTable> (Table.InterfaceImpl);
  740. this.member_ref_table = GetTable<MemberRefTable> (Table.MemberRef);
  741. this.constant_table = GetTable<ConstantTable> (Table.Constant);
  742. this.custom_attribute_table = GetTable<CustomAttributeTable> (Table.CustomAttribute);
  743. this.declsec_table = GetTable<DeclSecurityTable> (Table.DeclSecurity);
  744. this.standalone_sig_table = GetTable<StandAloneSigTable> (Table.StandAloneSig);
  745. this.event_map_table = GetTable<EventMapTable> (Table.EventMap);
  746. this.event_table = GetTable<EventTable> (Table.Event);
  747. this.property_map_table = GetTable<PropertyMapTable> (Table.PropertyMap);
  748. this.property_table = GetTable<PropertyTable> (Table.Property);
  749. this.typespec_table = GetTable<TypeSpecTable> (Table.TypeSpec);
  750. this.method_spec_table = GetTable<MethodSpecTable> (Table.MethodSpec);
  751. var row_equality_comparer = new RowEqualityComparer ();
  752. type_ref_map = new Dictionary<TypeRefRow, MetadataToken> (row_equality_comparer);
  753. type_spec_map = new Dictionary<uint, MetadataToken> ();
  754. member_ref_map = new Dictionary<MemberRefRow, MetadataToken> (row_equality_comparer);
  755. method_spec_map = new Dictionary<MethodSpecRow, MetadataToken> (row_equality_comparer);
  756. generic_parameters = new Collection<GenericParameter> ();
  757. this.document_table = GetTable<DocumentTable> (Table.Document);
  758. this.method_debug_information_table = GetTable<MethodDebugInformationTable> (Table.MethodDebugInformation);
  759. this.local_scope_table = GetTable<LocalScopeTable> (Table.LocalScope);
  760. this.local_variable_table = GetTable<LocalVariableTable> (Table.LocalVariable);
  761. this.local_constant_table = GetTable<LocalConstantTable> (Table.LocalConstant);
  762. this.import_scope_table = GetTable<ImportScopeTable> (Table.ImportScope);
  763. this.state_machine_method_table = GetTable<StateMachineMethodTable> (Table.StateMachineMethod);
  764. this.custom_debug_information_table = GetTable<CustomDebugInformationTable> (Table.CustomDebugInformation);
  765. this.document_map = new Dictionary<string, MetadataToken> (StringComparer.Ordinal);
  766. this.import_scope_map = new Dictionary<ImportScopeRow, MetadataToken> (row_equality_comparer);
  767. }
  768. public MetadataBuilder (ModuleDefinition module, PortablePdbWriterProvider writer_provider)
  769. {
  770. this.module = module;
  771. this.text_map = new TextMap ();
  772. this.symbol_writer_provider = writer_provider;
  773. this.string_heap = new StringHeapBuffer ();
  774. this.guid_heap = new GuidHeapBuffer ();
  775. this.user_string_heap = new UserStringHeapBuffer ();
  776. this.blob_heap = new BlobHeapBuffer ();
  777. this.table_heap = new TableHeapBuffer (module, this);
  778. this.pdb_heap = new PdbHeapBuffer();
  779. this.document_table = GetTable<DocumentTable> (Table.Document);
  780. this.method_debug_information_table = GetTable<MethodDebugInformationTable> (Table.MethodDebugInformation);
  781. this.local_scope_table = GetTable<LocalScopeTable> (Table.LocalScope);
  782. this.local_variable_table = GetTable<LocalVariableTable> (Table.LocalVariable);
  783. this.local_constant_table = GetTable<LocalConstantTable> (Table.LocalConstant);
  784. this.import_scope_table = GetTable<ImportScopeTable> (Table.ImportScope);
  785. this.state_machine_method_table = GetTable<StateMachineMethodTable> (Table.StateMachineMethod);
  786. this.custom_debug_information_table = GetTable<CustomDebugInformationTable> (Table.CustomDebugInformation);
  787. var row_equality_comparer = new RowEqualityComparer ();
  788. this.document_map = new Dictionary<string, MetadataToken> ();
  789. this.import_scope_map = new Dictionary<ImportScopeRow, MetadataToken> (row_equality_comparer);
  790. }
  791. public void SetSymbolWriter (ISymbolWriter writer)
  792. {
  793. symbol_writer = writer;
  794. if (symbol_writer == null && module.HasImage && module.Image.HasDebugTables ())
  795. symbol_writer = new PortablePdbWriter (this, module);
  796. }
  797. TextMap CreateTextMap ()
  798. {
  799. var map = new TextMap ();
  800. map.AddMap (TextSegment.ImportAddressTable, module.Architecture == TargetArchitecture.I386 ? 8 : 0);
  801. map.AddMap (TextSegment.CLIHeader, 0x48, 8);
  802. return map;
  803. }
  804. TTable GetTable<TTable> (Table table) where TTable : MetadataTable, new ()
  805. {
  806. return table_heap.GetTable<TTable> (table);
  807. }
  808. uint GetStringIndex (string @string)
  809. {
  810. if (string.IsNullOrEmpty (@string))
  811. return 0;
  812. return string_heap.GetStringIndex (@string);
  813. }
  814. uint GetGuidIndex (Guid guid)
  815. {
  816. return guid_heap.GetGuidIndex (guid);
  817. }
  818. uint GetBlobIndex (ByteBuffer blob)
  819. {
  820. if (blob.length == 0)
  821. return 0;
  822. return blob_heap.GetBlobIndex (blob);
  823. }
  824. uint GetBlobIndex (byte [] blob)
  825. {
  826. if (blob.IsNullOrEmpty ())
  827. return 0;
  828. return GetBlobIndex (new ByteBuffer (blob));
  829. }
  830. public void BuildMetadata ()
  831. {
  832. BuildModule ();
  833. table_heap.string_offsets = string_heap.WriteStrings ();
  834. table_heap.ComputeTableInformations ();
  835. table_heap.WriteTableHeap ();
  836. }
  837. void BuildModule ()
  838. {
  839. var table = GetTable<ModuleTable> (Table.Module);
  840. table.row.Col1 = GetStringIndex (module.Name);
  841. table.row.Col2 = GetGuidIndex (module.Mvid);
  842. var assembly = module.Assembly;
  843. if (assembly != null)
  844. BuildAssembly ();
  845. if (module.HasAssemblyReferences)
  846. AddAssemblyReferences ();
  847. if (module.HasModuleReferences)
  848. AddModuleReferences ();
  849. if (module.HasResources)
  850. AddResources ();
  851. if (module.HasExportedTypes)
  852. AddExportedTypes ();
  853. BuildTypes ();
  854. if (assembly != null) {
  855. if (assembly.HasCustomAttributes)
  856. AddCustomAttributes (assembly);
  857. if (assembly.HasSecurityDeclarations)
  858. AddSecurityDeclarations (assembly);
  859. }
  860. if (module.HasCustomAttributes)
  861. AddCustomAttributes (module);
  862. if (module.EntryPoint != null)
  863. entry_point = LookupToken (module.EntryPoint);
  864. }
  865. void BuildAssembly ()
  866. {
  867. var assembly = module.Assembly;
  868. var name = assembly.Name;
  869. var table = GetTable<AssemblyTable> (Table.Assembly);
  870. table.row = new AssemblyRow (
  871. name.HashAlgorithm,
  872. (ushort) name.Version.Major,
  873. (ushort) name.Version.Minor,
  874. (ushort) name.Version.Build,
  875. (ushort) name.Version.Revision,
  876. name.Attributes,
  877. GetBlobIndex (name.PublicKey),
  878. GetStringIndex (name.Name),
  879. GetStringIndex (name.Culture));
  880. if (assembly.Modules.Count > 1)
  881. BuildModules ();
  882. }
  883. void BuildModules ()
  884. {
  885. var modules = this.module.Assembly.Modules;
  886. var table = GetTable<FileTable> (Table.File);
  887. for (int i = 0; i < modules.Count; i++) {
  888. var module = modules [i];
  889. if (module.IsMain)
  890. continue;
  891. #if NET_CORE
  892. throw new NotSupportedException ();
  893. #else
  894. var parameters = new WriterParameters {
  895. SymbolWriterProvider = symbol_writer_provider,
  896. };
  897. var file_name = GetModuleFileName (module.Name);
  898. module.Write (file_name, parameters);
  899. var hash = CryptoService.ComputeHash (file_name);
  900. table.AddRow (new FileRow (
  901. FileAttributes.ContainsMetaData,
  902. GetStringIndex (module.Name),
  903. GetBlobIndex (hash)));
  904. #endif
  905. }
  906. }
  907. #if !NET_CORE
  908. string GetModuleFileName (string name)
  909. {
  910. if (string.IsNullOrEmpty (name))
  911. throw new NotSupportedException ();
  912. var path = Path.GetDirectoryName (fq_name);
  913. return Path.Combine (path, name);
  914. }
  915. #endif
  916. void AddAssemblyReferences ()
  917. {
  918. var references = module.AssemblyReferences;
  919. var table = GetTable<AssemblyRefTable> (Table.AssemblyRef);
  920. if (module.IsWindowsMetadata ())
  921. module.Projections.RemoveVirtualReferences (references);
  922. for (int i = 0; i < references.Count; i++) {
  923. var reference = references [i];
  924. var key_or_token = reference.PublicKey.IsNullOrEmpty ()
  925. ? reference.PublicKeyToken
  926. : reference.PublicKey;
  927. var version = reference.Version;
  928. var rid = table.AddRow (new AssemblyRefRow (
  929. (ushort) version.Major,
  930. (ushort) version.Minor,
  931. (ushort) version.Build,
  932. (ushort) version.Revision,
  933. reference.Attributes,
  934. GetBlobIndex (key_or_token),
  935. GetStringIndex (reference.Name),
  936. GetStringIndex (reference.Culture),
  937. GetBlobIndex (reference.Hash)));
  938. reference.token = new MetadataToken (TokenType.AssemblyRef, rid);
  939. }
  940. if (module.IsWindowsMetadata ())
  941. module.Projections.AddVirtualReferences (references);
  942. }
  943. void AddModuleReferences ()
  944. {
  945. var references = module.ModuleReferences;
  946. var table = GetTable<ModuleRefTable> (Table.ModuleRef);
  947. for (int i = 0; i < references.Count; i++) {
  948. var reference = references [i];
  949. reference.token = new MetadataToken (
  950. TokenType.ModuleRef,
  951. table.AddRow (GetStringIndex (reference.Name)));
  952. }
  953. }
  954. void AddResources ()
  955. {
  956. var resources = module.Resources;
  957. var table = GetTable<ManifestResourceTable> (Table.ManifestResource);
  958. for (int i = 0; i < resources.Count; i++) {
  959. var resource = resources [i];
  960. var row = new ManifestResourceRow (
  961. 0,
  962. resource.Attributes,
  963. GetStringIndex (resource.Name),
  964. 0);
  965. switch (resource.ResourceType) {
  966. case ResourceType.Embedded:
  967. row.Col1 = AddEmbeddedResource ((EmbeddedResource) resource);
  968. break;
  969. case ResourceType.Linked:
  970. row.Col4 = CodedIndex.Implementation.CompressMetadataToken (
  971. new MetadataToken (
  972. TokenType.File,
  973. AddLinkedResource ((LinkedResource) resource)));
  974. break;
  975. case ResourceType.AssemblyLinked:
  976. row.Col4 = CodedIndex.Implementation.CompressMetadataToken (
  977. ((AssemblyLinkedResource) resource).Assembly.MetadataToken);
  978. break;
  979. default:
  980. throw new NotSupportedException ();
  981. }
  982. table.AddRow (row);
  983. }
  984. }
  985. uint AddLinkedResource (LinkedResource resource)
  986. {
  987. var table = GetTable<FileTable> (Table.File);
  988. var hash = resource.Hash;
  989. if (hash.IsNullOrEmpty ())
  990. hash = CryptoService.ComputeHash (resource.File);
  991. return (uint) table.AddRow (new FileRow (
  992. FileAttributes.ContainsNoMetaData,
  993. GetStringIndex (resource.File),
  994. GetBlobIndex (hash)));
  995. }
  996. uint AddEmbeddedResource (EmbeddedResource resource)
  997. {
  998. return resources.AddResource (resource.GetResourceData ());
  999. }
  1000. void AddExportedTypes ()
  1001. {
  1002. var exported_types = module.ExportedTypes;
  1003. var table = GetTable<ExportedTypeTable> (Table.ExportedType);
  1004. for (int i = 0; i < exported_types.Count; i++) {
  1005. var exported_type = exported_types [i];
  1006. var rid = table.AddRow (new ExportedTypeRow (
  1007. exported_type.Attributes,
  1008. (uint) exported_type.Identifier,
  1009. GetStringIndex (exported_type.Name),
  1010. GetStringIndex (exported_type.Namespace),
  1011. MakeCodedRID (GetExportedTypeScope (exported_type), CodedIndex.Implementation)));
  1012. exported_type.token = new MetadataToken (TokenType.ExportedType, rid);
  1013. }
  1014. }
  1015. MetadataToken GetExportedTypeScope (ExportedType exported_type)
  1016. {
  1017. if (exported_type.DeclaringType != null)
  1018. return exported_type.DeclaringType.MetadataToken;
  1019. var scope = exported_type.Scope;
  1020. switch (scope.MetadataToken.TokenType) {
  1021. case TokenType.AssemblyRef:
  1022. return scope.MetadataToken;
  1023. case TokenType.ModuleRef:
  1024. var file_table = GetTable<FileTable> (Table.File);
  1025. for (int i = 0; i < file_table.length; i++)
  1026. if (file_table.rows [i].Col2 == GetStringIndex (scope.Name))
  1027. return new MetadataToken (TokenType.File, i + 1);
  1028. break;
  1029. }
  1030. throw new NotSupportedException ();
  1031. }
  1032. void BuildTypes ()
  1033. {
  1034. if (!module.HasTypes)
  1035. return;
  1036. AttachTokens ();
  1037. AddTypes ();
  1038. AddGenericParameters ();
  1039. }
  1040. void AttachTokens ()
  1041. {
  1042. var types = module.Types;
  1043. for (int i = 0; i < types.Count; i++)
  1044. AttachTypeToken (types [i]);
  1045. }
  1046. void AttachTypeToken (TypeDefinition type)
  1047. {
  1048. type.token = new MetadataToken (TokenType.TypeDef, type_rid++);
  1049. type.fields_range.Start = field_rid;
  1050. type.methods_range.Start = method_rid;
  1051. if (type.HasFields)
  1052. AttachFieldsToken (type);
  1053. if (type.HasMethods)
  1054. AttachMethodsToken (type);
  1055. if (type.HasNestedTypes)
  1056. AttachNestedTypesToken (type);
  1057. }
  1058. void AttachNestedTypesToken (TypeDefinition type)
  1059. {
  1060. var nested_types = type.NestedTypes;
  1061. for (int i = 0; i < nested_types.Count; i++)
  1062. AttachTypeToken (nested_types [i]);
  1063. }
  1064. void AttachFieldsToken (TypeDefinition type)
  1065. {
  1066. var fields = type.Fields;
  1067. type.fields_range.Length = (uint) fields.Count;
  1068. for (int i = 0; i < fields.Count; i++)
  1069. fields [i].token = new MetadataToken (TokenType.Field, field_rid++);
  1070. }
  1071. void AttachMethodsToken (TypeDefinition type)
  1072. {
  1073. var methods = type.Methods;
  1074. type.methods_range.Length = (uint) methods.Count;
  1075. for (int i = 0; i < methods.Count; i++)
  1076. methods [i].token = new MetadataToken (TokenType.Method, method_rid++);
  1077. }
  1078. MetadataToken GetTypeToken (TypeReference type)
  1079. {
  1080. if (type == null)
  1081. return MetadataToken.Zero;
  1082. if (type.IsDefinition)
  1083. return type.token;
  1084. if (type.IsTypeSpecification ())
  1085. return GetTypeSpecToken (type);
  1086. return GetTypeRefToken (type);
  1087. }
  1088. MetadataToken GetTypeSpecToken (TypeReference type)
  1089. {
  1090. var row = GetBlobIndex (GetTypeSpecSignature (type));
  1091. MetadataToken token;
  1092. if (type_spec_map.TryGetValue (row, out token))
  1093. return token;
  1094. return AddTypeSpecification (type, row);
  1095. }
  1096. MetadataToken AddTypeSpecification (TypeReference type, uint row)
  1097. {
  1098. type.token = new MetadataToken (TokenType.TypeSpec, typespec_table.AddRow (row));
  1099. var token = type.token;
  1100. type_spec_map.Add (row, token);
  1101. return token;
  1102. }
  1103. MetadataToken GetTypeRefToken (TypeReference type)
  1104. {
  1105. var projection = WindowsRuntimeProjections.RemoveProjection (type);
  1106. var row = CreateTypeRefRow (type);
  1107. MetadataToken token;
  1108. if (!type_ref_map.TryGetValue (row, out token))
  1109. token = AddTypeReference (type, row);
  1110. WindowsRuntimeProjections.ApplyProjection (type, projection);
  1111. return token;
  1112. }
  1113. TypeRefRow CreateTypeRefRow (TypeReference type)
  1114. {
  1115. var scope_token = GetScopeToken (type);
  1116. return new TypeRefRow (
  1117. MakeCodedRID (scope_token, CodedIndex.ResolutionScope),
  1118. GetStringIndex (type.Name),
  1119. GetStringIndex (type.Namespace));
  1120. }
  1121. MetadataToken GetScopeToken (TypeReference type)
  1122. {
  1123. if (type.IsNested)
  1124. return GetTypeRefToken (type.DeclaringType);
  1125. var scope = type.Scope;
  1126. if (scope == null)
  1127. return MetadataToken.Zero;
  1128. return scope.MetadataToken;
  1129. }
  1130. static CodedRID MakeCodedRID (IMetadataTokenProvider provider, CodedIndex index)
  1131. {
  1132. return MakeCodedRID (provider.MetadataToken, index);
  1133. }
  1134. static CodedRID MakeCodedRID (MetadataToken token, CodedIndex index)
  1135. {
  1136. return index.CompressMetadataToken (token);
  1137. }
  1138. MetadataToken AddTypeReference (TypeReference type, TypeRefRow row)
  1139. {
  1140. type.token = new MetadataToken (TokenType.TypeRef, type_ref_table.AddRow (row));
  1141. var token = type.token;
  1142. type_ref_map.Add (row, token);
  1143. return token;
  1144. }
  1145. void AddTypes ()
  1146. {
  1147. var types = module.Types;
  1148. for (int i = 0; i < types.Count; i++)
  1149. AddType (types [i]);
  1150. }
  1151. void AddType (TypeDefinition type)
  1152. {
  1153. var treatment = WindowsRuntimeProjections.RemoveProjection (type);
  1154. type_def_table.AddRow (new TypeDefRow (
  1155. type.Attributes,
  1156. GetStringIndex (type.Name),
  1157. GetStringIndex (type.Namespace),
  1158. MakeCodedRID (GetTypeToken (type.BaseType), CodedIndex.TypeDefOrRef),
  1159. type.fields_range.Start,
  1160. type.methods_range.Start));
  1161. if (type.HasGenericParameters)
  1162. AddGenericParameters (type);
  1163. if (type.HasInterfaces)
  1164. AddInterfaces (type);
  1165. AddLayoutInfo (type);
  1166. if (type.HasFields)
  1167. AddFields (type);
  1168. if (type.HasMethods)
  1169. AddMethods (type);
  1170. if (type.HasProperties)
  1171. AddProperties (type);
  1172. if (type.HasEvents)
  1173. AddEvents (type);
  1174. if (type.HasCustomAttributes)
  1175. AddCustomAttributes (type);
  1176. if (type.HasSecurityDeclarations)
  1177. AddSecurityDeclarations (type);
  1178. if (type.HasNestedTypes)
  1179. AddNestedTypes (type);
  1180. WindowsRuntimeProjections.ApplyProjection (type, treatment);
  1181. }
  1182. void AddGenericParameters (IGenericParameterProvider owner)
  1183. {
  1184. var parameters = owner.GenericParameters;
  1185. for (int i = 0; i < parameters.Count; i++)
  1186. generic_parameters.Add (parameters [i]);
  1187. }
  1188. sealed class GenericParameterComparer : IComparer<GenericParameter> {
  1189. public int Compare (GenericParameter a, GenericParameter b)
  1190. {
  1191. var a_owner = MakeCodedRID (a.Owner, CodedIndex.TypeOrMethodDef);
  1192. var b_owner = MakeCodedRID (b.Owner, CodedIndex.TypeOrMethodDef);
  1193. if (a_owner == b_owner) {
  1194. var a_pos = a.Position;
  1195. var b_pos = b.Position;
  1196. return a_pos == b_pos ? 0 : a_pos > b_pos ? 1 : -1;
  1197. }
  1198. return a_owner > b_owner ? 1 : -1;
  1199. }
  1200. }
  1201. void AddGenericParameters ()
  1202. {
  1203. var items = this.generic_parameters.items;
  1204. var size = this.generic_parameters.size;
  1205. Array.Sort (items, 0, size, new GenericParameterComparer ());
  1206. var generic_param_table = GetTable<GenericParamTable> (Table.GenericParam);
  1207. var generic_param_constraint_table = GetTable<GenericParamConstraintTable> (Table.GenericParamConstraint);
  1208. for (int i = 0; i < size; i++) {
  1209. var generic_parameter = items [i];
  1210. var rid = generic_param_table.AddRow (new GenericParamRow (
  1211. (ushort) generic_parameter.Position,
  1212. generic_parameter.Attributes,
  1213. MakeCodedRID (generic_parameter.Owner, CodedIndex.TypeOrMethodDef),
  1214. GetStringIndex (generic_parameter.Name)));
  1215. generic_parameter.token = new MetadataToken (TokenType.GenericParam, rid);
  1216. if (generic_parameter.HasConstraints)
  1217. AddConstraints (generic_parameter, generic_param_constraint_table);
  1218. if (generic_parameter.HasCustomAttributes)
  1219. AddCustomAttributes (generic_parameter);
  1220. }
  1221. }
  1222. void AddConstraints (GenericParameter generic_parameter, GenericParamConstraintTable table)
  1223. {
  1224. var constraints = generic_parameter.Constraints;
  1225. var gp_rid = generic_parameter.token.RID;
  1226. for (int i = 0; i < constraints.Count; i++) {
  1227. var constraint = constraints [i];
  1228. var rid = table.AddRow (new GenericParamConstraintRow (
  1229. gp_rid,
  1230. MakeCodedRID (GetTypeToken (constraint.ConstraintType), CodedIndex.TypeDefOrRef)));
  1231. constraint.token = new MetadataToken (TokenType.GenericParamConstraint, rid);
  1232. if (constraint.HasCustomAttributes)
  1233. AddCustomAttributes (constraint);
  1234. }
  1235. }
  1236. void AddInterfaces (TypeDefinition type)
  1237. {
  1238. var interfaces = type.Interfaces;
  1239. var type_rid = type.token.RID;
  1240. for (int i = 0; i < interfaces.Count; i++) {
  1241. var iface_impl = interfaces [i];
  1242. var rid = iface_impl_table.AddRow (new InterfaceImplRow (
  1243. type_rid,
  1244. MakeCodedRID (GetTypeToken (iface_impl.InterfaceType), CodedIndex.TypeDefOrRef)));
  1245. iface_impl.token = new MetadataToken (TokenType.InterfaceImpl, rid);
  1246. if (iface_impl.HasCustomAttributes)
  1247. AddCustomAttributes (iface_impl);
  1248. }
  1249. }
  1250. void AddLayoutInfo (TypeDefinition type)
  1251. {
  1252. if (type.HasLayoutInfo) {
  1253. var table = GetTable<ClassLayoutTable> (Table.ClassLayout);
  1254. table.AddRow (new ClassLayoutRow (
  1255. (ushort) type.PackingSize,
  1256. (uint) type.ClassSize,
  1257. type.token.RID));
  1258. return;
  1259. }
  1260. if (type.IsValueType && HasNoInstanceField (type)) {
  1261. var table = GetTable<ClassLayoutTable> (Table.ClassLayout);
  1262. table.AddRow (new ClassLayoutRow (0, 1, type.token.RID));
  1263. }
  1264. }
  1265. static bool HasNoInstanceField (TypeDefinition type)
  1266. {
  1267. if (!type.HasFields)
  1268. return true;
  1269. var fields = type.Fields;
  1270. for (int i = 0; i < fields.Count; i++)
  1271. if (!fields [i].IsStatic)
  1272. return false;
  1273. return true;
  1274. }
  1275. void AddNestedTypes (TypeDefinition type)
  1276. {
  1277. var nested_types = type.NestedTypes;
  1278. var nested_table = GetTable<NestedClassTable> (Table.NestedClass);
  1279. for (int i = 0; i < nested_types.Count; i++) {
  1280. var nested = nested_types [i];
  1281. AddType (nested);
  1282. nested_table.AddRow (new NestedClassRow (nested.token.RID, type.token.RID));
  1283. }
  1284. }
  1285. void AddFields (TypeDefinition type)
  1286. {
  1287. var fields = type.Fields;
  1288. for (int i = 0; i < fields.Count; i++)
  1289. AddField (fields [i]);
  1290. }
  1291. void AddField (FieldDefinition field)
  1292. {
  1293. var projection = WindowsRuntimeProjections.RemoveProjection (field);
  1294. field_table.AddRow (new FieldRow (
  1295. field.Attributes,
  1296. GetStringIndex (field.Name),
  1297. GetBlobIndex (GetFieldSignature (field))));
  1298. if (!field.InitialValue.IsNullOrEmpty ())
  1299. AddFieldRVA (field);
  1300. if (field.HasLayoutInfo)
  1301. AddFieldLayout (field);
  1302. if (field.HasCustomAttributes)
  1303. AddCustomAttributes (field);
  1304. if (field.HasConstant)
  1305. AddConstant (field, field.FieldType);
  1306. if (field.HasMarshalInfo)
  1307. AddMarshalInfo (field);
  1308. WindowsRuntimeProjections.ApplyProjection (field, projection);
  1309. }
  1310. void AddFieldRVA (FieldDefinition field)
  1311. {
  1312. var table = GetTable<FieldRVATable> (Table.FieldRVA);
  1313. table.AddRow (new FieldRVARow (
  1314. data.AddData (field.InitialValue),
  1315. field.token.RID));
  1316. }
  1317. void AddFieldLayout (FieldDefinition field)
  1318. {
  1319. var table = GetTable<FieldLayoutTable> (Table.FieldLayout);
  1320. table.AddRow (new FieldLayoutRow ((uint) field.Offset, field.token.RID));
  1321. }
  1322. void AddMethods (TypeDefinition type)
  1323. {
  1324. var methods = type.Methods;
  1325. for (int i = 0; i < methods.Count; i++)
  1326. AddMethod (methods [i]);
  1327. }
  1328. void AddMethod (MethodDefinition method)
  1329. {
  1330. var projection = WindowsRuntimeProjections.RemoveProjection (method);
  1331. method_table.AddRow (new MethodRow (
  1332. method.HasBody ? code.WriteMethodBody (method) : 0,
  1333. method.ImplAttributes,
  1334. method.Attributes,
  1335. GetStringIndex (method.Name),
  1336. GetBlobIndex (GetMethodSignature (method)),
  1337. param_rid));
  1338. AddParameters (method);
  1339. if (method.HasGenericParameters)
  1340. AddGenericParameters (method);
  1341. if (method.IsPInvokeImpl)
  1342. AddPInvokeInfo (method);
  1343. if (method.HasCustomAttributes)
  1344. AddCustomAttributes (method);
  1345. if (method.HasSecurityDeclarations)
  1346. AddSecurityDeclarations (method);
  1347. if (method.HasOverrides)
  1348. AddOverrides (method);
  1349. WindowsRuntimeProjections.ApplyProjection (method, projection);
  1350. }
  1351. void AddParameters (MethodDefinition method)
  1352. {
  1353. var return_parameter = method.MethodReturnType.parameter;
  1354. if (return_parameter != null && RequiresParameterRow (return_parameter))
  1355. AddParameter (0, return_parameter, param_table);
  1356. if (!method.HasParameters)
  1357. return;
  1358. var parameters = method.Parameters;
  1359. for (int i = 0; i < parameters.Count; i++) {
  1360. var parameter = parameters [i];
  1361. if (!RequiresParameterRow (parameter))
  1362. continue;
  1363. AddParameter ((ushort) (i + 1), parameter, param_table);
  1364. }
  1365. }
  1366. void AddPInvokeInfo (MethodDefinition method)
  1367. {
  1368. var pinvoke = method.PInvokeInfo;
  1369. if (pinvoke == null)
  1370. return;
  1371. var table = GetTable<ImplMapTable> (Table.ImplMap);
  1372. table.AddRow (new ImplMapRow (
  1373. pinvoke.Attributes,
  1374. MakeCodedRID (method, CodedIndex.MemberForwarded),
  1375. GetStringIndex (pinvoke.EntryPoint),
  1376. pinvoke.Module.MetadataToken.RID));
  1377. }
  1378. void AddOverrides (MethodDefinition method)
  1379. {
  1380. var overrides = method.Overrides;
  1381. var table = GetTable<MethodImplTable> (Table.MethodImpl);
  1382. for (int i = 0; i < overrides.Count; i++) {
  1383. table.AddRow (new MethodImplRow (
  1384. method.DeclaringType.token.RID,
  1385. MakeCodedRID (method, CodedIndex.MethodDefOrRef),
  1386. MakeCodedRID (LookupToken (overrides [i]), CodedIndex.MethodDefOrRef)));
  1387. }
  1388. }
  1389. static bool RequiresParameterRow (ParameterDefinition parameter)
  1390. {
  1391. return !string.IsNullOrEmpty (parameter.Name)
  1392. || parameter.Attributes != ParameterAttributes.None
  1393. || parameter.HasMarshalInfo
  1394. || parameter.HasConstant
  1395. || parameter.HasCustomAttributes;
  1396. }
  1397. void AddParameter (ushort sequence, ParameterDefinition parameter, ParamTable table)
  1398. {
  1399. table.AddRow (new ParamRow (
  1400. parameter.Attributes,
  1401. sequence,
  1402. GetStringIndex (parameter.Name)));
  1403. parameter.token = new MetadataToken (TokenType.Param, param_rid++);
  1404. if (parameter.HasCustomAttributes)
  1405. AddCustomAttributes (parameter);
  1406. if (parameter.HasConstant)
  1407. AddConstant (parameter, parameter.ParameterType);
  1408. if (parameter.HasMarshalInfo)
  1409. AddMarshalInfo (parameter);
  1410. }
  1411. void AddMarshalInfo (IMarshalInfoProvider owner)
  1412. {
  1413. var table = GetTable<FieldMarshalTable> (Table.FieldMarshal);
  1414. table.AddRow (new FieldMarshalRow (
  1415. MakeCodedRID (owner, CodedIndex.HasFieldMarshal),
  1416. GetBlobIndex (GetMarshalInfoSignature (owner))));
  1417. }
  1418. void AddProperties (TypeDefinition type)
  1419. {
  1420. var properties = type.Properties;
  1421. property_map_table.AddRow (new PropertyMapRow (type.token.RID, property_rid));
  1422. for (int i = 0; i < properties.Count; i++)
  1423. AddProperty (properties [i]);
  1424. }
  1425. void AddProperty (PropertyDefinition property)
  1426. {
  1427. property_table.AddRow (new PropertyRow (
  1428. property.Attributes,
  1429. GetStringIndex (property.Name),
  1430. GetBlobIndex (GetPropertySignature (property))));
  1431. property.token = new MetadataToken (TokenType.Property, property_rid++);
  1432. var method = property.GetMethod;
  1433. if (method != null)
  1434. AddSemantic (MethodSemanticsAttributes.Getter, property, method);
  1435. method = property.SetMethod;
  1436. if (method != null)
  1437. AddSemantic (MethodSemanticsAttributes.Setter, property, method);
  1438. if (property.HasOtherMethods)
  1439. AddOtherSemantic (property, property.OtherMethods);
  1440. if (property.HasCustomAttributes)
  1441. AddCustomAttributes (property);
  1442. if (property.HasConstant)
  1443. AddConstant (property, property.PropertyType);
  1444. }
  1445. void AddOtherSemantic (IMetadataTokenProvider owner, Collection<MethodDefinition> others)
  1446. {
  1447. for (int i = 0; i < others.Count; i++)
  1448. AddSemantic (MethodSemanticsAttributes.Other, owner, others [i]);
  1449. }
  1450. void AddEvents (TypeDefinition type)
  1451. {
  1452. var events = type.Events;
  1453. event_map_table.AddRow (new EventMapRow (type.token.RID, event_rid));
  1454. for (int i = 0; i < events.Count; i++)
  1455. AddEvent (events [i]);
  1456. }
  1457. void AddEvent (EventDefinition @event)
  1458. {
  1459. event_table.AddRow (new EventRow (
  1460. @event.Attributes,
  1461. GetStringIndex (@event.Name),
  1462. MakeCodedRID (GetTypeToken (@event.EventType), CodedIndex.TypeDefOrRef)));
  1463. @event.token = new MetadataToken (TokenType.Event, event_rid++);
  1464. var method = @event.AddMethod;
  1465. if (method != null)
  1466. AddSemantic (MethodSemanticsAttributes.AddOn, @event, method);
  1467. method = @event.InvokeMethod;
  1468. if (method != null)
  1469. AddSemantic (MethodSemanticsAttributes.Fire, @event, method);
  1470. method = @event.RemoveMethod;
  1471. if (method != null)
  1472. AddSemantic (MethodSemanticsAttributes.RemoveOn, @event, method);
  1473. if (@event.HasOtherMethods)
  1474. AddOtherSemantic (@event, @event.OtherMethods);
  1475. if (@event.HasCustomAttributes)
  1476. AddCustomAttributes (@event);
  1477. }
  1478. void AddSemantic (MethodSemanticsAttributes semantics, IMetadataTokenProvider provider, MethodDefinition method)
  1479. {
  1480. method.SemanticsAttributes = semantics;
  1481. var table = GetTable<MethodSemanticsTable> (Table.MethodSemantics);
  1482. table.AddRow (new MethodSemanticsRow (
  1483. semantics,
  1484. method.token.RID,
  1485. MakeCodedRID (provider, CodedIndex.HasSemantics)));
  1486. }
  1487. void AddConstant (IConstantProvider owner, TypeReference type)
  1488. {
  1489. var constant = owner.Constant;
  1490. var etype = GetConstantType (type, constant);
  1491. constant_table.AddRow (new ConstantRow (
  1492. etype,
  1493. MakeCodedRID (owner.MetadataToken, CodedIndex.HasConstant),
  1494. GetBlobIndex (GetConstantSignature (etype, constant))));
  1495. }
  1496. static ElementType GetConstantType (TypeReference constant_type, object constant)
  1497. {
  1498. if (constant == null)
  1499. return ElementType.Class;
  1500. var etype = constant_type.etype;
  1501. switch (etype) {
  1502. case ElementType.None:
  1503. var type = constant_type.CheckedResolve ();
  1504. if (type.IsEnum)
  1505. return GetConstantType (type.GetEnumUnderlyingType (), constant);
  1506. return ElementType.Class;
  1507. case ElementType.String:
  1508. return ElementType.String;
  1509. case ElementType.Object:
  1510. return GetConstantType (constant.GetType ());
  1511. case ElementType.Array:
  1512. case ElementType.SzArray:
  1513. case ElementType.MVar:
  1514. case ElementType.Var:
  1515. return ElementType.Class;
  1516. case ElementType.GenericInst:
  1517. var generic_instance = (GenericInstanceType) constant_type;
  1518. if (generic_instance.ElementType.IsTypeOf ("System", "Nullable`1"))
  1519. return GetConstantType (generic_instance.GenericArguments [0], constant);
  1520. return GetConstantType (((TypeSpecification) constant_type).ElementType, constant);
  1521. case ElementType.CModOpt:
  1522. case ElementType.CModReqD:
  1523. case ElementType.ByRef:
  1524. case ElementType.Sentinel:
  1525. return GetConstantType (((TypeSpecification) constant_type).ElementType, constant);
  1526. case ElementType.Boolean:
  1527. case ElementType.Char:
  1528. case ElementType.I:
  1529. case ElementType.I1:
  1530. case ElementType.I2:
  1531. case ElementType.I4:
  1532. case ElementType.I8:
  1533. case ElementType.U:
  1534. case ElementType.U1:
  1535. case ElementType.U2:
  1536. case ElementType.U4:
  1537. case ElementType.U8:
  1538. case ElementType.R4:
  1539. case ElementType.R8:
  1540. return GetConstantType (constant.GetType ());
  1541. default:
  1542. return etype;
  1543. }
  1544. }
  1545. static ElementType GetConstantType (Type type)
  1546. {
  1547. switch (Type.GetTypeCode (type)) {
  1548. case TypeCode.Boolean:
  1549. return ElementType.Boolean;
  1550. case TypeCode.Byte:
  1551. return ElementType.U1;
  1552. case TypeCode.SByte:
  1553. return ElementType.I1;
  1554. case TypeCode.Char:
  1555. return ElementType.Char;
  1556. case TypeCode.Int16:
  1557. return ElementType.I2;
  1558. case TypeCode.UInt16:
  1559. return ElementType.U2;
  1560. case TypeCode.Int32:
  1561. return ElementType.I4;
  1562. case TypeCode.UInt32:
  1563. return ElementType.U4;
  1564. case TypeCode.Int64:
  1565. return ElementType.I8;
  1566. case TypeCode.UInt64:
  1567. return ElementType.U8;
  1568. case TypeCode.Single:
  1569. return ElementType.R4;
  1570. case TypeCode.Double:
  1571. return ElementType.R8;
  1572. case TypeCode.String:
  1573. return ElementType.String;
  1574. default:
  1575. throw new NotSupportedException (type.FullName);
  1576. }
  1577. }
  1578. void AddCustomAttributes (ICustomAttributeProvider owner)
  1579. {
  1580. var custom_attributes = owner.CustomAttributes;
  1581. for (int i = 0; i < custom_attributes.Count; i++) {
  1582. var attribute = custom_attributes [i];
  1583. var projection = WindowsRuntimeProjections.RemoveProjection (attribute);
  1584. custom_attribute_table.AddRow (new CustomAttributeRow (
  1585. MakeCodedRID (owner, CodedIndex.HasCustomAttribute),
  1586. MakeCodedRID (LookupToken (attribute.Constructor), CodedIndex.CustomAttributeType),
  1587. GetBlobIndex (GetCustomAttributeSignature (attribute))));
  1588. WindowsRuntimeProjections.ApplyProjection (attribute, projection);
  1589. }
  1590. }
  1591. void AddSecurityDeclarations (ISecurityDeclarationProvider owner)
  1592. {
  1593. var declarations = owner.SecurityDeclarations;
  1594. for (int i = 0; i < declarations.Count; i++) {
  1595. var declaration = declarations [i];
  1596. declsec_table.AddRow (new DeclSecurityRow (
  1597. declaration.Action,
  1598. MakeCodedRID (owner, CodedIndex.HasDeclSecurity),
  1599. GetBlobIndex (GetSecurityDeclarationSignature (declaration))));
  1600. }
  1601. }
  1602. MetadataToken GetMemberRefToken (MemberReference member)
  1603. {
  1604. var projection = WindowsRuntimeProjections.RemoveProjection (member);
  1605. var row = CreateMemberRefRow (member);
  1606. MetadataToken token;
  1607. if (!member_ref_map.TryGetValue (row, out token))
  1608. token = AddMemberReference (member, row);
  1609. WindowsRuntimeProjections.ApplyProjection (member, projection);
  1610. return token;
  1611. }
  1612. MemberRefRow CreateMemberRefRow (MemberReference member)
  1613. {
  1614. return new MemberRefRow (
  1615. MakeCodedRID (GetTypeToken (member.DeclaringType), CodedIndex.MemberRefParent),
  1616. GetStringIndex (member.Name),
  1617. GetBlobIndex (GetMemberRefSignature (member)));
  1618. }
  1619. MetadataToken AddMemberReference (MemberReference member, MemberRefRow row)
  1620. {
  1621. member.token = new MetadataToken (TokenType.MemberRef, member_ref_table.AddRow (row));
  1622. var token = member.token;
  1623. member_ref_map.Add (row, token);
  1624. return token;
  1625. }
  1626. MetadataToken GetMethodSpecToken (MethodSpecification method_spec)
  1627. {
  1628. var row = CreateMethodSpecRow (method_spec);
  1629. MetadataToken token;
  1630. if (method_spec_map.TryGetValue (row, out token))
  1631. return token;
  1632. AddMethodSpecification (method_spec, row);
  1633. return method_spec.token;
  1634. }
  1635. void AddMethodSpecification (MethodSpecification method_spec, MethodSpecRow row)
  1636. {
  1637. method_spec.token = new MetadataToken (TokenType.MethodSpec, method_spec_table.AddRow (row));
  1638. method_spec_map.Add (row, method_spec.token);
  1639. }
  1640. MethodSpecRow CreateMethodSpecRow (MethodSpecification method_spec)
  1641. {
  1642. return new MethodSpecRow (
  1643. MakeCodedRID (LookupToken (method_spec.ElementMethod), CodedIndex.MethodDefOrRef),
  1644. GetBlobIndex (GetMethodSpecSignature (method_spec)));
  1645. }
  1646. SignatureWriter CreateSignatureWriter ()
  1647. {
  1648. return new SignatureWriter (this);
  1649. }
  1650. SignatureWriter GetMethodSpecSignature (MethodSpecification method_spec)
  1651. {
  1652. if (!method_spec.IsGenericInstance)
  1653. throw new NotSupportedException ();
  1654. var generic_instance = (GenericInstanceMethod) method_spec;
  1655. var signature = CreateSignatureWriter ();
  1656. signature.WriteByte (0x0a);
  1657. signature.WriteGenericInstanceSignature (generic_instance);
  1658. return signature;
  1659. }
  1660. public uint AddStandAloneSignature (uint signature)
  1661. {
  1662. return (uint) standalone_sig_table.AddRow (signature);
  1663. }
  1664. public uint GetLocalVariableBlobIndex (Collection<VariableDefinition> variables)
  1665. {
  1666. return GetBlobIndex (GetVariablesSignature (variables));
  1667. }
  1668. public uint GetCallSiteBlobIndex (CallSite call_site)
  1669. {
  1670. return GetBlobIndex (GetMethodSignature (call_site));
  1671. }
  1672. public uint GetConstantTypeBlobIndex (TypeReference constant_type)
  1673. {
  1674. return GetBlobIndex (GetConstantTypeSignature (constant_type));
  1675. }
  1676. SignatureWriter GetVariablesSignature (Collection<VariableDefinition> variables)
  1677. {
  1678. var signature = CreateSignatureWriter ();
  1679. signature.WriteByte (0x7);
  1680. signature.WriteCompressedUInt32 ((uint) variables.Count);
  1681. for (int i = 0; i < variables.Count; i++)
  1682. signature.WriteTypeSignature (variables [i].VariableType);
  1683. return signature;
  1684. }
  1685. SignatureWriter GetConstantTypeSignature (TypeReference constant_type)
  1686. {
  1687. var signature = CreateSignatureWriter ();
  1688. signature.WriteByte (0x6);
  1689. signature.WriteTypeSignature (constant_type);
  1690. return signature;
  1691. }
  1692. SignatureWriter GetFieldSignature (FieldReference field)
  1693. {
  1694. var signature = CreateSignatureWriter ();
  1695. signature.WriteByte (0x6);
  1696. signature.WriteTypeSignature (field.FieldType);
  1697. return signature;
  1698. }
  1699. SignatureWriter GetMethodSignature (IMethodSignature method)
  1700. {
  1701. var signature = CreateSignatureWriter ();
  1702. signature.WriteMethodSignature (method);
  1703. return signature;
  1704. }
  1705. SignatureWriter GetMemberRefSignature (MemberReference member)
  1706. {
  1707. var field = member as FieldReference;
  1708. if (field != null)
  1709. return GetFieldSignature (field);
  1710. var method = member as MethodReference;
  1711. if (method != null)
  1712. return GetMethodSignature (method);
  1713. throw new NotSupportedException ();
  1714. }
  1715. SignatureWriter GetPropertySignature (PropertyDefinition property)
  1716. {
  1717. var signature = CreateSignatureWriter ();
  1718. byte calling_convention = 0x8;
  1719. if (property.HasThis)
  1720. calling_convention |= 0x20;
  1721. uint param_count = 0;
  1722. Collection<ParameterDefinition> parameters = null;
  1723. if (property.HasParameters) {
  1724. parameters = property.Parameters;
  1725. param_count = (uint) parameters.Count;
  1726. }
  1727. signature.WriteByte (calling_convention);
  1728. signature.WriteCompressedUInt32 (param_count);
  1729. signature.WriteTypeSignature (property.PropertyType);
  1730. if (param_count == 0)
  1731. return signature;
  1732. for (int i = 0; i < param_count; i++)
  1733. signature.WriteTypeSignature (parameters [i].ParameterType);
  1734. return signature;
  1735. }
  1736. SignatureWriter GetTypeSpecSignature (TypeReference type)
  1737. {
  1738. var signature = CreateSignatureWriter ();
  1739. signature.WriteTypeSignature (type);
  1740. return signature;
  1741. }
  1742. SignatureWriter GetConstantSignature (ElementType type, object value)
  1743. {
  1744. var signature = CreateSignatureWriter ();
  1745. switch (type) {
  1746. case ElementType.Array:
  1747. case ElementType.SzArray:
  1748. case ElementType.Class:
  1749. case ElementType.Object:
  1750. case ElementType.None:
  1751. case ElementType.Var:
  1752. case ElementType.MVar:
  1753. signature.WriteInt32 (0);
  1754. break;
  1755. case ElementType.String:
  1756. signature.WriteConstantString ((string) value);
  1757. break;
  1758. default:
  1759. signature.WriteConstantPrimitive (value);
  1760. break;
  1761. }
  1762. return signature;
  1763. }
  1764. SignatureWriter GetCustomAttributeSignature (CustomAttribute attribute)
  1765. {
  1766. var signature = CreateSignatureWriter ();
  1767. if (!attribute.resolved) {
  1768. signature.WriteBytes (attribute.GetBlob ());
  1769. return signature;
  1770. }
  1771. signature.WriteUInt16 (0x0001);
  1772. signature.WriteCustomAttributeConstructorArguments (attribute);
  1773. signature.WriteCustomAttributeNamedArguments (attribute);
  1774. return signature;
  1775. }
  1776. SignatureWriter GetSecurityDeclarationSignature (SecurityDeclaration declaration)
  1777. {
  1778. var signature = CreateSignatureWriter ();
  1779. if (!declaration.resolved)
  1780. signature.WriteBytes (declaration.GetBlob ());
  1781. else if (module.Runtime < TargetRuntime.Net_2_0)
  1782. signature.WriteXmlSecurityDeclaration (declaration);
  1783. else
  1784. signature.WriteSecurityDeclaration (declaration);
  1785. return signature;
  1786. }
  1787. SignatureWriter GetMarshalInfoSignature (IMarshalInfoProvider owner)
  1788. {
  1789. var signature = CreateSignatureWriter ();
  1790. signature.WriteMarshalInfo (owner.MarshalInfo);
  1791. return signature;
  1792. }
  1793. static Exception CreateForeignMemberException (MemberReference member)
  1794. {
  1795. return new ArgumentException (string.Format ("Member '{0}' is declared in another module and needs to be imported", member));
  1796. }
  1797. public MetadataToken LookupToken (IMetadataTokenProvider provider)
  1798. {
  1799. if (provider == null)
  1800. throw new ArgumentNullException ();
  1801. if (metadata_builder != null)
  1802. return metadata_builder.LookupToken (provider);
  1803. var member = provider as MemberReference;
  1804. if (member == null || member.Module != module)
  1805. throw CreateForeignMemberException (member);
  1806. var token = provider.MetadataToken;
  1807. switch (token.TokenType) {
  1808. case TokenType.TypeDef:
  1809. case TokenType.Method:
  1810. case TokenType.Field:
  1811. case TokenType.Event:
  1812. case TokenType.Property:
  1813. return token;
  1814. case TokenType.TypeRef:
  1815. case TokenType.TypeSpec:
  1816. case TokenType.GenericParam:
  1817. return GetTypeToken ((TypeReference) provider);
  1818. case TokenType.MethodSpec:
  1819. return GetMethodSpecToken ((MethodSpecification) provider);
  1820. case TokenType.MemberRef:
  1821. return GetMemberRefToken (member);
  1822. default:
  1823. throw new NotSupportedException ();
  1824. }
  1825. }
  1826. public void AddMethodDebugInformation (MethodDebugInformation method_info)
  1827. {
  1828. if (method_info.HasSequencePoints)
  1829. AddSequencePoints (method_info);
  1830. if (method_info.Scope != null)
  1831. AddLocalScope (method_info, method_info.Scope);
  1832. if (method_info.StateMachineKickOffMethod != null)
  1833. AddStateMachineMethod (method_info);
  1834. AddCustomDebugInformations (method_info.Method);
  1835. }
  1836. void AddStateMachineMethod (MethodDebugInformation method_info)
  1837. {
  1838. state_machine_method_table.AddRow (new StateMachineMethodRow (method_info.Method.MetadataToken.RID, method_info.StateMachineKickOffMethod.MetadataToken.RID));
  1839. }
  1840. void AddLocalScope (MethodDebugInformation method_info, ScopeDebugInformation scope)
  1841. {
  1842. var rid = local_scope_table.AddRow (new LocalScopeRow (
  1843. method_info.Method.MetadataToken.RID,
  1844. scope.import != null ? AddImportScope (scope.import) : 0,
  1845. local_variable_rid,
  1846. local_constant_rid,
  1847. (uint) scope.Start.Offset,
  1848. (uint) ((scope.End.IsEndOfMethod ? method_info.code_size : scope.End.Offset) - scope.Start.Offset)));
  1849. scope.token = new MetadataToken (TokenType.LocalScope, rid);
  1850. AddCustomDebugInformations (scope);
  1851. if (scope.HasVariables)
  1852. AddLocalVariables (scope);
  1853. if (scope.HasConstants)
  1854. AddLocalConstants (scope);
  1855. for (int i = 0; i < scope.Scopes.Count; i++)
  1856. AddLocalScope (method_info, scope.Scopes [i]);
  1857. }
  1858. void AddLocalVariables (ScopeDebugInformation scope)
  1859. {
  1860. for (int i = 0; i < scope.Variables.Count; i++) {
  1861. var variable = scope.Variables [i];
  1862. local_variable_table.AddRow (new LocalVariableRow (variable.Attributes, (ushort) variable.Index, GetStringIndex (variable.Name)));
  1863. variable.token = new MetadataToken (TokenType.LocalVariable, local_variable_rid);
  1864. local_variable_rid++;
  1865. AddCustomDebugInformations (variable);
  1866. }
  1867. }
  1868. void AddLocalConstants (ScopeDebugInformation scope)
  1869. {
  1870. for (int i = 0; i < scope.Constants.Count; i++) {
  1871. var constant = scope.Constants [i];
  1872. local_constant_table.AddRow (new LocalConstantRow (GetStringIndex (constant.Name), GetBlobIndex (GetConstantSignature(constant))));
  1873. constant.token = new MetadataToken (TokenType.LocalConstant, local_constant_rid);
  1874. local_constant_rid++;
  1875. }
  1876. }
  1877. SignatureWriter GetConstantSignature (ConstantDebugInformation constant)
  1878. {
  1879. var type = constant.ConstantType;
  1880. var signature = CreateSignatureWriter ();
  1881. signature.WriteTypeSignature (type);
  1882. if (type.IsTypeOf ("System", "Decimal")) {
  1883. var bits = decimal.GetBits ((decimal) constant.Value);
  1884. var low = (uint) bits [0];
  1885. var mid = (uint) bits [1];
  1886. var high = (uint) bits [2];
  1887. var scale = (byte) (bits [3] >> 16);
  1888. var negative = (bits [3] & 0x80000000) != 0;
  1889. signature.WriteByte ((byte) (scale | (negative ? 0x80 : 0x00)));
  1890. signature.WriteUInt32 (low);
  1891. signature.WriteUInt32 (mid);
  1892. signature.WriteUInt32 (high);
  1893. return signature;
  1894. }
  1895. if (type.IsTypeOf ("System", "DateTime")) {
  1896. var date = (DateTime) constant.Value;
  1897. signature.WriteInt64 (date.Ticks);
  1898. return signature;
  1899. }
  1900. signature.WriteBytes (GetConstantSignature (type.etype, constant.Value));
  1901. return signature;
  1902. }
  1903. public void AddCustomDebugInformations (ICustomDebugInformationProvider provider)
  1904. {
  1905. if (!provider.HasCustomDebugInformations)
  1906. return;
  1907. var custom_infos = provider.CustomDebugInformations;
  1908. for (int i = 0; i < custom_infos.Count; i++) {
  1909. var custom_info = custom_infos [i];
  1910. switch (custom_info.Kind) {
  1911. case CustomDebugInformationKind.Binary:
  1912. var binary_info = (BinaryCustomDebugInformation) custom_info;
  1913. AddCustomDebugInformation (provider, binary_info, GetBlobIndex (binary_info.Data));
  1914. break;
  1915. case CustomDebugInformationKind.AsyncMethodBody:
  1916. AddAsyncMethodBodyDebugInformation (provider, (AsyncMethodBodyDebugInformation) custom_info);
  1917. break;
  1918. case CustomDebugInformationKind.StateMachineScope:
  1919. AddStateMachineScopeDebugInformation (provider, (StateMachineScopeDebugInformation) custom_info);
  1920. break;
  1921. case CustomDebugInformationKind.EmbeddedSource:
  1922. AddEmbeddedSourceDebugInformation (provider, (EmbeddedSourceDebugInformation) custom_info);
  1923. break;
  1924. case CustomDebugInformationKind.SourceLink:
  1925. AddSourceLinkDebugInformation (provider, (SourceLinkDebugInformation) custom_info);
  1926. break;
  1927. default:
  1928. throw new NotImplementedException ();
  1929. }
  1930. }
  1931. }
  1932. void AddStateMachineScopeDebugInformation (ICustomDebugInformationProvider provider, StateMachineScopeDebugInformation state_machine_scope)
  1933. {
  1934. var method_info = ((MethodDefinition) provider).DebugInformation;
  1935. var signature = CreateSignatureWriter ();
  1936. var scopes = state_machine_scope.Scopes;
  1937. for (int i = 0; i < scopes.Count; i++) {
  1938. var scope = scopes [i];
  1939. signature.WriteUInt32 ((uint) scope.Start.Offset);
  1940. var end_offset = scope.End.IsEndOfMethod
  1941. ? method_info.code_size
  1942. : scope.End.Offset;
  1943. signature.WriteUInt32 ((uint) (end_offset - scope.Start.Offset));
  1944. }
  1945. AddCustomDebugInformation (provider, state_machine_scope, signature);
  1946. }
  1947. void AddAsyncMethodBodyDebugInformation (ICustomDebugInformationProvider provider, AsyncMethodBodyDebugInformation async_method)
  1948. {
  1949. var signature = CreateSignatureWriter ();
  1950. signature.WriteUInt32 ((uint) async_method.catch_handler.Offset + 1);
  1951. if (!async_method.yields.IsNullOrEmpty ()) {
  1952. for (int i = 0; i < async_method.yields.Count; i++) {
  1953. signature.WriteUInt32 ((uint) async_method.yields [i].Offset);
  1954. signature.WriteUInt32 ((uint) async_method.resumes [i].Offset);
  1955. signature.WriteCompressedUInt32 (async_method.resume_methods [i].MetadataToken.RID);
  1956. }
  1957. }
  1958. AddCustomDebugInformation (provider, async_method, signature);
  1959. }
  1960. void AddEmbeddedSourceDebugInformation (ICustomDebugInformationProvider provider, EmbeddedSourceDebugInformation embedded_source)
  1961. {
  1962. var signature = CreateSignatureWriter ();
  1963. var content = embedded_source.content ?? Empty<byte>.Array;
  1964. if (embedded_source.compress) {
  1965. signature.WriteInt32 (content.Length);
  1966. var decompressed_stream = new MemoryStream (content);
  1967. var content_stream = new MemoryStream ();
  1968. using (var compress_stream = new DeflateStream (content_stream, CompressionMode.Compress, leaveOpen: true))
  1969. decompressed_stream.CopyTo (compress_stream);
  1970. signature.WriteBytes (content_stream.ToArray ());
  1971. } else {
  1972. signature.WriteInt32 (0);
  1973. signature.WriteBytes (content);
  1974. }
  1975. AddCustomDebugInformation (provider, embedded_source, signature);
  1976. }
  1977. void AddSourceLinkDebugInformation (ICustomDebugInformationProvider provider, SourceLinkDebugInformation source_link)
  1978. {
  1979. var signature = CreateSignatureWriter ();
  1980. signature.WriteBytes (Encoding.UTF8.GetBytes (source_link.content));
  1981. AddCustomDebugInformation (provider, source_link, signature);
  1982. }
  1983. void AddCustomDebugInformation (ICustomDebugInformationProvider provider, CustomDebugInformation custom_info, SignatureWriter signature)
  1984. {
  1985. AddCustomDebugInformation (provider, custom_info, GetBlobIndex (signature));
  1986. }
  1987. void AddCustomDebugInformation (ICustomDebugInformationProvider provider, CustomDebugInformation custom_info, uint blob_index)
  1988. {
  1989. var rid = custom_debug_information_table.AddRow (new CustomDebugInformationRow (
  1990. MakeCodedRID (provider.MetadataToken, CodedIndex.HasCustomDebugInformation),
  1991. GetGuidIndex (custom_info.Identifier),
  1992. blob_index));
  1993. custom_info.token = new MetadataToken (TokenType.CustomDebugInformation, rid);
  1994. }
  1995. uint AddImportScope (ImportDebugInformation import)
  1996. {
  1997. uint parent = 0;
  1998. if (import.Parent != null)
  1999. parent = AddImportScope (import.Parent);
  2000. uint targets_index = 0;
  2001. if (import.HasTargets) {
  2002. var signature = CreateSignatureWriter ();
  2003. for (int i = 0; i < import.Targets.Count; i++)
  2004. AddImportTarget (import.Targets [i], signature);
  2005. targets_index = GetBlobIndex (signature);
  2006. }
  2007. var row = new ImportScopeRow (parent, targets_index);
  2008. MetadataToken import_token;
  2009. if (import_scope_map.TryGetValue (row, out import_token))
  2010. return import_token.RID;
  2011. import_token = new MetadataToken (TokenType.ImportScope, import_scope_table.AddRow (row));
  2012. import_scope_map.Add (row, import_token);
  2013. return import_token.RID;
  2014. }
  2015. void AddImportTarget (ImportTarget target, SignatureWriter signature)
  2016. {
  2017. signature.WriteCompressedUInt32 ((uint)target.kind);
  2018. switch (target.kind) {
  2019. case ImportTargetKind.ImportNamespace:
  2020. signature.WriteCompressedUInt32 (GetUTF8StringBlobIndex (target.@namespace));
  2021. break;
  2022. case ImportTargetKind.ImportNamespaceInAssembly:
  2023. signature.WriteCompressedUInt32 (target.reference.MetadataToken.RID);
  2024. signature.WriteCompressedUInt32 (GetUTF8StringBlobIndex (target.@namespace));
  2025. break;
  2026. case ImportTargetKind.ImportType:
  2027. signature.WriteTypeToken (target.type);
  2028. break;
  2029. case ImportTargetKind.ImportXmlNamespaceWithAlias:
  2030. signature.WriteCompressedUInt32 (GetUTF8StringBlobIndex (target.alias));
  2031. signature.WriteCompressedUInt32 (GetUTF8StringBlobIndex (target.@namespace));
  2032. break;
  2033. case ImportTargetKind.ImportAlias:
  2034. signature.WriteCompressedUInt32 (GetUTF8StringBlobIndex (target.alias));
  2035. break;
  2036. case ImportTargetKind.DefineAssemblyAlias:
  2037. signature.WriteCompressedUInt32 (GetUTF8StringBlobIndex (target.alias));
  2038. signature.WriteCompressedUInt32 (target.reference.MetadataToken.RID);
  2039. break;
  2040. case ImportTargetKind.DefineNamespaceAlias:
  2041. signature.WriteCompressedUInt32 (GetUTF8StringBlobIndex (target.alias));
  2042. signature.WriteCompressedUInt32 (GetUTF8StringBlobIndex (target.@namespace));
  2043. break;
  2044. case ImportTargetKind.DefineNamespaceInAssemblyAlias:
  2045. signature.WriteCompressedUInt32 (GetUTF8StringBlobIndex (target.alias));
  2046. signature.WriteCompressedUInt32 (target.reference.MetadataToken.RID);
  2047. signature.WriteCompressedUInt32 (GetUTF8StringBlobIndex (target.@namespace));
  2048. break;
  2049. case ImportTargetKind.DefineTypeAlias:
  2050. signature.WriteCompressedUInt32 (GetUTF8StringBlobIndex (target.alias));
  2051. signature.WriteTypeToken (target.type);
  2052. break;
  2053. }
  2054. }
  2055. uint GetUTF8StringBlobIndex (string s)
  2056. {
  2057. return GetBlobIndex (Encoding.UTF8.GetBytes (s));
  2058. }
  2059. public MetadataToken GetDocumentToken (Document document)
  2060. {
  2061. MetadataToken token;
  2062. if (document_map.TryGetValue (document.Url, out token))
  2063. return token;
  2064. token = new MetadataToken (TokenType.Document, document_table.AddRow (
  2065. new DocumentRow (GetBlobIndex (GetDocumentNameSignature (document)),
  2066. GetGuidIndex (document.HashAlgorithm.ToGuid ()),
  2067. GetBlobIndex (document.Hash),
  2068. GetGuidIndex (document.Language.ToGuid ()))));
  2069. document.token = token;
  2070. AddCustomDebugInformations (document);
  2071. document_map.Add (document.Url, token);
  2072. return token;
  2073. }
  2074. SignatureWriter GetDocumentNameSignature (Document document)
  2075. {
  2076. var name = document.Url;
  2077. var signature = CreateSignatureWriter ();
  2078. char separator;
  2079. if (!TryGetDocumentNameSeparator (name, out separator)) {
  2080. signature.WriteByte (0);
  2081. signature.WriteCompressedUInt32 (GetUTF8StringBlobIndex (name));
  2082. return signature;
  2083. }
  2084. signature.WriteByte ((byte) separator);
  2085. var parts = name.Split (new [] { separator });
  2086. for (int i = 0; i < parts.Length; i++) {
  2087. if (parts [i] == String.Empty)
  2088. signature.WriteCompressedUInt32 (0);
  2089. else
  2090. signature.WriteCompressedUInt32 (GetUTF8StringBlobIndex (parts [i]));
  2091. }
  2092. return signature;
  2093. }
  2094. static bool TryGetDocumentNameSeparator (string path, out char separator)
  2095. {
  2096. const char unix = '/';
  2097. const char win = '\\';
  2098. const char zero = (char) 0;
  2099. separator = zero;
  2100. if (string.IsNullOrEmpty (path))
  2101. return false;
  2102. int unix_count = 0;
  2103. int win_count = 0;
  2104. for (int i = 0; i < path.Length; i++) {
  2105. if (path [i] == unix)
  2106. unix_count++;
  2107. else if (path [i] == win)
  2108. win_count++;
  2109. }
  2110. if (unix_count == 0 && win_count == 0)
  2111. return false;
  2112. if (unix_count >= win_count) {
  2113. separator = unix;
  2114. return true;
  2115. }
  2116. separator = win;
  2117. return true;
  2118. }
  2119. void AddSequencePoints (MethodDebugInformation info)
  2120. {
  2121. var rid = info.Method.MetadataToken.RID;
  2122. Document document;
  2123. if (info.TryGetUniqueDocument (out document))
  2124. method_debug_information_table.rows [rid - 1].Col1 = GetDocumentToken (document).RID;
  2125. var signature = CreateSignatureWriter ();
  2126. signature.WriteSequencePoints (info);
  2127. method_debug_information_table.rows [rid - 1].Col2 = GetBlobIndex (signature);
  2128. }
  2129. public void ComputeDeterministicMvid ()
  2130. {
  2131. var guid = CryptoService.ComputeGuid (CryptoService.ComputeHash (
  2132. data,
  2133. resources,
  2134. string_heap,
  2135. user_string_heap,
  2136. blob_heap,
  2137. table_heap,
  2138. code));
  2139. var position = guid_heap.position;
  2140. guid_heap.position = 0;
  2141. guid_heap.WriteBytes (guid.ToByteArray ());
  2142. guid_heap.position = position;
  2143. module.Mvid = guid;
  2144. }
  2145. }
  2146. sealed class SignatureWriter : ByteBuffer {
  2147. readonly MetadataBuilder metadata;
  2148. public SignatureWriter (MetadataBuilder metadata)
  2149. : base (6)
  2150. {
  2151. this.metadata = metadata;
  2152. }
  2153. public void WriteElementType (ElementType element_type)
  2154. {
  2155. WriteByte ((byte) element_type);
  2156. }
  2157. public void WriteUTF8String (string @string)
  2158. {
  2159. if (@string == null) {
  2160. WriteByte (0xff);
  2161. return;
  2162. }
  2163. var bytes = Encoding.UTF8.GetBytes (@string);
  2164. WriteCompressedUInt32 ((uint) bytes.Length);
  2165. WriteBytes (bytes);
  2166. }
  2167. public void WriteMethodSignature (IMethodSignature method)
  2168. {
  2169. byte calling_convention = (byte) method.CallingConvention;
  2170. if (method.HasThis)
  2171. calling_convention |= 0x20;
  2172. if (method.ExplicitThis)
  2173. calling_convention |= 0x40;
  2174. var generic_provider = method as IGenericParameterProvider;
  2175. var generic_arity = generic_provider != null && generic_provider.HasGenericParameters
  2176. ? generic_provider.GenericParameters.Count
  2177. : 0;
  2178. if (generic_arity > 0)
  2179. calling_convention |= 0x10;
  2180. var param_count = method.HasParameters ? method.Parameters.Count : 0;
  2181. WriteByte (calling_convention);
  2182. if (generic_arity > 0)
  2183. WriteCompressedUInt32 ((uint) generic_arity);
  2184. WriteCompressedUInt32 ((uint) param_count);
  2185. WriteTypeSignature (method.ReturnType);
  2186. if (param_count == 0)
  2187. return;
  2188. var parameters = method.Parameters;
  2189. for (int i = 0; i < param_count; i++)
  2190. WriteTypeSignature (parameters [i].ParameterType);
  2191. }
  2192. uint MakeTypeDefOrRefCodedRID (TypeReference type)
  2193. {
  2194. return CodedIndex.TypeDefOrRef.CompressMetadataToken (metadata.LookupToken (type));
  2195. }
  2196. public void WriteTypeToken (TypeReference type)
  2197. {
  2198. WriteCompressedUInt32 (MakeTypeDefOrRefCodedRID (type));
  2199. }
  2200. public void WriteTypeSignature (TypeReference type)
  2201. {
  2202. if (type == null)
  2203. throw new ArgumentNullException ();
  2204. var etype = type.etype;
  2205. switch (etype) {
  2206. case ElementType.MVar:
  2207. case ElementType.Var: {
  2208. var generic_parameter = (GenericParameter) type;
  2209. WriteElementType (etype);
  2210. var position = generic_parameter.Position;
  2211. if (position == -1)
  2212. throw new NotSupportedException ();
  2213. WriteCompressedUInt32 ((uint) position);
  2214. break;
  2215. }
  2216. case ElementType.GenericInst: {
  2217. var generic_instance = (GenericInstanceType) type;
  2218. WriteElementType (ElementType.GenericInst);
  2219. WriteElementType (generic_instance.IsValueType ? ElementType.ValueType : ElementType.Class);
  2220. WriteCompressedUInt32 (MakeTypeDefOrRefCodedRID (generic_instance.ElementType));
  2221. WriteGenericInstanceSignature (generic_instance);
  2222. break;
  2223. }
  2224. case ElementType.Ptr:
  2225. case ElementType.ByRef:
  2226. case ElementType.Pinned:
  2227. case ElementType.Sentinel: {
  2228. var type_spec = (TypeSpecification) type;
  2229. WriteElementType (etype);
  2230. WriteTypeSignature (type_spec.ElementType);
  2231. break;
  2232. }
  2233. case ElementType.FnPtr: {
  2234. var fptr = (FunctionPointerType) type;
  2235. WriteElementType (ElementType.FnPtr);
  2236. WriteMethodSignature (fptr);
  2237. break;
  2238. }
  2239. case ElementType.CModOpt:
  2240. case ElementType.CModReqD: {
  2241. var modifier = (IModifierType) type;
  2242. WriteModifierSignature (etype, modifier);
  2243. break;
  2244. }
  2245. case ElementType.Array: {
  2246. var array = (ArrayType) type;
  2247. if (!array.IsVector) {
  2248. WriteArrayTypeSignature (array);
  2249. break;
  2250. }
  2251. WriteElementType (ElementType.SzArray);
  2252. WriteTypeSignature (array.ElementType);
  2253. break;
  2254. }
  2255. case ElementType.None: {
  2256. WriteElementType (type.IsValueType ? ElementType.ValueType : ElementType.Class);
  2257. WriteCompressedUInt32 (MakeTypeDefOrRefCodedRID (type));
  2258. break;
  2259. }
  2260. default:
  2261. if (!TryWriteElementType (type))
  2262. throw new NotSupportedException ();
  2263. break;
  2264. }
  2265. }
  2266. void WriteArrayTypeSignature (ArrayType array)
  2267. {
  2268. WriteElementType (ElementType.Array);
  2269. WriteTypeSignature (array.ElementType);
  2270. var dimensions = array.Dimensions;
  2271. var rank = dimensions.Count;
  2272. WriteCompressedUInt32 ((uint) rank);
  2273. var sized = 0;
  2274. var lbounds = 0;
  2275. for (int i = 0; i < rank; i++) {
  2276. var dimension = dimensions [i];
  2277. if (dimension.UpperBound.HasValue) {
  2278. sized++;
  2279. lbounds++;
  2280. } else if (dimension.LowerBound.HasValue)
  2281. lbounds++;
  2282. }
  2283. var sizes = new int [sized];
  2284. var low_bounds = new int [lbounds];
  2285. for (int i = 0; i < lbounds; i++) {
  2286. var dimension = dimensions [i];
  2287. low_bounds [i] = dimension.LowerBound.GetValueOrDefault ();
  2288. if (dimension.UpperBound.HasValue)
  2289. sizes [i] = dimension.UpperBound.Value - low_bounds [i] + 1;
  2290. }
  2291. WriteCompressedUInt32 ((uint) sized);
  2292. for (int i = 0; i < sized; i++)
  2293. WriteCompressedUInt32 ((uint) sizes [i]);
  2294. WriteCompressedUInt32 ((uint) lbounds);
  2295. for (int i = 0; i < lbounds; i++)
  2296. WriteCompressedInt32 (low_bounds [i]);
  2297. }
  2298. public void WriteGenericInstanceSignature (IGenericInstance instance)
  2299. {
  2300. var generic_arguments = instance.GenericArguments;
  2301. var arity = generic_arguments.Count;
  2302. WriteCompressedUInt32 ((uint) arity);
  2303. for (int i = 0; i < arity; i++)
  2304. WriteTypeSignature (generic_arguments [i]);
  2305. }
  2306. void WriteModifierSignature (ElementType element_type, IModifierType type)
  2307. {
  2308. WriteElementType (element_type);
  2309. WriteCompressedUInt32 (MakeTypeDefOrRefCodedRID (type.ModifierType));
  2310. WriteTypeSignature (type.ElementType);
  2311. }
  2312. bool TryWriteElementType (TypeReference type)
  2313. {
  2314. var element = type.etype;
  2315. if (element == ElementType.None)
  2316. return false;
  2317. WriteElementType (element);
  2318. return true;
  2319. }
  2320. public void WriteConstantString (string value)
  2321. {
  2322. if (value != null)
  2323. WriteBytes (Encoding.Unicode.GetBytes (value));
  2324. else
  2325. WriteByte (0xff);
  2326. }
  2327. public void WriteConstantPrimitive (object value)
  2328. {
  2329. WritePrimitiveValue (value);
  2330. }
  2331. public void WriteCustomAttributeConstructorArguments (CustomAttribute attribute)
  2332. {
  2333. if (!attribute.HasConstructorArguments)
  2334. return;
  2335. var arguments = attribute.ConstructorArguments;
  2336. var parameters = attribute.Constructor.Parameters;
  2337. if (parameters.Count != arguments.Count)
  2338. throw new InvalidOperationException ();
  2339. for (int i = 0; i < arguments.Count; i++)
  2340. WriteCustomAttributeFixedArgument (parameters [i].ParameterType, arguments [i]);
  2341. }
  2342. void WriteCustomAttributeFixedArgument (TypeReference type, CustomAttributeArgument argument)
  2343. {
  2344. if (type.IsArray) {
  2345. WriteCustomAttributeFixedArrayArgument ((ArrayType) type, argument);
  2346. return;
  2347. }
  2348. WriteCustomAttributeElement (type, argument);
  2349. }
  2350. void WriteCustomAttributeFixedArrayArgument (ArrayType type, CustomAttributeArgument argument)
  2351. {
  2352. var values = argument.Value as CustomAttributeArgument [];
  2353. if (values == null) {
  2354. WriteUInt32 (0xffffffff);
  2355. return;
  2356. }
  2357. WriteInt32 (values.Length);
  2358. if (values.Length == 0)
  2359. return;
  2360. var element_type = type.ElementType;
  2361. for (int i = 0; i < values.Length; i++)
  2362. WriteCustomAttributeElement (element_type, values [i]);
  2363. }
  2364. void WriteCustomAttributeElement (TypeReference type, CustomAttributeArgument argument)
  2365. {
  2366. if (type.IsArray) {
  2367. WriteCustomAttributeFixedArrayArgument ((ArrayType) type, argument);
  2368. return;
  2369. }
  2370. if (type.etype == ElementType.Object) {
  2371. argument = (CustomAttributeArgument) argument.Value;
  2372. type = argument.Type;
  2373. WriteCustomAttributeFieldOrPropType (type);
  2374. WriteCustomAttributeElement (type, argument);
  2375. return;
  2376. }
  2377. WriteCustomAttributeValue (type, argument.Value);
  2378. }
  2379. void WriteCustomAttributeValue (TypeReference type, object value)
  2380. {
  2381. var etype = type.etype;
  2382. switch (etype) {
  2383. case ElementType.String:
  2384. var @string = (string) value;
  2385. if (@string == null)
  2386. WriteByte (0xff);
  2387. else
  2388. WriteUTF8String (@string);
  2389. break;
  2390. case ElementType.None:
  2391. if (type.IsTypeOf ("System", "Type"))
  2392. WriteTypeReference ((TypeReference) value);
  2393. else
  2394. WriteCustomAttributeEnumValue (type, value);
  2395. break;
  2396. default:
  2397. WritePrimitiveValue (value);
  2398. break;
  2399. }
  2400. }
  2401. void WritePrimitiveValue (object value)
  2402. {
  2403. if (value == null)
  2404. throw new ArgumentNullException ();
  2405. switch (Type.GetTypeCode (value.GetType ())) {
  2406. case TypeCode.Boolean:
  2407. WriteByte ((byte) (((bool) value) ? 1 : 0));
  2408. break;
  2409. case TypeCode.Byte:
  2410. WriteByte ((byte) value);
  2411. break;
  2412. case TypeCode.SByte:
  2413. WriteSByte ((sbyte) value);
  2414. break;
  2415. case TypeCode.Int16:
  2416. WriteInt16 ((short) value);
  2417. break;
  2418. case TypeCode.UInt16:
  2419. WriteUInt16 ((ushort) value);
  2420. break;
  2421. case TypeCode.Char:
  2422. WriteInt16 ((short) (char) value);
  2423. break;
  2424. case TypeCode.Int32:
  2425. WriteInt32 ((int) value);
  2426. break;
  2427. case TypeCode.UInt32:
  2428. WriteUInt32 ((uint) value);
  2429. break;
  2430. case TypeCode.Single:
  2431. WriteSingle ((float) value);
  2432. break;
  2433. case TypeCode.Int64:
  2434. WriteInt64 ((long) value);
  2435. break;
  2436. case TypeCode.UInt64:
  2437. WriteUInt64 ((ulong) value);
  2438. break;
  2439. case TypeCode.Double:
  2440. WriteDouble ((double) value);
  2441. break;
  2442. default:
  2443. throw new NotSupportedException (value.GetType ().FullName);
  2444. }
  2445. }
  2446. void WriteCustomAttributeEnumValue (TypeReference enum_type, object value)
  2447. {
  2448. var type = enum_type.CheckedResolve ();
  2449. if (!type.IsEnum)
  2450. throw new ArgumentException ();
  2451. WriteCustomAttributeValue (type.GetEnumUnderlyingType (), value);
  2452. }
  2453. void WriteCustomAttributeFieldOrPropType (TypeReference type)
  2454. {
  2455. if (type.IsArray) {
  2456. var array = (ArrayType) type;
  2457. WriteElementType (ElementType.SzArray);
  2458. WriteCustomAttributeFieldOrPropType (array.ElementType);
  2459. return;
  2460. }
  2461. var etype = type.etype;
  2462. switch (etype) {
  2463. case ElementType.Object:
  2464. WriteElementType (ElementType.Boxed);
  2465. return;
  2466. case ElementType.None:
  2467. if (type.IsTypeOf ("System", "Type"))
  2468. WriteElementType (ElementType.Type);
  2469. else {
  2470. WriteElementType (ElementType.Enum);
  2471. WriteTypeReference (type);
  2472. }
  2473. return;
  2474. default:
  2475. WriteElementType (etype);
  2476. return;
  2477. }
  2478. }
  2479. public void WriteCustomAttributeNamedArguments (CustomAttribute attribute)
  2480. {
  2481. var count = GetNamedArgumentCount (attribute);
  2482. WriteUInt16 ((ushort) count);
  2483. if (count == 0)
  2484. return;
  2485. WriteICustomAttributeNamedArguments (attribute);
  2486. }
  2487. static int GetNamedArgumentCount (ICustomAttribute attribute)
  2488. {
  2489. int count = 0;
  2490. if (attribute.HasFields)
  2491. count += attribute.Fields.Count;
  2492. if (attribute.HasProperties)
  2493. count += attribute.Properties.Count;
  2494. return count;
  2495. }
  2496. void WriteICustomAttributeNamedArguments (ICustomAttribute attribute)
  2497. {
  2498. if (attribute.HasFields)
  2499. WriteCustomAttributeNamedArguments (0x53, attribute.Fields);
  2500. if (attribute.HasProperties)
  2501. WriteCustomAttributeNamedArguments (0x54, attribute.Properties);
  2502. }
  2503. void WriteCustomAttributeNamedArguments (byte kind, Collection<CustomAttributeNamedArgument> named_arguments)
  2504. {
  2505. for (int i = 0; i < named_arguments.Count; i++)
  2506. WriteCustomAttributeNamedArgument (kind, named_arguments [i]);
  2507. }
  2508. void WriteCustomAttributeNamedArgument (byte kind, CustomAttributeNamedArgument named_argument)
  2509. {
  2510. var argument = named_argument.Argument;
  2511. WriteByte (kind);
  2512. WriteCustomAttributeFieldOrPropType (argument.Type);
  2513. WriteUTF8String (named_argument.Name);
  2514. WriteCustomAttributeFixedArgument (argument.Type, argument);
  2515. }
  2516. void WriteSecurityAttribute (SecurityAttribute attribute)
  2517. {
  2518. WriteTypeReference (attribute.AttributeType);
  2519. var count = GetNamedArgumentCount (attribute);
  2520. if (count == 0) {
  2521. WriteCompressedUInt32 (1); // length
  2522. WriteCompressedUInt32 (0); // count
  2523. return;
  2524. }
  2525. var buffer = new SignatureWriter (metadata);
  2526. buffer.WriteCompressedUInt32 ((uint) count);
  2527. buffer.WriteICustomAttributeNamedArguments (attribute);
  2528. WriteCompressedUInt32 ((uint) buffer.length);
  2529. WriteBytes (buffer);
  2530. }
  2531. public void WriteSecurityDeclaration (SecurityDeclaration declaration)
  2532. {
  2533. WriteByte ((byte) '.');
  2534. var attributes = declaration.security_attributes;
  2535. if (attributes == null)
  2536. throw new NotSupportedException ();
  2537. WriteCompressedUInt32 ((uint) attributes.Count);
  2538. for (int i = 0; i < attributes.Count; i++)
  2539. WriteSecurityAttribute (attributes [i]);
  2540. }
  2541. public void WriteXmlSecurityDeclaration (SecurityDeclaration declaration)
  2542. {
  2543. var xml = GetXmlSecurityDeclaration (declaration);
  2544. if (xml == null)
  2545. throw new NotSupportedException ();
  2546. WriteBytes (Encoding.Unicode.GetBytes (xml));
  2547. }
  2548. static string GetXmlSecurityDeclaration (SecurityDeclaration declaration)
  2549. {
  2550. if (declaration.security_attributes == null || declaration.security_attributes.Count != 1)
  2551. return null;
  2552. var attribute = declaration.security_attributes [0];
  2553. if (!attribute.AttributeType.IsTypeOf ("System.Security.Permissions", "PermissionSetAttribute"))
  2554. return null;
  2555. if (attribute.properties == null || attribute.properties.Count != 1)
  2556. return null;
  2557. var property = attribute.properties [0];
  2558. if (property.Name != "XML")
  2559. return null;
  2560. return (string) property.Argument.Value;
  2561. }
  2562. void WriteTypeReference (TypeReference type)
  2563. {
  2564. WriteUTF8String (TypeParser.ToParseable (type, top_level: false));
  2565. }
  2566. public void WriteMarshalInfo (MarshalInfo marshal_info)
  2567. {
  2568. WriteNativeType (marshal_info.native);
  2569. switch (marshal_info.native) {
  2570. case NativeType.Array: {
  2571. var array = (ArrayMarshalInfo) marshal_info;
  2572. if (array.element_type != NativeType.None)
  2573. WriteNativeType (array.element_type);
  2574. if (array.size_parameter_index > -1)
  2575. WriteCompressedUInt32 ((uint) array.size_parameter_index);
  2576. if (array.size > -1)
  2577. WriteCompressedUInt32 ((uint) array.size);
  2578. if (array.size_parameter_multiplier > -1)
  2579. WriteCompressedUInt32 ((uint) array.size_parameter_multiplier);
  2580. return;
  2581. }
  2582. case NativeType.SafeArray: {
  2583. var array = (SafeArrayMarshalInfo) marshal_info;
  2584. if (array.element_type != VariantType.None)
  2585. WriteVariantType (array.element_type);
  2586. return;
  2587. }
  2588. case NativeType.FixedArray: {
  2589. var array = (FixedArrayMarshalInfo) marshal_info;
  2590. if (array.size > -1)
  2591. WriteCompressedUInt32 ((uint) array.size);
  2592. if (array.element_type != NativeType.None)
  2593. WriteNativeType (array.element_type);
  2594. return;
  2595. }
  2596. case NativeType.FixedSysString:
  2597. var sys_string = (FixedSysStringMarshalInfo) marshal_info;
  2598. if (sys_string.size > -1)
  2599. WriteCompressedUInt32 ((uint) sys_string.size);
  2600. return;
  2601. case NativeType.CustomMarshaler:
  2602. var marshaler = (CustomMarshalInfo) marshal_info;
  2603. WriteUTF8String (marshaler.guid != Guid.Empty ? marshaler.guid.ToString () : string.Empty);
  2604. WriteUTF8String (marshaler.unmanaged_type);
  2605. WriteTypeReference (marshaler.managed_type);
  2606. WriteUTF8String (marshaler.cookie);
  2607. return;
  2608. }
  2609. }
  2610. void WriteNativeType (NativeType native)
  2611. {
  2612. WriteByte ((byte) native);
  2613. }
  2614. void WriteVariantType (VariantType variant)
  2615. {
  2616. WriteByte ((byte) variant);
  2617. }
  2618. public void WriteSequencePoints (MethodDebugInformation info)
  2619. {
  2620. var start_line = -1;
  2621. var start_column = -1;
  2622. WriteCompressedUInt32 (info.local_var_token.RID);
  2623. Document previous_document;
  2624. if (!info.TryGetUniqueDocument (out previous_document))
  2625. previous_document = null;
  2626. for (int i = 0; i < info.SequencePoints.Count; i++) {
  2627. var sequence_point = info.SequencePoints [i];
  2628. var document = sequence_point.Document;
  2629. if (previous_document != document) {
  2630. var document_token = metadata.GetDocumentToken (document);
  2631. if (previous_document != null)
  2632. WriteCompressedUInt32 (0);
  2633. WriteCompressedUInt32 (document_token.RID);
  2634. previous_document = document;
  2635. }
  2636. if (i > 0)
  2637. WriteCompressedUInt32 ((uint) (sequence_point.Offset - info.SequencePoints [i - 1].Offset));
  2638. else
  2639. WriteCompressedUInt32 ((uint) sequence_point.Offset);
  2640. if (sequence_point.IsHidden) {
  2641. WriteInt16 (0);
  2642. continue;
  2643. }
  2644. var delta_lines = sequence_point.EndLine - sequence_point.StartLine;
  2645. var delta_columns = sequence_point.EndColumn - sequence_point.StartColumn;
  2646. WriteCompressedUInt32 ((uint) delta_lines);
  2647. if (delta_lines == 0)
  2648. WriteCompressedUInt32((uint) delta_columns);
  2649. else
  2650. WriteCompressedInt32 (delta_columns);
  2651. if (start_line < 0) {
  2652. WriteCompressedUInt32 ((uint) sequence_point.StartLine);
  2653. WriteCompressedUInt32 ((uint) sequence_point.StartColumn);
  2654. } else {
  2655. WriteCompressedInt32 (sequence_point.StartLine - start_line);
  2656. WriteCompressedInt32 (sequence_point.StartColumn - start_column);
  2657. }
  2658. start_line = sequence_point.StartLine;
  2659. start_column = sequence_point.StartColumn;
  2660. }
  2661. }
  2662. }
  2663. static partial class Mixin {
  2664. public static bool TryGetUniqueDocument (this MethodDebugInformation info, out Document document)
  2665. {
  2666. document = info.SequencePoints [0].Document;
  2667. for (int i = 1; i < info.SequencePoints.Count; i++) {
  2668. var sequence_point = info.SequencePoints [i];
  2669. if (sequence_point.Document != document)
  2670. return false;
  2671. }
  2672. return true;
  2673. }
  2674. }
  2675. }