PageRenderTime 312ms CodeModel.GetById 201ms app.highlight 94ms RepoModel.GetById 1ms app.codeStats 1ms

/Mono.Cecil/AssemblyReader.cs

http://github.com/jbevain/cecil
C# | 3887 lines | 2977 code | 897 blank | 13 comment | 599 complexity | d42c832854fc52a9bb4626201d3ae696 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;
  16
  17using Mono.Collections.Generic;
  18using Mono.Cecil.Cil;
  19using Mono.Cecil.Metadata;
  20using Mono.Cecil.PE;
  21
  22using RVA = System.UInt32;
  23
  24namespace Mono.Cecil {
  25
  26	abstract class ModuleReader {
  27
  28		readonly protected ModuleDefinition module;
  29
  30		protected ModuleReader (Image image, ReadingMode mode)
  31		{
  32			this.module = new ModuleDefinition (image);
  33			this.module.ReadingMode = mode;
  34		}
  35
  36		protected abstract void ReadModule ();
  37		public abstract void ReadSymbols (ModuleDefinition module);
  38
  39		protected void ReadModuleManifest (MetadataReader reader)
  40		{
  41			reader.Populate (module);
  42
  43			ReadAssembly (reader);
  44		}
  45
  46		void ReadAssembly (MetadataReader reader)
  47		{
  48			var name = reader.ReadAssemblyNameDefinition ();
  49			if (name == null) {
  50				module.kind = ModuleKind.NetModule;
  51				return;
  52			}
  53
  54			var assembly = new AssemblyDefinition ();
  55			assembly.Name = name;
  56
  57			module.assembly = assembly;
  58			assembly.main_module = module;
  59		}
  60
  61		public static ModuleDefinition CreateModule (Image image, ReaderParameters parameters)
  62		{
  63			var reader = CreateModuleReader (image, parameters.ReadingMode);
  64			var module = reader.module;
  65
  66			if (parameters.assembly_resolver != null)
  67				module.assembly_resolver = Disposable.NotOwned (parameters.assembly_resolver);
  68
  69			if (parameters.metadata_resolver != null)
  70				module.metadata_resolver = parameters.metadata_resolver;
  71
  72			if (parameters.metadata_importer_provider != null)
  73				module.metadata_importer = parameters.metadata_importer_provider.GetMetadataImporter (module);
  74
  75			if (parameters.reflection_importer_provider != null)
  76				module.reflection_importer = parameters.reflection_importer_provider.GetReflectionImporter (module);
  77
  78			GetMetadataKind (module, parameters);
  79
  80			reader.ReadModule ();
  81
  82			ReadSymbols (module, parameters);
  83
  84			reader.ReadSymbols (module);
  85
  86			if (parameters.ReadingMode == ReadingMode.Immediate)
  87				module.MetadataSystem.Clear ();
  88
  89			return module;
  90		}
  91
  92		static void ReadSymbols (ModuleDefinition module, ReaderParameters parameters)
  93		{
  94			var symbol_reader_provider = parameters.SymbolReaderProvider;
  95
  96			if (symbol_reader_provider == null && parameters.ReadSymbols)
  97				symbol_reader_provider = new DefaultSymbolReaderProvider ();
  98
  99			if (symbol_reader_provider != null) {
 100				module.SymbolReaderProvider = symbol_reader_provider;
 101
 102				var reader = parameters.SymbolStream != null
 103					? symbol_reader_provider.GetSymbolReader (module, parameters.SymbolStream)
 104					: symbol_reader_provider.GetSymbolReader (module, module.FileName);
 105
 106				if (reader != null) {
 107					try {
 108						module.ReadSymbols (reader, parameters.ThrowIfSymbolsAreNotMatching);
 109					} catch (Exception) {
 110						reader.Dispose ();
 111						throw;
 112					}
 113				}
 114			}
 115
 116			if (module.Image.HasDebugTables ())
 117				module.ReadSymbols (new PortablePdbReader (module.Image, module));
 118		}
 119
 120		static void GetMetadataKind (ModuleDefinition module, ReaderParameters parameters)
 121		{
 122			if (!parameters.ApplyWindowsRuntimeProjections) {
 123				module.MetadataKind = MetadataKind.Ecma335;
 124				return;
 125			}
 126
 127			var runtime_version = module.RuntimeVersion;
 128
 129			if (!runtime_version.Contains ("WindowsRuntime"))
 130				module.MetadataKind = MetadataKind.Ecma335;
 131			else if (runtime_version.Contains ("CLR"))
 132				module.MetadataKind = MetadataKind.ManagedWindowsMetadata;
 133			else
 134				module.MetadataKind = MetadataKind.WindowsMetadata;
 135		}
 136
 137		static ModuleReader CreateModuleReader (Image image, ReadingMode mode)
 138		{
 139			switch (mode) {
 140			case ReadingMode.Immediate:
 141				return new ImmediateModuleReader (image);
 142			case ReadingMode.Deferred:
 143				return new DeferredModuleReader (image);
 144			default:
 145				throw new ArgumentException ();
 146			}
 147		}
 148	}
 149
 150	sealed class ImmediateModuleReader : ModuleReader {
 151
 152		bool resolve_attributes;
 153
 154		public ImmediateModuleReader (Image image)
 155			: base (image, ReadingMode.Immediate)
 156		{
 157		}
 158
 159		protected override void ReadModule ()
 160		{
 161			this.module.Read (this.module, (module, reader) => {
 162				ReadModuleManifest (reader);
 163				ReadModule (module, resolve_attributes: true);
 164			});
 165		}
 166
 167		public void ReadModule (ModuleDefinition module, bool resolve_attributes)
 168		{
 169			this.resolve_attributes = resolve_attributes;
 170
 171			if (module.HasAssemblyReferences)
 172				Mixin.Read (module.AssemblyReferences);
 173			if (module.HasResources)
 174				Mixin.Read (module.Resources);
 175			if (module.HasModuleReferences)
 176				Mixin.Read (module.ModuleReferences);
 177			if (module.HasTypes)
 178				ReadTypes (module.Types);
 179			if (module.HasExportedTypes)
 180				Mixin.Read (module.ExportedTypes);
 181
 182			ReadCustomAttributes (module);
 183
 184			var assembly = module.Assembly;
 185			if (assembly == null)
 186				return;
 187
 188			ReadCustomAttributes (assembly);
 189			ReadSecurityDeclarations (assembly);
 190		}
 191
 192		void ReadTypes (Collection<TypeDefinition> types)
 193		{
 194			for (int i = 0; i < types.Count; i++)
 195				ReadType (types [i]);
 196		}
 197
 198		void ReadType (TypeDefinition type)
 199		{
 200			ReadGenericParameters (type);
 201
 202			if (type.HasInterfaces)
 203				ReadInterfaces (type);
 204
 205			if (type.HasNestedTypes)
 206				ReadTypes (type.NestedTypes);
 207
 208			if (type.HasLayoutInfo)
 209				Mixin.Read (type.ClassSize);
 210
 211			if (type.HasFields)
 212				ReadFields (type);
 213
 214			if (type.HasMethods)
 215				ReadMethods (type);
 216
 217			if (type.HasProperties)
 218				ReadProperties (type);
 219
 220			if (type.HasEvents)
 221				ReadEvents (type);
 222
 223			ReadSecurityDeclarations (type);
 224			ReadCustomAttributes (type);
 225		}
 226
 227		void ReadInterfaces (TypeDefinition type)
 228		{
 229			var interfaces = type.Interfaces;
 230
 231			for (int i = 0; i < interfaces.Count; i++)
 232				ReadCustomAttributes (interfaces [i]);
 233		}
 234
 235		void ReadGenericParameters (IGenericParameterProvider provider)
 236		{
 237			if (!provider.HasGenericParameters)
 238				return;
 239
 240			var parameters = provider.GenericParameters;
 241
 242			for (int i = 0; i < parameters.Count; i++) {
 243				var parameter = parameters [i];
 244
 245				if (parameter.HasConstraints)
 246					ReadGenericParameterConstraints (parameter);
 247
 248				ReadCustomAttributes (parameter);
 249			}
 250		}
 251
 252		void ReadGenericParameterConstraints (GenericParameter parameter)
 253		{
 254			var constraints = parameter.Constraints;
 255
 256			for (int i = 0; i < constraints.Count; i++)
 257				ReadCustomAttributes (constraints [i]);
 258		}
 259
 260		void ReadSecurityDeclarations (ISecurityDeclarationProvider provider)
 261		{
 262			if (!provider.HasSecurityDeclarations)
 263				return;
 264
 265			var security_declarations = provider.SecurityDeclarations;
 266
 267			if (!resolve_attributes)
 268				return;
 269
 270			for (int i = 0; i < security_declarations.Count; i++) {
 271				var security_declaration = security_declarations [i];
 272
 273				Mixin.Read (security_declaration.SecurityAttributes);
 274			}
 275		}
 276
 277		void ReadCustomAttributes (ICustomAttributeProvider provider)
 278		{
 279			if (!provider.HasCustomAttributes)
 280				return;
 281
 282			var custom_attributes = provider.CustomAttributes;
 283
 284			if (!resolve_attributes)
 285				return;
 286
 287			for (int i = 0; i < custom_attributes.Count; i++) {
 288				var custom_attribute = custom_attributes [i];
 289
 290				Mixin.Read (custom_attribute.ConstructorArguments);
 291			}
 292		}
 293
 294		void ReadFields (TypeDefinition type)
 295		{
 296			var fields = type.Fields;
 297
 298			for (int i = 0; i < fields.Count; i++) {
 299				var field = fields [i];
 300
 301				if (field.HasConstant)
 302					Mixin.Read (field.Constant);
 303
 304				if (field.HasLayoutInfo)
 305					Mixin.Read (field.Offset);
 306
 307				if (field.RVA > 0)
 308					Mixin.Read (field.InitialValue);
 309
 310				if (field.HasMarshalInfo)
 311					Mixin.Read (field.MarshalInfo);
 312
 313				ReadCustomAttributes (field);
 314			}
 315		}
 316
 317		void ReadMethods (TypeDefinition type)
 318		{
 319			var methods = type.Methods;
 320
 321			for (int i = 0; i < methods.Count; i++) {
 322				var method = methods [i];
 323
 324				ReadGenericParameters (method);
 325
 326				if (method.HasParameters)
 327					ReadParameters (method);
 328
 329				if (method.HasOverrides)
 330					Mixin.Read (method.Overrides);
 331
 332				if (method.IsPInvokeImpl)
 333					Mixin.Read (method.PInvokeInfo);
 334
 335				ReadSecurityDeclarations (method);
 336				ReadCustomAttributes (method);
 337
 338				var return_type = method.MethodReturnType;
 339				if (return_type.HasConstant)
 340					Mixin.Read (return_type.Constant);
 341
 342				if (return_type.HasMarshalInfo)
 343					Mixin.Read (return_type.MarshalInfo);
 344
 345				ReadCustomAttributes (return_type);
 346			}
 347		}
 348
 349		void ReadParameters (MethodDefinition method)
 350		{
 351			var parameters = method.Parameters;
 352
 353			for (int i = 0; i < parameters.Count; i++) {
 354				var parameter = parameters [i];
 355
 356				if (parameter.HasConstant)
 357					Mixin.Read (parameter.Constant);
 358
 359				if (parameter.HasMarshalInfo)
 360					Mixin.Read (parameter.MarshalInfo);
 361
 362				ReadCustomAttributes (parameter);
 363			}
 364		}
 365
 366		void ReadProperties (TypeDefinition type)
 367		{
 368			var properties = type.Properties;
 369
 370			for (int i = 0; i < properties.Count; i++) {
 371				var property = properties [i];
 372
 373				Mixin.Read (property.GetMethod);
 374
 375				if (property.HasConstant)
 376					Mixin.Read (property.Constant);
 377
 378				ReadCustomAttributes (property);
 379			}
 380		}
 381
 382		void ReadEvents (TypeDefinition type)
 383		{
 384			var events = type.Events;
 385
 386			for (int i = 0; i < events.Count; i++) {
 387				var @event = events [i];
 388
 389				Mixin.Read (@event.AddMethod);
 390
 391				ReadCustomAttributes (@event);
 392			}
 393		}
 394
 395		public override void ReadSymbols (ModuleDefinition module)
 396		{
 397			if (module.symbol_reader == null)
 398				return;
 399
 400			ReadTypesSymbols (module.Types, module.symbol_reader);
 401		}
 402
 403		void ReadTypesSymbols (Collection<TypeDefinition> types, ISymbolReader symbol_reader)
 404		{
 405			for (int i = 0; i < types.Count; i++) {
 406				var type = types [i];
 407
 408				if (type.HasNestedTypes)
 409					ReadTypesSymbols (type.NestedTypes, symbol_reader);
 410
 411				if (type.HasMethods)
 412					ReadMethodsSymbols (type, symbol_reader);
 413			}
 414		}
 415
 416		void ReadMethodsSymbols (TypeDefinition type, ISymbolReader symbol_reader)
 417		{
 418			var methods = type.Methods;
 419			for (int i = 0; i < methods.Count; i++) {
 420				var method = methods [i];
 421
 422				if (method.HasBody && method.token.RID != 0 && method.debug_info == null)
 423					method.debug_info = symbol_reader.Read (method);
 424			}
 425		}
 426	}
 427
 428	sealed class DeferredModuleReader : ModuleReader {
 429
 430		public DeferredModuleReader (Image image)
 431			: base (image, ReadingMode.Deferred)
 432		{
 433		}
 434
 435		protected override void ReadModule ()
 436		{
 437			this.module.Read (this.module, (_, reader) => ReadModuleManifest (reader));
 438		}
 439
 440		public override void ReadSymbols (ModuleDefinition module)
 441		{
 442		}
 443	}
 444
 445	sealed class MetadataReader : ByteBuffer {
 446
 447		readonly internal Image image;
 448		readonly internal ModuleDefinition module;
 449		readonly internal MetadataSystem metadata;
 450
 451		internal CodeReader code;
 452		internal IGenericContext context;
 453
 454		readonly MetadataReader metadata_reader;
 455
 456		public MetadataReader (ModuleDefinition module)
 457			: base (module.Image.TableHeap.data)
 458		{
 459			this.image = module.Image;
 460			this.module = module;
 461			this.metadata = module.MetadataSystem;
 462			this.code = new CodeReader (this);
 463		}
 464
 465		public MetadataReader (Image image, ModuleDefinition module, MetadataReader metadata_reader)
 466			: base (image.TableHeap.data)
 467		{
 468			this.image = image;
 469			this.module = module;
 470			this.metadata = module.MetadataSystem;
 471			this.metadata_reader = metadata_reader;
 472		}
 473
 474		int GetCodedIndexSize (CodedIndex index)
 475		{
 476			return image.GetCodedIndexSize (index);
 477		}
 478
 479		uint ReadByIndexSize (int size)
 480		{
 481			if (size == 4)
 482				return ReadUInt32 ();
 483			else
 484				return ReadUInt16 ();
 485		}
 486
 487		byte [] ReadBlob ()
 488		{
 489			var blob_heap = image.BlobHeap;
 490			if (blob_heap == null) {
 491				position += 2;
 492				return Empty<byte>.Array;
 493			}
 494
 495			return blob_heap.Read (ReadBlobIndex ());
 496		}
 497
 498		byte [] ReadBlob (uint signature)
 499		{
 500			var blob_heap = image.BlobHeap;
 501			if (blob_heap == null)
 502				return Empty<byte>.Array;
 503
 504			return blob_heap.Read (signature);
 505		}
 506
 507		uint ReadBlobIndex ()
 508		{
 509			var blob_heap = image.BlobHeap;
 510			return ReadByIndexSize (blob_heap != null ? blob_heap.IndexSize : 2);
 511		}
 512
 513		void GetBlobView (uint signature, out byte [] blob, out int index, out int count)
 514		{
 515			var blob_heap = image.BlobHeap;
 516			if (blob_heap == null) {
 517				blob = null;
 518				index = count = 0;
 519				return;
 520			}
 521
 522			blob_heap.GetView (signature, out blob, out index, out count);
 523		}
 524
 525		string ReadString ()
 526		{
 527			return image.StringHeap.Read (ReadByIndexSize (image.StringHeap.IndexSize));
 528		}
 529
 530		uint ReadStringIndex ()
 531		{
 532			return ReadByIndexSize (image.StringHeap.IndexSize);
 533		}
 534
 535		Guid ReadGuid ()
 536		{
 537			return image.GuidHeap.Read (ReadByIndexSize (image.GuidHeap.IndexSize));
 538		}
 539
 540		uint ReadTableIndex (Table table)
 541		{
 542			return ReadByIndexSize (image.GetTableIndexSize (table));
 543		}
 544
 545		MetadataToken ReadMetadataToken (CodedIndex index)
 546		{
 547			return index.GetMetadataToken (ReadByIndexSize (GetCodedIndexSize (index)));
 548		}
 549
 550		int MoveTo (Table table)
 551		{
 552			var info = image.TableHeap [table];
 553			if (info.Length != 0)
 554				this.position = (int) info.Offset;
 555
 556			return (int) info.Length;
 557		}
 558
 559		bool MoveTo (Table table, uint row)
 560		{
 561			var info = image.TableHeap [table];
 562			var length = info.Length;
 563			if (length == 0 || row > length)
 564				return false;
 565
 566			this.position = (int) (info.Offset + (info.RowSize * (row - 1)));
 567			return true;
 568		}
 569
 570		public AssemblyNameDefinition ReadAssemblyNameDefinition ()
 571		{
 572			if (MoveTo (Table.Assembly) == 0)
 573				return null;
 574
 575			var name = new AssemblyNameDefinition ();
 576
 577			name.HashAlgorithm = (AssemblyHashAlgorithm) ReadUInt32 ();
 578
 579			PopulateVersionAndFlags (name);
 580
 581			name.PublicKey = ReadBlob ();
 582
 583			PopulateNameAndCulture (name);
 584
 585			return name;
 586		}
 587
 588		public ModuleDefinition Populate (ModuleDefinition module)
 589		{
 590			if (MoveTo (Table.Module) == 0)
 591				return module;
 592
 593			Advance (2); // Generation
 594
 595			module.Name = ReadString ();
 596			module.Mvid = ReadGuid ();
 597
 598			return module;
 599		}
 600
 601		void InitializeAssemblyReferences ()
 602		{
 603			if (metadata.AssemblyReferences != null)
 604				return;
 605
 606			int length = MoveTo (Table.AssemblyRef);
 607			var references = metadata.AssemblyReferences = new AssemblyNameReference [length];
 608
 609			for (uint i = 0; i < length; i++) {
 610				var reference = new AssemblyNameReference ();
 611				reference.token = new MetadataToken (TokenType.AssemblyRef, i + 1);
 612
 613				PopulateVersionAndFlags (reference);
 614
 615				var key_or_token = ReadBlob ();
 616
 617				if (reference.HasPublicKey)
 618					reference.PublicKey = key_or_token;
 619				else
 620					reference.PublicKeyToken = key_or_token;
 621
 622				PopulateNameAndCulture (reference);
 623
 624				reference.Hash = ReadBlob ();
 625
 626				references [i] = reference;
 627			}
 628		}
 629
 630		public Collection<AssemblyNameReference> ReadAssemblyReferences ()
 631		{
 632			InitializeAssemblyReferences ();
 633
 634			var references = new Collection<AssemblyNameReference> (metadata.AssemblyReferences);
 635			if (module.IsWindowsMetadata ())
 636				module.Projections.AddVirtualReferences (references);
 637
 638			return references;
 639		}
 640
 641		public MethodDefinition ReadEntryPoint ()
 642		{
 643			if (module.Image.EntryPointToken == 0)
 644				return null;
 645
 646			var token = new MetadataToken (module.Image.EntryPointToken);
 647			return GetMethodDefinition (token.RID);
 648		}
 649
 650		public Collection<ModuleDefinition> ReadModules ()
 651		{
 652			var modules = new Collection<ModuleDefinition> (1);
 653			modules.Add (this.module);
 654
 655			int length = MoveTo (Table.File);
 656			for (uint i = 1; i <= length; i++) {
 657				var attributes = (FileAttributes) ReadUInt32 ();
 658				var name = ReadString ();
 659				ReadBlobIndex ();
 660
 661				if (attributes != FileAttributes.ContainsMetaData)
 662					continue;
 663
 664				var parameters = new ReaderParameters {
 665					ReadingMode = module.ReadingMode,
 666					SymbolReaderProvider = module.SymbolReaderProvider,
 667					AssemblyResolver = module.AssemblyResolver
 668				};
 669
 670				modules.Add (ModuleDefinition.ReadModule (
 671					GetModuleFileName (name), parameters));
 672			}
 673
 674			return modules;
 675		}
 676
 677		string GetModuleFileName (string name)
 678		{
 679			if (module.FileName == null)
 680				throw new NotSupportedException ();
 681
 682			var path = Path.GetDirectoryName (module.FileName);
 683			return Path.Combine (path, name);
 684		}
 685
 686		void InitializeModuleReferences ()
 687		{
 688			if (metadata.ModuleReferences != null)
 689				return;
 690
 691			int length = MoveTo (Table.ModuleRef);
 692			var references = metadata.ModuleReferences = new ModuleReference [length];
 693
 694			for (uint i = 0; i < length; i++) {
 695				var reference = new ModuleReference (ReadString ());
 696				reference.token = new MetadataToken (TokenType.ModuleRef, i + 1);
 697
 698				references [i] = reference;
 699			}
 700		}
 701
 702		public Collection<ModuleReference> ReadModuleReferences ()
 703		{
 704			InitializeModuleReferences ();
 705
 706			return new Collection<ModuleReference> (metadata.ModuleReferences);
 707		}
 708
 709		public bool HasFileResource ()
 710		{
 711			int length = MoveTo (Table.File);
 712			if (length == 0)
 713				return false;
 714
 715			for (uint i = 1; i <= length; i++)
 716				if (ReadFileRecord (i).Col1 == FileAttributes.ContainsNoMetaData)
 717					return true;
 718
 719			return false;
 720		}
 721
 722		public Collection<Resource> ReadResources ()
 723		{
 724			int length = MoveTo (Table.ManifestResource);
 725			var resources = new Collection<Resource> (length);
 726
 727			for (int i = 1; i <= length; i++) {
 728				var offset = ReadUInt32 ();
 729				var flags = (ManifestResourceAttributes) ReadUInt32 ();
 730				var name = ReadString ();
 731				var implementation = ReadMetadataToken (CodedIndex.Implementation);
 732
 733				Resource resource;
 734
 735				if (implementation.RID == 0) {
 736					resource = new EmbeddedResource (name, flags, offset, this);
 737				} else if (implementation.TokenType == TokenType.AssemblyRef) {
 738					resource = new AssemblyLinkedResource (name, flags) {
 739						Assembly = (AssemblyNameReference) GetTypeReferenceScope (implementation),
 740					};
 741				} else if (implementation.TokenType == TokenType.File) {
 742					var file_record = ReadFileRecord (implementation.RID);
 743
 744					resource = new LinkedResource (name, flags) {
 745						File = file_record.Col2,
 746						hash = ReadBlob (file_record.Col3)
 747					};
 748				} else
 749					continue;
 750
 751				resources.Add (resource);
 752			}
 753
 754			return resources;
 755		}
 756
 757		Row<FileAttributes, string, uint> ReadFileRecord (uint rid)
 758		{
 759			var position = this.position;
 760
 761			if (!MoveTo (Table.File, rid))
 762				throw new ArgumentException ();
 763
 764			var record = new Row<FileAttributes, string, uint> (
 765				(FileAttributes) ReadUInt32 (),
 766				ReadString (),
 767				ReadBlobIndex ());
 768
 769			this.position = position;
 770
 771			return record;
 772		}
 773
 774		public byte [] GetManagedResource (uint offset)
 775		{
 776			return image.GetReaderAt (image.Resources.VirtualAddress, offset, (o, reader) => {
 777				reader.Advance ((int) o);
 778				return reader.ReadBytes (reader.ReadInt32 ());
 779			}) ?? Empty<byte>.Array;
 780		}
 781
 782		void PopulateVersionAndFlags (AssemblyNameReference name)
 783		{
 784			name.Version = new Version (
 785				ReadUInt16 (),
 786				ReadUInt16 (),
 787				ReadUInt16 (),
 788				ReadUInt16 ());
 789
 790			name.Attributes = (AssemblyAttributes) ReadUInt32 ();
 791		}
 792
 793		void PopulateNameAndCulture (AssemblyNameReference name)
 794		{
 795			name.Name = ReadString ();
 796			name.Culture = ReadString ();
 797		}
 798
 799		public TypeDefinitionCollection ReadTypes ()
 800		{
 801			InitializeTypeDefinitions ();
 802			var mtypes = metadata.Types;
 803			var type_count = mtypes.Length - metadata.NestedTypes.Count;
 804			var types = new TypeDefinitionCollection (module, type_count);
 805
 806			for (int i = 0; i < mtypes.Length; i++) {
 807				var type = mtypes [i];
 808				if (IsNested (type.Attributes))
 809					continue;
 810
 811				types.Add (type);
 812			}
 813
 814			if (image.HasTable (Table.MethodPtr) || image.HasTable (Table.FieldPtr))
 815				CompleteTypes ();
 816
 817			return types;
 818		}
 819
 820		void CompleteTypes ()
 821		{
 822			var types = metadata.Types;
 823
 824			for (int i = 0; i < types.Length; i++) {
 825				var type = types [i];
 826
 827				Mixin.Read (type.Fields);
 828				Mixin.Read (type.Methods);
 829			}
 830		}
 831
 832		void InitializeTypeDefinitions ()
 833		{
 834			if (metadata.Types != null)
 835				return;
 836
 837			InitializeNestedTypes ();
 838			InitializeFields ();
 839			InitializeMethods ();
 840
 841			int length = MoveTo (Table.TypeDef);
 842			var types = metadata.Types = new TypeDefinition [length];
 843
 844			for (uint i = 0; i < length; i++) {
 845				if (types [i] != null)
 846					continue;
 847
 848				types [i] = ReadType (i + 1);
 849			}
 850
 851			if (module.IsWindowsMetadata ()) {
 852				for (uint i = 0; i < length; i++) {
 853					WindowsRuntimeProjections.Project (types [i]);
 854				}
 855			}
 856		}
 857
 858		static bool IsNested (TypeAttributes attributes)
 859		{
 860			switch (attributes & TypeAttributes.VisibilityMask) {
 861			case TypeAttributes.NestedAssembly:
 862			case TypeAttributes.NestedFamANDAssem:
 863			case TypeAttributes.NestedFamily:
 864			case TypeAttributes.NestedFamORAssem:
 865			case TypeAttributes.NestedPrivate:
 866			case TypeAttributes.NestedPublic:
 867				return true;
 868			default:
 869				return false;
 870			}
 871		}
 872
 873		public bool HasNestedTypes (TypeDefinition type)
 874		{
 875			Collection<uint> mapping;
 876			InitializeNestedTypes ();
 877
 878			if (!metadata.TryGetNestedTypeMapping (type, out mapping))
 879				return false;
 880
 881			return mapping.Count > 0;
 882		}
 883
 884		public Collection<TypeDefinition> ReadNestedTypes (TypeDefinition type)
 885		{
 886			InitializeNestedTypes ();
 887			Collection<uint> mapping;
 888			if (!metadata.TryGetNestedTypeMapping (type, out mapping))
 889				return new MemberDefinitionCollection<TypeDefinition> (type);
 890
 891			var nested_types = new MemberDefinitionCollection<TypeDefinition> (type, mapping.Count);
 892
 893			for (int i = 0; i < mapping.Count; i++) {
 894				var nested_type = GetTypeDefinition (mapping [i]);
 895
 896				if (nested_type != null)
 897					nested_types.Add (nested_type);
 898			}
 899
 900			metadata.RemoveNestedTypeMapping (type);
 901
 902			return nested_types;
 903		}
 904
 905		void InitializeNestedTypes ()
 906		{
 907			if (metadata.NestedTypes != null)
 908				return;
 909
 910			var length = MoveTo (Table.NestedClass);
 911
 912			metadata.NestedTypes = new Dictionary<uint, Collection<uint>> (length);
 913			metadata.ReverseNestedTypes = new Dictionary<uint, uint> (length);
 914
 915			if (length == 0)
 916				return;
 917
 918			for (int i = 1; i <= length; i++) {
 919				var nested = ReadTableIndex (Table.TypeDef);
 920				var declaring = ReadTableIndex (Table.TypeDef);
 921
 922				AddNestedMapping (declaring, nested);
 923			}
 924		}
 925
 926		void AddNestedMapping (uint declaring, uint nested)
 927		{
 928			metadata.SetNestedTypeMapping (declaring, AddMapping (metadata.NestedTypes, declaring, nested));
 929			metadata.SetReverseNestedTypeMapping (nested, declaring);
 930		}
 931
 932		static Collection<TValue> AddMapping<TKey, TValue> (Dictionary<TKey, Collection<TValue>> cache, TKey key, TValue value)
 933		{
 934			Collection<TValue> mapped;
 935			if (!cache.TryGetValue (key, out mapped)) {
 936				mapped = new Collection<TValue> ();
 937			}
 938			mapped.Add (value);
 939			return mapped;
 940		}
 941
 942		TypeDefinition ReadType (uint rid)
 943		{
 944			if (!MoveTo (Table.TypeDef, rid))
 945				return null;
 946
 947			var attributes = (TypeAttributes) ReadUInt32 ();
 948			var name = ReadString ();
 949			var @namespace = ReadString ();
 950			var type = new TypeDefinition (@namespace, name, attributes);
 951			type.token = new MetadataToken (TokenType.TypeDef, rid);
 952			type.scope = module;
 953			type.module = module;
 954
 955			metadata.AddTypeDefinition (type);
 956
 957			this.context = type;
 958
 959			type.BaseType = GetTypeDefOrRef (ReadMetadataToken (CodedIndex.TypeDefOrRef));
 960
 961			type.fields_range = ReadListRange (rid, Table.TypeDef, Table.Field);
 962			type.methods_range = ReadListRange (rid, Table.TypeDef, Table.Method);
 963
 964			if (IsNested (attributes))
 965				type.DeclaringType = GetNestedTypeDeclaringType (type);
 966
 967			return type;
 968		}
 969
 970		TypeDefinition GetNestedTypeDeclaringType (TypeDefinition type)
 971		{
 972			uint declaring_rid;
 973			if (!metadata.TryGetReverseNestedTypeMapping (type, out declaring_rid))
 974				return null;
 975
 976			metadata.RemoveReverseNestedTypeMapping (type);
 977			return GetTypeDefinition (declaring_rid);
 978		}
 979
 980		Range ReadListRange (uint current_index, Table current, Table target)
 981		{
 982			var list = new Range ();
 983
 984			var start = ReadTableIndex (target);
 985			if (start == 0)
 986				return list;
 987
 988			uint next_index;
 989			var current_table = image.TableHeap [current];
 990
 991			if (current_index == current_table.Length)
 992				next_index = image.TableHeap [target].Length + 1;
 993			else {
 994				var position = this.position;
 995				this.position += (int) (current_table.RowSize - image.GetTableIndexSize (target));
 996				next_index = ReadTableIndex (target);
 997				this.position = position;
 998			}
 999
1000			list.Start = start;
1001			list.Length = next_index - start;
1002
1003			return list;
1004		}
1005
1006		public Row<short, int> ReadTypeLayout (TypeDefinition type)
1007		{
1008			InitializeTypeLayouts ();
1009			Row<ushort, uint> class_layout;
1010			var rid = type.token.RID;
1011			if (!metadata.ClassLayouts.TryGetValue (rid, out class_layout))
1012				return new Row<short, int> (Mixin.NoDataMarker, Mixin.NoDataMarker);
1013
1014			type.PackingSize = (short) class_layout.Col1;
1015			type.ClassSize = (int) class_layout.Col2;
1016
1017			metadata.ClassLayouts.Remove (rid);
1018
1019			return new Row<short, int> ((short) class_layout.Col1, (int) class_layout.Col2);
1020		}
1021
1022		void InitializeTypeLayouts ()
1023		{
1024			if (metadata.ClassLayouts != null)
1025				return;
1026
1027			int length = MoveTo (Table.ClassLayout);
1028
1029			var class_layouts = metadata.ClassLayouts = new Dictionary<uint, Row<ushort, uint>> (length);
1030
1031			for (uint i = 0; i < length; i++) {
1032				var packing_size = ReadUInt16 ();
1033				var class_size = ReadUInt32 ();
1034
1035				var parent = ReadTableIndex (Table.TypeDef);
1036
1037				class_layouts.Add (parent, new Row<ushort, uint> (packing_size, class_size));
1038			}
1039		}
1040
1041		public TypeReference GetTypeDefOrRef (MetadataToken token)
1042		{
1043			return (TypeReference) LookupToken (token);
1044		}
1045
1046		public TypeDefinition GetTypeDefinition (uint rid)
1047		{
1048			InitializeTypeDefinitions ();
1049
1050			var type = metadata.GetTypeDefinition (rid);
1051			if (type != null)
1052				return type;
1053
1054			type = ReadTypeDefinition (rid);
1055
1056			if (module.IsWindowsMetadata ())
1057				WindowsRuntimeProjections.Project (type);
1058
1059			return type;
1060		}
1061
1062		TypeDefinition ReadTypeDefinition (uint rid)
1063		{
1064			if (!MoveTo (Table.TypeDef, rid))
1065				return null;
1066
1067			return ReadType (rid);
1068		}
1069
1070		void InitializeTypeReferences ()
1071		{
1072			if (metadata.TypeReferences != null)
1073				return;
1074
1075			metadata.TypeReferences = new TypeReference [image.GetTableLength (Table.TypeRef)];
1076		}
1077
1078		public TypeReference GetTypeReference (string scope, string full_name)
1079		{
1080			InitializeTypeReferences ();
1081
1082			var length = metadata.TypeReferences.Length;
1083
1084			for (uint i = 1; i <= length; i++) {
1085				var type = GetTypeReference (i);
1086
1087				if (type.FullName != full_name)
1088					continue;
1089
1090				if (string.IsNullOrEmpty (scope))
1091					return type;
1092
1093				if (type.Scope.Name == scope)
1094					return type;
1095			}
1096
1097			return null;
1098		}
1099
1100		TypeReference GetTypeReference (uint rid)
1101		{
1102			InitializeTypeReferences ();
1103
1104			var type = metadata.GetTypeReference (rid);
1105			if (type != null)
1106				return type;
1107
1108			return ReadTypeReference (rid);
1109		}
1110
1111		TypeReference ReadTypeReference (uint rid)
1112		{
1113			if (!MoveTo (Table.TypeRef, rid))
1114				return null;
1115
1116			TypeReference declaring_type = null;
1117			IMetadataScope scope;
1118
1119			var scope_token = ReadMetadataToken (CodedIndex.ResolutionScope);
1120
1121			var name = ReadString ();
1122			var @namespace = ReadString ();
1123
1124			var type = new TypeReference (
1125				@namespace,
1126				name,
1127				module,
1128				null);
1129
1130			type.token = new MetadataToken (TokenType.TypeRef, rid);
1131
1132			metadata.AddTypeReference (type);
1133
1134			if (scope_token.TokenType == TokenType.TypeRef) {
1135				if (scope_token.RID != rid) {
1136					declaring_type = GetTypeDefOrRef (scope_token);
1137
1138					scope = declaring_type != null
1139						? declaring_type.Scope
1140						: module;
1141				} else // obfuscated typeref row pointing to self
1142					scope = module;
1143			} else
1144				scope = GetTypeReferenceScope (scope_token);
1145
1146			type.scope = scope;
1147			type.DeclaringType = declaring_type;
1148
1149			MetadataSystem.TryProcessPrimitiveTypeReference (type);
1150
1151			if (type.Module.IsWindowsMetadata ())
1152				WindowsRuntimeProjections.Project (type);
1153
1154			return type;
1155		}
1156
1157		IMetadataScope GetTypeReferenceScope (MetadataToken scope)
1158		{
1159			if (scope.TokenType == TokenType.Module)
1160				return module;
1161
1162			IMetadataScope[] scopes;
1163
1164			switch (scope.TokenType) {
1165			case TokenType.AssemblyRef:
1166				InitializeAssemblyReferences ();
1167				scopes = metadata.AssemblyReferences;
1168				break;
1169			case TokenType.ModuleRef:
1170				InitializeModuleReferences ();
1171				scopes = metadata.ModuleReferences;
1172				break;
1173			default:
1174				throw new NotSupportedException ();
1175			}
1176
1177			var index = scope.RID - 1;
1178			if (index < 0 || index >= scopes.Length)
1179				return null;
1180
1181			return scopes [index];
1182		}
1183
1184		public IEnumerable<TypeReference> GetTypeReferences ()
1185		{
1186			InitializeTypeReferences ();
1187
1188			var length = image.GetTableLength (Table.TypeRef);
1189
1190			var type_references = new TypeReference [length];
1191
1192			for (uint i = 1; i <= length; i++)
1193				type_references [i - 1] = GetTypeReference (i);
1194
1195			return type_references;
1196		}
1197
1198		TypeReference GetTypeSpecification (uint rid)
1199		{
1200			if (!MoveTo (Table.TypeSpec, rid))
1201				return null;
1202
1203			var reader = ReadSignature (ReadBlobIndex ());
1204			var type = reader.ReadTypeSignature ();
1205			if (type.token.RID == 0)
1206				type.token = new MetadataToken (TokenType.TypeSpec, rid);
1207
1208			return type;
1209		}
1210
1211		SignatureReader ReadSignature (uint signature)
1212		{
1213			return new SignatureReader (signature, this);
1214		}
1215
1216		public bool HasInterfaces (TypeDefinition type)
1217		{
1218			InitializeInterfaces ();
1219			Collection<Row<uint, MetadataToken>> mapping;
1220
1221			return metadata.TryGetInterfaceMapping (type, out mapping);
1222		}
1223
1224		public InterfaceImplementationCollection ReadInterfaces (TypeDefinition type)
1225		{
1226			InitializeInterfaces ();
1227			Collection<Row<uint, MetadataToken>> mapping;
1228
1229			if (!metadata.TryGetInterfaceMapping (type, out mapping))
1230				return new InterfaceImplementationCollection (type);
1231
1232			var interfaces = new InterfaceImplementationCollection (type, mapping.Count);
1233
1234			this.context = type;
1235
1236			for (int i = 0; i < mapping.Count; i++) {
1237				interfaces.Add (
1238					new InterfaceImplementation (
1239						GetTypeDefOrRef (mapping [i].Col2),
1240						new MetadataToken(TokenType.InterfaceImpl, mapping [i].Col1)));
1241			}
1242
1243			metadata.RemoveInterfaceMapping (type);
1244
1245			return interfaces;
1246		}
1247
1248		void InitializeInterfaces ()
1249		{
1250			if (metadata.Interfaces != null)
1251				return;
1252
1253			int length = MoveTo (Table.InterfaceImpl);
1254
1255			metadata.Interfaces = new Dictionary<uint, Collection<Row<uint, MetadataToken>>> (length);
1256
1257			for (uint i = 1; i <= length; i++) {
1258				var type = ReadTableIndex (Table.TypeDef);
1259				var @interface = ReadMetadataToken (CodedIndex.TypeDefOrRef);
1260
1261				AddInterfaceMapping (type, new Row<uint, MetadataToken> (i, @interface));
1262			}
1263		}
1264
1265		void AddInterfaceMapping (uint type, Row<uint, MetadataToken> @interface)
1266		{
1267			metadata.SetInterfaceMapping (type, AddMapping (metadata.Interfaces, type, @interface));
1268		}
1269
1270		public Collection<FieldDefinition> ReadFields (TypeDefinition type)
1271		{
1272			var fields_range = type.fields_range;
1273			if (fields_range.Length == 0)
1274				return new MemberDefinitionCollection<FieldDefinition> (type);
1275
1276			var fields = new MemberDefinitionCollection<FieldDefinition> (type, (int) fields_range.Length);
1277			this.context = type;
1278
1279			if (!MoveTo (Table.FieldPtr, fields_range.Start)) {
1280				if (!MoveTo (Table.Field, fields_range.Start))
1281					return fields;
1282
1283				for (uint i = 0; i < fields_range.Length; i++)
1284					ReadField (fields_range.Start + i, fields);
1285			} else
1286				ReadPointers (Table.FieldPtr, Table.Field, fields_range, fields, ReadField);
1287
1288			return fields;
1289		}
1290
1291		void ReadField (uint field_rid, Collection<FieldDefinition> fields)
1292		{
1293			var attributes = (FieldAttributes) ReadUInt16 ();
1294			var name = ReadString ();
1295			var signature = ReadBlobIndex ();
1296
1297			var field = new FieldDefinition (name, attributes, ReadFieldType (signature));
1298			field.token = new MetadataToken (TokenType.Field, field_rid);
1299			metadata.AddFieldDefinition (field);
1300
1301			if (IsDeleted (field))
1302				return;
1303
1304			fields.Add (field);
1305
1306			if (module.IsWindowsMetadata ())
1307				WindowsRuntimeProjections.Project (field);
1308		}
1309
1310		void InitializeFields ()
1311		{
1312			if (metadata.Fields != null)
1313				return;
1314
1315			metadata.Fields = new FieldDefinition [image.GetTableLength (Table.Field)];
1316		}
1317
1318		TypeReference ReadFieldType (uint signature)
1319		{
1320			var reader = ReadSignature (signature);
1321
1322			const byte field_sig = 0x6;
1323
1324			if (reader.ReadByte () != field_sig)
1325				throw new NotSupportedException ();
1326
1327			return reader.ReadTypeSignature ();
1328		}
1329
1330		public int ReadFieldRVA (FieldDefinition field)
1331		{
1332			InitializeFieldRVAs ();
1333			var rid = field.token.RID;
1334
1335			RVA rva;
1336			if (!metadata.FieldRVAs.TryGetValue (rid, out rva))
1337				return 0;
1338
1339			var size = GetFieldTypeSize (field.FieldType);
1340
1341			if (size == 0 || rva == 0)
1342				return 0;
1343
1344			metadata.FieldRVAs.Remove (rid);
1345
1346			field.InitialValue = GetFieldInitializeValue (size, rva);
1347
1348			return (int) rva;
1349		}
1350
1351		byte [] GetFieldInitializeValue (int size, RVA rva)
1352		{
1353			return image.GetReaderAt (rva, size, (s, reader) => reader.ReadBytes (s)) ?? Empty<byte>.Array;
1354		}
1355
1356		static int GetFieldTypeSize (TypeReference type)
1357		{
1358			int size = 0;
1359
1360			switch (type.etype) {
1361			case ElementType.Boolean:
1362			case ElementType.U1:
1363			case ElementType.I1:
1364				size = 1;
1365				break;
1366			case ElementType.U2:
1367			case ElementType.I2:
1368			case ElementType.Char:
1369				size = 2;
1370				break;
1371			case ElementType.U4:
1372			case ElementType.I4:
1373			case ElementType.R4:
1374				size = 4;
1375				break;
1376			case ElementType.U8:
1377			case ElementType.I8:
1378			case ElementType.R8:
1379				size = 8;
1380				break;
1381			case ElementType.Ptr:
1382			case ElementType.FnPtr:
1383				size = IntPtr.Size;
1384				break;
1385			case ElementType.CModOpt:
1386			case ElementType.CModReqD:
1387				return GetFieldTypeSize (((IModifierType) type).ElementType);
1388			default:
1389				var field_type = type.Resolve ();
1390				if (field_type != null && field_type.HasLayoutInfo)
1391					size = field_type.ClassSize;
1392
1393				break;
1394			}
1395
1396			return size;
1397		}
1398
1399		void InitializeFieldRVAs ()
1400		{
1401			if (metadata.FieldRVAs != null)
1402				return;
1403
1404			int length = MoveTo (Table.FieldRVA);
1405
1406			var field_rvas = metadata.FieldRVAs = new Dictionary<uint, uint> (length);
1407
1408			for (int i = 0; i < length; i++) {
1409				var rva = ReadUInt32 ();
1410				var field = ReadTableIndex (Table.Field);
1411
1412				field_rvas.Add (field, rva);
1413			}
1414		}
1415
1416		public int ReadFieldLayout (FieldDefinition field)
1417		{
1418			InitializeFieldLayouts ();
1419			var rid = field.token.RID;
1420			uint offset;
1421			if (!metadata.FieldLayouts.TryGetValue (rid, out offset))
1422				return Mixin.NoDataMarker;
1423
1424			metadata.FieldLayouts.Remove (rid);
1425
1426			return (int) offset;
1427		}
1428
1429		void InitializeFieldLayouts ()
1430		{
1431			if (metadata.FieldLayouts != null)
1432				return;
1433
1434			int length = MoveTo (Table.FieldLayout);
1435
1436			var field_layouts = metadata.FieldLayouts = new Dictionary<uint, uint> (length);
1437
1438			for (int i = 0; i < length; i++) {
1439				var offset = ReadUInt32 ();
1440				var field = ReadTableIndex (Table.Field);
1441
1442				field_layouts.Add (field, offset);
1443			}
1444		}
1445
1446		public bool HasEvents (TypeDefinition type)
1447		{
1448			InitializeEvents ();
1449
1450			Range range;
1451			if (!metadata.TryGetEventsRange (type, out range))
1452				return false;
1453
1454			return range.Length > 0;
1455		}
1456
1457		public Collection<EventDefinition> ReadEvents (TypeDefinition type)
1458		{
1459			InitializeEvents ();
1460			Range range;
1461
1462			if (!metadata.TryGetEventsRange (type, out range))
1463				return new MemberDefinitionCollection<EventDefinition> (type);
1464
1465			var events = new MemberDefinitionCollection<EventDefinition> (type, (int) range.Length);
1466
1467			metadata.RemoveEventsRange (type);
1468
1469			if (range.Length == 0)
1470				return events;
1471
1472			this.context = type;
1473
1474			if (!MoveTo (Table.EventPtr, range.Start)) {
1475				if (!MoveTo (Table.Event, range.Start))
1476					return events;
1477
1478				for (uint i = 0; i < range.Length; i++)
1479					ReadEvent (range.Start + i, events);
1480			} else
1481				ReadPointers (Table.EventPtr, Table.Event, range, events, ReadEvent);
1482
1483			return events;
1484		}
1485
1486		void ReadEvent (uint event_rid, Collection<EventDefinition> events)
1487		{
1488			var attributes = (EventAttributes) ReadUInt16 ();
1489			var name = ReadString ();
1490			var event_type = GetTypeDefOrRef (ReadMetadataToken (CodedIndex.TypeDefOrRef));
1491
1492			var @event = new EventDefinition (name, attributes, event_type);
1493			@event.token = new MetadataToken (TokenType.Event, event_rid);
1494
1495			if (IsDeleted (@event))
1496				return;
1497
1498			events.Add (@event);
1499		}
1500
1501		void InitializeEvents ()
1502		{
1503			if (metadata.Events != null)
1504				return;
1505
1506			int length = MoveTo (Table.EventMap);
1507
1508			metadata.Events = new Dictionary<uint, Range> (length);
1509
1510			for (uint i = 1; i <= length; i++) {
1511				var type_rid = ReadTableIndex (Table.TypeDef);
1512				Range events_range = ReadListRange (i, Table.EventMap, Table.Event);
1513				metadata.AddEventsRange (type_rid, events_range);
1514			}
1515		}
1516
1517		public bool HasProperties (TypeDefinition type)
1518		{
1519			InitializeProperties ();
1520
1521			Range range;
1522			if (!metadata.TryGetPropertiesRange (type, out range))
1523				return false;
1524
1525			return range.Length > 0;
1526		}
1527
1528		public Collection<PropertyDefinition> ReadProperties (TypeDefinition type)
1529		{
1530			InitializeProperties ();
1531
1532			Range range;
1533
1534			if (!metadata.TryGetPropertiesRange (type, out range))
1535				return new MemberDefinitionCollection<PropertyDefinition> (type);
1536
1537			metadata.RemovePropertiesRange (type);
1538
1539			var properties = new MemberDefinitionCollection<PropertyDefinition> (type, (int) range.Length);
1540
1541			if (range.Length == 0)
1542				return properties;
1543
1544			this.context = type;
1545
1546			if (!MoveTo (Table.PropertyPtr, range.Start)) {
1547				if (!MoveTo (Table.Property, range.Start))
1548					return properties;
1549				for (uint i = 0; i < range.Length; i++)
1550					ReadProperty (range.Start + i, properties);
1551			} else
1552				ReadPointers (Table.PropertyPtr, Table.Property, range, properties, ReadProperty);
1553
1554			return properties;
1555		}
1556
1557		void ReadProperty (uint property_rid, Collection<PropertyDefinition> properties)
1558		{
1559			var attributes = (PropertyAttributes) ReadUInt16 ();
1560			var name = ReadString ();
1561			var signature = ReadBlobIndex ();
1562
1563			var reader = ReadSignature (signature);
1564			const byte property_signature = 0x8;
1565
1566			var calling_convention = reader.ReadByte ();
1567
1568			if ((calling_convention & property_signature) == 0)
1569				throw new NotSupportedException ();
1570
1571			var has_this = (calling_convention & 0x20) != 0;
1572
1573			reader.ReadCompressedUInt32 (); // count
1574
1575			var property = new PropertyDefinition (name, attributes, reader.ReadTypeSignature ());
1576			property.HasThis = has_this;
1577			property.token = new MetadataToken (TokenType.Property, property_rid);
1578
1579			if (IsDeleted (property))
1580				return;
1581
1582			properties.Add (property);
1583		}
1584
1585		void InitializeProperties ()
1586		{
1587			if (metadata.Properties != null)
1588				return;
1589
1590			int length = MoveTo (Table.PropertyMap);
1591
1592			metadata.Properties = new Dictionary<uint, Range> (length);
1593
1594			for (uint i = 1; i <= length; i++) {
1595				var type_rid = ReadTableIndex (Table.TypeDef);
1596				var properties_range = ReadListRange (i, Table.PropertyMap, Table.Property);
1597				metadata.AddPropertiesRange (type_rid, properties_range);
1598			}
1599		}
1600
1601		MethodSemanticsAttributes ReadMethodSemantics (MethodDefinition method)
1602		{
1603			InitializeMethodSemantics ();
1604			Row<MethodSemanticsAttributes, MetadataToken> row;
1605			if (!metadata.Semantics.TryGetValue (method.token.RID, out row))
1606				return MethodSemanticsAttributes.None;
1607
1608			var type = method.DeclaringType;
1609
1610			switch (row.Col1) {
1611			case MethodSemanticsAttributes.AddOn:
1612				GetEvent (type, row.Col2).add_method = method;
1613				break;
1614			case MethodSemanticsAttributes.Fire:
1615				GetEvent (type, row.Col2).invoke_method = method;
1616				break;
1617			case MethodSemanticsAttributes.RemoveOn:
1618				GetEvent (type, row.Col2).remove_method = method;
1619				break;
1620			case MethodSemanticsAttributes.Getter:
1621				GetProperty (type, row.Col2).get_method = method;
1622				break;
1623			case MethodSemanticsAttributes.Setter:
1624				GetProperty (type, row.Col2).set_method = method;
1625				break;
1626			case MethodSemanticsAttributes.Other:
1627				switch (row.Col2.TokenType) {
1628				case TokenType.Event: {
1629					var @event = GetEvent (type, row.Col2);
1630					if (@event.other_methods == null)
1631						@event.other_methods = new Collection<MethodDefinition> ();
1632
1633					@event.other_methods.Add (method);
1634					break;
1635				}
1636				case TokenType.Property: {
1637					var property = GetProperty (type, row.Col2);
1638					if (property.other_methods == null)
1639						property.other_methods = new Collection<MethodDefinition> ();
1640
1641					property.other_methods.Add (method);
1642
1643					break;
1644				}
1645				default:
1646					throw new NotSupportedException ();
1647				}
1648				break;
1649			default:
1650				throw new NotSupportedException ();
1651			}
1652
1653			metadata.Semantics.Remove (method.token.RID);
1654
1655			return row.Col1;
1656		}
1657
1658		static EventDefinition GetEvent (TypeDefinition type, MetadataToken token)
1659		{
1660			if (token.TokenType != TokenType.Event)
1661				throw new ArgumentException ();
1662
1663			return GetMember (type.Events, token);
1664		}
1665
1666		static PropertyDefinition GetProperty (TypeDefinition type, MetadataToken token)
1667		{
1668			if (token.TokenType != TokenType.Property)
1669				throw new ArgumentException ();
1670
1671			return GetMember (type.Properties, token);
1672		}
1673
1674		static TMember GetMember<TMember> (Collection<TMember> members, MetadataToken token) where TMember : IMemberDefinition
1675		{
1676			for (int i = 0; i < members.Count; i++) {
1677				var member = members [i];
1678				if (member.MetadataToken == token)
1679					return member;
1680			}
1681
1682			throw new ArgumentException ();
1683		}
1684
1685		void InitializeMethodSemantics ()
1686		{
1687			if (metadata.Semantics != null)
1688				return;
1689
1690			int length = MoveTo (Table.MethodSemantics);
1691
1692			var semantics = metadata.Semantics = new Dictionary<uint, Row<MethodSemanticsAttributes, MetadataToken>> (0);
1693
1694			for (uint i = 0; i < length; i++) {
1695				var attributes = (MethodSemanticsAttributes) ReadUInt16 ();
1696				var method_rid = ReadTableIndex (Table.Method);
1697				var association = ReadMetadataToken (CodedIndex.HasSemantics);
1698
1699				semantics [method_rid] = new Row<MethodSemanticsAttributes, MetadataToken> (attributes, association);
1700			}
1701		}
1702
1703		public void ReadMethods (PropertyDefinition property)
1704		{
1705			ReadAllSemantics (property.DeclaringType);
1706		}
1707
1708		public void ReadMethods (EventDefinition @event)
1709		{
1710			ReadAllSemantics (@event.DeclaringType);
1711		}
1712
1713		public void ReadAllSemantics (MethodDefinition method)
1714		{
1715			ReadAllSemantics (method.DeclaringType);
1716		}
1717
1718		void ReadAllSemantics (TypeDefinition type)
1719		{
1720			var methods = type.Methods;
1721			for (int i = 0; i < methods.Count; i++) {
1722				var method = methods [i];
1723				if (method.sem_attrs_ready)
1724					continue;
1725
1726				method.sem_attrs = ReadMethodSemantics (method);
1727				method.sem_attrs_ready = true;
1728			}
1729		}
1730
1731		public Collection<MethodDefinition> ReadMethods (TypeDefinition type)
1732		{
1733			var methods_range = type.methods_range;
1734			if (methods_range.Length == 0)
1735				return new MemberDefinitionCollection<MethodDefinition> (type);
1736
1737			var methods = new MemberDefinitionCollection<MethodDefinition> (type, (int) methods_range.Length);
1738			if (!MoveTo (Table.MethodPtr, methods_range.Start)) {
1739				if (!MoveTo (Table.Method, methods_range.Start))
1740					return methods;
1741
1742				for (uint i = 0; i < methods_range.Length; i++)
1743					ReadMethod (methods_range.Start + i, methods);
1744			} else
1745				ReadPointers (Table.MethodPtr, Table.Method, methods_range, methods, ReadMethod);
1746
1747			return methods;
1748		}
1749
1750		void ReadPointers<TMember> (Table ptr, Table table, Range range, Collection<TMember> members, Action<uint, Collection<TMember>> reader)
1751			where TMember : IMemberDefinition
1752		{
1753			for (uint i = 0; i < range.Length; i++) {
1754				MoveTo (ptr, range.Start + i);
1755
1756				var rid = ReadTableIndex (table);
1757				MoveTo (table, rid);
1758
1759				reader (rid, members);
1760			}
1761		}
1762
1763		static bool IsDeleted (IMemberDefinition member)
1764		{
1765			return member.IsSpecialName && member.Name == "_Deleted";
1766		}
1767
1768		void InitializeMethods ()
1769		{
1770			if (metadata.Methods != null)
1771				return;
1772
1773			metadata.Methods = new MethodDefinition [image.GetTableLength (Table.Method)];
1774		}
1775
1776		void ReadMethod (uint method_rid, Collection<MethodDefinition> methods)
1777		{
1778			var method = new MethodDefinition ();
1779			method.rva = ReadUInt32 ();
1780			method.ImplAttributes = (MethodImplAttributes) ReadUInt16 ();
1781			method.Attributes = (MethodAttributes) ReadUInt16 ();
1782			method.Name = ReadString ();
1783			method.token = new MetadataToken (TokenType.Method, method_rid);
1784
1785			if (IsDeleted (method))
1786				return;
1787
1788			methods.Add (method); // attach method
1789
1790			var signature = ReadBlobIndex ();
1791			var param_range = ReadListRange (method_rid, Table.Method, Table.Param);
1792
1793			this.context = method;
1794
1795			ReadMethodSignature (signature, method);
1796			metadata.AddMethodDefinition (method);
1797
1798			if (param_range.Length != 0) {
1799				var position = base.position;
1800				ReadParameters (method, param_range);
1801				base.position = position;
1802			}
1803
1804			if (module.IsWindowsMetadata ())
1805				WindowsRuntimeProjections.Project (method);
1806		}
1807
1808		void ReadParameters (MethodDefinition method, Range param_range)
1809		{
1810			if (!MoveTo (Table.ParamPtr, param_range.Start)) {
1811				if (!MoveTo (Table.Param, param_range.Start))
1812					return;
1813
1814				for (uint i = 0; i < param_range.Length; i++)
1815					ReadParameter (param_range.Start + i, method);
1816			} else
1817				ReadParameterPointers (method, param_range);
1818		}
1819
1820		void ReadParameterPointers (MethodDefinition method, Range range)
1821		{
1822			for (uint i = 0; i < range.Length; i++) {
1823				MoveTo (Table.ParamPtr, range.Start + i);
1824
1825				var rid = ReadTableIndex (Table.Param);
1826
1827				MoveTo (Table.Param, rid);
1828
1829				ReadParameter (rid, method);
1830			}
1831		}
1832
1833		void ReadParameter (uint param_rid, MethodDefinition method)
1834		{
1835			var attributes = (ParameterAttributes) ReadUInt16 ();
1836			var sequence = ReadUInt16 ();
1837			var name = ReadString ();
1838
1839			var parameter = sequence == 0
1840				? method.MethodReturnType.Parameter
1841				: method.Parameters [sequence - 1];
1842
1843			parameter.token = new MetadataToken (TokenType.Param, param_rid);
1844			parameter.Name = name;
1845			parameter.Attributes = attributes;
1846		}
1847
1848		void ReadMethodSignature (uint signature, IMethodSignature method)
1849		{
1850			var reader = ReadSignature (signature);
1851			reader.ReadMethodSignature (method);
1852		}
1853
1854		public PInvokeInfo ReadPInvokeInfo (MethodDefinition method)
1855		{
1856			InitializePInvokes ();
1857			Row<PInvokeAttributes, uint, uint> row;
1858
1859			var rid = method.token.RID;
1860
1861			if (!metadata.PInvokes.TryGetValue (rid, out row))
1862				return null;
1863
1864			metadata.PInvokes.Remove (rid);
1865
1866			return new PInvokeInfo (
1867				row.Col1,
1868				image.StringHeap.Read (row.Col2),
1869				module.ModuleReferences [(int) row.Col3 - 1]);
1870		}
1871
1872		void InitializePInvokes ()
1873		{
1874			if (metadata.PInvokes != null)
1875				return;
1876
1877			int length = MoveTo (Table.ImplMap);
1878
1879			var pinvokes = metadata.PInvokes = new Dictionary<uint, Row<PInvokeAttributes, uint, uint>> (length);
1880
1881			for (int i = 1; i <= length; i++) {
1882				var attributes = (PInvokeAttributes) ReadUInt16 ();
1883				var method = ReadMetadataToken (CodedIndex.MemberForwarded);
1884				var name = ReadStringIndex ();
1885				var scope = ReadTableIndex (Table.File);
1886
1887				if (method.TokenType != TokenType.Method)
1888					continue;
1889
1890				pinvokes.Add (method.RID, new Row<PInvokeAttributes, uint, uint> (attributes, name, scope));
1891			}
1892		}
1893
1894		public bool HasGenericParameters (IGenericParameterProvider provider)
1895		{
1896			InitializeGenericParameters ();
1897
1898			Range [] ranges;
1899			if (!metadata.TryGetGenericParameterRanges (provider, out ranges))
1900				return false;
1901
1902			return RangesSize (ranges) > 0;
1903		}
1904
1905		public Collection<GenericParameter> ReadGenericParameters (IGenericParameterProvider provider)
1906		{
1907			InitializeGenericParameters ();
1908
1909			Range [] ranges;
1910			if (!metadata.TryGetGenericParameterRanges (provider, out ranges))
1911				return new GenericParameterCollection (provider);
1912
1913			metadata.RemoveGenericParameterRange (provider);
1914
1915			var generic_parameters = new GenericParameterCollection (provider, RangesSize (ranges));
1916
1917			for (int i = 0; i < ranges.Length; i++)
1918				ReadGenericParametersRange (ranges [i], provider, generic_parameters);
1919
1920			return generic_parameters;
1921		}
1922
1923		void ReadGenericParametersRange (Range range, IGenericParameterProvider provider, GenericParameterCollection generic_parameters)
1924		{
1925			if (!MoveTo (Table.GenericParam, range.Start))
1926				return;
1927
1928			for (uint i = 0; i < range.Length; i++) {
1929				ReadUInt16 (); // index
1930				var flags = (GenericParameterAttributes) ReadUInt16 ();
1931				ReadMetadataToken (CodedIndex.TypeOrMethodDef);
1932				var name = ReadString ();
1933
1934				var parameter = new GenericParameter (name, provider);
1935				parameter.token = new MetadataToken (TokenType.GenericParam, range.Start + i);
1936				parameter.Attributes = flags;
1937
1938				generic_parameters.Add (parameter);
1939			}
1940		}
1941
1942		void InitializeGenericParameters ()
1943		{
1944			if (metadata.GenericParameters != null)
1945				return;
1946
1947			metadata.GenericParameters = InitializeRanges (
1948				Table.GenericParam, () => {
1949					Advance (4);
1950					var next = ReadMetadataToken (CodedIndex.TypeOrMethodDef);
1951					ReadStringIndex ();
1952					return next;
1953			});
1954		}
1955
1956		Dictionary<MetadataToken, Range []> InitializeRanges (Table table, Func<MetadataToken> get_next)
1957		{
1958			int length = MoveTo (table);
1959			var ranges = new Dictionary<MetadataToken, Range []> (length);
1960
1961			if (length == 0)
1962				return ranges;
1963
1964			MetadataToken owner = MetadataToken.Zero;
1965			Range range = new Range (1, 0);
1966
1967			for (uint i = 1; i <= length; i++) {
1968				var next = get_next ();
1969
1970				if (i == 1) {
1971					owner = next;
1972					range.Length++;
1973				} else if (next != owner) {
1974					AddRange (ranges, owner, range);
1975					range = new Range (i, 1);
1976					owner = next;
1977				} else
1978					range.Length++;
1979			}
1980
1981			AddRange (ranges, owner, range);
1982
1983			return ranges;
1984		}
1985
1986		static void AddRange (Dictionary<MetadataToken, Range []> ranges, MetadataToken owner, Range range)
1987		{
1988			if (owner.RID == 0)
1989				return;
1990
1991			Range [] slots;
1992			if (!ranges.TryGetValue (owner, out slots)) {
1993				ranges.Add (owner, new [] { range });
1994				return;
1995			}
1996
1997			ranges [owner] = slots.Add(range);
1998		}
1999
2000		public bool HasGenericConstraints (GenericParameter generic_parameter)
2001		{
2002			InitializeGenericConstraints ();
2003
2004			Collection<Row<uint, MetadataToken>> mapping;
2005			if (!metadata.TryGetGenericConstraintMapping (generic_parameter, out mapping))
2006				return false;
2007
2008			return mapping.Count > 0;
2009		}
2010
2011		public GenericParameterConst

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