PageRenderTime 123ms CodeModel.GetById 24ms app.highlight 85ms RepoModel.GetById 1ms 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

Large files files are truncated, but you can click here to view the full file

   1//
   2// Author:
   3//   Jb Evain (jbevain@gmail.com)
   4//
   5// Copyright (c) 2008 - 2015 Jb Evain
   6// Copyright (c) 2008 - 2011 Novell, Inc.
   7//
   8// Licensed under the MIT/X11 license.
   9//
  10
  11using System;
  12using System.Collections.Generic;
  13using System.IO;
  14using System.IO.Compression;
  15using System.Text;
  16using System.Security.Cryptography;
  17
  18using Mono;
  19using Mono.Collections.Generic;
  20using Mono.Cecil.Cil;
  21using Mono.Cecil.Metadata;
  22using Mono.Cecil.PE;
  23
  24using RVA = System.UInt32;
  25using RID = System.UInt32;
  26using CodedRID = System.UInt32;
  27using StringIndex = System.UInt32;
  28using BlobIndex = System.UInt32;
  29using GuidIndex = System.UInt32;
  30
  31namespace Mono.Cecil {
  32
  33	using ModuleRow      = Row<StringIndex, GuidIndex>;
  34	using TypeRefRow     = Row<CodedRID, StringIndex, StringIndex>;
  35	using TypeDefRow     = Row<TypeAttributes, StringIndex, StringIndex, CodedRID, RID, RID>;
  36	using FieldRow       = Row<FieldAttributes, StringIndex, BlobIndex>;
  37	using MethodRow      = Row<RVA, MethodImplAttributes, MethodAttributes, StringIndex, BlobIndex, RID>;
  38	using ParamRow       = Row<ParameterAttributes, ushort, StringIndex>;
  39	using InterfaceImplRow = Row<uint, CodedRID>;
  40	using MemberRefRow   = Row<CodedRID, StringIndex, BlobIndex>;
  41	using ConstantRow    = Row<ElementType, CodedRID, BlobIndex>;
  42	using CustomAttributeRow = Row<CodedRID, CodedRID, BlobIndex>;
  43	using FieldMarshalRow = Row<CodedRID, BlobIndex>;
  44	using DeclSecurityRow = Row<SecurityAction, CodedRID, BlobIndex>;
  45	using ClassLayoutRow = Row<ushort, uint, RID>;
  46	using FieldLayoutRow = Row<uint, RID>;
  47	using EventMapRow    = Row<RID, RID>;
  48	using EventRow       = Row<EventAttributes, StringIndex, CodedRID>;
  49	using PropertyMapRow = Row<RID, RID>;
  50	using PropertyRow    = Row<PropertyAttributes, StringIndex, BlobIndex>;
  51	using MethodSemanticsRow = Row<MethodSemanticsAttributes, RID, CodedRID>;
  52	using MethodImplRow  = Row<RID, CodedRID, CodedRID>;
  53	using ImplMapRow     = Row<PInvokeAttributes, CodedRID, StringIndex, RID>;
  54	using FieldRVARow    = Row<RVA, RID>;
  55	using AssemblyRow    = Row<AssemblyHashAlgorithm, ushort, ushort, ushort, ushort, AssemblyAttributes, uint, uint, uint>;
  56	using AssemblyRefRow = Row<ushort, ushort, ushort, ushort, AssemblyAttributes, uint, uint, uint, uint>;
  57	using FileRow        = Row<FileAttributes, StringIndex, BlobIndex>;
  58	using ExportedTypeRow = Row<TypeAttributes, uint, StringIndex, StringIndex, CodedRID>;
  59	using ManifestResourceRow = Row<uint, ManifestResourceAttributes, StringIndex, CodedRID>;
  60	using NestedClassRow = Row<RID, RID>;
  61	using GenericParamRow = Row<ushort, GenericParameterAttributes, CodedRID, StringIndex>;
  62	using MethodSpecRow = Row<CodedRID, BlobIndex>;
  63	using GenericParamConstraintRow = Row<RID, CodedRID>;
  64	using DocumentRow = Row<BlobIndex, GuidIndex, BlobIndex, GuidIndex>;
  65	using MethodDebugInformationRow = Row<RID, BlobIndex>;
  66	using LocalScopeRow = Row<RID, RID, RID, RID, uint, uint>;
  67	using LocalVariableRow = Row<VariableAttributes, ushort, StringIndex>;
  68	using LocalConstantRow = Row<StringIndex, BlobIndex>;
  69	using ImportScopeRow = Row<RID, BlobIndex>;
  70	using StateMachineMethodRow = Row<RID, RID>;
  71	using CustomDebugInformationRow = Row<CodedRID, GuidIndex, BlobIndex>;
  72
  73	static class ModuleWriter {
  74
  75		public static void WriteModule (ModuleDefinition module, Disposable<Stream> stream, WriterParameters parameters)
  76		{
  77			using (stream)
  78				Write (module, stream, parameters);
  79		}
  80
  81		static void Write (ModuleDefinition module, Disposable<Stream> stream, WriterParameters parameters)
  82		{
  83			if ((module.Attributes & ModuleAttributes.ILOnly) == 0)
  84				throw new NotSupportedException ("Writing mixed-mode assemblies is not supported");
  85
  86			if (module.HasImage && module.ReadingMode == ReadingMode.Deferred) {
  87				var immediate_reader = new ImmediateModuleReader (module.Image);
  88				immediate_reader.ReadModule (module, resolve_attributes: false);
  89				immediate_reader.ReadSymbols (module);
  90			}
  91
  92			module.MetadataSystem.Clear ();
  93
  94			if (module.symbol_reader != null)
  95				module.symbol_reader.Dispose ();
  96
  97			var name = module.assembly != null ? module.assembly.Name : null;
  98			var fq_name = stream.value.GetFileName ();
  99			var timestamp = parameters.Timestamp ?? module.timestamp;
 100			var symbol_writer_provider = parameters.SymbolWriterProvider;
 101
 102			if (symbol_writer_provider == null && parameters.WriteSymbols)
 103				symbol_writer_provider = new DefaultSymbolWriterProvider ();
 104
 105			if (parameters.HasStrongNameKey && name != null) {
 106				name.PublicKey = CryptoService.GetPublicKey (parameters);
 107				module.Attributes |= ModuleAttributes.StrongNameSigned;
 108			}
 109
 110			if (parameters.DeterministicMvid)
 111				module.Mvid = Guid.Empty;
 112
 113			var metadata = new MetadataBuilder (module, fq_name, timestamp, symbol_writer_provider);
 114			try {
 115				module.metadata_builder = metadata;
 116
 117				using (var symbol_writer = GetSymbolWriter (module, fq_name, symbol_writer_provider, parameters)) {
 118					metadata.SetSymbolWriter (symbol_writer);
 119					BuildMetadata (module, metadata);
 120
 121					if (parameters.DeterministicMvid)
 122						metadata.ComputeDeterministicMvid ();
 123
 124					var writer = ImageWriter.CreateWriter (module, metadata, stream);
 125					stream.value.SetLength (0);
 126					writer.WriteImage ();
 127
 128					if (parameters.HasStrongNameKey)
 129						CryptoService.StrongName (stream.value, writer, parameters);
 130				}
 131			} finally {
 132				module.metadata_builder = null;
 133			}
 134		}
 135
 136		static void BuildMetadata (ModuleDefinition module, MetadataBuilder metadata)
 137		{
 138			if (!module.HasImage) {
 139				metadata.BuildMetadata ();
 140				return;
 141			}
 142
 143			module.Read (metadata, (builder, _) => {
 144				builder.BuildMetadata ();
 145				return builder;
 146			});
 147		}
 148
 149		static ISymbolWriter GetSymbolWriter (ModuleDefinition module, string fq_name, ISymbolWriterProvider symbol_writer_provider, WriterParameters parameters)
 150		{
 151			if (symbol_writer_provider == null)
 152				return null;
 153
 154			if (parameters.SymbolStream != null)
 155				return symbol_writer_provider.GetSymbolWriter (module, parameters.SymbolStream);
 156
 157			return symbol_writer_provider.GetSymbolWriter (module, fq_name);
 158		}
 159	}
 160
 161	abstract class MetadataTable {
 162
 163		public abstract int Length { get; }
 164
 165		public bool IsLarge {
 166			get { return Length > ushort.MaxValue; }
 167		}
 168
 169		public abstract void Write (TableHeapBuffer buffer);
 170		public abstract void Sort ();
 171	}
 172
 173	abstract class OneRowTable<TRow> : MetadataTable where TRow : struct {
 174
 175		internal TRow row;
 176
 177		public sealed override int Length {
 178			get { return 1; }
 179		}
 180
 181		public sealed override void Sort ()
 182		{
 183		}
 184	}
 185
 186	abstract class MetadataTable<TRow> : MetadataTable where TRow : struct {
 187
 188		internal TRow [] rows = new TRow [2];
 189		internal int length;
 190
 191		public sealed override int Length {
 192			get { return length; }
 193		}
 194
 195		public int AddRow (TRow row)
 196		{
 197			if (rows.Length == length)
 198				Grow ();
 199
 200			rows [length++] = row;
 201			return length;
 202		}
 203
 204		void Grow ()
 205		{
 206			var rows = new TRow [this.rows.Length * 2];
 207			Array.Copy (this.rows, rows, this.rows.Length);
 208			this.rows = rows;
 209		}
 210
 211		public override void Sort ()
 212		{
 213		}
 214	}
 215
 216	abstract class SortedTable<TRow> : MetadataTable<TRow>, IComparer<TRow> where TRow : struct {
 217
 218		public sealed override void Sort ()
 219		{
 220			MergeSort<TRow>.Sort (rows, 0, this.length, this);
 221		}
 222
 223		protected static int Compare (uint x, uint y)
 224		{
 225			return x == y ? 0 : x > y ? 1 : -1;
 226		}
 227
 228		public abstract int Compare (TRow x, TRow y);
 229	}
 230
 231	sealed class ModuleTable : OneRowTable<ModuleRow> {
 232
 233		public override void Write (TableHeapBuffer buffer)
 234		{
 235			buffer.WriteUInt16 (0);		// Generation
 236			buffer.WriteString (row.Col1);	// Name
 237			buffer.WriteGuid (row.Col2);		// Mvid
 238			buffer.WriteUInt16 (0);		// EncId
 239			buffer.WriteUInt16 (0);		// EncBaseId
 240		}
 241	}
 242
 243	sealed class TypeRefTable : MetadataTable<TypeRefRow> {
 244
 245		public override void Write (TableHeapBuffer buffer)
 246		{
 247			for (int i = 0; i < length; i++) {
 248				buffer.WriteCodedRID (
 249					rows [i].Col1, CodedIndex.ResolutionScope);	// Scope
 250				buffer.WriteString (rows [i].Col2);			// Name
 251				buffer.WriteString (rows [i].Col3);			// Namespace
 252			}
 253		}
 254	}
 255
 256	sealed class TypeDefTable : MetadataTable<TypeDefRow> {
 257
 258		public override void Write (TableHeapBuffer buffer)
 259		{
 260			for (int i = 0; i < length; i++) {
 261				buffer.WriteUInt32 ((uint) rows [i].Col1);	// Attributes
 262				buffer.WriteString (rows [i].Col2);			// Name
 263				buffer.WriteString (rows [i].Col3);			// Namespace
 264				buffer.WriteCodedRID (
 265					rows [i].Col4, CodedIndex.TypeDefOrRef);	// Extends
 266				buffer.WriteRID (rows [i].Col5, Table.Field);	// FieldList
 267				buffer.WriteRID (rows [i].Col6, Table.Method);	// MethodList
 268			}
 269		}
 270	}
 271
 272	sealed class FieldTable : MetadataTable<FieldRow> {
 273
 274		public override void Write (TableHeapBuffer buffer)
 275		{
 276			for (int i = 0; i < length; i++) {
 277				buffer.WriteUInt16 ((ushort) rows [i].Col1);	// Attributes
 278				buffer.WriteString (rows [i].Col2);			// Name
 279				buffer.WriteBlob (rows [i].Col3);			// Signature
 280			}
 281		}
 282	}
 283
 284	sealed class MethodTable : MetadataTable<MethodRow> {
 285
 286		public override void Write (TableHeapBuffer buffer)
 287		{
 288			for (int i = 0; i < length; i++) {
 289				buffer.WriteUInt32 (rows [i].Col1);		// RVA
 290				buffer.WriteUInt16 ((ushort) rows [i].Col2);	// ImplFlags
 291				buffer.WriteUInt16 ((ushort) rows [i].Col3);	// Flags
 292				buffer.WriteString (rows [i].Col4);		// Name
 293				buffer.WriteBlob (rows [i].Col5);		// Signature
 294				buffer.WriteRID (rows [i].Col6, Table.Param);	// ParamList
 295			}
 296		}
 297	}
 298
 299	sealed class ParamTable : MetadataTable<ParamRow> {
 300
 301		public override void Write (TableHeapBuffer buffer)
 302		{
 303			for (int i = 0; i < length; i++) {
 304				buffer.WriteUInt16 ((ushort) rows [i].Col1);	// Attributes
 305				buffer.WriteUInt16 (rows [i].Col2);		// Sequence
 306				buffer.WriteString (rows [i].Col3);		// Name
 307			}
 308		}
 309	}
 310
 311	sealed class InterfaceImplTable : MetadataTable<InterfaceImplRow> {
 312
 313		public override void Write (TableHeapBuffer buffer)
 314		{
 315			for (int i = 0; i < length; i++) {
 316				buffer.WriteRID (rows [i].Col1, Table.TypeDef);		// Class
 317				buffer.WriteCodedRID (rows [i].Col2, CodedIndex.TypeDefOrRef);	// Interface
 318			}
 319		}
 320
 321		/*public override int Compare (InterfaceImplRow x, InterfaceImplRow y)
 322		{
 323			return (int) (x.Col1 == y.Col1 ? y.Col2 - x.Col2 : x.Col1 - y.Col1);
 324		}*/
 325	}
 326
 327	sealed class MemberRefTable : MetadataTable<MemberRefRow> {
 328
 329		public override void Write (TableHeapBuffer buffer)
 330		{
 331			for (int i = 0; i < length; i++) {
 332				buffer.WriteCodedRID (rows [i].Col1, CodedIndex.MemberRefParent);
 333				buffer.WriteString (rows [i].Col2);
 334				buffer.WriteBlob (rows [i].Col3);
 335			}
 336		}
 337	}
 338
 339	sealed class ConstantTable : SortedTable<ConstantRow> {
 340
 341		public override void Write (TableHeapBuffer buffer)
 342		{
 343			for (int i = 0; i < length; i++) {
 344				buffer.WriteUInt16 ((ushort) rows [i].Col1);
 345				buffer.WriteCodedRID (rows [i].Col2, CodedIndex.HasConstant);
 346				buffer.WriteBlob (rows [i].Col3);
 347			}
 348		}
 349
 350		public override int Compare (ConstantRow x, ConstantRow y)
 351		{
 352			return Compare (x.Col2, y.Col2);
 353		}
 354	}
 355
 356	sealed class CustomAttributeTable : SortedTable<CustomAttributeRow> {
 357
 358		public override void Write (TableHeapBuffer buffer)
 359		{
 360			for (int i = 0; i < length; i++) {
 361				buffer.WriteCodedRID (rows [i].Col1, CodedIndex.HasCustomAttribute);	// Parent
 362				buffer.WriteCodedRID (rows [i].Col2, CodedIndex.CustomAttributeType);	// Type
 363				buffer.WriteBlob (rows [i].Col3);
 364			}
 365		}
 366
 367		public override int Compare (CustomAttributeRow x, CustomAttributeRow y)
 368		{
 369			return Compare (x.Col1, y.Col1);
 370		}
 371	}
 372
 373	sealed class FieldMarshalTable : SortedTable<FieldMarshalRow> {
 374
 375		public override void Write (TableHeapBuffer buffer)
 376		{
 377			for (int i = 0; i < length; i++) {
 378				buffer.WriteCodedRID (rows [i].Col1, CodedIndex.HasFieldMarshal);
 379				buffer.WriteBlob (rows [i].Col2);
 380			}
 381		}
 382
 383		public override int Compare (FieldMarshalRow x, FieldMarshalRow y)
 384		{
 385			return Compare (x.Col1, y.Col1);
 386		}
 387	}
 388
 389	sealed class DeclSecurityTable : SortedTable<DeclSecurityRow> {
 390
 391		public override void Write (TableHeapBuffer buffer)
 392		{
 393			for (int i = 0; i < length; i++) {
 394				buffer.WriteUInt16 ((ushort) rows [i].Col1);
 395				buffer.WriteCodedRID (rows [i].Col2, CodedIndex.HasDeclSecurity);
 396				buffer.WriteBlob (rows [i].Col3);
 397			}
 398		}
 399
 400		public override int Compare (DeclSecurityRow x, DeclSecurityRow y)
 401		{
 402			return Compare (x.Col2, y.Col2);
 403		}
 404	}
 405
 406	sealed class ClassLayoutTable : SortedTable<ClassLayoutRow> {
 407
 408		public override void Write (TableHeapBuffer buffer)
 409		{
 410			for (int i = 0; i < length; i++) {
 411				buffer.WriteUInt16 (rows [i].Col1);		// PackingSize
 412				buffer.WriteUInt32 (rows [i].Col2);		// ClassSize
 413				buffer.WriteRID (rows [i].Col3, Table.TypeDef);	// Parent
 414			}
 415		}
 416
 417		public override int Compare (ClassLayoutRow x, ClassLayoutRow y)
 418		{
 419			return Compare (x.Col3, y.Col3);
 420		}
 421	}
 422
 423	sealed class FieldLayoutTable : SortedTable<FieldLayoutRow> {
 424
 425		public override void Write (TableHeapBuffer buffer)
 426		{
 427			for (int i = 0; i < length; i++) {
 428				buffer.WriteUInt32 (rows [i].Col1);		// Offset
 429				buffer.WriteRID (rows [i].Col2, Table.Field);	// Parent
 430			}
 431		}
 432
 433		public override int Compare (FieldLayoutRow x, FieldLayoutRow y)
 434		{
 435			return Compare (x.Col2, y.Col2);
 436		}
 437	}
 438
 439	sealed class StandAloneSigTable : MetadataTable<uint> {
 440
 441		public override void Write (TableHeapBuffer buffer)
 442		{
 443			for (int i = 0; i < length; i++)
 444				buffer.WriteBlob (rows [i]);
 445		}
 446	}
 447
 448	sealed class EventMapTable : MetadataTable<EventMapRow> {
 449
 450		public override void Write (TableHeapBuffer buffer)
 451		{
 452			for (int i = 0; i < length; i++) {
 453				buffer.WriteRID (rows [i].Col1, Table.TypeDef);		// Parent
 454				buffer.WriteRID (rows [i].Col2, Table.Event);		// EventList
 455			}
 456		}
 457	}
 458
 459	sealed class EventTable : MetadataTable<EventRow> {
 460
 461		public override void Write (TableHeapBuffer buffer)
 462		{
 463			for (int i = 0; i < length; i++) {
 464				buffer.WriteUInt16 ((ushort) rows [i].Col1);	// Flags
 465				buffer.WriteString (rows [i].Col2);		// Name
 466				buffer.WriteCodedRID (rows [i].Col3, CodedIndex.TypeDefOrRef);	// EventType
 467			}
 468		}
 469	}
 470
 471	sealed class PropertyMapTable : MetadataTable<PropertyMapRow> {
 472
 473		public override void Write (TableHeapBuffer buffer)
 474		{
 475			for (int i = 0; i < length; i++) {
 476				buffer.WriteRID (rows [i].Col1, Table.TypeDef);		// Parent
 477				buffer.WriteRID (rows [i].Col2, Table.Property);	// PropertyList
 478			}
 479		}
 480	}
 481
 482	sealed class PropertyTable : MetadataTable<PropertyRow> {
 483
 484		public override void Write (TableHeapBuffer buffer)
 485		{
 486			for (int i = 0; i < length; i++) {
 487				buffer.WriteUInt16 ((ushort) rows [i].Col1);	// Flags
 488				buffer.WriteString (rows [i].Col2);		// Name
 489				buffer.WriteBlob (rows [i].Col3);		// Type
 490			}
 491		}
 492	}
 493
 494	sealed class MethodSemanticsTable : SortedTable<MethodSemanticsRow> {
 495
 496		public override void Write (TableHeapBuffer buffer)
 497		{
 498			for (int i = 0; i < length; i++) {
 499				buffer.WriteUInt16 ((ushort) rows [i].Col1);	// Flags
 500				buffer.WriteRID (rows [i].Col2, Table.Method);	// Method
 501				buffer.WriteCodedRID (rows [i].Col3, CodedIndex.HasSemantics);	// Association
 502			}
 503		}
 504
 505		public override int Compare (MethodSemanticsRow x, MethodSemanticsRow y)
 506		{
 507			return Compare (x.Col3, y.Col3);
 508		}
 509	}
 510
 511	sealed class MethodImplTable : MetadataTable<MethodImplRow> {
 512
 513		public override void Write (TableHeapBuffer buffer)
 514		{
 515			for (int i = 0; i < length; i++) {
 516				buffer.WriteRID (rows [i].Col1, Table.TypeDef);	// Class
 517				buffer.WriteCodedRID (rows [i].Col2, CodedIndex.MethodDefOrRef);	// MethodBody
 518				buffer.WriteCodedRID (rows [i].Col3, CodedIndex.MethodDefOrRef);	// MethodDeclaration
 519			}
 520		}
 521	}
 522
 523	sealed class ModuleRefTable : MetadataTable<uint> {
 524
 525		public override void Write (TableHeapBuffer buffer)
 526		{
 527			for (int i = 0; i < length; i++)
 528				buffer.WriteString (rows [i]);	// Name
 529		}
 530	}
 531
 532	sealed class TypeSpecTable : MetadataTable<uint> {
 533
 534		public override void Write (TableHeapBuffer buffer)
 535		{
 536			for (int i = 0; i < length; i++)
 537				buffer.WriteBlob (rows [i]);	// Signature
 538		}
 539	}
 540
 541	sealed class ImplMapTable : SortedTable<ImplMapRow> {
 542
 543		public override void Write (TableHeapBuffer buffer)
 544		{
 545			for (int i = 0; i < length; i++) {
 546				buffer.WriteUInt16 ((ushort) rows [i].Col1);	// Flags
 547				buffer.WriteCodedRID (rows [i].Col2, CodedIndex.MemberForwarded);	// MemberForwarded
 548				buffer.WriteString (rows [i].Col3);		// ImportName
 549				buffer.WriteRID (rows [i].Col4, Table.ModuleRef);	// ImportScope
 550			}
 551		}
 552
 553		public override int Compare (ImplMapRow x, ImplMapRow y)
 554		{
 555			return Compare (x.Col2, y.Col2);
 556		}
 557	}
 558
 559	sealed class FieldRVATable : SortedTable<FieldRVARow> {
 560
 561		internal int position;
 562
 563		public override void Write (TableHeapBuffer buffer)
 564		{
 565			position = buffer.position;
 566			for (int i = 0; i < length; i++) {
 567				buffer.WriteUInt32 (rows [i].Col1);		// RVA
 568				buffer.WriteRID (rows [i].Col2, Table.Field);	// Field
 569			}
 570		}
 571
 572		public override int Compare (FieldRVARow x, FieldRVARow y)
 573		{
 574			return Compare (x.Col2, y.Col2);
 575		}
 576	}
 577
 578	sealed class AssemblyTable : OneRowTable<AssemblyRow> {
 579
 580		public override void Write (TableHeapBuffer buffer)
 581		{
 582			buffer.WriteUInt32 ((uint) row.Col1);	// AssemblyHashAlgorithm
 583			buffer.WriteUInt16 (row.Col2);			// MajorVersion
 584			buffer.WriteUInt16 (row.Col3);			// MinorVersion
 585			buffer.WriteUInt16 (row.Col4);			// Build
 586			buffer.WriteUInt16 (row.Col5);			// Revision
 587			buffer.WriteUInt32 ((uint) row.Col6);	// Flags
 588			buffer.WriteBlob (row.Col7);			// PublicKey
 589			buffer.WriteString (row.Col8);			// Name
 590			buffer.WriteString (row.Col9);			// Culture
 591		}
 592	}
 593
 594	sealed class AssemblyRefTable : MetadataTable<AssemblyRefRow> {
 595
 596		public override void Write (TableHeapBuffer buffer)
 597		{
 598			for (int i = 0; i < length; i++) {
 599				buffer.WriteUInt16 (rows [i].Col1);		// MajorVersion
 600				buffer.WriteUInt16 (rows [i].Col2);		// MinorVersion
 601				buffer.WriteUInt16 (rows [i].Col3);		// Build
 602				buffer.WriteUInt16 (rows [i].Col4);		// Revision
 603				buffer.WriteUInt32 ((uint) rows [i].Col5);	// Flags
 604				buffer.WriteBlob (rows [i].Col6);		// PublicKeyOrToken
 605				buffer.WriteString (rows [i].Col7);		// Name
 606				buffer.WriteString (rows [i].Col8);		// Culture
 607				buffer.WriteBlob (rows [i].Col9);		// Hash
 608			}
 609		}
 610	}
 611
 612	sealed class FileTable : MetadataTable<FileRow> {
 613
 614		public override void Write (TableHeapBuffer buffer)
 615		{
 616			for (int i = 0; i < length; i++) {
 617				buffer.WriteUInt32 ((uint) rows [i].Col1);
 618				buffer.WriteString (rows [i].Col2);
 619				buffer.WriteBlob (rows [i].Col3);
 620			}
 621		}
 622	}
 623
 624	sealed class ExportedTypeTable : MetadataTable<ExportedTypeRow> {
 625
 626		public override void Write (TableHeapBuffer buffer)
 627		{
 628			for (int i = 0; i < length; i++) {
 629				buffer.WriteUInt32 ((uint) rows [i].Col1);
 630				buffer.WriteUInt32 (rows [i].Col2);
 631				buffer.WriteString (rows [i].Col3);
 632				buffer.WriteString (rows [i].Col4);
 633				buffer.WriteCodedRID (rows [i].Col5, CodedIndex.Implementation);
 634			}
 635		}
 636	}
 637
 638	sealed class ManifestResourceTable : MetadataTable<ManifestResourceRow> {
 639
 640		public override void Write (TableHeapBuffer buffer)
 641		{
 642			for (int i = 0; i < length; i++) {
 643				buffer.WriteUInt32 (rows [i].Col1);
 644				buffer.WriteUInt32 ((uint) rows [i].Col2);
 645				buffer.WriteString (rows [i].Col3);
 646				buffer.WriteCodedRID (rows [i].Col4, CodedIndex.Implementation);
 647			}
 648		}
 649	}
 650
 651	sealed class NestedClassTable : SortedTable<NestedClassRow> {
 652
 653		public override void Write (TableHeapBuffer buffer)
 654		{
 655			for (int i = 0; i < length; i++) {
 656				buffer.WriteRID (rows [i].Col1, Table.TypeDef);		// NestedClass
 657				buffer.WriteRID (rows [i].Col2, Table.TypeDef);		// EnclosingClass
 658			}
 659		}
 660
 661		public override int Compare (NestedClassRow x, NestedClassRow y)
 662		{
 663			return Compare (x.Col1, y.Col1);
 664		}
 665	}
 666
 667	sealed class GenericParamTable : MetadataTable<GenericParamRow> {
 668
 669		public override void Write (TableHeapBuffer buffer)
 670		{
 671			for (int i = 0; i < length; i++) {
 672				buffer.WriteUInt16 (rows [i].Col1);		// Number
 673				buffer.WriteUInt16 ((ushort) rows [i].Col2);	// Flags
 674				buffer.WriteCodedRID (rows [i].Col3, CodedIndex.TypeOrMethodDef);	// Owner
 675				buffer.WriteString (rows [i].Col4);		// Name
 676			}
 677		}
 678	}
 679
 680	sealed class MethodSpecTable : MetadataTable<MethodSpecRow> {
 681
 682		public override void Write (TableHeapBuffer buffer)
 683		{
 684			for (int i = 0; i < length; i++) {
 685				buffer.WriteCodedRID (rows [i].Col1, CodedIndex.MethodDefOrRef);	// Method
 686				buffer.WriteBlob (rows [i].Col2);	// Instantiation
 687			}
 688		}
 689	}
 690
 691	sealed class GenericParamConstraintTable : MetadataTable<GenericParamConstraintRow> {
 692
 693		public override void Write (TableHeapBuffer buffer)
 694		{
 695			for (int i = 0; i < length; i++) {
 696				buffer.WriteRID (rows [i].Col1, Table.GenericParam);	// Owner
 697				buffer.WriteCodedRID (rows [i].Col2, CodedIndex.TypeDefOrRef);	// Constraint
 698			}
 699		}
 700	}
 701
 702	sealed class DocumentTable : MetadataTable<DocumentRow> {
 703
 704		public override void Write (TableHeapBuffer buffer)
 705		{
 706			for (int i = 0; i < length; i++) {
 707				buffer.WriteBlob (rows [i].Col1);	// Name
 708				buffer.WriteGuid (rows [i].Col2);	// HashAlgorithm
 709				buffer.WriteBlob (rows [i].Col3);	// Hash
 710				buffer.WriteGuid (rows [i].Col4);	// Language
 711			}
 712		}
 713	}
 714
 715	sealed class MethodDebugInformationTable : MetadataTable<MethodDebugInformationRow> {
 716
 717		public override void Write (TableHeapBuffer buffer)
 718		{
 719			for (int i = 0; i < length; i++) {
 720				buffer.WriteRID (rows [i].Col1, Table.Document);	// Document
 721				buffer.WriteBlob (rows [i].Col2);	// SequencePoints
 722			}
 723		}
 724	}
 725
 726	sealed class LocalScopeTable : MetadataTable<LocalScopeRow> {
 727
 728		public override void Write (TableHeapBuffer buffer)
 729		{
 730			for (int i = 0; i < length; i++) {
 731				buffer.WriteRID (rows [i].Col1, Table.Method);	// Method
 732				buffer.WriteRID (rows [i].Col2, Table.ImportScope);	// ImportScope
 733				buffer.WriteRID (rows [i].Col3, Table.LocalVariable); // VariableList
 734				buffer.WriteRID (rows [i].Col4, Table.LocalConstant); // ConstantList
 735				buffer.WriteUInt32 (rows [i].Col5); // StartOffset
 736				buffer.WriteUInt32 (rows [i].Col6); // Length
 737			}
 738		}
 739	}
 740
 741	sealed class LocalVariableTable : MetadataTable<LocalVariableRow> {
 742
 743		public override void Write (TableHeapBuffer buffer)
 744		{
 745			for (int i = 0; i < length; i++) {
 746				buffer.WriteUInt16 ((ushort) rows [i].Col1);	// Attributes
 747				buffer.WriteUInt16 (rows [i].Col2);	// Index
 748				buffer.WriteString (rows [i].Col3); // Name
 749			}
 750		}
 751	}
 752
 753	sealed class LocalConstantTable : MetadataTable<LocalConstantRow> {
 754
 755		public override void Write (TableHeapBuffer buffer)
 756		{
 757			for (int i = 0; i < length; i++) {
 758				buffer.WriteString (rows [i].Col1);	// Name
 759				buffer.WriteBlob (rows [i].Col2);	// Signature
 760			}
 761		}
 762	}
 763
 764	sealed class ImportScopeTable : MetadataTable<ImportScopeRow> {
 765
 766		public override void Write (TableHeapBuffer buffer)
 767		{
 768			for (int i = 0; i < length; i++) {
 769				buffer.WriteRID (rows [i].Col1, Table.ImportScope);	// Parent
 770				buffer.WriteBlob (rows [i].Col2);	// Imports
 771			}
 772		}
 773	}
 774
 775	sealed class StateMachineMethodTable : MetadataTable<StateMachineMethodRow> {
 776
 777		public override void Write (TableHeapBuffer buffer)
 778		{
 779			for (int i = 0; i < length; i++) {
 780				buffer.WriteRID (rows [i].Col1, Table.Method);	// MoveNextMethod
 781				buffer.WriteRID (rows [i].Col2, Table.Method);	// KickoffMethod
 782			}
 783		}
 784	}
 785
 786	sealed class CustomDebugInformationTable : SortedTable<CustomDebugInformationRow> {
 787
 788		public override void Write (TableHeapBuffer buffer)
 789		{
 790			for (int i = 0; i < length; i++) {
 791				buffer.WriteCodedRID (rows [i].Col1, CodedIndex.HasCustomDebugInformation);	// Parent
 792				buffer.WriteGuid (rows [i].Col2);	// Kind
 793				buffer.WriteBlob (rows [i].Col3);	// Value
 794			}
 795		}
 796
 797		public override int Compare (CustomDebugInformationRow x, CustomDebugInformationRow y)
 798		{
 799			return Compare(x.Col1, y.Col1);
 800		}
 801	}
 802
 803	sealed class MetadataBuilder {
 804
 805		readonly internal ModuleDefinition module;
 806		readonly internal ISymbolWriterProvider symbol_writer_provider;
 807		internal ISymbolWriter symbol_writer;
 808		readonly internal TextMap text_map;
 809		readonly internal string fq_name;
 810		readonly internal uint timestamp;
 811
 812		readonly Dictionary<TypeRefRow, MetadataToken> type_ref_map;
 813		readonly Dictionary<uint, MetadataToken> type_spec_map;
 814		readonly Dictionary<MemberRefRow, MetadataToken> member_ref_map;
 815		readonly Dictionary<MethodSpecRow, MetadataToken> method_spec_map;
 816		readonly Collection<GenericParameter> generic_parameters;
 817
 818		readonly internal CodeWriter code;
 819		readonly internal DataBuffer data;
 820		readonly internal ResourceBuffer resources;
 821		readonly internal StringHeapBuffer string_heap;
 822		readonly internal GuidHeapBuffer guid_heap;
 823		readonly internal UserStringHeapBuffer user_string_heap;
 824		readonly internal BlobHeapBuffer blob_heap;
 825		readonly internal TableHeapBuffer table_heap;
 826		readonly internal PdbHeapBuffer pdb_heap;
 827
 828		internal MetadataToken entry_point;
 829
 830		internal RID type_rid = 1;
 831		internal RID field_rid = 1;
 832		internal RID method_rid = 1;
 833		internal RID param_rid = 1;
 834		internal RID property_rid = 1;
 835		internal RID event_rid = 1;
 836		internal RID local_variable_rid = 1;
 837		internal RID local_constant_rid = 1;
 838
 839		readonly TypeRefTable type_ref_table;
 840		readonly TypeDefTable type_def_table;
 841		readonly FieldTable field_table;
 842		readonly MethodTable method_table;
 843		readonly ParamTable param_table;
 844		readonly InterfaceImplTable iface_impl_table;
 845		readonly MemberRefTable member_ref_table;
 846		readonly ConstantTable constant_table;
 847		readonly CustomAttributeTable custom_attribute_table;
 848		readonly DeclSecurityTable declsec_table;
 849		readonly StandAloneSigTable standalone_sig_table;
 850		readonly EventMapTable event_map_table;
 851		readonly EventTable event_table;
 852		readonly PropertyMapTable property_map_table;
 853		readonly PropertyTable property_table;
 854		readonly TypeSpecTable typespec_table;
 855		readonly MethodSpecTable method_spec_table;
 856
 857		internal MetadataBuilder metadata_builder;
 858
 859		readonly DocumentTable document_table;
 860		readonly MethodDebugInformationTable method_debug_information_table;
 861		readonly LocalScopeTable local_scope_table;
 862		readonly LocalVariableTable local_variable_table;
 863		readonly LocalConstantTable local_constant_table;
 864		readonly ImportScopeTable import_scope_table;
 865		readonly StateMachineMethodTable state_machine_method_table;
 866		readonly CustomDebugInformationTable custom_debug_information_table;
 867
 868		readonly Dictionary<ImportScopeRow, MetadataToken> import_scope_map;
 869		readonly Dictionary<string, MetadataToken> document_map;
 870
 871		public MetadataBuilder (ModuleDefinition module, string fq_name, uint timestamp, ISymbolWriterProvider symbol_writer_provider)
 872		{
 873			this.module = module;
 874			this.text_map = CreateTextMap ();
 875			this.fq_name = fq_name;
 876			this.timestamp = timestamp;
 877			this.symbol_writer_provider = symbol_writer_provider;
 878
 879			this.code = new CodeWriter (this);
 880			this.data = new DataBuffer ();
 881			this.resources = new ResourceBuffer ();
 882			this.string_heap = new StringHeapBuffer ();
 883			this.guid_heap = new GuidHeapBuffer ();
 884			this.user_string_heap = new UserStringHeapBuffer ();
 885			this.blob_heap = new BlobHeapBuffer ();
 886			this.table_heap = new TableHeapBuffer (module, this);
 887
 888			this.type_ref_table = GetTable<TypeRefTable> (Table.TypeRef);
 889			this.type_def_table = GetTable<TypeDefTable> (Table.TypeDef);
 890			this.field_table = GetTable<FieldTable> (Table.Field);
 891			this.method_table = GetTable<MethodTable> (Table.Method);
 892			this.param_table = GetTable<ParamTable> (Table.Param);
 893			this.iface_impl_table = GetTable<InterfaceImplTable> (Table.InterfaceImpl);
 894			this.member_ref_table = GetTable<MemberRefTable> (Table.MemberRef);
 895			this.constant_table = GetTable<ConstantTable> (Table.Constant);
 896			this.custom_attribute_table = GetTable<CustomAttributeTable> (Table.CustomAttribute);
 897			this.declsec_table = GetTable<DeclSecurityTable> (Table.DeclSecurity);
 898			this.standalone_sig_table = GetTable<StandAloneSigTable> (Table.StandAloneSig);
 899			this.event_map_table = GetTable<EventMapTable> (Table.EventMap);
 900			this.event_table = GetTable<EventTable> (Table.Event);
 901			this.property_map_table = GetTable<PropertyMapTable> (Table.PropertyMap);
 902			this.property_table = GetTable<PropertyTable> (Table.Property);
 903			this.typespec_table = GetTable<TypeSpecTable> (Table.TypeSpec);
 904			this.method_spec_table = GetTable<MethodSpecTable> (Table.MethodSpec);
 905
 906			var row_equality_comparer = new RowEqualityComparer ();
 907			type_ref_map = new Dictionary<TypeRefRow, MetadataToken> (row_equality_comparer);
 908			type_spec_map = new Dictionary<uint, MetadataToken> ();
 909			member_ref_map = new Dictionary<MemberRefRow, MetadataToken> (row_equality_comparer);
 910			method_spec_map = new Dictionary<MethodSpecRow, MetadataToken> (row_equality_comparer);
 911			generic_parameters = new Collection<GenericParameter> ();
 912
 913			this.document_table = GetTable<DocumentTable> (Table.Document);
 914			this.method_debug_information_table = GetTable<MethodDebugInformationTable> (Table.MethodDebugInformation);
 915			this.local_scope_table = GetTable<LocalScopeTable> (Table.LocalScope);
 916			this.local_variable_table = GetTable<LocalVariableTable> (Table.LocalVariable);
 917			this.local_constant_table = GetTable<LocalConstantTable> (Table.LocalConstant);
 918			this.import_scope_table = GetTable<ImportScopeTable> (Table.ImportScope);
 919			this.state_machine_method_table = GetTable<StateMachineMethodTable> (Table.StateMachineMethod);
 920			this.custom_debug_information_table = GetTable<CustomDebugInformationTable> (Table.CustomDebugInformation);
 921
 922			this.document_map = new Dictionary<string, MetadataToken> (StringComparer.Ordinal);
 923			this.import_scope_map = new Dictionary<ImportScopeRow, MetadataToken> (row_equality_comparer);
 924		}
 925
 926		public MetadataBuilder (ModuleDefinition module, PortablePdbWriterProvider writer_provider)
 927		{
 928			this.module = module;
 929			this.text_map = new TextMap ();
 930			this.symbol_writer_provider = writer_provider;
 931
 932			this.string_heap = new StringHeapBuffer ();
 933			this.guid_heap = new GuidHeapBuffer ();
 934			this.user_string_heap = new UserStringHeapBuffer ();
 935			this.blob_heap = new BlobHeapBuffer ();
 936			this.table_heap = new TableHeapBuffer (module, this);
 937			this.pdb_heap = new PdbHeapBuffer();
 938
 939			this.document_table = GetTable<DocumentTable> (Table.Document);
 940			this.method_debug_information_table = GetTable<MethodDebugInformationTable> (Table.MethodDebugInformation);
 941			this.local_scope_table = GetTable<LocalScopeTable> (Table.LocalScope);
 942			this.local_variable_table = GetTable<LocalVariableTable> (Table.LocalVariable);
 943			this.local_constant_table = GetTable<LocalConstantTable> (Table.LocalConstant);
 944			this.import_scope_table = GetTable<ImportScopeTable> (Table.ImportScope);
 945			this.state_machine_method_table = GetTable<StateMachineMethodTable> (Table.StateMachineMethod);
 946			this.custom_debug_information_table = GetTable<CustomDebugInformationTable> (Table.CustomDebugInformation);
 947
 948			var row_equality_comparer = new RowEqualityComparer ();
 949
 950			this.document_map = new Dictionary<string, MetadataToken> ();
 951			this.import_scope_map = new Dictionary<ImportScopeRow, MetadataToken> (row_equality_comparer);
 952		}
 953
 954		public void SetSymbolWriter (ISymbolWriter writer)
 955		{
 956			symbol_writer = writer;
 957
 958			if (symbol_writer == null && module.HasImage && module.Image.HasDebugTables ())
 959				symbol_writer = new PortablePdbWriter (this, module);
 960		}
 961
 962		TextMap CreateTextMap ()
 963		{
 964			var map = new TextMap ();
 965			map.AddMap (TextSegment.ImportAddressTable, module.Architecture == TargetArchitecture.I386 ? 8 : 0);
 966			map.AddMap (TextSegment.CLIHeader, 0x48, 8);
 967			return map;
 968		}
 969
 970		TTable GetTable<TTable> (Table table) where TTable : MetadataTable, new ()
 971		{
 972			return table_heap.GetTable<TTable> (table);
 973		}
 974
 975		uint GetStringIndex (string @string)
 976		{
 977			if (string.IsNullOrEmpty (@string))
 978				return 0;
 979
 980			return string_heap.GetStringIndex (@string);
 981		}
 982
 983		uint GetGuidIndex (Guid guid)
 984		{
 985			return guid_heap.GetGuidIndex (guid);
 986		}
 987
 988		uint GetBlobIndex (ByteBuffer blob)
 989		{
 990			if (blob.length == 0)
 991				return 0;
 992
 993			return blob_heap.GetBlobIndex (blob);
 994		}
 995
 996		uint GetBlobIndex (byte [] blob)
 997		{
 998			if (blob.IsNullOrEmpty ())
 999				return 0;
1000
1001			return GetBlobIndex (new ByteBuffer (blob));
1002		}
1003
1004		public void BuildMetadata ()
1005		{
1006			BuildModule ();
1007
1008			table_heap.string_offsets = string_heap.WriteStrings ();
1009			table_heap.ComputeTableInformations ();
1010			table_heap.WriteTableHeap ();
1011		}
1012
1013		void BuildModule ()
1014		{
1015			var table = GetTable<ModuleTable> (Table.Module);
1016			table.row.Col1 = GetStringIndex (module.Name);
1017			table.row.Col2 = GetGuidIndex (module.Mvid);
1018
1019			var assembly = module.Assembly;
1020
1021			if (assembly != null)
1022				BuildAssembly ();
1023
1024			if (module.HasAssemblyReferences)
1025				AddAssemblyReferences ();
1026
1027			if (module.HasModuleReferences)
1028				AddModuleReferences ();
1029
1030			if (module.HasResources)
1031				AddResources ();
1032
1033			if (module.HasExportedTypes)
1034				AddExportedTypes ();
1035
1036			BuildTypes ();
1037
1038			if (assembly != null) {
1039				if (assembly.HasCustomAttributes)
1040					AddCustomAttributes (assembly);
1041
1042				if (assembly.HasSecurityDeclarations)
1043					AddSecurityDeclarations (assembly);
1044			}
1045
1046			if (module.HasCustomAttributes)
1047				AddCustomAttributes (module);
1048
1049			if (module.EntryPoint != null)
1050				entry_point = LookupToken (module.EntryPoint);
1051		}
1052
1053		void BuildAssembly ()
1054		{
1055			var assembly = module.Assembly;
1056			var name = assembly.Name;
1057
1058			var table = GetTable<AssemblyTable> (Table.Assembly);
1059
1060			table.row = new AssemblyRow (
1061				name.HashAlgorithm,
1062				(ushort) name.Version.Major,
1063				(ushort) name.Version.Minor,
1064				(ushort) name.Version.Build,
1065				(ushort) name.Version.Revision,
1066				name.Attributes,
1067				GetBlobIndex (name.PublicKey),
1068				GetStringIndex (name.Name),
1069				GetStringIndex (name.Culture));
1070
1071			if (assembly.Modules.Count > 1)
1072				BuildModules ();
1073		}
1074
1075		void BuildModules ()
1076		{
1077			var modules = this.module.Assembly.Modules;
1078			var table = GetTable<FileTable> (Table.File);
1079
1080			for (int i = 0; i < modules.Count; i++) {
1081				var module = modules [i];
1082				if (module.IsMain)
1083					continue;
1084
1085#if NET_CORE
1086				throw new NotSupportedException ();
1087#else
1088				var parameters = new WriterParameters {
1089					SymbolWriterProvider = symbol_writer_provider,
1090				};
1091
1092				var file_name = GetModuleFileName (module.Name);
1093				module.Write (file_name, parameters);
1094
1095				var hash = CryptoService.ComputeHash (file_name);
1096
1097				table.AddRow (new FileRow (
1098					FileAttributes.ContainsMetaData,
1099					GetStringIndex (module.Name),
1100					GetBlobIndex (hash)));
1101#endif
1102			}
1103		}
1104
1105#if !NET_CORE
1106		string GetModuleFileName (string name)
1107		{
1108			if (string.IsNullOrEmpty (name))
1109				throw new NotSupportedException ();
1110
1111			var path = Path.GetDirectoryName (fq_name);
1112			return Path.Combine (path, name);
1113		}
1114#endif
1115
1116		void AddAssemblyReferences ()
1117		{
1118			var references = module.AssemblyReferences;
1119			var table = GetTable<AssemblyRefTable> (Table.AssemblyRef);
1120
1121			if (module.IsWindowsMetadata ())
1122				module.Projections.RemoveVirtualReferences (references);
1123
1124			for (int i = 0; i < references.Count; i++) {
1125				var reference = references [i];
1126
1127				var key_or_token = reference.PublicKey.IsNullOrEmpty ()
1128					? reference.PublicKeyToken
1129					: reference.PublicKey;
1130
1131				var version = reference.Version;
1132
1133				var rid = table.AddRow (new AssemblyRefRow (
1134					(ushort) version.Major,
1135					(ushort) version.Minor,
1136					(ushort) version.Build,
1137					(ushort) version.Revision,
1138					reference.Attributes,
1139					GetBlobIndex (key_or_token),
1140					GetStringIndex (reference.Name),
1141					GetStringIndex (reference.Culture),
1142					GetBlobIndex (reference.Hash)));
1143
1144				reference.token = new MetadataToken (TokenType.AssemblyRef, rid);
1145			}
1146
1147			if (module.IsWindowsMetadata ())
1148				module.Projections.AddVirtualReferences (references);
1149		}
1150
1151		void AddModuleReferences ()
1152		{
1153			var references = module.ModuleReferences;
1154			var table = GetTable<ModuleRefTable> (Table.ModuleRef);
1155
1156			for (int i = 0; i < references.Count; i++) {
1157				var reference = references [i];
1158
1159				reference.token = new MetadataToken (
1160					TokenType.ModuleRef,
1161					table.AddRow (GetStringIndex (reference.Name)));
1162			}
1163		}
1164
1165		void AddResources ()
1166		{
1167			var resources = module.Resources;
1168			var table = GetTable<ManifestResourceTable> (Table.ManifestResource);
1169
1170			for (int i = 0; i < resources.Count; i++) {
1171				var resource = resources [i];
1172
1173				var row = new ManifestResourceRow (
1174					0,
1175					resource.Attributes,
1176					GetStringIndex (resource.Name),
1177					0);
1178
1179				switch (resource.ResourceType) {
1180				case ResourceType.Embedded:
1181					row.Col1 = AddEmbeddedResource ((EmbeddedResource) resource);
1182					break;
1183				case ResourceType.Linked:
1184					row.Col4 = CodedIndex.Implementation.CompressMetadataToken (
1185						new MetadataToken (
1186							TokenType.File,
1187							AddLinkedResource ((LinkedResource) resource)));
1188					break;
1189				case ResourceType.AssemblyLinked:
1190					row.Col4 = CodedIndex.Implementation.CompressMetadataToken (
1191						((AssemblyLinkedResource) resource).Assembly.MetadataToken);
1192					break;
1193				default:
1194					throw new NotSupportedException ();
1195				}
1196
1197				table.AddRow (row);
1198			}
1199		}
1200
1201		uint AddLinkedResource (LinkedResource resource)
1202		{
1203			var table = GetTable<FileTable> (Table.File);
1204			var hash = resource.Hash;
1205
1206			if (hash.IsNullOrEmpty ())
1207				hash = CryptoService.ComputeHash (resource.File);
1208
1209			return (uint) table.AddRow (new FileRow (
1210				FileAttributes.ContainsNoMetaData,
1211				GetStringIndex (resource.File),
1212				GetBlobIndex (hash)));
1213		}
1214
1215		uint AddEmbeddedResource (EmbeddedResource resource)
1216		{
1217			return resources.AddResource (resource.GetResourceData ());
1218		}
1219
1220		void AddExportedTypes ()
1221		{
1222			var exported_types = module.ExportedTypes;
1223			var table = GetTable<ExportedTypeTable> (Table.ExportedType);
1224
1225			for (int i = 0; i < exported_types.Count; i++) {
1226				var exported_type = exported_types [i];
1227
1228				var rid = table.AddRow (new ExportedTypeRow (
1229					exported_type.Attributes,
1230					(uint) exported_type.Identifier,
1231					GetStringIndex (exported_type.Name),
1232					GetStringIndex (exported_type.Namespace),
1233					MakeCodedRID (GetExportedTypeScope (exported_type), CodedIndex.Implementation)));
1234
1235				exported_type.token = new MetadataToken (TokenType.ExportedType, rid);
1236			}
1237		}
1238
1239		MetadataToken GetExportedTypeScope (ExportedType exported_type)
1240		{
1241			if (exported_type.DeclaringType != null)
1242				return exported_type.DeclaringType.MetadataToken;
1243
1244			var scope = exported_type.Scope;
1245			switch (scope.MetadataToken.TokenType) {
1246			case TokenType.AssemblyRef:
1247				return scope.MetadataToken;
1248			case TokenType.ModuleRef:
1249				var file_table = GetTable<FileTable> (Table.File);
1250				for (int i = 0; i < file_table.length; i++)
1251					if (file_table.rows [i].Col2 == GetStringIndex (scope.Name))
1252						return new MetadataToken (TokenType.File, i + 1);
1253
1254				break;
1255			}
1256
1257			throw new NotSupportedException ();
1258		}
1259
1260		void BuildTypes ()
1261		{
1262			if (!module.HasTypes)
1263				return;
1264
1265			AttachTokens ();
1266			AddTypes ();
1267			AddGenericParameters ();
1268		}
1269
1270		void AttachTokens ()
1271		{
1272			var types = module.Types;
1273
1274			for (int i = 0; i < types.Count; i++)
1275				AttachTypeToken (types [i]);
1276		}
1277
1278		void AttachTypeToken (TypeDefinition type)
1279		{
1280			type.token = new MetadataToken (TokenType.TypeDef, type_rid++);
1281			type.fields_range.Start = field_rid;
1282			type.methods_range.Start = method_rid;
1283
1284			if (type.HasFields)
1285				AttachFieldsToken (type);
1286
1287			if (type.HasMethods)
1288				AttachMethodsToken (type);
1289
1290			if (type.HasNestedTypes)
1291				AttachNestedTypesToken (type);
1292		}
1293
1294		void AttachNestedTypesToken (TypeDefinition type)
1295		{
1296			var nested_types = type.NestedTypes;
1297			for (int i = 0; i < nested_types.Count; i++)
1298				AttachTypeToken (nested_types [i]);
1299		}
1300
1301		void AttachFieldsToken (TypeDefinition type)
1302		{
1303			var fields = type.Fields;
1304			type.fields_range.Length = (uint) fields.Count;
1305			for (int i = 0; i < fields.Count; i++)
1306				fields [i].token = new MetadataToken (TokenType.Field, field_rid++);
1307		}
1308
1309		void AttachMethodsToken (TypeDefinition type)
1310		{
1311			var methods = type.Methods;
1312			type.methods_range.Length = (uint) methods.Count;
1313			for (int i = 0; i < methods.Count; i++)
1314				methods [i].token = new MetadataToken (TokenType.Method, method_rid++);
1315		}
1316
1317		MetadataToken GetTypeToken (TypeReference type)
1318		{
1319			if (type == null)
1320				return MetadataToken.Zero;
1321
1322			if (type.IsDefinition)
1323				return type.token;
1324
1325			if (type.IsTypeSpecification ())
1326				return GetTypeSpecToken (type);
1327
1328			return GetTypeRefToken (type);
1329		}
1330
1331		MetadataToken GetTypeSpecToken (TypeReference type)
1332		{
1333			var row = GetBlobIndex (GetTypeSpecSignature (type));
1334
1335			MetadataToken token;
1336			if (type_spec_map.TryGetValue (row, out token))
1337				return token;
1338
1339			return AddTypeSpecification (type, row);
1340		}
1341
1342		MetadataToken AddTypeSpecification (TypeReference type, uint row)
1343		{
1344			type.token = new MetadataToken (TokenType.TypeSpec, typespec_table.AddRow (row));
1345
1346			var token = type.token;
1347			type_spec_map.Add (row, token);
1348			return token;
1349		}
1350
1351		MetadataToken GetTypeRefToken (TypeReference type)
1352		{
1353			var projection = WindowsRuntimeProjections.RemoveProjection (type);
1354
1355			var row = CreateTypeRefRow (type);
1356
1357			MetadataToken token;
1358			if (!type_ref_map.TryGetValue (row, out token))
1359				token = AddTypeReference (type, row);
1360
1361			WindowsRuntimeProjections.ApplyProjection (type, projection);
1362
1363			return token;
1364		}
1365
1366		TypeRefRow CreateTypeRefRow (TypeReference type)
1367		{
1368			var scope_token = GetScopeToken (type);
1369
1370			return new TypeRefRow (
1371				MakeCodedRID (scope_token, CodedIndex.ResolutionScope),
1372				GetStringIndex (type.Name),
1373				GetStringIndex (type.Namespace));
1374		}
1375
1376		MetadataToken GetScopeToken (TypeReference type)
1377		{
1378			if (type.IsNested)
1379				return GetTypeRefToken (type.DeclaringType);
1380
1381			var scope = type.Scope;
1382
1383			if (scope == null)
1384				return MetadataToken.Zero;
1385
1386			return scope.MetadataToken;
1387		}
1388
1389		static CodedRID MakeCodedRID (IMetadataTokenProvider provider, CodedIndex index)
1390		{
1391			return MakeCodedRID (provider.MetadataToken, index);
1392		}
1393
1394		static CodedRID MakeCodedRID (MetadataToken token, CodedIndex index)
1395		{
1396			return index.CompressMetadataToken (token);
1397		}
1398
1399		MetadataToken AddTypeReference (TypeReference type, TypeRefRow row)
1400		{
1401			type.token = new MetadataToken (TokenType.TypeRef, type_ref_table.AddRow (row));
1402
1403			var token = type.token;
1404			type_ref_map.Add (row, token);
1405			return token;
1406		}
1407
1408		void AddTypes ()
1409		{
1410			var types = module.Types;
1411
1412			for (int i = 0; i < types.Count; i++)
1413				AddType (types [i]);
1414		}
1415
1416		void AddType (TypeDefinition type)
1417		{
1418			var treatment = WindowsRuntimeProjections.RemoveProjection (type);
1419
1420			type_def_table.AddRow (new TypeDefRow (
1421				type.Attributes,
1422				GetStringIndex (type.Name),
1423				GetStringIndex (type.Namespace),
1424				MakeCodedRID (GetTypeToken (type.BaseType), CodedIndex.TypeDefOrRef),
1425				type.fields_range.Start,
1426				type.methods_range.Start));
1427
1428			if (type.HasGenericParameters)
1429				AddGenericParameters (type);
1430
1431			if (type.HasInterfaces)
1432				AddInterfaces (type);
1433
1434			AddLayoutInfo (type);
1435
1436			if (type.HasFields)
1437				AddFields (type);
1438
1439			if (type.HasMethods)
1440				AddMethods (type);
1441
1442			if (type.HasProperties)
1443				AddProperties (type);
1444
1445			if (type.HasEvents)
1446				AddEvents (type);
1447
1448			if (type.HasCustomAttributes)
1449				AddCustomAttributes (type);
1450
1451			if (type.HasSecurityDeclarations)
1452				AddSecurityDeclarations (type);
1453
1454			if (type.HasNestedTypes)
1455				AddNestedTypes (type);
1456
1457			WindowsRuntimeProjections.ApplyProjection (type, treatment);
1458		}
1459
1460		void AddGenericParameters (IGenericParameterProvider owner)
1461		{
1462			var parameters = owner.GenericParameters;
1463
1464			for (int i = 0; i < parameters.Count; i++)
1465				generic_parameters.Add (parameters [i]);
1466		}
1467
1468		sealed class GenericParameterComparer : IComparer<GenericParameter> {
1469
1470			public int Compare (GenericParameter a, GenericParameter b)
1471			{
1472				var a_owner = MakeCodedRID (a.Owner, CodedIndex.TypeOrMethodDef);
1473				var b_owner = MakeCodedRID (b.Owner, CodedIndex.TypeOrMethodDef);
1474				if (a_owner == b_owner) {
1475					var a_pos = a.Position;
1476					var b_pos = b.Position;
1477					return a_pos == b_pos ? 0 : a_pos > b_pos ? 1 : -1;
1478				}
1479
1480				return a_owner > b_owner ? 1 : -1;
1481			}
1482		}
1483
1484		void AddGenericParameters ()
1485		{
1486			var items = this.generic_parameters.items;
1487			var size = this.generic_parameters.size;
1488			Array.Sort (items, 0, size, new GenericParameterComparer ());
1489
1490			var generic_param_table = GetTable<GenericParamTable> (Table.GenericParam);
1491			var generic_param_constraint_table = GetTable<GenericParamConstraintTable> (Table.GenericParamConstraint);
1492
1493			for (int i = 0; i < size; i++) {
1494				var generic_parameter = items [i];
1495
1496				var rid = generic_param_table.AddRow (new GenericParamRow (
1497					(ushort) generic_parameter.Position,
1498					generic_parameter.Attributes,
1499					MakeCodedRID (generic_parameter.Owner, CodedIndex.TypeOrMethodDef),
1500					GetStringIndex (generic_parameter.Name)));
1501
1502				generic_parameter.token = new MetadataToken (TokenType.GenericParam, rid);
1503
1504				if (generic_parameter.HasConstraints)
1505					AddConstraints (generic_parameter, generic_param_constraint_table);
1506
1507				if (generic_parameter.HasCustomAttributes)
1508					AddCustomAttributes (generic_parameter);
1509			}
1510		}
1511
1512		void AddConstraints (GenericParameter generic_parameter, GenericParamConstraintTable table)
1513		{
1514			var constraints = generic_parameter.Constraints;
1515
1516			var gp_rid = generic_parameter.token.RID;
1517
1518			for (int i = 0; i < constraints.Count; i++) {
1519				var constraint = constraints [i];
1520
1521				var rid = table.AddRow (new GenericParamConstraintRow (
1522					gp_rid,
1523					MakeCodedRID (GetTypeToken (constraint.ConstraintType), CodedIndex.TypeDefOrRef)));
1524
1525				constraint.token = new MetadataToken (TokenType.GenericParamConstraint, rid);
1526
1527				if (constraint.HasCustomAttributes)
1528					AddCustomAttributes (constraint);
1529			}
1530		}
1531
1532		void AddInterfaces (TypeDefinition type)
1533		{
1534			var interfaces = type.Interfaces;
1535			var type_rid = type.token.RID;
1536
1537			for (int i = 0; i < interfaces.Count; i++) {
1538				var iface_impl = interfaces [i];
1539
1540				var rid = iface_impl_table.AddRow (new InterfaceImplRow (
1541					type_rid,
1542					MakeCodedRID (GetTypeToken (iface_impl.InterfaceType), CodedIndex.TypeDefOrRef)));
1543
1544				iface_impl.token = new MetadataToken (TokenType.InterfaceImpl, rid);
1545
1546				if (iface_impl.HasCustomAttributes)
1547					AddCustomAttributes (iface_impl);
1548			}
1549		}
1550
1551		void AddLayoutInfo (TypeDefinition type)
1552		{
1553			if (type.HasLayoutInfo) {
1554				var table = GetTable<ClassLayoutTable> (Table.ClassLayout);
1555
1556				table.AddRow (new ClassLayoutRow (
1557					(ushort) type.PackingSize,
1558					(uint) type.ClassSize,
1559					type.token.RID));
1560
1561				return;
1562			}
1563
1564			if (type.IsValueType && HasNoInstanceField (type)) {
1565				var table = GetTable<ClassLayoutTable> (Table.ClassLayout);
1566
1567				table.AddRow (new ClassLayoutRow (0, 1, type.token.RID));
1568			}
1569		}
1570
1571		static bool HasNoInstanceField (TypeDefinition type)
1572		{
1573			if (!type.HasFields)
1574				return true;
1575
1576			var fields = type.Fields;
1577
1578			for (int i = 0; i < fields.Count; i++)
1579				if (!fields [i].IsStatic)
1580					return false;
1581
1582			return true;
1583		}
1584
1585		void AddNestedTypes (TypeDefinition type)
1586		{
1587			var nested_types = type.NestedTypes;
1588			var nested_table = GetTable<NestedClassTable> (Table.NestedClass);
1589
1590			for (int i = 0; i < nested_types.Count; i++) {
1591				var nested = nested_types [i];
1592				AddType (nested);
1593				nested_table.AddRow (new NestedClassRow (nested.token.RID, type.token.RID));
1594			}
1595		}
1596
1597		void AddFields (TypeDefinition type)
1598		{
1599			var fields = type.Fields;
1600
1601			for (int i = 0; i < fields.Count; i++)
1602				AddField (fields [i]);
1603		}
1604
1605		void AddField (FieldDefinition field)
1606		{
1607			var projection = WindowsRuntimeProjections.RemoveProjection (field);
1608
1609			field_table.AddRow (new FieldRow (
1610				field.Attributes,
1611				GetStringIndex (field.Name),
1612				GetBlobIndex (GetFieldSignature (field))));
1613
1614			if (!field.InitialValue.IsNullOrEmpty ())
1615				AddFieldRVA (field);
1616
1617			if (field.HasLayoutInfo)
1618				AddFieldLayout (field);
1619
1620			if (field.HasCustomAttributes)
1621				AddCustomAttributes (field);
1622
1623			if (field.HasConstant)
1624				AddConstant (field, field.FieldType);
1625
1626			if (field.HasMarshalInfo)
1627				AddMarshalInfo (field);
1628
1629			WindowsRuntimeProjections.ApplyProjection (field, projection);
1630		}
1631
1632		void AddFieldRVA (FieldDefinition field)
1633		{
1634			var table = GetTable<FieldRVATable> (Table.FieldRVA);
1635			table.AddRow (new FieldRVARow (
1636				data.AddData (field.InitialValue),
1637				field.token.RID));
1638		}
1639
1640		void AddFieldLayout (FieldDefinition field)
1641		{
1642			var table = GetTable<FieldLayoutTable> (Table.FieldLayout);
1643			table.AddRow (new FieldLayoutRow ((uint) field.Offset, field.token.RID));
1644		}
1645
1646		void AddMethods (TypeDefinition type)
1647		{
1648			var methods = type.Methods;
1649
1650			for (int i = 0; i < methods.Count; i++)
1651				AddMethod (methods [i]);
1652		}
1653
1654		void AddMethod (MethodDefinition method)
1655		{
1656			var projection = WindowsRuntimeProjections.RemoveProjection (method);
1657
1658			method_table.AddRow (new MethodRow (
1659				method.HasBody ? code.WriteMethodBody (method) : 0,
1660				method.ImplAttributes,
1661				method.Attributes,
1662				GetStringIndex (method.Name),
1663				GetBlobIndex (GetMethodSignature (method)),
1664				param_rid));
1665
1666			AddParameters (method);
1667
1668			if (method.HasGenericParameters)
1669				AddGenericParameters (method);
1670
1671			if (method.IsPInvokeImpl)
1672				AddPInvokeInfo (method);
1673
1674			if (method.HasCustomAttributes)
1675				AddCustomAttributes (method);
1676
1677			if (method.HasSecurityDeclarations)
1678				AddSecurityDeclarations (method);
1679
1680			if (method.HasOverrides)
1681				AddOverrides (method);
1682
1683			WindowsRuntimeProjections.ApplyProjection (method, projection);
1684		}
1685
1686		void AddParameters (MethodDefinition method)
1687		{
1688			var return_parameter = method.MethodReturnType.parameter;
1689
1690			if (return_parameter != null && RequiresParameterRow (return_parameter))
1691				AddParameter (0, return_parameter, param_table);
1692
1693			if (!method.HasParameters)
1694				return;
1695
1696			var parameters = method.Parameters;
1697
1698			for (int i = 0; i < parameters.Count; i++) {
1699				var parameter = parameters [i];
1700				if (!RequiresParameterRow (parameter))
1701					continue;
1702
1703				AddParameter ((ushort) (i + 1), parameter, param_table);
1704			}
1705		}
1706
1707		v

Large files files are truncated, but you can click here to view the full file