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 
11 using System;
12 using System.Collections.Generic;
13 using System.IO;
14 using System.IO.Compression;
15 using System.Text;
16 
17 using Mono.Collections.Generic;
18 using Mono.Cecil.Cil;
19 using Mono.Cecil.Metadata;
20 using Mono.Cecil.PE;
21 
22 using RVA = System.UInt32;
23 
24 namespace Mono.Cecil {
25 
26 	abstract class ModuleReader {
27 
28 		readonly protected ModuleDefinition module;
29 
ModuleReader(Image image, ReadingMode mode)30 		protected ModuleReader (Image image, ReadingMode mode)
31 		{
32 			this.module = new ModuleDefinition (image);
33 			this.module.ReadingMode = mode;
34 		}
35 
ReadModule()36 		protected abstract void ReadModule ();
ReadSymbols(ModuleDefinition module)37 		public abstract void ReadSymbols (ModuleDefinition module);
38 
ReadModuleManifest(MetadataReader reader)39 		protected void ReadModuleManifest (MetadataReader reader)
40 		{
41 			reader.Populate (module);
42 
43 			ReadAssembly (reader);
44 		}
45 
ReadAssembly(MetadataReader reader)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 
CreateModule(Image image, ReaderParameters parameters)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 !READ_ONLY
73 			if (parameters.metadata_importer_provider != null)
74 				module.metadata_importer = parameters.metadata_importer_provider.GetMetadataImporter (module);
75 			if (parameters.reflection_importer_provider != null)
76 				module.reflection_importer = parameters.reflection_importer_provider.GetReflectionImporter (module);
77 #endif
78 
79 			GetMetadataKind (module, parameters);
80 
81 			reader.ReadModule ();
82 
83 			ReadSymbols (module, parameters);
84 
85 			reader.ReadSymbols (module);
86 
87 			if (parameters.ReadingMode == ReadingMode.Immediate)
88 				module.MetadataSystem.Clear ();
89 
90 			return module;
91 		}
92 
ReadSymbols(ModuleDefinition module, ReaderParameters parameters)93 		static void ReadSymbols (ModuleDefinition module, ReaderParameters parameters)
94 		{
95 			var symbol_reader_provider = parameters.SymbolReaderProvider;
96 
97 			if (symbol_reader_provider == null && parameters.ReadSymbols)
98 				symbol_reader_provider = new DefaultSymbolReaderProvider ();
99 
100 			if (symbol_reader_provider != null) {
101 				module.SymbolReaderProvider = symbol_reader_provider;
102 
103 				var reader = parameters.SymbolStream != null
104 					? symbol_reader_provider.GetSymbolReader (module, parameters.SymbolStream)
105 					: symbol_reader_provider.GetSymbolReader (module, module.FileName);
106 
107 				if (reader != null)
108 					module.ReadSymbols (reader);
109 			}
110 
111 			if (module.Image.HasDebugTables ())
112 				module.ReadSymbols (new PortablePdbReader (module.Image, module));
113 		}
114 
GetMetadataKind(ModuleDefinition module, ReaderParameters parameters)115 		static void GetMetadataKind (ModuleDefinition module, ReaderParameters parameters)
116 		{
117 			if (!parameters.ApplyWindowsRuntimeProjections) {
118 				module.MetadataKind = MetadataKind.Ecma335;
119 				return;
120 			}
121 
122 			var runtime_version = module.RuntimeVersion;
123 
124 			if (!runtime_version.Contains ("WindowsRuntime"))
125 				module.MetadataKind = MetadataKind.Ecma335;
126 			else if (runtime_version.Contains ("CLR"))
127 				module.MetadataKind = MetadataKind.ManagedWindowsMetadata;
128 			else
129 				module.MetadataKind = MetadataKind.WindowsMetadata;
130 		}
131 
CreateModuleReader(Image image, ReadingMode mode)132 		static ModuleReader CreateModuleReader (Image image, ReadingMode mode)
133 		{
134 			switch (mode) {
135 			case ReadingMode.Immediate:
136 				return new ImmediateModuleReader (image);
137 			case ReadingMode.Deferred:
138 				return new DeferredModuleReader (image);
139 			default:
140 				throw new ArgumentException ();
141 			}
142 		}
143 	}
144 
145 	sealed class ImmediateModuleReader : ModuleReader {
146 
147 		bool resolve_attributes;
148 
ImmediateModuleReader(Image image)149 		public ImmediateModuleReader (Image image)
150 			: base (image, ReadingMode.Immediate)
151 		{
152 		}
153 
ReadModule()154 		protected override void ReadModule ()
155 		{
156 			this.module.Read (this.module, (module, reader) => {
157 				ReadModuleManifest (reader);
158 				ReadModule (module, resolve_attributes: true);
159 			});
160 		}
161 
ReadModule(ModuleDefinition module, bool resolve_attributes)162 		public void ReadModule (ModuleDefinition module, bool resolve_attributes)
163 		{
164 			this.resolve_attributes = resolve_attributes;
165 
166 			if (module.HasAssemblyReferences)
167 				Mixin.Read (module.AssemblyReferences);
168 			if (module.HasResources)
169 				Mixin.Read (module.Resources);
170 			if (module.HasModuleReferences)
171 				Mixin.Read (module.ModuleReferences);
172 			if (module.HasTypes)
173 				ReadTypes (module.Types);
174 			if (module.HasExportedTypes)
175 				Mixin.Read (module.ExportedTypes);
176 
177 			ReadCustomAttributes (module);
178 
179 			var assembly = module.Assembly;
180 			if (assembly == null)
181 				return;
182 
183 			ReadCustomAttributes (assembly);
184 			ReadSecurityDeclarations (assembly);
185 		}
186 
ReadTypes(Collection<TypeDefinition> types)187 		void ReadTypes (Collection<TypeDefinition> types)
188 		{
189 			for (int i = 0; i < types.Count; i++)
190 				ReadType (types [i]);
191 		}
192 
ReadType(TypeDefinition type)193 		void ReadType (TypeDefinition type)
194 		{
195 			ReadGenericParameters (type);
196 
197 			if (type.HasInterfaces)
198 				ReadInterfaces (type);
199 
200 			if (type.HasNestedTypes)
201 				ReadTypes (type.NestedTypes);
202 
203 			if (type.HasLayoutInfo)
204 				Mixin.Read (type.ClassSize);
205 
206 			if (type.HasFields)
207 				ReadFields (type);
208 
209 			if (type.HasMethods)
210 				ReadMethods (type);
211 
212 			if (type.HasProperties)
213 				ReadProperties (type);
214 
215 			if (type.HasEvents)
216 				ReadEvents (type);
217 
218 			ReadSecurityDeclarations (type);
219 			ReadCustomAttributes (type);
220 		}
221 
ReadInterfaces(TypeDefinition type)222 		void ReadInterfaces (TypeDefinition type)
223 		{
224 			var interfaces = type.Interfaces;
225 
226 			for (int i = 0; i < interfaces.Count; i++)
227 				ReadCustomAttributes (interfaces [i]);
228 		}
229 
ReadGenericParameters(IGenericParameterProvider provider)230 		void ReadGenericParameters (IGenericParameterProvider provider)
231 		{
232 			if (!provider.HasGenericParameters)
233 				return;
234 
235 			var parameters = provider.GenericParameters;
236 
237 			for (int i = 0; i < parameters.Count; i++) {
238 				var parameter = parameters [i];
239 
240 				if (parameter.HasConstraints)
241 					Mixin.Read (parameter.Constraints);
242 
243 				ReadCustomAttributes (parameter);
244 			}
245 		}
246 
ReadSecurityDeclarations(ISecurityDeclarationProvider provider)247 		void ReadSecurityDeclarations (ISecurityDeclarationProvider provider)
248 		{
249 			if (!provider.HasSecurityDeclarations)
250 				return;
251 
252 			var security_declarations = provider.SecurityDeclarations;
253 
254 			if (!resolve_attributes)
255 				return;
256 
257 			for (int i = 0; i < security_declarations.Count; i++) {
258 				var security_declaration = security_declarations [i];
259 
260 				Mixin.Read (security_declaration.SecurityAttributes);
261 			}
262 		}
263 
ReadCustomAttributes(ICustomAttributeProvider provider)264 		void ReadCustomAttributes (ICustomAttributeProvider provider)
265 		{
266 			if (!provider.HasCustomAttributes)
267 				return;
268 
269 			var custom_attributes = provider.CustomAttributes;
270 
271 			if (!resolve_attributes)
272 				return;
273 
274 			for (int i = 0; i < custom_attributes.Count; i++) {
275 				var custom_attribute = custom_attributes [i];
276 
277 				Mixin.Read (custom_attribute.ConstructorArguments);
278 			}
279 		}
280 
ReadFields(TypeDefinition type)281 		void ReadFields (TypeDefinition type)
282 		{
283 			var fields = type.Fields;
284 
285 			for (int i = 0; i < fields.Count; i++) {
286 				var field = fields [i];
287 
288 				if (field.HasConstant)
289 					Mixin.Read (field.Constant);
290 
291 				if (field.HasLayoutInfo)
292 					Mixin.Read (field.Offset);
293 
294 				if (field.RVA > 0)
295 					Mixin.Read (field.InitialValue);
296 
297 				if (field.HasMarshalInfo)
298 					Mixin.Read (field.MarshalInfo);
299 
300 				ReadCustomAttributes (field);
301 			}
302 		}
303 
ReadMethods(TypeDefinition type)304 		void ReadMethods (TypeDefinition type)
305 		{
306 			var methods = type.Methods;
307 
308 			for (int i = 0; i < methods.Count; i++) {
309 				var method = methods [i];
310 
311 				ReadGenericParameters (method);
312 
313 				if (method.HasParameters)
314 					ReadParameters (method);
315 
316 				if (method.HasOverrides)
317 					Mixin.Read (method.Overrides);
318 
319 				if (method.IsPInvokeImpl)
320 					Mixin.Read (method.PInvokeInfo);
321 
322 				ReadSecurityDeclarations (method);
323 				ReadCustomAttributes (method);
324 
325 				var return_type = method.MethodReturnType;
326 				if (return_type.HasConstant)
327 					Mixin.Read (return_type.Constant);
328 
329 				if (return_type.HasMarshalInfo)
330 					Mixin.Read (return_type.MarshalInfo);
331 
332 				ReadCustomAttributes (return_type);
333 			}
334 		}
335 
ReadParameters(MethodDefinition method)336 		void ReadParameters (MethodDefinition method)
337 		{
338 			var parameters = method.Parameters;
339 
340 			for (int i = 0; i < parameters.Count; i++) {
341 				var parameter = parameters [i];
342 
343 				if (parameter.HasConstant)
344 					Mixin.Read (parameter.Constant);
345 
346 				if (parameter.HasMarshalInfo)
347 					Mixin.Read (parameter.MarshalInfo);
348 
349 				ReadCustomAttributes (parameter);
350 			}
351 		}
352 
ReadProperties(TypeDefinition type)353 		void ReadProperties (TypeDefinition type)
354 		{
355 			var properties = type.Properties;
356 
357 			for (int i = 0; i < properties.Count; i++) {
358 				var property = properties [i];
359 
360 				Mixin.Read (property.GetMethod);
361 
362 				if (property.HasConstant)
363 					Mixin.Read (property.Constant);
364 
365 				ReadCustomAttributes (property);
366 			}
367 		}
368 
ReadEvents(TypeDefinition type)369 		void ReadEvents (TypeDefinition type)
370 		{
371 			var events = type.Events;
372 
373 			for (int i = 0; i < events.Count; i++) {
374 				var @event = events [i];
375 
376 				Mixin.Read (@event.AddMethod);
377 
378 				ReadCustomAttributes (@event);
379 			}
380 		}
381 
ReadSymbols(ModuleDefinition module)382 		public override void ReadSymbols (ModuleDefinition module)
383 		{
384 			if (module.symbol_reader == null)
385 				return;
386 
387 			ReadTypesSymbols (module.Types, module.symbol_reader);
388 		}
389 
ReadTypesSymbols(Collection<TypeDefinition> types, ISymbolReader symbol_reader)390 		void ReadTypesSymbols (Collection<TypeDefinition> types, ISymbolReader symbol_reader)
391 		{
392 			for (int i = 0; i < types.Count; i++) {
393 				var type = types [i];
394 
395 				if (type.HasNestedTypes)
396 					ReadTypesSymbols (type.NestedTypes, symbol_reader);
397 
398 				if (type.HasMethods)
399 					ReadMethodsSymbols (type, symbol_reader);
400 			}
401 		}
402 
ReadMethodsSymbols(TypeDefinition type, ISymbolReader symbol_reader)403 		void ReadMethodsSymbols (TypeDefinition type, ISymbolReader symbol_reader)
404 		{
405 			var methods = type.Methods;
406 			for (int i = 0; i < methods.Count; i++) {
407 				var method = methods [i];
408 
409 				if (method.HasBody && method.token.RID != 0 && method.debug_info == null)
410 					method.debug_info = symbol_reader.Read (method);
411 			}
412 		}
413 	}
414 
415 	sealed class DeferredModuleReader : ModuleReader {
416 
DeferredModuleReader(Image image)417 		public DeferredModuleReader (Image image)
418 			: base (image, ReadingMode.Deferred)
419 		{
420 		}
421 
ReadModule()422 		protected override void ReadModule ()
423 		{
424 			this.module.Read (this.module, (_, reader) => ReadModuleManifest (reader));
425 		}
426 
ReadSymbols(ModuleDefinition module)427 		public override void ReadSymbols (ModuleDefinition module)
428 		{
429 		}
430 	}
431 
432 	sealed class MetadataReader : ByteBuffer {
433 
434 		readonly internal Image image;
435 		readonly internal ModuleDefinition module;
436 		readonly internal MetadataSystem metadata;
437 
438 		internal CodeReader code;
439 		internal IGenericContext context;
440 
441 		readonly MetadataReader metadata_reader;
442 
MetadataReader(ModuleDefinition module)443 		public MetadataReader (ModuleDefinition module)
444 			: base (module.Image.TableHeap.data)
445 		{
446 			this.image = module.Image;
447 			this.module = module;
448 			this.metadata = module.MetadataSystem;
449 			this.code = new CodeReader (this);
450 		}
451 
MetadataReader(Image image, ModuleDefinition module, MetadataReader metadata_reader)452 		public MetadataReader (Image image, ModuleDefinition module, MetadataReader metadata_reader)
453 			: base (image.TableHeap.data)
454 		{
455 			this.image = image;
456 			this.module = module;
457 			this.metadata = module.MetadataSystem;
458 			this.metadata_reader = metadata_reader;
459 		}
460 
GetCodedIndexSize(CodedIndex index)461 		int GetCodedIndexSize (CodedIndex index)
462 		{
463 			return image.GetCodedIndexSize (index);
464 		}
465 
ReadByIndexSize(int size)466 		uint ReadByIndexSize (int size)
467 		{
468 			if (size == 4)
469 				return ReadUInt32 ();
470 			else
471 				return ReadUInt16 ();
472 		}
473 
ReadBlob()474 		byte [] ReadBlob ()
475 		{
476 			var blob_heap = image.BlobHeap;
477 			if (blob_heap == null) {
478 				position += 2;
479 				return Empty<byte>.Array;
480 			}
481 
482 			return blob_heap.Read (ReadBlobIndex ());
483 		}
484 
ReadBlob(uint signature)485 		byte [] ReadBlob (uint signature)
486 		{
487 			var blob_heap = image.BlobHeap;
488 			if (blob_heap == null)
489 				return Empty<byte>.Array;
490 
491 			return blob_heap.Read (signature);
492 		}
493 
ReadBlobIndex()494 		uint ReadBlobIndex ()
495 		{
496 			var blob_heap = image.BlobHeap;
497 			return ReadByIndexSize (blob_heap != null ? blob_heap.IndexSize : 2);
498 		}
499 
GetBlobView(uint signature, out byte [] blob, out int index, out int count)500 		void GetBlobView (uint signature, out byte [] blob, out int index, out int count)
501 		{
502 			var blob_heap = image.BlobHeap;
503 			if (blob_heap == null) {
504 				blob = null;
505 				index = count = 0;
506 				return;
507 			}
508 
509 			blob_heap.GetView (signature, out blob, out index, out count);
510 		}
511 
ReadString()512 		string ReadString ()
513 		{
514 			return image.StringHeap.Read (ReadByIndexSize (image.StringHeap.IndexSize));
515 		}
516 
ReadStringIndex()517 		uint ReadStringIndex ()
518 		{
519 			return ReadByIndexSize (image.StringHeap.IndexSize);
520 		}
521 
ReadGuid()522 		Guid ReadGuid ()
523 		{
524 			return image.GuidHeap.Read (ReadByIndexSize (image.GuidHeap.IndexSize));
525 		}
526 
ReadTableIndex(Table table)527 		uint ReadTableIndex (Table table)
528 		{
529 			return ReadByIndexSize (image.GetTableIndexSize (table));
530 		}
531 
ReadMetadataToken(CodedIndex index)532 		MetadataToken ReadMetadataToken (CodedIndex index)
533 		{
534 			return index.GetMetadataToken (ReadByIndexSize (GetCodedIndexSize (index)));
535 		}
536 
MoveTo(Table table)537 		int MoveTo (Table table)
538 		{
539 			var info = image.TableHeap [table];
540 			if (info.Length != 0)
541 				this.position = (int) info.Offset;
542 
543 			return (int) info.Length;
544 		}
545 
MoveTo(Table table, uint row)546 		bool MoveTo (Table table, uint row)
547 		{
548 			var info = image.TableHeap [table];
549 			var length = info.Length;
550 			if (length == 0 || row > length)
551 				return false;
552 
553 			this.position = (int) (info.Offset + (info.RowSize * (row - 1)));
554 			return true;
555 		}
556 
ReadAssemblyNameDefinition()557 		public AssemblyNameDefinition ReadAssemblyNameDefinition ()
558 		{
559 			if (MoveTo (Table.Assembly) == 0)
560 				return null;
561 
562 			var name = new AssemblyNameDefinition ();
563 
564 			name.HashAlgorithm = (AssemblyHashAlgorithm) ReadUInt32 ();
565 
566 			PopulateVersionAndFlags (name);
567 
568 			name.PublicKey = ReadBlob ();
569 
570 			PopulateNameAndCulture (name);
571 
572 			return name;
573 		}
574 
Populate(ModuleDefinition module)575 		public ModuleDefinition Populate (ModuleDefinition module)
576 		{
577 			if (MoveTo (Table.Module) == 0)
578 				return module;
579 
580 			Advance (2); // Generation
581 
582 			module.Name = ReadString ();
583 			module.Mvid = ReadGuid ();
584 
585 			return module;
586 		}
587 
InitializeAssemblyReferences()588 		void InitializeAssemblyReferences ()
589 		{
590 			if (metadata.AssemblyReferences != null)
591 				return;
592 
593 			int length = MoveTo (Table.AssemblyRef);
594 			var references = metadata.AssemblyReferences = new AssemblyNameReference [length];
595 
596 			for (uint i = 0; i < length; i++) {
597 				var reference = new AssemblyNameReference ();
598 				reference.token = new MetadataToken (TokenType.AssemblyRef, i + 1);
599 
600 				PopulateVersionAndFlags (reference);
601 
602 				var key_or_token = ReadBlob ();
603 
604 				if (reference.HasPublicKey)
605 					reference.PublicKey = key_or_token;
606 				else
607 					reference.PublicKeyToken = key_or_token;
608 
609 				PopulateNameAndCulture (reference);
610 
611 				reference.Hash = ReadBlob ();
612 
613 				references [i] = reference;
614 			}
615 		}
616 
ReadAssemblyReferences()617 		public Collection<AssemblyNameReference> ReadAssemblyReferences ()
618 		{
619 			InitializeAssemblyReferences ();
620 
621 			var references = new Collection<AssemblyNameReference> (metadata.AssemblyReferences);
622 			if (module.IsWindowsMetadata ())
623 				module.Projections.AddVirtualReferences (references);
624 
625 			return references;
626 		}
627 
ReadEntryPoint()628 		public MethodDefinition ReadEntryPoint ()
629 		{
630 			if (module.Image.EntryPointToken == 0)
631 				return null;
632 
633 			var token = new MetadataToken (module.Image.EntryPointToken);
634 			return GetMethodDefinition (token.RID);
635 		}
636 
ReadModules()637 		public Collection<ModuleDefinition> ReadModules ()
638 		{
639 			var modules = new Collection<ModuleDefinition> (1);
640 			modules.Add (this.module);
641 
642 			int length = MoveTo (Table.File);
643 			for (uint i = 1; i <= length; i++) {
644 				var attributes = (FileAttributes) ReadUInt32 ();
645 				var name = ReadString ();
646 				ReadBlobIndex ();
647 
648 				if (attributes != FileAttributes.ContainsMetaData)
649 					continue;
650 
651 				var parameters = new ReaderParameters {
652 					ReadingMode = module.ReadingMode,
653 					SymbolReaderProvider = module.SymbolReaderProvider,
654 					AssemblyResolver = module.AssemblyResolver
655 				};
656 
657 				modules.Add (ModuleDefinition.ReadModule (
658 					GetModuleFileName (name), parameters));
659 			}
660 
661 			return modules;
662 		}
663 
GetModuleFileName(string name)664 		string GetModuleFileName (string name)
665 		{
666 			if (module.FileName == null)
667 				throw new NotSupportedException ();
668 
669 			var path = Path.GetDirectoryName (module.FileName);
670 			return Path.Combine (path, name);
671 		}
672 
InitializeModuleReferences()673 		void InitializeModuleReferences ()
674 		{
675 			if (metadata.ModuleReferences != null)
676 				return;
677 
678 			int length = MoveTo (Table.ModuleRef);
679 			var references = metadata.ModuleReferences = new ModuleReference [length];
680 
681 			for (uint i = 0; i < length; i++) {
682 				var reference = new ModuleReference (ReadString ());
683 				reference.token = new MetadataToken (TokenType.ModuleRef, i + 1);
684 
685 				references [i] = reference;
686 			}
687 		}
688 
ReadModuleReferences()689 		public Collection<ModuleReference> ReadModuleReferences ()
690 		{
691 			InitializeModuleReferences ();
692 
693 			return new Collection<ModuleReference> (metadata.ModuleReferences);
694 		}
695 
HasFileResource()696 		public bool HasFileResource ()
697 		{
698 			int length = MoveTo (Table.File);
699 			if (length == 0)
700 				return false;
701 
702 			for (uint i = 1; i <= length; i++)
703 				if (ReadFileRecord (i).Col1 == FileAttributes.ContainsNoMetaData)
704 					return true;
705 
706 			return false;
707 		}
708 
ReadResources()709 		public Collection<Resource> ReadResources ()
710 		{
711 			int length = MoveTo (Table.ManifestResource);
712 			var resources = new Collection<Resource> (length);
713 
714 			for (int i = 1; i <= length; i++) {
715 				var offset = ReadUInt32 ();
716 				var flags = (ManifestResourceAttributes) ReadUInt32 ();
717 				var name = ReadString ();
718 				var implementation = ReadMetadataToken (CodedIndex.Implementation);
719 
720 				Resource resource;
721 
722 				if (implementation.RID == 0) {
723 					resource = new EmbeddedResource (name, flags, offset, this);
724 				} else if (implementation.TokenType == TokenType.AssemblyRef) {
725 					resource = new AssemblyLinkedResource (name, flags) {
726 						Assembly = (AssemblyNameReference) GetTypeReferenceScope (implementation),
727 					};
728 				} else if (implementation.TokenType == TokenType.File) {
729 					var file_record = ReadFileRecord (implementation.RID);
730 
731 					resource = new LinkedResource (name, flags) {
732 						File = file_record.Col2,
733 						hash = ReadBlob (file_record.Col3)
734 					};
735 				} else
736 					continue;
737 
738 				resources.Add (resource);
739 			}
740 
741 			return resources;
742 		}
743 
ReadFileRecord(uint rid)744 		Row<FileAttributes, string, uint> ReadFileRecord (uint rid)
745 		{
746 			var position = this.position;
747 
748 			if (!MoveTo (Table.File, rid))
749 				throw new ArgumentException ();
750 
751 			var record = new Row<FileAttributes, string, uint> (
752 				(FileAttributes) ReadUInt32 (),
753 				ReadString (),
754 				ReadBlobIndex ());
755 
756 			this.position = position;
757 
758 			return record;
759 		}
760 
GetManagedResource(uint offset)761 		public byte [] GetManagedResource (uint offset)
762 		{
763 			return image.GetReaderAt (image.Resources.VirtualAddress, offset, (o, reader) => {
764 				reader.Advance ((int) o);
765 				return reader.ReadBytes (reader.ReadInt32 ());
766 			}) ?? Empty<byte>.Array;
767 		}
768 
PopulateVersionAndFlags(AssemblyNameReference name)769 		void PopulateVersionAndFlags (AssemblyNameReference name)
770 		{
771 			name.Version = new Version (
772 				ReadUInt16 (),
773 				ReadUInt16 (),
774 				ReadUInt16 (),
775 				ReadUInt16 ());
776 
777 			name.Attributes = (AssemblyAttributes) ReadUInt32 ();
778 		}
779 
PopulateNameAndCulture(AssemblyNameReference name)780 		void PopulateNameAndCulture (AssemblyNameReference name)
781 		{
782 			name.Name = ReadString ();
783 			name.Culture = ReadString ();
784 		}
785 
ReadTypes()786 		public TypeDefinitionCollection ReadTypes ()
787 		{
788 			InitializeTypeDefinitions ();
789 			var mtypes = metadata.Types;
790 			var type_count = mtypes.Length - metadata.NestedTypes.Count;
791 			var types = new TypeDefinitionCollection (module, type_count);
792 
793 			for (int i = 0; i < mtypes.Length; i++) {
794 				var type = mtypes [i];
795 				if (IsNested (type.Attributes))
796 					continue;
797 
798 				types.Add (type);
799 			}
800 
801 			if (image.HasTable (Table.MethodPtr) || image.HasTable (Table.FieldPtr))
802 				CompleteTypes ();
803 
804 			return types;
805 		}
806 
CompleteTypes()807 		void CompleteTypes ()
808 		{
809 			var types = metadata.Types;
810 
811 			for (int i = 0; i < types.Length; i++) {
812 				var type = types [i];
813 
814 				Mixin.Read (type.Fields);
815 				Mixin.Read (type.Methods);
816 			}
817 		}
818 
InitializeTypeDefinitions()819 		void InitializeTypeDefinitions ()
820 		{
821 			if (metadata.Types != null)
822 				return;
823 
824 			InitializeNestedTypes ();
825 			InitializeFields ();
826 			InitializeMethods ();
827 
828 			int length = MoveTo (Table.TypeDef);
829 			var types = metadata.Types = new TypeDefinition [length];
830 
831 			for (uint i = 0; i < length; i++) {
832 				if (types [i] != null)
833 					continue;
834 
835 				types [i] = ReadType (i + 1);
836 			}
837 		}
838 
IsNested(TypeAttributes attributes)839 		static bool IsNested (TypeAttributes attributes)
840 		{
841 			switch (attributes & TypeAttributes.VisibilityMask) {
842 			case TypeAttributes.NestedAssembly:
843 			case TypeAttributes.NestedFamANDAssem:
844 			case TypeAttributes.NestedFamily:
845 			case TypeAttributes.NestedFamORAssem:
846 			case TypeAttributes.NestedPrivate:
847 			case TypeAttributes.NestedPublic:
848 				return true;
849 			default:
850 				return false;
851 			}
852 		}
853 
HasNestedTypes(TypeDefinition type)854 		public bool HasNestedTypes (TypeDefinition type)
855 		{
856 			Collection<uint> mapping;
857 			InitializeNestedTypes ();
858 
859 			if (!metadata.TryGetNestedTypeMapping (type, out mapping))
860 				return false;
861 
862 			return mapping.Count > 0;
863 		}
864 
ReadNestedTypes(TypeDefinition type)865 		public Collection<TypeDefinition> ReadNestedTypes (TypeDefinition type)
866 		{
867 			InitializeNestedTypes ();
868 			Collection<uint> mapping;
869 			if (!metadata.TryGetNestedTypeMapping (type, out mapping))
870 				return new MemberDefinitionCollection<TypeDefinition> (type);
871 
872 			var nested_types = new MemberDefinitionCollection<TypeDefinition> (type, mapping.Count);
873 
874 			for (int i = 0; i < mapping.Count; i++) {
875 				var nested_type = GetTypeDefinition (mapping [i]);
876 
877 				if (nested_type != null)
878 					nested_types.Add (nested_type);
879 			}
880 
881 			metadata.RemoveNestedTypeMapping (type);
882 
883 			return nested_types;
884 		}
885 
InitializeNestedTypes()886 		void InitializeNestedTypes ()
887 		{
888 			if (metadata.NestedTypes != null)
889 				return;
890 
891 			var length = MoveTo (Table.NestedClass);
892 
893 			metadata.NestedTypes = new Dictionary<uint, Collection<uint>> (length);
894 			metadata.ReverseNestedTypes = new Dictionary<uint, uint> (length);
895 
896 			if (length == 0)
897 				return;
898 
899 			for (int i = 1; i <= length; i++) {
900 				var nested = ReadTableIndex (Table.TypeDef);
901 				var declaring = ReadTableIndex (Table.TypeDef);
902 
903 				AddNestedMapping (declaring, nested);
904 			}
905 		}
906 
AddNestedMapping(uint declaring, uint nested)907 		void AddNestedMapping (uint declaring, uint nested)
908 		{
909 			metadata.SetNestedTypeMapping (declaring, AddMapping (metadata.NestedTypes, declaring, nested));
910 			metadata.SetReverseNestedTypeMapping (nested, declaring);
911 		}
912 
AddMapping(Dictionary<TKey, Collection<TValue>> cache, TKey key, TValue value)913 		static Collection<TValue> AddMapping<TKey, TValue> (Dictionary<TKey, Collection<TValue>> cache, TKey key, TValue value)
914 		{
915 			Collection<TValue> mapped;
916 			if (!cache.TryGetValue (key, out mapped)) {
917 				mapped = new Collection<TValue> ();
918 			}
919 			mapped.Add (value);
920 			return mapped;
921 		}
922 
ReadType(uint rid)923 		TypeDefinition ReadType (uint rid)
924 		{
925 			if (!MoveTo (Table.TypeDef, rid))
926 				return null;
927 
928 			var attributes = (TypeAttributes) ReadUInt32 ();
929 			var name = ReadString ();
930 			var @namespace = ReadString ();
931 			var type = new TypeDefinition (@namespace, name, attributes);
932 			type.token = new MetadataToken (TokenType.TypeDef, rid);
933 			type.scope = module;
934 			type.module = module;
935 
936 			metadata.AddTypeDefinition (type);
937 
938 			this.context = type;
939 
940 			type.BaseType = GetTypeDefOrRef (ReadMetadataToken (CodedIndex.TypeDefOrRef));
941 
942 			type.fields_range = ReadListRange (rid, Table.TypeDef, Table.Field);
943 			type.methods_range = ReadListRange (rid, Table.TypeDef, Table.Method);
944 
945 			if (IsNested (attributes))
946 				type.DeclaringType = GetNestedTypeDeclaringType (type);
947 
948 			if (module.IsWindowsMetadata ())
949 				WindowsRuntimeProjections.Project (type);
950 
951 			return type;
952 		}
953 
GetNestedTypeDeclaringType(TypeDefinition type)954 		TypeDefinition GetNestedTypeDeclaringType (TypeDefinition type)
955 		{
956 			uint declaring_rid;
957 			if (!metadata.TryGetReverseNestedTypeMapping (type, out declaring_rid))
958 				return null;
959 
960 			metadata.RemoveReverseNestedTypeMapping (type);
961 			return GetTypeDefinition (declaring_rid);
962 		}
963 
ReadListRange(uint current_index, Table current, Table target)964 		Range ReadListRange (uint current_index, Table current, Table target)
965 		{
966 			var list = new Range ();
967 
968 			var start = ReadTableIndex (target);
969 			if (start == 0)
970 				return list;
971 
972 			uint next_index;
973 			var current_table = image.TableHeap [current];
974 
975 			if (current_index == current_table.Length)
976 				next_index = image.TableHeap [target].Length + 1;
977 			else {
978 				var position = this.position;
979 				this.position += (int) (current_table.RowSize - image.GetTableIndexSize (target));
980 				next_index = ReadTableIndex (target);
981 				this.position = position;
982 			}
983 
984 			list.Start = start;
985 			list.Length = next_index - start;
986 
987 			return list;
988 		}
989 
ReadTypeLayout(TypeDefinition type)990 		public Row<short, int> ReadTypeLayout (TypeDefinition type)
991 		{
992 			InitializeTypeLayouts ();
993 			Row<ushort, uint> class_layout;
994 			var rid = type.token.RID;
995 			if (!metadata.ClassLayouts.TryGetValue (rid, out class_layout))
996 				return new Row<short, int> (Mixin.NoDataMarker, Mixin.NoDataMarker);
997 
998 			type.PackingSize = (short) class_layout.Col1;
999 			type.ClassSize = (int) class_layout.Col2;
1000 
1001 			metadata.ClassLayouts.Remove (rid);
1002 
1003 			return new Row<short, int> ((short) class_layout.Col1, (int) class_layout.Col2);
1004 		}
1005 
InitializeTypeLayouts()1006 		void InitializeTypeLayouts ()
1007 		{
1008 			if (metadata.ClassLayouts != null)
1009 				return;
1010 
1011 			int length = MoveTo (Table.ClassLayout);
1012 
1013 			var class_layouts = metadata.ClassLayouts = new Dictionary<uint, Row<ushort, uint>> (length);
1014 
1015 			for (uint i = 0; i < length; i++) {
1016 				var packing_size = ReadUInt16 ();
1017 				var class_size = ReadUInt32 ();
1018 
1019 				var parent = ReadTableIndex (Table.TypeDef);
1020 
1021 				class_layouts.Add (parent, new Row<ushort, uint> (packing_size, class_size));
1022 			}
1023 		}
1024 
GetTypeDefOrRef(MetadataToken token)1025 		public TypeReference GetTypeDefOrRef (MetadataToken token)
1026 		{
1027 			return (TypeReference) LookupToken (token);
1028 		}
1029 
GetTypeDefinition(uint rid)1030 		public TypeDefinition GetTypeDefinition (uint rid)
1031 		{
1032 			InitializeTypeDefinitions ();
1033 
1034 			var type = metadata.GetTypeDefinition (rid);
1035 			if (type != null)
1036 				return type;
1037 
1038 			return ReadTypeDefinition (rid);
1039 		}
1040 
ReadTypeDefinition(uint rid)1041 		TypeDefinition ReadTypeDefinition (uint rid)
1042 		{
1043 			if (!MoveTo (Table.TypeDef, rid))
1044 				return null;
1045 
1046 			return ReadType (rid);
1047 		}
1048 
InitializeTypeReferences()1049 		void InitializeTypeReferences ()
1050 		{
1051 			if (metadata.TypeReferences != null)
1052 				return;
1053 
1054 			metadata.TypeReferences = new TypeReference [image.GetTableLength (Table.TypeRef)];
1055 		}
1056 
GetTypeReference(string scope, string full_name)1057 		public TypeReference GetTypeReference (string scope, string full_name)
1058 		{
1059 			InitializeTypeReferences ();
1060 
1061 			var length = metadata.TypeReferences.Length;
1062 
1063 			for (uint i = 1; i <= length; i++) {
1064 				var type = GetTypeReference (i);
1065 
1066 				if (type.FullName != full_name)
1067 					continue;
1068 
1069 				if (string.IsNullOrEmpty (scope))
1070 					return type;
1071 
1072 				if (type.Scope.Name == scope)
1073 					return type;
1074 			}
1075 
1076 			return null;
1077 		}
1078 
GetTypeReference(uint rid)1079 		TypeReference GetTypeReference (uint rid)
1080 		{
1081 			InitializeTypeReferences ();
1082 
1083 			var type = metadata.GetTypeReference (rid);
1084 			if (type != null)
1085 				return type;
1086 
1087 			return ReadTypeReference (rid);
1088 		}
1089 
ReadTypeReference(uint rid)1090 		TypeReference ReadTypeReference (uint rid)
1091 		{
1092 			if (!MoveTo (Table.TypeRef, rid))
1093 				return null;
1094 
1095 			TypeReference declaring_type = null;
1096 			IMetadataScope scope;
1097 
1098 			var scope_token = ReadMetadataToken (CodedIndex.ResolutionScope);
1099 
1100 			var name = ReadString ();
1101 			var @namespace = ReadString ();
1102 
1103 			var type = new TypeReference (
1104 				@namespace,
1105 				name,
1106 				module,
1107 				null);
1108 
1109 			type.token = new MetadataToken (TokenType.TypeRef, rid);
1110 
1111 			metadata.AddTypeReference (type);
1112 
1113 			if (scope_token.TokenType == TokenType.TypeRef) {
1114 				declaring_type = GetTypeDefOrRef (scope_token);
1115 
1116 				scope = declaring_type != null
1117 					? declaring_type.Scope
1118 					: module;
1119 			} else
1120 				scope = GetTypeReferenceScope (scope_token);
1121 
1122 			type.scope = scope;
1123 			type.DeclaringType = declaring_type;
1124 
1125 			MetadataSystem.TryProcessPrimitiveTypeReference (type);
1126 
1127 			if (type.Module.IsWindowsMetadata ())
1128 				WindowsRuntimeProjections.Project (type);
1129 
1130 			return type;
1131 		}
1132 
GetTypeReferenceScope(MetadataToken scope)1133 		IMetadataScope GetTypeReferenceScope (MetadataToken scope)
1134 		{
1135 			if (scope.TokenType == TokenType.Module)
1136 				return module;
1137 
1138 			IMetadataScope[] scopes;
1139 
1140 			switch (scope.TokenType) {
1141 			case TokenType.AssemblyRef:
1142 				InitializeAssemblyReferences ();
1143 				scopes = metadata.AssemblyReferences;
1144 				break;
1145 			case TokenType.ModuleRef:
1146 				InitializeModuleReferences ();
1147 				scopes = metadata.ModuleReferences;
1148 				break;
1149 			default:
1150 				throw new NotSupportedException ();
1151 			}
1152 
1153 			var index = scope.RID - 1;
1154 			if (index < 0 || index >= scopes.Length)
1155 				return null;
1156 
1157 			return scopes [index];
1158 		}
1159 
GetTypeReferences()1160 		public IEnumerable<TypeReference> GetTypeReferences ()
1161 		{
1162 			InitializeTypeReferences ();
1163 
1164 			var length = image.GetTableLength (Table.TypeRef);
1165 
1166 			var type_references = new TypeReference [length];
1167 
1168 			for (uint i = 1; i <= length; i++)
1169 				type_references [i - 1] = GetTypeReference (i);
1170 
1171 			return type_references;
1172 		}
1173 
GetTypeSpecification(uint rid)1174 		TypeReference GetTypeSpecification (uint rid)
1175 		{
1176 			if (!MoveTo (Table.TypeSpec, rid))
1177 				return null;
1178 
1179 			var reader = ReadSignature (ReadBlobIndex ());
1180 			var type = reader.ReadTypeSignature ();
1181 			if (type.token.RID == 0)
1182 				type.token = new MetadataToken (TokenType.TypeSpec, rid);
1183 
1184 			return type;
1185 		}
1186 
ReadSignature(uint signature)1187 		SignatureReader ReadSignature (uint signature)
1188 		{
1189 			return new SignatureReader (signature, this);
1190 		}
1191 
HasInterfaces(TypeDefinition type)1192 		public bool HasInterfaces (TypeDefinition type)
1193 		{
1194 			InitializeInterfaces ();
1195 			Collection<Row<uint, MetadataToken>> mapping;
1196 
1197 			return metadata.TryGetInterfaceMapping (type, out mapping);
1198 		}
1199 
ReadInterfaces(TypeDefinition type)1200 		public InterfaceImplementationCollection ReadInterfaces (TypeDefinition type)
1201 		{
1202 			InitializeInterfaces ();
1203 			Collection<Row<uint, MetadataToken>> mapping;
1204 
1205 			if (!metadata.TryGetInterfaceMapping (type, out mapping))
1206 				return new InterfaceImplementationCollection (type);
1207 
1208 			var interfaces = new InterfaceImplementationCollection (type, mapping.Count);
1209 
1210 			this.context = type;
1211 
1212 			for (int i = 0; i < mapping.Count; i++) {
1213 				interfaces.Add (
1214 					new InterfaceImplementation (
1215 						GetTypeDefOrRef (mapping [i].Col2),
1216 						new MetadataToken(TokenType.InterfaceImpl, mapping [i].Col1)));
1217 			}
1218 
1219 			metadata.RemoveInterfaceMapping (type);
1220 
1221 			return interfaces;
1222 		}
1223 
InitializeInterfaces()1224 		void InitializeInterfaces ()
1225 		{
1226 			if (metadata.Interfaces != null)
1227 				return;
1228 
1229 			int length = MoveTo (Table.InterfaceImpl);
1230 
1231 			metadata.Interfaces = new Dictionary<uint, Collection<Row<uint, MetadataToken>>> (length);
1232 
1233 			for (uint i = 1; i <= length; i++) {
1234 				var type = ReadTableIndex (Table.TypeDef);
1235 				var @interface = ReadMetadataToken (CodedIndex.TypeDefOrRef);
1236 
1237 				AddInterfaceMapping (type, new Row<uint, MetadataToken> (i, @interface));
1238 			}
1239 		}
1240 
AddInterfaceMapping(uint type, Row<uint, MetadataToken> @interface)1241 		void AddInterfaceMapping (uint type, Row<uint, MetadataToken> @interface)
1242 		{
1243 			metadata.SetInterfaceMapping (type, AddMapping (metadata.Interfaces, type, @interface));
1244 		}
1245 
ReadFields(TypeDefinition type)1246 		public Collection<FieldDefinition> ReadFields (TypeDefinition type)
1247 		{
1248 			var fields_range = type.fields_range;
1249 			if (fields_range.Length == 0)
1250 				return new MemberDefinitionCollection<FieldDefinition> (type);
1251 
1252 			var fields = new MemberDefinitionCollection<FieldDefinition> (type, (int) fields_range.Length);
1253 			this.context = type;
1254 
1255 			if (!MoveTo (Table.FieldPtr, fields_range.Start)) {
1256 				if (!MoveTo (Table.Field, fields_range.Start))
1257 					return fields;
1258 
1259 				for (uint i = 0; i < fields_range.Length; i++)
1260 					ReadField (fields_range.Start + i, fields);
1261 			} else
1262 				ReadPointers (Table.FieldPtr, Table.Field, fields_range, fields, ReadField);
1263 
1264 			return fields;
1265 		}
1266 
ReadField(uint field_rid, Collection<FieldDefinition> fields)1267 		void ReadField (uint field_rid, Collection<FieldDefinition> fields)
1268 		{
1269 			var attributes = (FieldAttributes) ReadUInt16 ();
1270 			var name = ReadString ();
1271 			var signature = ReadBlobIndex ();
1272 
1273 			var field = new FieldDefinition (name, attributes, ReadFieldType (signature));
1274 			field.token = new MetadataToken (TokenType.Field, field_rid);
1275 			metadata.AddFieldDefinition (field);
1276 
1277 			if (IsDeleted (field))
1278 				return;
1279 
1280 			fields.Add (field);
1281 
1282 			if (module.IsWindowsMetadata ())
1283 				WindowsRuntimeProjections.Project (field);
1284 		}
1285 
InitializeFields()1286 		void InitializeFields ()
1287 		{
1288 			if (metadata.Fields != null)
1289 				return;
1290 
1291 			metadata.Fields = new FieldDefinition [image.GetTableLength (Table.Field)];
1292 		}
1293 
ReadFieldType(uint signature)1294 		TypeReference ReadFieldType (uint signature)
1295 		{
1296 			var reader = ReadSignature (signature);
1297 
1298 			const byte field_sig = 0x6;
1299 
1300 			if (reader.ReadByte () != field_sig)
1301 				throw new NotSupportedException ();
1302 
1303 			return reader.ReadTypeSignature ();
1304 		}
1305 
ReadFieldRVA(FieldDefinition field)1306 		public int ReadFieldRVA (FieldDefinition field)
1307 		{
1308 			InitializeFieldRVAs ();
1309 			var rid = field.token.RID;
1310 
1311 			RVA rva;
1312 			if (!metadata.FieldRVAs.TryGetValue (rid, out rva))
1313 				return 0;
1314 
1315 			var size = GetFieldTypeSize (field.FieldType);
1316 
1317 			if (size == 0 || rva == 0)
1318 				return 0;
1319 
1320 			metadata.FieldRVAs.Remove (rid);
1321 
1322 			field.InitialValue = GetFieldInitializeValue (size, rva);
1323 
1324 			return (int) rva;
1325 		}
1326 
GetFieldInitializeValue(int size, RVA rva)1327 		byte [] GetFieldInitializeValue (int size, RVA rva)
1328 		{
1329 			return image.GetReaderAt (rva, size, (s, reader) => reader.ReadBytes (s)) ?? Empty<byte>.Array;
1330 		}
1331 
GetFieldTypeSize(TypeReference type)1332 		static int GetFieldTypeSize (TypeReference type)
1333 		{
1334 			int size = 0;
1335 
1336 			switch (type.etype) {
1337 			case ElementType.Boolean:
1338 			case ElementType.U1:
1339 			case ElementType.I1:
1340 				size = 1;
1341 				break;
1342 			case ElementType.U2:
1343 			case ElementType.I2:
1344 			case ElementType.Char:
1345 				size = 2;
1346 				break;
1347 			case ElementType.U4:
1348 			case ElementType.I4:
1349 			case ElementType.R4:
1350 				size = 4;
1351 				break;
1352 			case ElementType.U8:
1353 			case ElementType.I8:
1354 			case ElementType.R8:
1355 				size = 8;
1356 				break;
1357 			case ElementType.Ptr:
1358 			case ElementType.FnPtr:
1359 				size = IntPtr.Size;
1360 				break;
1361 			case ElementType.CModOpt:
1362 			case ElementType.CModReqD:
1363 				return GetFieldTypeSize (((IModifierType) type).ElementType);
1364 			default:
1365 				var field_type = type.Resolve ();
1366 				if (field_type != null && field_type.HasLayoutInfo)
1367 					size = field_type.ClassSize;
1368 
1369 				break;
1370 			}
1371 
1372 			return size;
1373 		}
1374 
InitializeFieldRVAs()1375 		void InitializeFieldRVAs ()
1376 		{
1377 			if (metadata.FieldRVAs != null)
1378 				return;
1379 
1380 			int length = MoveTo (Table.FieldRVA);
1381 
1382 			var field_rvas = metadata.FieldRVAs = new Dictionary<uint, uint> (length);
1383 
1384 			for (int i = 0; i < length; i++) {
1385 				var rva = ReadUInt32 ();
1386 				var field = ReadTableIndex (Table.Field);
1387 
1388 				field_rvas.Add (field, rva);
1389 			}
1390 		}
1391 
ReadFieldLayout(FieldDefinition field)1392 		public int ReadFieldLayout (FieldDefinition field)
1393 		{
1394 			InitializeFieldLayouts ();
1395 			var rid = field.token.RID;
1396 			uint offset;
1397 			if (!metadata.FieldLayouts.TryGetValue (rid, out offset))
1398 				return Mixin.NoDataMarker;
1399 
1400 			metadata.FieldLayouts.Remove (rid);
1401 
1402 			return (int) offset;
1403 		}
1404 
InitializeFieldLayouts()1405 		void InitializeFieldLayouts ()
1406 		{
1407 			if (metadata.FieldLayouts != null)
1408 				return;
1409 
1410 			int length = MoveTo (Table.FieldLayout);
1411 
1412 			var field_layouts = metadata.FieldLayouts = new Dictionary<uint, uint> (length);
1413 
1414 			for (int i = 0; i < length; i++) {
1415 				var offset = ReadUInt32 ();
1416 				var field = ReadTableIndex (Table.Field);
1417 
1418 				field_layouts.Add (field, offset);
1419 			}
1420 		}
1421 
HasEvents(TypeDefinition type)1422 		public bool HasEvents (TypeDefinition type)
1423 		{
1424 			InitializeEvents ();
1425 
1426 			Range range;
1427 			if (!metadata.TryGetEventsRange (type, out range))
1428 				return false;
1429 
1430 			return range.Length > 0;
1431 		}
1432 
ReadEvents(TypeDefinition type)1433 		public Collection<EventDefinition> ReadEvents (TypeDefinition type)
1434 		{
1435 			InitializeEvents ();
1436 			Range range;
1437 
1438 			if (!metadata.TryGetEventsRange (type, out range))
1439 				return new MemberDefinitionCollection<EventDefinition> (type);
1440 
1441 			var events = new MemberDefinitionCollection<EventDefinition> (type, (int) range.Length);
1442 
1443 			metadata.RemoveEventsRange (type);
1444 
1445 			if (range.Length == 0)
1446 				return events;
1447 
1448 			this.context = type;
1449 
1450 			if (!MoveTo (Table.EventPtr, range.Start)) {
1451 				if (!MoveTo (Table.Event, range.Start))
1452 					return events;
1453 
1454 				for (uint i = 0; i < range.Length; i++)
1455 					ReadEvent (range.Start + i, events);
1456 			} else
1457 				ReadPointers (Table.EventPtr, Table.Event, range, events, ReadEvent);
1458 
1459 			return events;
1460 		}
1461 
ReadEvent(uint event_rid, Collection<EventDefinition> events)1462 		void ReadEvent (uint event_rid, Collection<EventDefinition> events)
1463 		{
1464 			var attributes = (EventAttributes) ReadUInt16 ();
1465 			var name = ReadString ();
1466 			var event_type = GetTypeDefOrRef (ReadMetadataToken (CodedIndex.TypeDefOrRef));
1467 
1468 			var @event = new EventDefinition (name, attributes, event_type);
1469 			@event.token = new MetadataToken (TokenType.Event, event_rid);
1470 
1471 			if (IsDeleted (@event))
1472 				return;
1473 
1474 			events.Add (@event);
1475 		}
1476 
InitializeEvents()1477 		void InitializeEvents ()
1478 		{
1479 			if (metadata.Events != null)
1480 				return;
1481 
1482 			int length = MoveTo (Table.EventMap);
1483 
1484 			metadata.Events = new Dictionary<uint, Range> (length);
1485 
1486 			for (uint i = 1; i <= length; i++) {
1487 				var type_rid = ReadTableIndex (Table.TypeDef);
1488 				Range events_range = ReadListRange (i, Table.EventMap, Table.Event);
1489 				metadata.AddEventsRange (type_rid, events_range);
1490 			}
1491 		}
1492 
HasProperties(TypeDefinition type)1493 		public bool HasProperties (TypeDefinition type)
1494 		{
1495 			InitializeProperties ();
1496 
1497 			Range range;
1498 			if (!metadata.TryGetPropertiesRange (type, out range))
1499 				return false;
1500 
1501 			return range.Length > 0;
1502 		}
1503 
ReadProperties(TypeDefinition type)1504 		public Collection<PropertyDefinition> ReadProperties (TypeDefinition type)
1505 		{
1506 			InitializeProperties ();
1507 
1508 			Range range;
1509 
1510 			if (!metadata.TryGetPropertiesRange (type, out range))
1511 				return new MemberDefinitionCollection<PropertyDefinition> (type);
1512 
1513 			metadata.RemovePropertiesRange (type);
1514 
1515 			var properties = new MemberDefinitionCollection<PropertyDefinition> (type, (int) range.Length);
1516 
1517 			if (range.Length == 0)
1518 				return properties;
1519 
1520 			this.context = type;
1521 
1522 			if (!MoveTo (Table.PropertyPtr, range.Start)) {
1523 				if (!MoveTo (Table.Property, range.Start))
1524 					return properties;
1525 				for (uint i = 0; i < range.Length; i++)
1526 					ReadProperty (range.Start + i, properties);
1527 			} else
1528 				ReadPointers (Table.PropertyPtr, Table.Property, range, properties, ReadProperty);
1529 
1530 			return properties;
1531 		}
1532 
ReadProperty(uint property_rid, Collection<PropertyDefinition> properties)1533 		void ReadProperty (uint property_rid, Collection<PropertyDefinition> properties)
1534 		{
1535 			var attributes = (PropertyAttributes) ReadUInt16 ();
1536 			var name = ReadString ();
1537 			var signature = ReadBlobIndex ();
1538 
1539 			var reader = ReadSignature (signature);
1540 			const byte property_signature = 0x8;
1541 
1542 			var calling_convention = reader.ReadByte ();
1543 
1544 			if ((calling_convention & property_signature) == 0)
1545 				throw new NotSupportedException ();
1546 
1547 			var has_this = (calling_convention & 0x20) != 0;
1548 
1549 			reader.ReadCompressedUInt32 (); // count
1550 
1551 			var property = new PropertyDefinition (name, attributes, reader.ReadTypeSignature ());
1552 			property.HasThis = has_this;
1553 			property.token = new MetadataToken (TokenType.Property, property_rid);
1554 
1555 			if (IsDeleted (property))
1556 				return;
1557 
1558 			properties.Add (property);
1559 		}
1560 
InitializeProperties()1561 		void InitializeProperties ()
1562 		{
1563 			if (metadata.Properties != null)
1564 				return;
1565 
1566 			int length = MoveTo (Table.PropertyMap);
1567 
1568 			metadata.Properties = new Dictionary<uint, Range> (length);
1569 
1570 			for (uint i = 1; i <= length; i++) {
1571 				var type_rid = ReadTableIndex (Table.TypeDef);
1572 				var properties_range = ReadListRange (i, Table.PropertyMap, Table.Property);
1573 				metadata.AddPropertiesRange (type_rid, properties_range);
1574 			}
1575 		}
1576 
ReadMethodSemantics(MethodDefinition method)1577 		MethodSemanticsAttributes ReadMethodSemantics (MethodDefinition method)
1578 		{
1579 			InitializeMethodSemantics ();
1580 			Row<MethodSemanticsAttributes, MetadataToken> row;
1581 			if (!metadata.Semantics.TryGetValue (method.token.RID, out row))
1582 				return MethodSemanticsAttributes.None;
1583 
1584 			var type = method.DeclaringType;
1585 
1586 			switch (row.Col1) {
1587 			case MethodSemanticsAttributes.AddOn:
1588 				GetEvent (type, row.Col2).add_method = method;
1589 				break;
1590 			case MethodSemanticsAttributes.Fire:
1591 				GetEvent (type, row.Col2).invoke_method = method;
1592 				break;
1593 			case MethodSemanticsAttributes.RemoveOn:
1594 				GetEvent (type, row.Col2).remove_method = method;
1595 				break;
1596 			case MethodSemanticsAttributes.Getter:
1597 				GetProperty (type, row.Col2).get_method = method;
1598 				break;
1599 			case MethodSemanticsAttributes.Setter:
1600 				GetProperty (type, row.Col2).set_method = method;
1601 				break;
1602 			case MethodSemanticsAttributes.Other:
1603 				switch (row.Col2.TokenType) {
1604 				case TokenType.Event: {
1605 					var @event = GetEvent (type, row.Col2);
1606 					if (@event.other_methods == null)
1607 						@event.other_methods = new Collection<MethodDefinition> ();
1608 
1609 					@event.other_methods.Add (method);
1610 					break;
1611 				}
1612 				case TokenType.Property: {
1613 					var property = GetProperty (type, row.Col2);
1614 					if (property.other_methods == null)
1615 						property.other_methods = new Collection<MethodDefinition> ();
1616 
1617 					property.other_methods.Add (method);
1618 
1619 					break;
1620 				}
1621 				default:
1622 					throw new NotSupportedException ();
1623 				}
1624 				break;
1625 			default:
1626 				throw new NotSupportedException ();
1627 			}
1628 
1629 			metadata.Semantics.Remove (method.token.RID);
1630 
1631 			return row.Col1;
1632 		}
1633 
GetEvent(TypeDefinition type, MetadataToken token)1634 		static EventDefinition GetEvent (TypeDefinition type, MetadataToken token)
1635 		{
1636 			if (token.TokenType != TokenType.Event)
1637 				throw new ArgumentException ();
1638 
1639 			return GetMember (type.Events, token);
1640 		}
1641 
GetProperty(TypeDefinition type, MetadataToken token)1642 		static PropertyDefinition GetProperty (TypeDefinition type, MetadataToken token)
1643 		{
1644 			if (token.TokenType != TokenType.Property)
1645 				throw new ArgumentException ();
1646 
1647 			return GetMember (type.Properties, token);
1648 		}
1649 
1650 		static TMember GetMember<TMember> (Collection<TMember> members, MetadataToken token) where TMember : IMemberDefinition
1651 		{
1652 			for (int i = 0; i < members.Count; i++) {
1653 				var member = members [i];
1654 				if (member.MetadataToken == token)
1655 					return member;
1656 			}
1657 
1658 			throw new ArgumentException ();
1659 		}
1660 
InitializeMethodSemantics()1661 		void InitializeMethodSemantics ()
1662 		{
1663 			if (metadata.Semantics != null)
1664 				return;
1665 
1666 			int length = MoveTo (Table.MethodSemantics);
1667 
1668 			var semantics = metadata.Semantics = new Dictionary<uint, Row<MethodSemanticsAttributes, MetadataToken>> (0);
1669 
1670 			for (uint i = 0; i < length; i++) {
1671 				var attributes = (MethodSemanticsAttributes) ReadUInt16 ();
1672 				var method_rid = ReadTableIndex (Table.Method);
1673 				var association = ReadMetadataToken (CodedIndex.HasSemantics);
1674 
1675 				semantics [method_rid] = new Row<MethodSemanticsAttributes, MetadataToken> (attributes, association);
1676 			}
1677 		}
1678 
ReadMethods(PropertyDefinition property)1679 		public void ReadMethods (PropertyDefinition property)
1680 		{
1681 			ReadAllSemantics (property.DeclaringType);
1682 		}
1683 
1684 		public void ReadMethods (EventDefinition @event)
1685 		{
1686 			ReadAllSemantics (@event.DeclaringType);
1687 		}
1688 
ReadAllSemantics(MethodDefinition method)1689 		public void ReadAllSemantics (MethodDefinition method)
1690 		{
1691 			ReadAllSemantics (method.DeclaringType);
1692 		}
1693 
ReadAllSemantics(TypeDefinition type)1694 		void ReadAllSemantics (TypeDefinition type)
1695 		{
1696 			var methods = type.Methods;
1697 			for (int i = 0; i < methods.Count; i++) {
1698 				var method = methods [i];
1699 				if (method.sem_attrs_ready)
1700 					continue;
1701 
1702 				method.sem_attrs = ReadMethodSemantics (method);
1703 				method.sem_attrs_ready = true;
1704 			}
1705 		}
1706 
ReadMethods(TypeDefinition type)1707 		public Collection<MethodDefinition> ReadMethods (TypeDefinition type)
1708 		{
1709 			var methods_range = type.methods_range;
1710 			if (methods_range.Length == 0)
1711 				return new MemberDefinitionCollection<MethodDefinition> (type);
1712 
1713 			var methods = new MemberDefinitionCollection<MethodDefinition> (type, (int) methods_range.Length);
1714 			if (!MoveTo (Table.MethodPtr, methods_range.Start)) {
1715 				if (!MoveTo (Table.Method, methods_range.Start))
1716 					return methods;
1717 
1718 				for (uint i = 0; i < methods_range.Length; i++)
1719 					ReadMethod (methods_range.Start + i, methods);
1720 			} else
1721 				ReadPointers (Table.MethodPtr, Table.Method, methods_range, methods, ReadMethod);
1722 
1723 			return methods;
1724 		}
1725 
1726 		void ReadPointers<TMember> (Table ptr, Table table, Range range, Collection<TMember> members, Action<uint, Collection<TMember>> reader)
1727 			where TMember : IMemberDefinition
1728 		{
1729 			for (uint i = 0; i < range.Length; i++) {
1730 				MoveTo (ptr, range.Start + i);
1731 
1732 				var rid = ReadTableIndex (table);
1733 				MoveTo (table, rid);
1734 
1735 				reader (rid, members);
1736 			}
1737 		}
1738 
IsDeleted(IMemberDefinition member)1739 		static bool IsDeleted (IMemberDefinition member)
1740 		{
1741 			return member.IsSpecialName && member.Name == "_Deleted";
1742 		}
1743 
InitializeMethods()1744 		void InitializeMethods ()
1745 		{
1746 			if (metadata.Methods != null)
1747 				return;
1748 
1749 			metadata.Methods = new MethodDefinition [image.GetTableLength (Table.Method)];
1750 		}
1751 
ReadMethod(uint method_rid, Collection<MethodDefinition> methods)1752 		void ReadMethod (uint method_rid, Collection<MethodDefinition> methods)
1753 		{
1754 			var method = new MethodDefinition ();
1755 			method.rva = ReadUInt32 ();
1756 			method.ImplAttributes = (MethodImplAttributes) ReadUInt16 ();
1757 			method.Attributes = (MethodAttributes) ReadUInt16 ();
1758 			method.Name = ReadString ();
1759 			method.token = new MetadataToken (TokenType.Method, method_rid);
1760 
1761 			if (IsDeleted (method))
1762 				return;
1763 
1764 			methods.Add (method); // attach method
1765 
1766 			var signature = ReadBlobIndex ();
1767 			var param_range = ReadListRange (method_rid, Table.Method, Table.Param);
1768 
1769 			this.context = method;
1770 
1771 			ReadMethodSignature (signature, method);
1772 			metadata.AddMethodDefinition (method);
1773 
1774 			if (param_range.Length != 0) {
1775 				var position = base.position;
1776 				ReadParameters (method, param_range);
1777 				base.position = position;
1778 			}
1779 
1780 			if (module.IsWindowsMetadata ())
1781 				WindowsRuntimeProjections.Project (method);
1782 		}
1783 
ReadParameters(MethodDefinition method, Range param_range)1784 		void ReadParameters (MethodDefinition method, Range param_range)
1785 		{
1786 			if (!MoveTo (Table.ParamPtr, param_range.Start)) {
1787 				if (!MoveTo (Table.Param, param_range.Start))
1788 					return;
1789 
1790 				for (uint i = 0; i < param_range.Length; i++)
1791 					ReadParameter (param_range.Start + i, method);
1792 			} else
1793 				ReadParameterPointers (method, param_range);
1794 		}
1795 
ReadParameterPointers(MethodDefinition method, Range range)1796 		void ReadParameterPointers (MethodDefinition method, Range range)
1797 		{
1798 			for (uint i = 0; i < range.Length; i++) {
1799 				MoveTo (Table.ParamPtr, range.Start + i);
1800 
1801 				var rid = ReadTableIndex (Table.Param);
1802 
1803 				MoveTo (Table.Param, rid);
1804 
1805 				ReadParameter (rid, method);
1806 			}
1807 		}
1808 
ReadParameter(uint param_rid, MethodDefinition method)1809 		void ReadParameter (uint param_rid, MethodDefinition method)
1810 		{
1811 			var attributes = (ParameterAttributes) ReadUInt16 ();
1812 			var sequence = ReadUInt16 ();
1813 			var name = ReadString ();
1814 
1815 			var parameter = sequence == 0
1816 				? method.MethodReturnType.Parameter
1817 				: method.Parameters [sequence - 1];
1818 
1819 			parameter.token = new MetadataToken (TokenType.Param, param_rid);
1820 			parameter.Name = name;
1821 			parameter.Attributes = attributes;
1822 		}
1823 
ReadMethodSignature(uint signature, IMethodSignature method)1824 		void ReadMethodSignature (uint signature, IMethodSignature method)
1825 		{
1826 			var reader = ReadSignature (signature);
1827 			reader.ReadMethodSignature (method);
1828 		}
1829 
ReadPInvokeInfo(MethodDefinition method)1830 		public PInvokeInfo ReadPInvokeInfo (MethodDefinition method)
1831 		{
1832 			InitializePInvokes ();
1833 			Row<PInvokeAttributes, uint, uint> row;
1834 
1835 			var rid = method.token.RID;
1836 
1837 			if (!metadata.PInvokes.TryGetValue (rid, out row))
1838 				return null;
1839 
1840 			metadata.PInvokes.Remove (rid);
1841 
1842 			return new PInvokeInfo (
1843 				row.Col1,
1844 				image.StringHeap.Read (row.Col2),
1845 				module.ModuleReferences [(int) row.Col3 - 1]);
1846 		}
1847 
InitializePInvokes()1848 		void InitializePInvokes ()
1849 		{
1850 			if (metadata.PInvokes != null)
1851 				return;
1852 
1853 			int length = MoveTo (Table.ImplMap);
1854 
1855 			var pinvokes = metadata.PInvokes = new Dictionary<uint, Row<PInvokeAttributes, uint, uint>> (length);
1856 
1857 			for (int i = 1; i <= length; i++) {
1858 				var attributes = (PInvokeAttributes) ReadUInt16 ();
1859 				var method = ReadMetadataToken (CodedIndex.MemberForwarded);
1860 				var name = ReadStringIndex ();
1861 				var scope = ReadTableIndex (Table.File);
1862 
1863 				if (method.TokenType != TokenType.Method)
1864 					continue;
1865 
1866 				pinvokes.Add (method.RID, new Row<PInvokeAttributes, uint, uint> (attributes, name, scope));
1867 			}
1868 		}
1869 
HasGenericParameters(IGenericParameterProvider provider)1870 		public bool HasGenericParameters (IGenericParameterProvider provider)
1871 		{
1872 			InitializeGenericParameters ();
1873 
1874 			Range [] ranges;
1875 			if (!metadata.TryGetGenericParameterRanges (provider, out ranges))
1876 				return false;
1877 
1878 			return RangesSize (ranges) > 0;
1879 		}
1880 
ReadGenericParameters(IGenericParameterProvider provider)1881 		public Collection<GenericParameter> ReadGenericParameters (IGenericParameterProvider provider)
1882 		{
1883 			InitializeGenericParameters ();
1884 
1885 			Range [] ranges;
1886 			if (!metadata.TryGetGenericParameterRanges (provider, out ranges))
1887 				return new GenericParameterCollection (provider);
1888 
1889 			metadata.RemoveGenericParameterRange (provider);
1890 
1891 			var generic_parameters = new GenericParameterCollection (provider, RangesSize (ranges));
1892 
1893 			for (int i = 0; i < ranges.Length; i++)
1894 				ReadGenericParametersRange (ranges [i], provider, generic_parameters);
1895 
1896 			return generic_parameters;
1897 		}
1898 
ReadGenericParametersRange(Range range, IGenericParameterProvider provider, GenericParameterCollection generic_parameters)1899 		void ReadGenericParametersRange (Range range, IGenericParameterProvider provider, GenericParameterCollection generic_parameters)
1900 		{
1901 			if (!MoveTo (Table.GenericParam, range.Start))
1902 				return;
1903 
1904 			for (uint i = 0; i < range.Length; i++) {
1905 				ReadUInt16 (); // index
1906 				var flags = (GenericParameterAttributes) ReadUInt16 ();
1907 				ReadMetadataToken (CodedIndex.TypeOrMethodDef);
1908 				var name = ReadString ();
1909 
1910 				var parameter = new GenericParameter (name, provider);
1911 				parameter.token = new MetadataToken (TokenType.GenericParam, range.Start + i);
1912 				parameter.Attributes = flags;
1913 
1914 				generic_parameters.Add (parameter);
1915 			}
1916 		}
1917 
InitializeGenericParameters()1918 		void InitializeGenericParameters ()
1919 		{
1920 			if (metadata.GenericParameters != null)
1921 				return;
1922 
1923 			metadata.GenericParameters = InitializeRanges (
1924 				Table.GenericParam, () => {
1925 					Advance (4);
1926 					var next = ReadMetadataToken (CodedIndex.TypeOrMethodDef);
1927 					ReadStringIndex ();
1928 					return next;
1929 			});
1930 		}
1931 
InitializeRanges(Table table, Func<MetadataToken> get_next)1932 		Dictionary<MetadataToken, Range []> InitializeRanges (Table table, Func<MetadataToken> get_next)
1933 		{
1934 			int length = MoveTo (table);
1935 			var ranges = new Dictionary<MetadataToken, Range []> (length);
1936 
1937 			if (length == 0)
1938 				return ranges;
1939 
1940 			MetadataToken owner = MetadataToken.Zero;
1941 			Range range = new Range (1, 0);
1942 
1943 			for (uint i = 1; i <= length; i++) {
1944 				var next = get_next ();
1945 
1946 				if (i == 1) {
1947 					owner = next;
1948 					range.Length++;
1949 				} else if (next != owner) {
1950 					AddRange (ranges, owner, range);
1951 					range = new Range (i, 1);
1952 					owner = next;
1953 				} else
1954 					range.Length++;
1955 			}
1956 
1957 			AddRange (ranges, owner, range);
1958 
1959 			return ranges;
1960 		}
1961 
AddRange(Dictionary<MetadataToken, Range []> ranges, MetadataToken owner, Range range)1962 		static void AddRange (Dictionary<MetadataToken, Range []> ranges, MetadataToken owner, Range range)
1963 		{
1964 			if (owner.RID == 0)
1965 				return;
1966 
1967 			Range [] slots;
1968 			if (!ranges.TryGetValue (owner, out slots)) {
1969 				ranges.Add (owner, new [] { range });
1970 				return;
1971 			}
1972 
1973 			ranges [owner] = slots.Add(range);
1974 		}
1975 
HasGenericConstraints(GenericParameter generic_parameter)1976 		public bool HasGenericConstraints (GenericParameter generic_parameter)
1977 		{
1978 			InitializeGenericConstraints ();
1979 
1980 			Collection<MetadataToken> mapping;
1981 			if (!metadata.TryGetGenericConstraintMapping (generic_parameter, out mapping))
1982 				return false;
1983 
1984 			return mapping.Count > 0;
1985 		}
1986 
ReadGenericConstraints(GenericParameter generic_parameter)1987 		public Collection<TypeReference> ReadGenericConstraints (GenericParameter generic_parameter)
1988 		{
1989 			InitializeGenericConstraints ();
1990 
1991 			Collection<MetadataToken> mapping;
1992 			if (!metadata.TryGetGenericConstraintMapping (generic_parameter, out mapping))
1993 				return new Collection<TypeReference> ();
1994 
1995 			var constraints = new Collection<TypeReference> (mapping.Count);
1996 
1997 			this.context = (IGenericContext) generic_parameter.Owner;
1998 
1999 			for (int i = 0; i < mapping.Count; i++)
2000 				constraints.Add (GetTypeDefOrRef (mapping [i]));
2001 
2002 			metadata.RemoveGenericConstraintMapping (generic_parameter);
2003 
2004 			return constraints;
2005 		}
2006 
InitializeGenericConstraints()2007 		void InitializeGenericConstraints ()
2008 		{
2009 			if (metadata.GenericConstraints != null)
2010 				return;
2011 
2012 			var length = MoveTo (Table.GenericParamConstraint);
2013 
2014 			metadata.GenericConstraints = new Dictionary<uint, Collection<MetadataToken>> (length);
2015 
2016 			for (int i = 1; i <= length; i++)
2017 				AddGenericConstraintMapping (
2018 					ReadTableIndex (Table.GenericParam),
2019 					ReadMetadataToken (CodedIndex.TypeDefOrRef));
2020 		}
2021 
AddGenericConstraintMapping(uint generic_parameter, MetadataToken constraint)2022 		void AddGenericConstraintMapping (uint generic_parameter, MetadataToken constraint)
2023 		{
2024 			metadata.SetGenericConstraintMapping (
2025 				generic_parameter,
2026 				AddMapping (metadata.GenericConstraints, generic_parameter, constraint));
2027 		}
2028 
HasOverrides(MethodDefinition method)2029 		public bool HasOverrides (MethodDefinition method)
2030 		{
2031 			InitializeOverrides ();
2032 			Collection<MetadataToken> mapping;
2033 
2034 			if (!metadata.TryGetOverrideMapping (method, out mapping))
2035 				return false;
2036 
2037 			return mapping.Count > 0;
2038 		}
2039 
ReadOverrides(MethodDefinition method)2040 		public Collection<MethodReference> ReadOverrides (MethodDefinition method)
2041 		{
2042 			InitializeOverrides ();
2043 
2044 			Collection<MetadataToken> mapping;
2045 			if (!metadata.TryGetOverrideMapping (method, out mapping))
2046 				return new Collection<MethodReference> ();
2047 
2048 			var overrides = new Collection<MethodReference> (mapping.Count);
2049 
2050 			this.context = method;
2051 
2052 			for (int i = 0; i < mapping.Count; i++)
2053 				overrides.Add ((MethodReference) LookupToken (mapping [i]));
2054 
2055 			metadata.RemoveOverrideMapping (method);
2056 
2057 			return overrides;
2058 		}
2059 
InitializeOverrides()2060 		void InitializeOverrides ()
2061 		{
2062 			if (metadata.Overrides != null)
2063 				return;
2064 
2065 			var length = MoveTo (Table.MethodImpl);
2066 
2067 			metadata.Overrides = new Dictionary<uint, Collection<MetadataToken>> (length);
2068 
2069 			for (int i = 1; i <= length; i++) {
2070 				ReadTableIndex (Table.TypeDef);
2071 
2072 				var method = ReadMetadataToken (CodedIndex.MethodDefOrRef);
2073 				if (method.TokenType != TokenType.Method)
2074 					throw new NotSupportedException ();
2075 
2076 				var @override = ReadMetadataToken (CodedIndex.MethodDefOrRef);
2077 
2078 				AddOverrideMapping (method.RID, @override);
2079 			}
2080 		}
2081 
AddOverrideMapping(uint method_rid, MetadataToken @override)2082 		void AddOverrideMapping (uint method_rid, MetadataToken @override)
2083 		{
2084 			metadata.SetOverrideMapping (
2085 				method_rid,
2086 				AddMapping (metadata.Overrides, method_rid, @override));
2087 		}
2088 
ReadMethodBody(MethodDefinition method)2089 		public MethodBody ReadMethodBody (MethodDefinition method)
2090 		{
2091 			return code.ReadMethodBody (method);
2092 		}
2093 
ReadCodeSize(MethodDefinition method)2094 		public int ReadCodeSize (MethodDefinition method)
2095 		{
2096 			return code.ReadCodeSize (method);
2097 		}
2098 
ReadCallSite(MetadataToken token)2099 		public CallSite ReadCallSite (MetadataToken token)
2100 		{
2101 			if (!MoveTo (Table.StandAloneSig, token.RID))
2102 				return null;
2103 
2104 			var signature = ReadBlobIndex ();
2105 
2106 			var call_site = new CallSite ();
2107 
2108 			ReadMethodSignature (signature, call_site);
2109 
2110 			call_site.MetadataToken = token;
2111 
2112 			return call_site;
2113 		}
2114 
ReadVariables(MetadataToken local_var_token)2115 		public VariableDefinitionCollection ReadVariables (MetadataToken local_var_token)
2116 		{
2117 			if (!MoveTo (Table.StandAloneSig, local_var_token.RID))
2118 				return null;
2119 
2120 			var reader = ReadSignature (ReadBlobIndex ());
2121 			const byte local_sig = 0x7;
2122 
2123 			if (reader.ReadByte () != local_sig)
2124 				throw new NotSupportedException ();
2125 
2126 			var count = reader.ReadCompressedUInt32 ();
2127 			if (count == 0)
2128 				return null;
2129 
2130 			var variables = new VariableDefinitionCollection ((int) count);
2131 
2132 			for (int i = 0; i < count; i++)
2133 				variables.Add (new VariableDefinition (reader.ReadTypeSignature ()));
2134 
2135 			return variables;
2136 		}
2137 
LookupToken(MetadataToken token)2138 		public IMetadataTokenProvider LookupToken (MetadataToken token)
2139 		{
2140 			var rid = token.RID;
2141 
2142 			if (rid == 0)
2143 				return null;
2144 
2145 			if (metadata_reader != null)
2146 				return metadata_reader.LookupToken (token);
2147 
2148 			IMetadataTokenProvider element;
2149 			var position = this.position;
2150 			var context = this.context;
2151 
2152 			switch (token.TokenType) {
2153 			case TokenType.TypeDef:
2154 				element = GetTypeDefinition (rid);
2155 				break;
2156 			case TokenType.TypeRef:
2157 				element = GetTypeReference (rid);
2158 				break;
2159 			case TokenType.TypeSpec:
2160 				element = GetTypeSpecification (rid);
2161 				break;
2162 			case TokenType.Field:
2163 				element = GetFieldDefinition (rid);
2164 				break;
2165 			case TokenType.Method:
2166 				element = GetMethodDefinition (rid);
2167 				break;
2168 			case TokenType.MemberRef:
2169 				element = GetMemberReference (rid);
2170 				break;
2171 			case TokenType.MethodSpec:
2172 				element = GetMethodSpecification (rid);
2173 				break;
2174 			default:
2175 				return null;
2176 			}
2177 
2178 			this.position = position;
2179 			this.context = context;
2180 
2181 			return element;
2182 		}
2183 
GetFieldDefinition(uint rid)2184 		public FieldDefinition GetFieldDefinition (uint rid)
2185 		{
2186 			InitializeTypeDefinitions ();
2187 
2188 			var field = metadata.GetFieldDefinition (rid);
2189 			if (field != null)
2190 				return field;
2191 
2192 			return LookupField (rid);
2193 		}
2194 
LookupField(uint rid)2195 		FieldDefinition LookupField (uint rid)
2196 		{
2197 			var type = metadata.GetFieldDeclaringType (rid);
2198 			if (type == null)
2199 				return null;
2200 
2201 			Mixin.Read (type.Fields);
2202 
2203 			return metadata.GetFieldDefinition (rid);
2204 		}
2205 
GetMethodDefinition(uint rid)2206 		public MethodDefinition GetMethodDefinition (uint rid)
2207 		{
2208 			InitializeTypeDefinitions ();
2209 
2210 			var method = metadata.GetMethodDefinition (rid);
2211 			if (method != null)
2212 				return method;
2213 
2214 			return LookupMethod (rid);
2215 		}
2216 
LookupMethod(uint rid)2217 		MethodDefinition LookupMethod (uint rid)
2218 		{
2219 			var type = metadata.GetMethodDeclaringType (rid);
2220 			if (type == null)
2221 				return null;
2222 
2223 			Mixin.Read (type.Methods);
2224 
2225 			return metadata.GetMethodDefinition (rid);
2226 		}
2227 
GetMethodSpecification(uint rid)2228 		MethodSpecification GetMethodSpecification (uint rid)
2229 		{
2230 			if (!MoveTo (Table.MethodSpec, rid))
2231 				return null;
2232 
2233 			var element_method = (MethodReference) LookupToken (
2234 				ReadMetadataToken (CodedIndex.MethodDefOrRef));
2235 			var signature = ReadBlobIndex ();
2236 
2237 			var method_spec = ReadMethodSpecSignature (signature, element_method);
2238 			method_spec.token = new MetadataToken (TokenType.MethodSpec, rid);
2239 			return method_spec;
2240 		}
2241 
ReadMethodSpecSignature(uint signature, MethodReference method)2242 		MethodSpecification ReadMethodSpecSignature (uint signature, MethodReference method)
2243 		{
2244 			var reader = ReadSignature (signature);
2245 			const byte methodspec_sig = 0x0a;
2246 
2247 			var call_conv = reader.ReadByte ();
2248 
2249 			if (call_conv != methodspec_sig)
2250 				throw new NotSupportedException ();
2251 
2252 			var instance = new GenericInstanceMethod (method);
2253 
2254 			reader.ReadGenericInstanceSignature (method, instance);
2255 
2256 			return instance;
2257 		}
2258 
GetMemberReference(uint rid)2259 		MemberReference GetMemberReference (uint rid)
2260 		{
2261 			InitializeMemberReferences ();
2262 
2263 			var member = metadata.GetMemberReference (rid);
2264 			if (member != null)
2265 				return member;
2266 
2267 			member = ReadMemberReference (rid);
2268 			if (member != null && !member.ContainsGenericParameter)
2269 				metadata.AddMemberReference (member);
2270 			return member;
2271 		}
2272 
ReadMemberReference(uint rid)2273 		MemberReference ReadMemberReference (uint rid)
2274 		{
2275 			if (!MoveTo (Table.MemberRef, rid))
2276 				return null;
2277 
2278 			var token = ReadMetadataToken (CodedIndex.MemberRefParent);
2279 			var name = ReadString ();
2280 			var signature = ReadBlobIndex ();
2281 
2282 			MemberReference member;
2283 
2284 			switch (token.TokenType) {
2285 			case TokenType.TypeDef:
2286 			case TokenType.TypeRef:
2287 			case TokenType.TypeSpec:
2288 				member = ReadTypeMemberReference (token, name, signature);
2289 				break;
2290 			case TokenType.Method:
2291 				member = ReadMethodMemberReference (token, name, signature);
2292 				break;
2293 			default:
2294 				throw new NotSupportedException ();
2295 			}
2296 
2297 			member.token = new MetadataToken (TokenType.MemberRef, rid);
2298 
2299 			if (module.IsWindowsMetadata ())
2300 				WindowsRuntimeProjections.Project (member);
2301 
2302 			return member;
2303 		}
2304 
ReadTypeMemberReference(MetadataToken type, string name, uint signature)2305 		MemberReference ReadTypeMemberReference (MetadataToken type, string name, uint signature)
2306 		{
2307 			var declaring_type = GetTypeDefOrRef (type);
2308 
2309 			if (!declaring_type.IsArray)
2310 				this.context = declaring_type;
2311 
2312 			var member = ReadMemberReferenceSignature (signature, declaring_type);
2313 			member.Name = name;
2314 
2315 			return member;
2316 		}
2317 
ReadMemberReferenceSignature(uint signature, TypeReference declaring_type)2318 		MemberReference ReadMemberReferenceSignature (uint signature, TypeReference declaring_type)
2319 		{
2320 			var reader = ReadSignature (signature);
2321 			const byte field_sig = 0x6;
2322 
2323 			if (reader.buffer [reader.position] == field_sig) {
2324 				reader.position++;
2325 				var field = new FieldReference ();
2326 				field.DeclaringType = declaring_type;
2327 				field.FieldType = reader.ReadTypeSignature ();
2328 				return field;
2329 			} else {
2330 				var method = new MethodReference ();
2331 				method.DeclaringType = declaring_type;
2332 				reader.ReadMethodSignature (method);
2333 				return method;
2334 			}
2335 		}
2336 
ReadMethodMemberReference(MetadataToken token, string name, uint signature)2337 		MemberReference ReadMethodMemberReference (MetadataToken token, string name, uint signature)
2338 		{
2339 			var method = GetMethodDefinition (token.RID);
2340 
2341 			this.context = method;
2342 
2343 			var member = ReadMemberReferenceSignature (signature, method.DeclaringType);
2344 			member.Name = name;
2345 
2346 			return member;
2347 		}
2348 
InitializeMemberReferences()2349 		void InitializeMemberReferences ()
2350 		{
2351 			if (metadata.MemberReferences != null)
2352 				return;
2353 
2354 			metadata.MemberReferences = new MemberReference [image.GetTableLength (Table.MemberRef)];
2355 		}
2356 
GetMemberReferences()2357 		public IEnumerable<MemberReference> GetMemberReferences ()
2358 		{
2359 			InitializeMemberReferences ();
2360 
2361 			var length = image.GetTableLength (Table.MemberRef);
2362 
2363 			var type_system = module.TypeSystem;
2364 
2365 			var context = new MethodDefinition (string.Empty, MethodAttributes.Static, type_system.Void);
2366 			context.DeclaringType = new TypeDefinition (string.Empty, string.Empty, TypeAttributes.Public);
2367 
2368 			var member_references = new MemberReference [length];
2369 
2370 			for (uint i = 1; i <= length; i++) {
2371 				this.context = context;
2372 				member_references [i - 1] = GetMemberReference (i);
2373 			}
2374 
2375 			return member_references;
2376 		}
2377 
InitializeConstants()2378 		void InitializeConstants ()
2379 		{
2380 			if (metadata.Constants != null)
2381 				return;
2382 
2383 			var length = MoveTo (Table.Constant);
2384 
2385 			var constants = metadata.Constants = new Dictionary<MetadataToken, Row<ElementType, uint>> (length);
2386 
2387 			for (uint i = 1; i <= length; i++) {
2388 				var type = (ElementType) ReadUInt16 ();
2389 				var owner = ReadMetadataToken (CodedIndex.HasConstant);
2390 				var signature = ReadBlobIndex ();
2391 
2392 				constants.Add (owner, new Row<ElementType, uint> (type, signature));
2393 			}
2394 		}
2395 
ReadConstantSignature(MetadataToken token)2396 		public TypeReference ReadConstantSignature (MetadataToken token)
2397 		{
2398 			if (token.TokenType != TokenType.Signature)
2399 				throw new NotSupportedException ();
2400 
2401 			if (!MoveTo (Table.StandAloneSig, token.RID))
2402 				return null;
2403 
2404 			return ReadFieldType (ReadBlobIndex ());
2405 		}
2406 
ReadConstant(IConstantProvider owner)2407 		public object ReadConstant (IConstantProvider owner)
2408 		{
2409 			InitializeConstants ();
2410 
2411 			Row<ElementType, uint> row;
2412 			if (!metadata.Constants.TryGetValue (owner.MetadataToken, out row))
2413 				return Mixin.NoValue;
2414 
2415 			metadata.Constants.Remove (owner.MetadataToken);
2416 
2417 			return ReadConstantValue (row.Col1, row.Col2);
2418 		}
2419 
ReadConstantValue(ElementType etype, uint signature)2420 		object ReadConstantValue (ElementType etype, uint signature)
2421 		{
2422 			switch (etype) {
2423 			case ElementType.Class:
2424 			case ElementType.Object:
2425 				return null;
2426 			case ElementType.String:
2427 				return ReadConstantString (signature);
2428 			default:
2429 				return ReadConstantPrimitive (etype, signature);
2430 			}
2431 		}
2432 
ReadConstantString(uint signature)2433 		string ReadConstantString (uint signature)
2434 		{
2435 			byte [] blob;
2436 			int index, count;
2437 
2438 			GetBlobView (signature, out blob, out index, out count);
2439 			if (count == 0)
2440 				return string.Empty;
2441 
2442 			if ((count & 1) == 1)
2443 				count--;
2444 
2445 			return Encoding.Unicode.GetString (blob, index, count);
2446 		}
2447 
ReadConstantPrimitive(ElementType type, uint signature)2448 		object ReadConstantPrimitive (ElementType type, uint signature)
2449 		{
2450 			var reader = ReadSignature (signature);
2451 			return reader.ReadConstantSignature (type);
2452 		}
2453 
InitializeCustomAttributes()2454 		internal void InitializeCustomAttributes ()
2455 		{
2456 			if (metadata.CustomAttributes != null)
2457 				return;
2458 
2459 			metadata.CustomAttributes = InitializeRanges (
2460 				Table.CustomAttribute, () => {
2461 					var next = ReadMetadataToken (CodedIndex.HasCustomAttribute);
2462 					ReadMetadataToken (CodedIndex.CustomAttributeType);
2463 					ReadBlobIndex ();
2464 					return next;
2465 			});
2466 		}
2467 
HasCustomAttributes(ICustomAttributeProvider owner)2468 		public bool HasCustomAttributes (ICustomAttributeProvider owner)
2469 		{
2470 			InitializeCustomAttributes ();
2471 
2472 			Range [] ranges;
2473 			if (!metadata.TryGetCustomAttributeRanges (owner, out ranges))
2474 				return false;
2475 
2476 			return RangesSize (ranges) > 0;
2477 		}
2478 
ReadCustomAttributes(ICustomAttributeProvider owner)2479 		public Collection<CustomAttribute> ReadCustomAttributes (ICustomAttributeProvider owner)
2480 		{
2481 			InitializeCustomAttributes ();
2482 
2483 			Range [] ranges;
2484 			if (!metadata.TryGetCustomAttributeRanges (owner, out ranges))
2485 				return new Collection<CustomAttribute> ();
2486 
2487 			var custom_attributes = new Collection<CustomAttribute> (RangesSize (ranges));
2488 
2489 			for (int i = 0; i < ranges.Length; i++)
2490 				ReadCustomAttributeRange (ranges [i], custom_attributes);
2491 
2492 			metadata.RemoveCustomAttributeRange (owner);
2493 
2494 			if (module.IsWindowsMetadata ())
2495 				foreach (var custom_attribute in custom_attributes)
2496 					WindowsRuntimeProjections.Project (owner, custom_attribute);
2497 
2498 			return custom_attributes;
2499 		}
2500 
ReadCustomAttributeRange(Range range, Collection<CustomAttribute> custom_attributes)2501 		void ReadCustomAttributeRange (Range range, Collection<CustomAttribute> custom_attributes)
2502 		{
2503 			if (!MoveTo (Table.CustomAttribute, range.Start))
2504 				return;
2505 
2506 			for (var i = 0; i < range.Length; i++) {
2507 				ReadMetadataToken (CodedIndex.HasCustomAttribute);
2508 
2509 				var constructor = (MethodReference) LookupToken (
2510 					ReadMetadataToken (CodedIndex.CustomAttributeType));
2511 
2512 				var signature = ReadBlobIndex ();
2513 
2514 				custom_attributes.Add (new CustomAttribute (signature, constructor));
2515 			}
2516 		}
2517 
RangesSize(Range [] ranges)2518 		static int RangesSize (Range [] ranges)
2519 		{
2520 			uint size = 0;
2521 			for (int i = 0; i < ranges.Length; i++)
2522 				size += ranges [i].Length;
2523 
2524 			return (int) size;
2525 		}
2526 
GetCustomAttributes()2527 		public IEnumerable<CustomAttribute> GetCustomAttributes ()
2528 		{
2529 			InitializeTypeDefinitions ();
2530 
2531 			var length = image.TableHeap [Table.CustomAttribute].Length;
2532 			var custom_attributes = new Collection<CustomAttribute> ((int) length);
2533 			ReadCustomAttributeRange (new Range (1, length), custom_attributes);
2534 
2535 			return custom_attributes;
2536 		}
2537 
ReadCustomAttributeBlob(uint signature)2538 		public byte [] ReadCustomAttributeBlob (uint signature)
2539 		{
2540 			return ReadBlob (signature);
2541 		}
2542 
ReadCustomAttributeSignature(CustomAttribute attribute)2543 		public void ReadCustomAttributeSignature (CustomAttribute attribute)
2544 		{
2545 			var reader = ReadSignature (attribute.signature);
2546 
2547 			if (!reader.CanReadMore ())
2548 				return;
2549 
2550 			if (reader.ReadUInt16 () != 0x0001)
2551 				throw new InvalidOperationException ();
2552 
2553 			var constructor = attribute.Constructor;
2554 			if (constructor.HasParameters)
2555 				reader.ReadCustomAttributeConstructorArguments (attribute, constructor.Parameters);
2556 
2557 			if (!reader.CanReadMore ())
2558 				return;
2559 
2560 			var named = reader.ReadUInt16 ();
2561 
2562 			if (named == 0)
2563 				return;
2564 
2565 			reader.ReadCustomAttributeNamedArguments (named, ref attribute.fields, ref attribute.properties);
2566 		}
2567 
InitializeMarshalInfos()2568 		void InitializeMarshalInfos ()
2569 		{
2570 			if (metadata.FieldMarshals != null)
2571 				return;
2572 
2573 			var length = MoveTo (Table.FieldMarshal);
2574 
2575 			var marshals = metadata.FieldMarshals = new Dictionary<MetadataToken, uint> (length);
2576 
2577 			for (int i = 0; i < length; i++) {
2578 				var token = ReadMetadataToken (CodedIndex.HasFieldMarshal);
2579 				var signature = ReadBlobIndex ();
2580 				if (token.RID == 0)
2581 					continue;
2582 
2583 				marshals.Add (token, signature);
2584 			}
2585 		}
2586 
HasMarshalInfo(IMarshalInfoProvider owner)2587 		public bool HasMarshalInfo (IMarshalInfoProvider owner)
2588 		{
2589 			InitializeMarshalInfos ();
2590 
2591 			return metadata.FieldMarshals.ContainsKey (owner.MetadataToken);
2592 		}
2593 
ReadMarshalInfo(IMarshalInfoProvider owner)2594 		public MarshalInfo ReadMarshalInfo (IMarshalInfoProvider owner)
2595 		{
2596 			InitializeMarshalInfos ();
2597 
2598 			uint signature;
2599 			if (!metadata.FieldMarshals.TryGetValue (owner.MetadataToken, out signature))
2600 				return null;
2601 
2602 			var reader = ReadSignature (signature);
2603 
2604 			metadata.FieldMarshals.Remove (owner.MetadataToken);
2605 
2606 			return reader.ReadMarshalInfo ();
2607 		}
2608 
InitializeSecurityDeclarations()2609 		void InitializeSecurityDeclarations ()
2610 		{
2611 			if (metadata.SecurityDeclarations != null)
2612 				return;
2613 
2614 			metadata.SecurityDeclarations = InitializeRanges (
2615 				Table.DeclSecurity, () => {
2616 					ReadUInt16 ();
2617 					var next = ReadMetadataToken (CodedIndex.HasDeclSecurity);
2618 					ReadBlobIndex ();
2619 					return next;
2620 			});
2621 		}
2622 
HasSecurityDeclarations(ISecurityDeclarationProvider owner)2623 		public bool HasSecurityDeclarations (ISecurityDeclarationProvider owner)
2624 		{
2625 			InitializeSecurityDeclarations ();
2626 
2627 			Range [] ranges;
2628 			if (!metadata.TryGetSecurityDeclarationRanges (owner, out ranges))
2629 				return false;
2630 
2631 			return RangesSize (ranges) > 0;
2632 		}
2633 
ReadSecurityDeclarations(ISecurityDeclarationProvider owner)2634 		public Collection<SecurityDeclaration> ReadSecurityDeclarations (ISecurityDeclarationProvider owner)
2635 		{
2636 			InitializeSecurityDeclarations ();
2637 
2638 			Range [] ranges;
2639 			if (!metadata.TryGetSecurityDeclarationRanges (owner, out ranges))
2640 				return new Collection<SecurityDeclaration> ();
2641 
2642 			var security_declarations = new Collection<SecurityDeclaration> (RangesSize (ranges));
2643 
2644 			for (int i = 0; i < ranges.Length; i++)
2645 				ReadSecurityDeclarationRange (ranges [i], security_declarations);
2646 
2647 			metadata.RemoveSecurityDeclarationRange (owner);
2648 
2649 			return security_declarations;
2650 		}
2651 
ReadSecurityDeclarationRange(Range range, Collection<SecurityDeclaration> security_declarations)2652 		void ReadSecurityDeclarationRange (Range range, Collection<SecurityDeclaration> security_declarations)
2653 		{
2654 			if (!MoveTo (Table.DeclSecurity, range.Start))
2655 				return;
2656 
2657 			for (int i = 0; i < range.Length; i++) {
2658 				var action = (SecurityAction) ReadUInt16 ();
2659 				ReadMetadataToken (CodedIndex.HasDeclSecurity);
2660 				var signature = ReadBlobIndex ();
2661 
2662 				security_declarations.Add (new SecurityDeclaration (action, signature, module));
2663 			}
2664 		}
2665 
ReadSecurityDeclarationBlob(uint signature)2666 		public byte [] ReadSecurityDeclarationBlob (uint signature)
2667 		{
2668 			return ReadBlob (signature);
2669 		}
2670 
ReadSecurityDeclarationSignature(SecurityDeclaration declaration)2671 		public void ReadSecurityDeclarationSignature (SecurityDeclaration declaration)
2672 		{
2673 			var signature = declaration.signature;
2674 			var reader = ReadSignature (signature);
2675 
2676 			if (reader.buffer [reader.position] != '.') {
2677 				ReadXmlSecurityDeclaration (signature, declaration);
2678 				return;
2679 			}
2680 
2681 			reader.position++;
2682 			var count = reader.ReadCompressedUInt32 ();
2683 			var attributes = new Collection<SecurityAttribute> ((int) count);
2684 
2685 			for (int i = 0; i < count; i++)
2686 				attributes.Add (reader.ReadSecurityAttribute ());
2687 
2688 			declaration.security_attributes = attributes;
2689 		}
2690 
ReadXmlSecurityDeclaration(uint signature, SecurityDeclaration declaration)2691 		void ReadXmlSecurityDeclaration (uint signature, SecurityDeclaration declaration)
2692 		{
2693 			var attributes = new Collection<SecurityAttribute> (1);
2694 
2695 			var attribute = new SecurityAttribute (
2696 				module.TypeSystem.LookupType ("System.Security.Permissions", "PermissionSetAttribute"));
2697 
2698 			attribute.properties = new Collection<CustomAttributeNamedArgument> (1);
2699 			attribute.properties.Add (
2700 				new CustomAttributeNamedArgument (
2701 					"XML",
2702 					new CustomAttributeArgument (
2703 						module.TypeSystem.String,
2704 						ReadUnicodeStringBlob (signature))));
2705 
2706 			attributes.Add (attribute);
2707 
2708 			declaration.security_attributes = attributes;
2709 		}
2710 
ReadExportedTypes()2711 		public Collection<ExportedType> ReadExportedTypes ()
2712 		{
2713 			var length = MoveTo (Table.ExportedType);
2714 			if (length == 0)
2715 				return new Collection<ExportedType> ();
2716 
2717 			var exported_types = new Collection<ExportedType> (length);
2718 
2719 			for (int i = 1; i <= length; i++) {
2720 				var attributes = (TypeAttributes) ReadUInt32 ();
2721 				var identifier = ReadUInt32 ();
2722 				var name = ReadString ();
2723 				var @namespace = ReadString ();
2724 				var implementation = ReadMetadataToken (CodedIndex.Implementation);
2725 
2726 				ExportedType declaring_type = null;
2727 				IMetadataScope scope = null;
2728 
2729 				switch (implementation.TokenType) {
2730 				case TokenType.AssemblyRef:
2731 				case TokenType.File:
2732 					scope = GetExportedTypeScope (implementation);
2733 					break;
2734 				case TokenType.ExportedType:
2735 					// FIXME: if the table is not properly sorted
2736 					declaring_type = exported_types [(int) implementation.RID - 1];
2737 					break;
2738 				}
2739 
2740 				var exported_type = new ExportedType (@namespace, name, module, scope) {
2741 					Attributes = attributes,
2742 					Identifier = (int) identifier,
2743 					DeclaringType = declaring_type,
2744 				};
2745 				exported_type.token = new MetadataToken (TokenType.ExportedType, i);
2746 
2747 				exported_types.Add (exported_type);
2748 			}
2749 
2750 			return exported_types;
2751 		}
2752 
GetExportedTypeScope(MetadataToken token)2753 		IMetadataScope GetExportedTypeScope (MetadataToken token)
2754 		{
2755 			var position = this.position;
2756 			IMetadataScope scope;
2757 
2758 			switch (token.TokenType) {
2759 			case TokenType.AssemblyRef:
2760 				InitializeAssemblyReferences ();
2761 				scope = metadata.GetAssemblyNameReference (token.RID);
2762 				break;
2763 			case TokenType.File:
2764 				InitializeModuleReferences ();
2765 				scope = GetModuleReferenceFromFile (token);
2766 				break;
2767 			default:
2768 				throw new NotSupportedException ();
2769 			}
2770 
2771 			this.position = position;
2772 			return scope;
2773 		}
2774 
GetModuleReferenceFromFile(MetadataToken token)2775 		ModuleReference GetModuleReferenceFromFile (MetadataToken token)
2776 		{
2777 			if (!MoveTo (Table.File, token.RID))
2778 				return null;
2779 
2780 			ReadUInt32 ();
2781 			var file_name = ReadString ();
2782 			var modules = module.ModuleReferences;
2783 
2784 			ModuleReference reference;
2785 			for (int i = 0; i < modules.Count; i++) {
2786 				reference = modules [i];
2787 				if (reference.Name == file_name)
2788 					return reference;
2789 			}
2790 
2791 			reference = new ModuleReference (file_name);
2792 			modules.Add (reference);
2793 			return reference;
2794 		}
2795 
InitializeDocuments()2796 		void InitializeDocuments ()
2797 		{
2798 			if (metadata.Documents != null)
2799 				return;
2800 
2801 			int length = MoveTo (Table.Document);
2802 
2803 			var documents = metadata.Documents = new Document [length];
2804 
2805 			for (uint i = 1; i <= length; i++) {
2806 				var name_index = ReadBlobIndex ();
2807 				var hash_algorithm = ReadGuid ();
2808 				var hash = ReadBlob ();
2809 				var language = ReadGuid ();
2810 
2811 				var signature = ReadSignature (name_index);
2812 				var name = signature.ReadDocumentName ();
2813 
2814 				documents [i - 1] = new Document (name) {
2815 					HashAlgorithm = hash_algorithm.ToHashAlgorithm (),
2816 					Hash = hash,
2817 					Language = language.ToLanguage (),
2818 					token = new MetadataToken (TokenType.Document, i),
2819 				};
2820 			}
2821 		}
2822 
ReadSequencePoints(MethodDefinition method)2823 		public Collection<SequencePoint> ReadSequencePoints (MethodDefinition method)
2824 		{
2825 			InitializeDocuments ();
2826 
2827 			if (!MoveTo (Table.MethodDebugInformation, method.MetadataToken.RID))
2828 				return new Collection<SequencePoint> (0);
2829 
2830 			var document_index = ReadTableIndex (Table.Document);
2831 			var signature = ReadBlobIndex ();
2832 			if (signature == 0)
2833 				return new Collection<SequencePoint> (0);
2834 
2835 			var document = GetDocument (document_index);
2836 			var reader = ReadSignature (signature);
2837 
2838 			return reader.ReadSequencePoints (document);
2839 		}
2840 
GetDocument(uint rid)2841 		public Document GetDocument (uint rid)
2842 		{
2843 			var document = metadata.GetDocument (rid);
2844 			if (document == null)
2845 				return null;
2846 
2847 			document.custom_infos = GetCustomDebugInformation (document);
2848 			return document;
2849 		}
2850 
InitializeLocalScopes()2851 		void InitializeLocalScopes ()
2852 		{
2853 			if (metadata.LocalScopes != null)
2854 				return;
2855 
2856 			InitializeMethods ();
2857 
2858 			int length = MoveTo (Table.LocalScope);
2859 
2860 			metadata.LocalScopes = new Dictionary<uint, Collection<Row<uint, Range, Range, uint, uint, uint>>> ();
2861 
2862 			for (uint i = 1; i <= length; i++) {
2863 				var method = ReadTableIndex (Table.Method);
2864 				var import = ReadTableIndex (Table.ImportScope);
2865 				var variables = ReadListRange (i, Table.LocalScope, Table.LocalVariable);
2866 				var constants = ReadListRange (i, Table.LocalScope, Table.LocalConstant);
2867 				var scope_start = ReadUInt32 ();
2868 				var scope_length = ReadUInt32 ();
2869 
2870 				metadata.SetLocalScopes (method, AddMapping (metadata.LocalScopes, method, new Row<uint, Range, Range, uint, uint, uint> (import, variables, constants, scope_start, scope_length, i)));
2871 			}
2872 		}
2873 
ReadScope(MethodDefinition method)2874 		public ScopeDebugInformation ReadScope (MethodDefinition method)
2875 		{
2876 			InitializeLocalScopes ();
2877 			InitializeImportScopes ();
2878 
2879 			Collection<Row<uint, Range, Range, uint, uint, uint>> records;
2880 			if (!metadata.TryGetLocalScopes (method, out records))
2881 				return null;
2882 
2883 			var method_scope = null as ScopeDebugInformation;
2884 
2885 			for (int i = 0; i < records.Count; i++) {
2886 				var scope = ReadLocalScope (records [i]);
2887 
2888 				if (i == 0) {
2889 					method_scope = scope;
2890 					continue;
2891 				}
2892 
2893 				if (!AddScope (method_scope.scopes, scope))
2894 					method_scope.Scopes.Add (scope);
2895 			}
2896 
2897 			return method_scope;
2898 		}
2899 
AddScope(Collection<ScopeDebugInformation> scopes, ScopeDebugInformation scope)2900 		static bool AddScope (Collection<ScopeDebugInformation> scopes, ScopeDebugInformation scope)
2901 		{
2902 			if (scopes.IsNullOrEmpty ())
2903 				return false;
2904 
2905 			foreach (var sub_scope in scopes) {
2906 				if (sub_scope.HasScopes && AddScope (sub_scope.Scopes, scope))
2907 					return true;
2908 
2909 				if (scope.Start.Offset >= sub_scope.Start.Offset && scope.End.Offset <= sub_scope.End.Offset) {
2910 					sub_scope.Scopes.Add (scope);
2911 					return true;
2912 				}
2913 			}
2914 
2915 			return false;
2916 		}
2917 
ReadLocalScope(Row<uint, Range, Range, uint, uint, uint> record)2918 		ScopeDebugInformation ReadLocalScope (Row<uint, Range, Range, uint, uint, uint> record)
2919 		{
2920 			var scope = new ScopeDebugInformation
2921 			{
2922 				start = new InstructionOffset ((int) record.Col4),
2923 				end = new InstructionOffset ((int) (record.Col4 + record.Col5)),
2924 				token = new MetadataToken (TokenType.LocalScope, record.Col6),
2925 			};
2926 
2927 			if (record.Col1 > 0)
2928 				scope.import = metadata.GetImportScope (record.Col1);
2929 
2930 			if (record.Col2.Length > 0) {
2931 				scope.variables = new Collection<VariableDebugInformation> ((int) record.Col2.Length);
2932 				for (uint i = 0; i < record.Col2.Length; i++) {
2933 					var variable = ReadLocalVariable (record.Col2.Start + i);
2934 					if (variable != null)
2935 						scope.variables.Add (variable);
2936 				}
2937 			}
2938 
2939 			if (record.Col3.Length > 0) {
2940 				scope.constants = new Collection<ConstantDebugInformation> ((int) record.Col3.Length);
2941 				for (uint i = 0; i < record.Col3.Length; i++) {
2942 					var constant = ReadLocalConstant (record.Col3.Start + i);
2943 					if (constant != null)
2944 						scope.constants.Add (constant);
2945 				}
2946 			}
2947 
2948 			return scope;
2949 		}
2950 
ReadLocalVariable(uint rid)2951 		VariableDebugInformation ReadLocalVariable (uint rid)
2952 		{
2953 			if (!MoveTo (Table.LocalVariable, rid))
2954 				return null;
2955 
2956 			var attributes = (VariableAttributes) ReadUInt16 ();
2957 			var index = ReadUInt16 ();
2958 			var name = ReadString ();
2959 
2960 			var variable = new VariableDebugInformation (index, name) { Attributes = attributes, token = new MetadataToken (TokenType.LocalVariable, rid) };
2961 			variable.custom_infos = GetCustomDebugInformation (variable);
2962 			return variable;
2963 		}
2964 
ReadLocalConstant(uint rid)2965 		ConstantDebugInformation ReadLocalConstant (uint rid)
2966 		{
2967 			if (!MoveTo (Table.LocalConstant, rid))
2968 				return null;
2969 
2970 			var name = ReadString ();
2971 			var signature = ReadSignature (ReadBlobIndex ());
2972 			var type = signature.ReadTypeSignature ();
2973 
2974 			object value;
2975 			if (type.etype == ElementType.String) {
2976 				if (signature.buffer [signature.position] != 0xff) {
2977 					var bytes = signature.ReadBytes ((int) (signature.sig_length - (signature.position - signature.start)));
2978 					value = Encoding.Unicode.GetString (bytes, 0, bytes.Length);
2979 				} else
2980 					value = null;
2981 			} else if (type.IsTypeOf ("System", "Decimal")) {
2982 				var b = signature.ReadByte ();
2983 				value = new decimal (signature.ReadInt32 (), signature.ReadInt32 (), signature.ReadInt32 (), (b & 0x80) != 0, (byte) (b & 0x7f));
2984 			} else if (type.IsTypeOf ("System", "DateTime")) {
2985 				value = new DateTime (signature.ReadInt64());
2986 			} else if (type.etype == ElementType.Object || type.etype == ElementType.None || type.etype == ElementType.Class) {
2987 				value = null;
2988 			} else
2989 				value = signature.ReadConstantSignature (type.etype);
2990 
2991 			var constant = new ConstantDebugInformation (name, type, value) { token = new MetadataToken (TokenType.LocalConstant, rid) };
2992 			constant.custom_infos = GetCustomDebugInformation (constant);
2993 			return constant;
2994 		}
2995 
InitializeImportScopes()2996 		void InitializeImportScopes ()
2997 		{
2998 			if (metadata.ImportScopes != null)
2999 				return;
3000 
3001 			var length = MoveTo (Table.ImportScope);
3002 
3003 			metadata.ImportScopes = new ImportDebugInformation [length];
3004 
3005 			for (int i = 1; i <= length; i++) {
3006 				ReadTableIndex (Table.ImportScope);
3007 
3008 				var import = new ImportDebugInformation ();
3009 				import.token = new MetadataToken (TokenType.ImportScope, i);
3010 
3011 				var signature = ReadSignature (ReadBlobIndex ());
3012 				while (signature.CanReadMore ())
3013 					import.Targets.Add (ReadImportTarget (signature));
3014 
3015 				metadata.ImportScopes [i - 1] = import;
3016 			}
3017 
3018 			MoveTo (Table.ImportScope);
3019 
3020 			for (int i = 0; i < length; i++) {
3021 				var parent = ReadTableIndex (Table.ImportScope);
3022 
3023 				ReadBlobIndex ();
3024 
3025 				if (parent != 0)
3026 					metadata.ImportScopes [i].Parent = metadata.GetImportScope (parent);
3027 			}
3028 		}
3029 
ReadUTF8StringBlob(uint signature)3030 		public string ReadUTF8StringBlob (uint signature)
3031 		{
3032 			return ReadStringBlob (signature, Encoding.UTF8);
3033 		}
3034 
ReadUnicodeStringBlob(uint signature)3035 		string ReadUnicodeStringBlob (uint signature)
3036 		{
3037 			return ReadStringBlob (signature, Encoding.Unicode);
3038 		}
3039 
ReadStringBlob(uint signature, Encoding encoding)3040 		string ReadStringBlob (uint signature, Encoding encoding)
3041 		{
3042 			byte [] blob;
3043 			int index, count;
3044 
3045 			GetBlobView (signature, out blob, out index, out count);
3046 			if (count == 0)
3047 				return string.Empty;
3048 
3049 			return encoding.GetString (blob, index, count);
3050 		}
3051 
ReadImportTarget(SignatureReader signature)3052 		ImportTarget ReadImportTarget (SignatureReader signature)
3053 		{
3054 			AssemblyNameReference reference = null;
3055 			string @namespace = null;
3056 			string alias = null;
3057 			TypeReference type = null;
3058 
3059 			var kind = (ImportTargetKind) signature.ReadCompressedUInt32 ();
3060 			switch (kind) {
3061 			case ImportTargetKind.ImportNamespace:
3062 				@namespace = ReadUTF8StringBlob (signature.ReadCompressedUInt32 ());
3063 				break;
3064 			case ImportTargetKind.ImportNamespaceInAssembly:
3065 				reference = metadata.GetAssemblyNameReference (signature.ReadCompressedUInt32 ());
3066 				@namespace = ReadUTF8StringBlob (signature.ReadCompressedUInt32 ());
3067 				break;
3068 			case ImportTargetKind.ImportType:
3069 				type = signature.ReadTypeToken ();
3070 				break;
3071 			case ImportTargetKind.ImportXmlNamespaceWithAlias:
3072 				alias = ReadUTF8StringBlob (signature.ReadCompressedUInt32 ());
3073 				@namespace = ReadUTF8StringBlob (signature.ReadCompressedUInt32 ());
3074 				break;
3075 			case ImportTargetKind.ImportAlias:
3076 				alias = ReadUTF8StringBlob (signature.ReadCompressedUInt32 ());
3077 				break;
3078 			case ImportTargetKind.DefineAssemblyAlias:
3079 				alias = ReadUTF8StringBlob (signature.ReadCompressedUInt32 ());
3080 				reference = metadata.GetAssemblyNameReference (signature.ReadCompressedUInt32 ());
3081 				break;
3082 			case ImportTargetKind.DefineNamespaceAlias:
3083 				alias = ReadUTF8StringBlob (signature.ReadCompressedUInt32 ());
3084 				@namespace = ReadUTF8StringBlob (signature.ReadCompressedUInt32 ());
3085 				break;
3086 			case ImportTargetKind.DefineNamespaceInAssemblyAlias:
3087 				alias = ReadUTF8StringBlob (signature.ReadCompressedUInt32 ());
3088 				reference = metadata.GetAssemblyNameReference (signature.ReadCompressedUInt32 ());
3089 				@namespace = ReadUTF8StringBlob (signature.ReadCompressedUInt32 ());
3090 				break;
3091 			case ImportTargetKind.DefineTypeAlias:
3092 				alias = ReadUTF8StringBlob (signature.ReadCompressedUInt32 ());
3093 				type = signature.ReadTypeToken ();
3094 				break;
3095 			}
3096 
3097 			return new ImportTarget (kind) {
3098 				alias = alias,
3099 				type = type,
3100 				@namespace = @namespace,
3101 				reference = reference,
3102 			};
3103 		}
3104 
InitializeStateMachineMethods()3105 		void InitializeStateMachineMethods ()
3106 		{
3107 			if (metadata.StateMachineMethods != null)
3108 				return;
3109 
3110 			var length = MoveTo (Table.StateMachineMethod);
3111 
3112 			metadata.StateMachineMethods = new Dictionary<uint, uint> (length);
3113 
3114 			for (int i = 0; i < length; i++)
3115 				metadata.StateMachineMethods.Add (ReadTableIndex (Table.Method), ReadTableIndex (Table.Method));
3116 		}
3117 
ReadStateMachineKickoffMethod(MethodDefinition method)3118 		public MethodDefinition ReadStateMachineKickoffMethod (MethodDefinition method)
3119 		{
3120 			InitializeStateMachineMethods ();
3121 
3122 			uint rid;
3123 			if (!metadata.TryGetStateMachineKickOffMethod (method, out rid))
3124 				return null;
3125 
3126 			return GetMethodDefinition (rid);
3127 		}
3128 
InitializeCustomDebugInformations()3129 		void InitializeCustomDebugInformations ()
3130 		{
3131 			if (metadata.CustomDebugInformations != null)
3132 				return;
3133 
3134 			var length = MoveTo (Table.CustomDebugInformation);
3135 
3136 			metadata.CustomDebugInformations = new Dictionary<MetadataToken, Row<Guid, uint, uint> []> ();
3137 
3138 			for (uint i = 1; i <= length; i++) {
3139 				var token = ReadMetadataToken (CodedIndex.HasCustomDebugInformation);
3140 				var info = new Row<Guid, uint, uint> (ReadGuid (), ReadBlobIndex (), i);
3141 
3142 				Row<Guid, uint, uint> [] infos;
3143 				metadata.CustomDebugInformations.TryGetValue (token, out infos);
3144 				metadata.CustomDebugInformations [token] = infos.Add (info);
3145 			}
3146 		}
3147 
GetCustomDebugInformation(ICustomDebugInformationProvider provider)3148 		public Collection<CustomDebugInformation> GetCustomDebugInformation (ICustomDebugInformationProvider provider)
3149 		{
3150 			InitializeCustomDebugInformations ();
3151 
3152 			Row<Guid, uint, uint> [] rows;
3153 			if (!metadata.CustomDebugInformations.TryGetValue (provider.MetadataToken, out rows))
3154 				return null;
3155 
3156 			var infos = new Collection<CustomDebugInformation> (rows.Length);
3157 
3158 			for (int i = 0; i < rows.Length; i++) {
3159 				if (rows [i].Col1 == StateMachineScopeDebugInformation.KindIdentifier) {
3160 					var signature = ReadSignature (rows [i].Col2);
3161 					var scopes = new Collection<StateMachineScope> ();
3162 
3163 					while (signature.CanReadMore ()) {
3164 						var start = signature.ReadInt32 ();
3165 						var end = start + signature.ReadInt32 ();
3166 						scopes.Add (new StateMachineScope (start, end));
3167 					}
3168 
3169 					var state_machine = new StateMachineScopeDebugInformation ();
3170 					state_machine.scopes = scopes;
3171 
3172 					infos.Add (state_machine);
3173 				} else if (rows [i].Col1 == AsyncMethodBodyDebugInformation.KindIdentifier) {
3174 					var signature = ReadSignature (rows [i].Col2);
3175 
3176 					var catch_offset = signature.ReadInt32 () - 1;
3177 					var yields = new Collection<InstructionOffset> ();
3178 					var resumes = new Collection<InstructionOffset> ();
3179 					var resume_methods = new Collection<MethodDefinition> ();
3180 
3181 					while (signature.CanReadMore ()) {
3182 						yields.Add (new InstructionOffset (signature.ReadInt32 ()));
3183 						resumes.Add (new InstructionOffset (signature.ReadInt32 ()));
3184 						resume_methods.Add (GetMethodDefinition (signature.ReadCompressedUInt32 ()));
3185 					}
3186 
3187 					var async_body = new AsyncMethodBodyDebugInformation (catch_offset);
3188 					async_body.yields = yields;
3189 					async_body.resumes = resumes;
3190 					async_body.resume_methods = resume_methods;
3191 
3192 					infos.Add (async_body);
3193 				} else if (rows [i].Col1 == EmbeddedSourceDebugInformation.KindIdentifier) {
3194 					var signature = ReadSignature (rows [i].Col2);
3195 					var format = signature.ReadInt32 ();
3196 					var length = signature.sig_length - 4;
3197 
3198 					var info = null as CustomDebugInformation;
3199 
3200 					if (format == 0) {
3201 						info = new EmbeddedSourceDebugInformation (signature.ReadBytes ((int) length), compress: false);
3202 					} else if (format > 0) {
3203 						var compressed_stream = new MemoryStream (signature.ReadBytes ((int) length));
3204 						var decompressed_document = new byte [format]; // if positive, format is the decompressed length of the document
3205 						var decompressed_stream = new MemoryStream (decompressed_document);
3206 
3207 						using (var deflate_stream = new DeflateStream (compressed_stream, CompressionMode.Decompress, leaveOpen: true))
3208 							deflate_stream.CopyTo (decompressed_stream);
3209 
3210 						info = new EmbeddedSourceDebugInformation (decompressed_document, compress: true);
3211 					} else if (format < 0) {
3212 						info = new BinaryCustomDebugInformation (rows [i].Col1, ReadBlob (rows [i].Col2));
3213 					}
3214 
3215 					infos.Add (info);
3216 				} else if (rows [i].Col1 == SourceLinkDebugInformation.KindIdentifier) {
3217 					infos.Add (new SourceLinkDebugInformation (Encoding.UTF8.GetString (ReadBlob (rows [i].Col2))));
3218 				} else {
3219 					infos.Add (new BinaryCustomDebugInformation (rows [i].Col1, ReadBlob (rows [i].Col2)));
3220 				}
3221 
3222 				infos [i].token = new MetadataToken (TokenType.CustomDebugInformation, rows [i].Col3);
3223 			}
3224 
3225 			return infos;
3226 		}
3227 	}
3228 
3229 	sealed class SignatureReader : ByteBuffer {
3230 
3231 		readonly MetadataReader reader;
3232 		readonly internal uint start, sig_length;
3233 
3234 		TypeSystem TypeSystem {
3235 			get { return reader.module.TypeSystem; }
3236 		}
3237 
SignatureReader(uint blob, MetadataReader reader)3238 		public SignatureReader (uint blob, MetadataReader reader)
3239 			: base (reader.image.BlobHeap.data)
3240 		{
3241 			this.reader = reader;
3242 			this.position = (int) blob;
3243 			this.sig_length = ReadCompressedUInt32();
3244 			this.start = (uint) this.position;
3245 		}
3246 
ReadTypeTokenSignature()3247 		MetadataToken ReadTypeTokenSignature ()
3248 		{
3249 			return CodedIndex.TypeDefOrRef.GetMetadataToken (ReadCompressedUInt32 ());
3250 		}
3251 
GetGenericParameter(GenericParameterType type, uint var)3252 		GenericParameter GetGenericParameter (GenericParameterType type, uint var)
3253 		{
3254 			var context = reader.context;
3255 			int index = (int) var;
3256 
3257 			if (context == null)
3258 				return GetUnboundGenericParameter (type, index);
3259 
3260 			IGenericParameterProvider provider;
3261 
3262 			switch (type) {
3263 			case GenericParameterType.Type:
3264 				provider = context.Type;
3265 				break;
3266 			case GenericParameterType.Method:
3267 				provider = context.Method;
3268 				break;
3269 			default:
3270 				throw new NotSupportedException ();
3271 			}
3272 
3273 			if (!context.IsDefinition)
3274 				CheckGenericContext (provider, index);
3275 
3276 			if (index >= provider.GenericParameters.Count)
3277 				return GetUnboundGenericParameter (type, index);
3278 
3279 			return provider.GenericParameters [index];
3280 		}
3281 
GetUnboundGenericParameter(GenericParameterType type, int index)3282 		GenericParameter GetUnboundGenericParameter (GenericParameterType type, int index)
3283 		{
3284 			return new GenericParameter (index, type, reader.module);
3285 		}
3286 
CheckGenericContext(IGenericParameterProvider owner, int index)3287 		static void CheckGenericContext (IGenericParameterProvider owner, int index)
3288 		{
3289 			var owner_parameters = owner.GenericParameters;
3290 
3291 			for (int i = owner_parameters.Count; i <= index; i++)
3292 				owner_parameters.Add (new GenericParameter (owner));
3293 		}
3294 
ReadGenericInstanceSignature(IGenericParameterProvider provider, IGenericInstance instance)3295 		public void ReadGenericInstanceSignature (IGenericParameterProvider provider, IGenericInstance instance)
3296 		{
3297 			var arity = ReadCompressedUInt32 ();
3298 
3299 			if (!provider.IsDefinition)
3300 				CheckGenericContext (provider, (int) arity - 1);
3301 
3302 			var instance_arguments = instance.GenericArguments;
3303 
3304 			for (int i = 0; i < arity; i++)
3305 				instance_arguments.Add (ReadTypeSignature ());
3306 		}
3307 
ReadArrayTypeSignature()3308 		ArrayType ReadArrayTypeSignature ()
3309 		{
3310 			var array = new ArrayType (ReadTypeSignature ());
3311 
3312 			var rank = ReadCompressedUInt32 ();
3313 
3314 			var sizes = new uint [ReadCompressedUInt32 ()];
3315 			for (int i = 0; i < sizes.Length; i++)
3316 				sizes [i] = ReadCompressedUInt32 ();
3317 
3318 			var low_bounds = new int [ReadCompressedUInt32 ()];
3319 			for (int i = 0; i < low_bounds.Length; i++)
3320 				low_bounds [i] = ReadCompressedInt32 ();
3321 
3322 			array.Dimensions.Clear ();
3323 
3324 			for (int i = 0; i < rank; i++) {
3325 				int? lower = null, upper = null;
3326 
3327 				if (i < low_bounds.Length)
3328 					lower = low_bounds [i];
3329 
3330 				if (i < sizes.Length)
3331 					upper = lower + (int) sizes [i] - 1;
3332 
3333 				array.Dimensions.Add (new ArrayDimension (lower, upper));
3334 			}
3335 
3336 			return array;
3337 		}
3338 
GetTypeDefOrRef(MetadataToken token)3339 		TypeReference GetTypeDefOrRef (MetadataToken token)
3340 		{
3341 			return reader.GetTypeDefOrRef (token);
3342 		}
3343 
ReadTypeSignature()3344 		public TypeReference ReadTypeSignature ()
3345 		{
3346 			return ReadTypeSignature ((ElementType) ReadByte ());
3347 		}
3348 
ReadTypeToken()3349 		public TypeReference ReadTypeToken ()
3350 		{
3351 			return GetTypeDefOrRef (ReadTypeTokenSignature ());
3352 		}
3353 
ReadTypeSignature(ElementType etype)3354 		TypeReference ReadTypeSignature (ElementType etype)
3355 		{
3356 			switch (etype) {
3357 			case ElementType.ValueType: {
3358 				var value_type = GetTypeDefOrRef (ReadTypeTokenSignature ());
3359 				value_type.KnownValueType ();
3360 				return value_type;
3361 			}
3362 			case ElementType.Class:
3363 				return GetTypeDefOrRef (ReadTypeTokenSignature ());
3364 			case ElementType.Ptr:
3365 				return new PointerType (ReadTypeSignature ());
3366 			case ElementType.FnPtr: {
3367 				var fptr = new FunctionPointerType ();
3368 				ReadMethodSignature (fptr);
3369 				return fptr;
3370 			}
3371 			case ElementType.ByRef:
3372 				return new ByReferenceType (ReadTypeSignature ());
3373 			case ElementType.Pinned:
3374 				return new PinnedType (ReadTypeSignature ());
3375 			case ElementType.SzArray:
3376 				return new ArrayType (ReadTypeSignature ());
3377 			case ElementType.Array:
3378 				return ReadArrayTypeSignature ();
3379 			case ElementType.CModOpt:
3380 				return new OptionalModifierType (
3381 					GetTypeDefOrRef (ReadTypeTokenSignature ()), ReadTypeSignature ());
3382 			case ElementType.CModReqD:
3383 				return new RequiredModifierType (
3384 					GetTypeDefOrRef (ReadTypeTokenSignature ()), ReadTypeSignature ());
3385 			case ElementType.Sentinel:
3386 				return new SentinelType (ReadTypeSignature ());
3387 			case ElementType.Var:
3388 				return GetGenericParameter (GenericParameterType.Type, ReadCompressedUInt32 ());
3389 			case ElementType.MVar:
3390 				return GetGenericParameter (GenericParameterType.Method, ReadCompressedUInt32 ());
3391 			case ElementType.GenericInst: {
3392 				var is_value_type = ReadByte () == (byte) ElementType.ValueType;
3393 				var element_type = GetTypeDefOrRef (ReadTypeTokenSignature ());
3394 				var generic_instance = new GenericInstanceType (element_type);
3395 
3396 				ReadGenericInstanceSignature (element_type, generic_instance);
3397 
3398 				if (is_value_type) {
3399 					generic_instance.KnownValueType ();
3400 					element_type.GetElementType ().KnownValueType ();
3401 				}
3402 
3403 				return generic_instance;
3404 			}
3405 			case ElementType.Object: return TypeSystem.Object;
3406 			case ElementType.Void: return TypeSystem.Void;
3407 			case ElementType.TypedByRef: return TypeSystem.TypedReference;
3408 			case ElementType.I: return TypeSystem.IntPtr;
3409 			case ElementType.U: return TypeSystem.UIntPtr;
3410 			default: return GetPrimitiveType (etype);
3411 			}
3412 		}
3413 
ReadMethodSignature(IMethodSignature method)3414 		public void ReadMethodSignature (IMethodSignature method)
3415 		{
3416 			var calling_convention = ReadByte ();
3417 
3418 			const byte has_this = 0x20;
3419 			const byte explicit_this = 0x40;
3420 
3421 			if ((calling_convention & has_this) != 0) {
3422 				method.HasThis = true;
3423 				calling_convention = (byte) (calling_convention & ~has_this);
3424 			}
3425 
3426 			if ((calling_convention & explicit_this) != 0) {
3427 				method.ExplicitThis = true;
3428 				calling_convention = (byte) (calling_convention & ~explicit_this);
3429 			}
3430 
3431 			method.CallingConvention = (MethodCallingConvention) calling_convention;
3432 
3433 			var generic_context = method as MethodReference;
3434 			if (generic_context != null && !generic_context.DeclaringType.IsArray)
3435 				reader.context = generic_context;
3436 
3437 			if ((calling_convention & 0x10) != 0) {
3438 				var arity = ReadCompressedUInt32 ();
3439 
3440 				if (generic_context != null && !generic_context.IsDefinition)
3441 					CheckGenericContext (generic_context, (int) arity -1 );
3442 			}
3443 
3444 			var param_count = ReadCompressedUInt32 ();
3445 
3446 			method.MethodReturnType.ReturnType = ReadTypeSignature ();
3447 
3448 			if (param_count == 0)
3449 				return;
3450 
3451 			Collection<ParameterDefinition> parameters;
3452 
3453 			var method_ref = method as MethodReference;
3454 			if (method_ref != null)
3455 				parameters = method_ref.parameters = new ParameterDefinitionCollection (method, (int) param_count);
3456 			else
3457 				parameters = method.Parameters;
3458 
3459 			for (int i = 0; i < param_count; i++)
3460 				parameters.Add (new ParameterDefinition (ReadTypeSignature ()));
3461 		}
3462 
ReadConstantSignature(ElementType type)3463 		public object ReadConstantSignature (ElementType type)
3464 		{
3465 			return ReadPrimitiveValue (type);
3466 		}
3467 
ReadCustomAttributeConstructorArguments(CustomAttribute attribute, Collection<ParameterDefinition> parameters)3468 		public void ReadCustomAttributeConstructorArguments (CustomAttribute attribute, Collection<ParameterDefinition> parameters)
3469 		{
3470 			var count = parameters.Count;
3471 			if (count == 0)
3472 				return;
3473 
3474 			attribute.arguments = new Collection<CustomAttributeArgument> (count);
3475 
3476 			for (int i = 0; i < count; i++)
3477 				attribute.arguments.Add (
3478 					ReadCustomAttributeFixedArgument (parameters [i].ParameterType));
3479 		}
3480 
ReadCustomAttributeFixedArgument(TypeReference type)3481 		CustomAttributeArgument ReadCustomAttributeFixedArgument (TypeReference type)
3482 		{
3483 			if (type.IsArray)
3484 				return ReadCustomAttributeFixedArrayArgument ((ArrayType) type);
3485 
3486 			return ReadCustomAttributeElement (type);
3487 		}
3488 
ReadCustomAttributeNamedArguments(ushort count, ref Collection<CustomAttributeNamedArgument> fields, ref Collection<CustomAttributeNamedArgument> properties)3489 		public void ReadCustomAttributeNamedArguments (ushort count, ref Collection<CustomAttributeNamedArgument> fields, ref Collection<CustomAttributeNamedArgument> properties)
3490 		{
3491 			for (int i = 0; i < count; i++) {
3492 				if (!CanReadMore ())
3493 					return;
3494 				ReadCustomAttributeNamedArgument (ref fields, ref properties);
3495 			}
3496 		}
3497 
ReadCustomAttributeNamedArgument(ref Collection<CustomAttributeNamedArgument> fields, ref Collection<CustomAttributeNamedArgument> properties)3498 		void ReadCustomAttributeNamedArgument (ref Collection<CustomAttributeNamedArgument> fields, ref Collection<CustomAttributeNamedArgument> properties)
3499 		{
3500 			var kind = ReadByte ();
3501 			var type = ReadCustomAttributeFieldOrPropType ();
3502 			var name = ReadUTF8String ();
3503 
3504 			Collection<CustomAttributeNamedArgument> container;
3505 			switch (kind) {
3506 			case 0x53:
3507 				container = GetCustomAttributeNamedArgumentCollection (ref fields);
3508 				break;
3509 			case 0x54:
3510 				container = GetCustomAttributeNamedArgumentCollection (ref properties);
3511 				break;
3512 			default:
3513 				throw new NotSupportedException ();
3514 			}
3515 
3516 			container.Add (new CustomAttributeNamedArgument (name, ReadCustomAttributeFixedArgument (type)));
3517 		}
3518 
GetCustomAttributeNamedArgumentCollection(ref Collection<CustomAttributeNamedArgument> collection)3519 		static Collection<CustomAttributeNamedArgument> GetCustomAttributeNamedArgumentCollection (ref Collection<CustomAttributeNamedArgument> collection)
3520 		{
3521 			if (collection != null)
3522 				return collection;
3523 
3524 			return collection = new Collection<CustomAttributeNamedArgument> ();
3525 		}
3526 
ReadCustomAttributeFixedArrayArgument(ArrayType type)3527 		CustomAttributeArgument ReadCustomAttributeFixedArrayArgument (ArrayType type)
3528 		{
3529 			var length = ReadUInt32 ();
3530 
3531 			if (length == 0xffffffff)
3532 				return new CustomAttributeArgument (type, null);
3533 
3534 			if (length == 0)
3535 				return new CustomAttributeArgument (type, Empty<CustomAttributeArgument>.Array);
3536 
3537 			var arguments = new CustomAttributeArgument [length];
3538 			var element_type = type.ElementType;
3539 
3540 			for (int i = 0; i < length; i++)
3541 				arguments [i] = ReadCustomAttributeElement (element_type);
3542 
3543 			return new CustomAttributeArgument (type, arguments);
3544 		}
3545 
ReadCustomAttributeElement(TypeReference type)3546 		CustomAttributeArgument ReadCustomAttributeElement (TypeReference type)
3547 		{
3548 			if (type.IsArray)
3549 				return ReadCustomAttributeFixedArrayArgument ((ArrayType) type);
3550 
3551 			return new CustomAttributeArgument (
3552 				type,
3553 				type.etype == ElementType.Object
3554 					? ReadCustomAttributeElement (ReadCustomAttributeFieldOrPropType ())
3555 					: ReadCustomAttributeElementValue (type));
3556 		}
3557 
ReadCustomAttributeElementValue(TypeReference type)3558 		object ReadCustomAttributeElementValue (TypeReference type)
3559 		{
3560 			var etype = type.etype;
3561 
3562 			switch (etype) {
3563 			case ElementType.String:
3564 				return ReadUTF8String ();
3565 			case ElementType.None:
3566 				if (type.IsTypeOf ("System", "Type"))
3567 					return ReadTypeReference ();
3568 
3569 				return ReadCustomAttributeEnum (type);
3570 			default:
3571 				return ReadPrimitiveValue (etype);
3572 			}
3573 		}
3574 
ReadPrimitiveValue(ElementType type)3575 		object ReadPrimitiveValue (ElementType type)
3576 		{
3577 			switch (type) {
3578 			case ElementType.Boolean:
3579 				return ReadByte () == 1;
3580 			case ElementType.I1:
3581 				return (sbyte) ReadByte ();
3582 			case ElementType.U1:
3583 				return ReadByte ();
3584 			case ElementType.Char:
3585 				return (char) ReadUInt16 ();
3586 			case ElementType.I2:
3587 				return ReadInt16 ();
3588 			case ElementType.U2:
3589 				return ReadUInt16 ();
3590 			case ElementType.I4:
3591 				return ReadInt32 ();
3592 			case ElementType.U4:
3593 				return ReadUInt32 ();
3594 			case ElementType.I8:
3595 				return ReadInt64 ();
3596 			case ElementType.U8:
3597 				return ReadUInt64 ();
3598 			case ElementType.R4:
3599 				return ReadSingle ();
3600 			case ElementType.R8:
3601 				return ReadDouble ();
3602 			default:
3603 				throw new NotImplementedException (type.ToString ());
3604 			}
3605 		}
3606 
GetPrimitiveType(ElementType etype)3607 		TypeReference GetPrimitiveType (ElementType etype)
3608 		{
3609 			switch (etype) {
3610 			case ElementType.Boolean:
3611 				return TypeSystem.Boolean;
3612 			case ElementType.Char:
3613 				return TypeSystem.Char;
3614 			case ElementType.I1:
3615 				return TypeSystem.SByte;
3616 			case ElementType.U1:
3617 				return TypeSystem.Byte;
3618 			case ElementType.I2:
3619 				return TypeSystem.Int16;
3620 			case ElementType.U2:
3621 				return TypeSystem.UInt16;
3622 			case ElementType.I4:
3623 				return TypeSystem.Int32;
3624 			case ElementType.U4:
3625 				return TypeSystem.UInt32;
3626 			case ElementType.I8:
3627 				return TypeSystem.Int64;
3628 			case ElementType.U8:
3629 				return TypeSystem.UInt64;
3630 			case ElementType.R4:
3631 				return TypeSystem.Single;
3632 			case ElementType.R8:
3633 				return TypeSystem.Double;
3634 			case ElementType.String:
3635 				return TypeSystem.String;
3636 			default:
3637 				throw new NotImplementedException (etype.ToString ());
3638 			}
3639 		}
3640 
ReadCustomAttributeFieldOrPropType()3641 		TypeReference ReadCustomAttributeFieldOrPropType ()
3642 		{
3643 			var etype = (ElementType) ReadByte ();
3644 
3645 			switch (etype) {
3646 			case ElementType.Boxed:
3647 				return TypeSystem.Object;
3648 			case ElementType.SzArray:
3649 				return new ArrayType (ReadCustomAttributeFieldOrPropType ());
3650 			case ElementType.Enum:
3651 				return ReadTypeReference ();
3652 			case ElementType.Type:
3653 				return TypeSystem.LookupType ("System", "Type");
3654 			default:
3655 				return GetPrimitiveType (etype);
3656 			}
3657 		}
3658 
ReadTypeReference()3659 		public TypeReference ReadTypeReference ()
3660 		{
3661 			return TypeParser.ParseType (reader.module, ReadUTF8String ());
3662 		}
3663 
ReadCustomAttributeEnum(TypeReference enum_type)3664 		object ReadCustomAttributeEnum (TypeReference enum_type)
3665 		{
3666 			var type = enum_type.CheckedResolve ();
3667 			if (!type.IsEnum)
3668 				throw new ArgumentException ();
3669 
3670 			return ReadCustomAttributeElementValue (type.GetEnumUnderlyingType ());
3671 		}
3672 
ReadSecurityAttribute()3673 		public SecurityAttribute ReadSecurityAttribute ()
3674 		{
3675 			var attribute = new SecurityAttribute (ReadTypeReference ());
3676 
3677 			ReadCompressedUInt32 ();
3678 
3679 			ReadCustomAttributeNamedArguments (
3680 				(ushort) ReadCompressedUInt32 (),
3681 				ref attribute.fields,
3682 				ref attribute.properties);
3683 
3684 			return attribute;
3685 		}
3686 
ReadMarshalInfo()3687 		public MarshalInfo ReadMarshalInfo ()
3688 		{
3689 			var native = ReadNativeType ();
3690 			switch (native) {
3691 			case NativeType.Array: {
3692 				var array = new ArrayMarshalInfo ();
3693 				if (CanReadMore ())
3694 					array.element_type = ReadNativeType ();
3695 				if (CanReadMore ())
3696 					array.size_parameter_index = (int) ReadCompressedUInt32 ();
3697 				if (CanReadMore ())
3698 					array.size = (int) ReadCompressedUInt32 ();
3699 				if (CanReadMore ())
3700 					array.size_parameter_multiplier = (int) ReadCompressedUInt32 ();
3701 				return array;
3702 			}
3703 			case NativeType.SafeArray: {
3704 				var array = new SafeArrayMarshalInfo ();
3705 				if (CanReadMore ())
3706 					array.element_type = ReadVariantType ();
3707 				return array;
3708 			}
3709 			case NativeType.FixedArray: {
3710 				var array = new FixedArrayMarshalInfo ();
3711 				if (CanReadMore ())
3712 					array.size = (int) ReadCompressedUInt32 ();
3713 				if (CanReadMore ())
3714 					array.element_type = ReadNativeType ();
3715 				return array;
3716 			}
3717 			case NativeType.FixedSysString: {
3718 				var sys_string = new FixedSysStringMarshalInfo ();
3719 				if (CanReadMore ())
3720 					sys_string.size = (int) ReadCompressedUInt32 ();
3721 				return sys_string;
3722 			}
3723 			case NativeType.CustomMarshaler: {
3724 				var marshaler = new CustomMarshalInfo ();
3725 				var guid_value = ReadUTF8String ();
3726 				marshaler.guid = !string.IsNullOrEmpty (guid_value) ? new Guid (guid_value) : Guid.Empty;
3727 				marshaler.unmanaged_type = ReadUTF8String ();
3728 				marshaler.managed_type = ReadTypeReference ();
3729 				marshaler.cookie = ReadUTF8String ();
3730 				return marshaler;
3731 			}
3732 			default:
3733 				return new MarshalInfo (native);
3734 			}
3735 		}
3736 
ReadNativeType()3737 		NativeType ReadNativeType ()
3738 		{
3739 			return (NativeType) ReadByte ();
3740 		}
3741 
ReadVariantType()3742 		VariantType ReadVariantType ()
3743 		{
3744 			return (VariantType) ReadByte ();
3745 		}
3746 
ReadUTF8String()3747 		string ReadUTF8String ()
3748 		{
3749 			if (buffer [position] == 0xff) {
3750 				position++;
3751 				return null;
3752 			}
3753 
3754 			var length = (int) ReadCompressedUInt32 ();
3755 			if (length == 0)
3756 				return string.Empty;
3757 
3758 			var @string = Encoding.UTF8.GetString (buffer, position,
3759 				buffer [position + length - 1] == 0 ? length - 1 : length);
3760 
3761 			position += length;
3762 			return @string;
3763 		}
3764 
ReadDocumentName()3765 		public string ReadDocumentName ()
3766 		{
3767 			var separator = (char) buffer [position];
3768 			position++;
3769 
3770 			var builder = new StringBuilder ();
3771 			for (int i = 0; CanReadMore (); i++) {
3772 				if (i > 0 && separator != 0)
3773 					builder.Append (separator);
3774 
3775 				uint part = ReadCompressedUInt32 ();
3776 				if (part != 0)
3777 					builder.Append (reader.ReadUTF8StringBlob (part));
3778 			}
3779 
3780 			return builder.ToString ();
3781 		}
3782 
ReadSequencePoints(Document document)3783 		public Collection<SequencePoint> ReadSequencePoints (Document document)
3784 		{
3785 			var sequence_points = new Collection<SequencePoint> ();
3786 
3787 			ReadCompressedUInt32 (); // local_sig_token
3788 
3789 			if (document == null)
3790 				document = reader.GetDocument (ReadCompressedUInt32 ());
3791 
3792 			var offset = 0;
3793 			var start_line = 0;
3794 			var start_column = 0;
3795 			var first_non_hidden = true;
3796 
3797 			for (var i = 0; CanReadMore (); i++) {
3798 				var delta_il = (int) ReadCompressedUInt32 ();
3799 				if (i > 0 && delta_il == 0) {
3800 					document = reader.GetDocument (ReadCompressedUInt32 ());
3801 					continue;
3802 				}
3803 
3804 				offset += delta_il;
3805 
3806 				var delta_lines = (int) ReadCompressedUInt32 ();
3807 				var delta_columns = delta_lines == 0
3808 					? (int) ReadCompressedUInt32 ()
3809 					: ReadCompressedInt32 ();
3810 
3811 				if (delta_lines == 0 && delta_columns == 0) {
3812 					sequence_points.Add (new SequencePoint (offset, document) {
3813 						StartLine = 0xfeefee,
3814 						EndLine = 0xfeefee,
3815 						StartColumn = 0,
3816 						EndColumn = 0,
3817 					});
3818 					continue;
3819 				}
3820 
3821 				if (first_non_hidden) {
3822 					start_line = (int) ReadCompressedUInt32 ();
3823 					start_column = (int) ReadCompressedUInt32 ();
3824 				} else {
3825 					start_line += ReadCompressedInt32 ();
3826 					start_column += ReadCompressedInt32 ();
3827 				}
3828 
3829 				sequence_points.Add (new SequencePoint (offset, document) {
3830 					StartLine = start_line,
3831 					StartColumn = start_column,
3832 					EndLine = start_line + delta_lines,
3833 					EndColumn = start_column + delta_columns,
3834 				});
3835 				first_non_hidden = false;
3836 			}
3837 
3838 			return sequence_points;
3839 		}
3840 
CanReadMore()3841 		public bool CanReadMore ()
3842 		{
3843 			return position - start < sig_length;
3844 		}
3845 	}
3846 }
3847