5c6c230265437c4b723440baf2ca61a71ee8c6fe
[mono.git] / mcs / class / Mono.Cecil / Mono.Cecil / AssemblyReader.cs
1 //
2 // AssemblyReader.cs
3 //
4 // Author:
5 //   Jb Evain (jbevain@gmail.com)
6 //
7 // Copyright (c) 2008 - 2010 Jb Evain
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28
29 using System;
30 using System.Collections.Generic;
31 using System.IO;
32 using System.Text;
33
34 using Mono.Collections.Generic;
35 using Mono.Cecil.Cil;
36 using Mono.Cecil.Metadata;
37 using Mono.Cecil.PE;
38
39 using RVA = System.UInt32;
40
41 namespace Mono.Cecil {
42
43         abstract class ModuleReader {
44
45                 readonly protected Image image;
46                 readonly protected ModuleDefinition module;
47
48                 protected ModuleReader (Image image, ReadingMode mode)
49                 {
50                         this.image = image;
51                         this.module = new ModuleDefinition (image);
52                         this.module.ReadingMode = mode;
53                 }
54
55                 protected abstract void ReadModule ();
56
57                 protected void ReadModuleManifest (MetadataReader reader)
58                 {
59                         reader.Populate (module);
60
61                         ReadAssembly (reader);
62                 }
63
64                 void ReadAssembly (MetadataReader reader)
65                 {
66                         var name = reader.ReadAssemblyNameDefinition ();
67                         if (name == null) {
68                                 module.kind = ModuleKind.NetModule;
69                                 return;
70                         }
71
72                         var assembly = new AssemblyDefinition ();
73                         assembly.Name = name;
74
75                         module.assembly = assembly;
76                         assembly.main_module = module;
77                 }
78
79                 public static ModuleDefinition CreateModuleFrom (Image image, ReaderParameters parameters)
80                 {
81                         var module = ReadModule (image, parameters);
82
83                         ReadSymbols (module, parameters);
84
85                         if (parameters.AssemblyResolver != null)
86                                 module.assembly_resolver = parameters.AssemblyResolver;
87
88                         return module;
89                 }
90
91                 static void ReadSymbols (ModuleDefinition module, ReaderParameters parameters)
92                 {
93                         var symbol_reader_provider = parameters.SymbolReaderProvider;
94
95                         if (symbol_reader_provider == null && parameters.ReadSymbols)
96                                 symbol_reader_provider = SymbolProvider.GetPlatformReaderProvider ();
97
98                         if (symbol_reader_provider != null) {
99                                 module.SymbolReaderProvider = symbol_reader_provider;
100
101                                 var reader = parameters.SymbolStream != null
102                                         ? symbol_reader_provider.GetSymbolReader (module, parameters.SymbolStream)
103                                         : symbol_reader_provider.GetSymbolReader (module, module.FullyQualifiedName);
104
105                                 module.ReadSymbols (reader);
106                         }
107                 }
108
109                 static ModuleDefinition ReadModule (Image image, ReaderParameters parameters)
110                 {
111                         var reader = CreateModuleReader (image, parameters.ReadingMode);
112                         reader.ReadModule ();
113                         return reader.module;
114                 }
115
116                 static ModuleReader CreateModuleReader (Image image, ReadingMode mode)
117                 {
118                         switch (mode) {
119                         case ReadingMode.Immediate:
120                                 return new ImmediateModuleReader (image);
121                         case ReadingMode.Deferred:
122                                 return new DeferredModuleReader (image);
123                         default:
124                                 throw new ArgumentException ();
125                         }
126                 }
127         }
128
129         sealed class ImmediateModuleReader : ModuleReader {
130
131                 public ImmediateModuleReader (Image image)
132                         : base (image, ReadingMode.Immediate)
133                 {
134                 }
135
136                 protected override void ReadModule ()
137                 {
138                         this.module.Read (this.module, (module, reader) => {
139                                 ReadModuleManifest (reader);
140                                 ReadModule (module);
141                                 return module;
142                         });
143                 }
144
145                 public static void ReadModule (ModuleDefinition module)
146                 {
147                         if (module.HasAssemblyReferences)
148                                 Read (module.AssemblyReferences);
149                         if (module.HasResources)
150                                 Read (module.Resources);
151                         if (module.HasModuleReferences)
152                                 Read (module.ModuleReferences);
153                         if (module.HasTypes)
154                                 ReadTypes (module.Types);
155                         if (module.HasExportedTypes)
156                                 Read (module.ExportedTypes);
157                         if (module.HasCustomAttributes)
158                                 Read (module.CustomAttributes);
159
160                         var assembly = module.Assembly;
161                         if (assembly == null)
162                                 return;
163
164                         if (assembly.HasCustomAttributes)
165                                 Read (assembly.CustomAttributes);
166                         if (assembly.HasSecurityDeclarations)
167                                 Read (assembly.SecurityDeclarations);
168                 }
169
170                 static void ReadTypes (Collection<TypeDefinition> types)
171                 {
172                         for (int i = 0; i < types.Count; i++)
173                                 ReadType (types [i]);
174                 }
175
176                 static void ReadType (TypeDefinition type)
177                 {
178                         ReadGenericParameters (type);
179
180                         if (type.HasInterfaces)
181                                 Read (type.Interfaces);
182
183                         if (type.HasNestedTypes)
184                                 ReadTypes (type.NestedTypes);
185
186                         if (type.HasLayoutInfo)
187                                 Read (type.ClassSize);
188
189                         if (type.HasFields)
190                                 ReadFields (type);
191
192                         if (type.HasMethods)
193                                 ReadMethods (type);
194
195                         if (type.HasProperties)
196                                 ReadProperties (type);
197
198                         if (type.HasEvents)
199                                 ReadEvents (type);
200
201                         ReadSecurityDeclarations (type);
202                         ReadCustomAttributes (type);
203                 }
204
205                 static void ReadGenericParameters (IGenericParameterProvider provider)
206                 {
207                         if (!provider.HasGenericParameters)
208                                 return;
209
210                         var parameters = provider.GenericParameters;
211
212                         for (int i = 0; i < parameters.Count; i++) {
213                                 var parameter = parameters [i];
214
215                                 if (parameter.HasConstraints)
216                                         Read (parameter.Constraints);
217
218                                 if (parameter.HasCustomAttributes)
219                                         Read (parameter.CustomAttributes);
220                         }
221                 }
222
223                 static void ReadSecurityDeclarations (ISecurityDeclarationProvider provider)
224                 {
225                         if (provider.HasSecurityDeclarations)
226                                 Read (provider.SecurityDeclarations);
227                 }
228
229                 static void ReadCustomAttributes (ICustomAttributeProvider provider)
230                 {
231                         if (provider.HasCustomAttributes)
232                                 Read (provider.CustomAttributes);
233                 }
234
235                 static void ReadFields (TypeDefinition type)
236                 {
237                         var fields = type.Fields;
238
239                         for (int i = 0; i < fields.Count; i++) {
240                                 var field = fields [i];
241
242                                 if (field.HasConstant)
243                                         Read (field.Constant);
244
245                                 if (field.HasLayoutInfo)
246                                         Read (field.Offset);
247
248                                 if (field.RVA > 0)
249                                         Read (field.InitialValue);
250
251                                 if (field.HasMarshalInfo)
252                                         Read (field.MarshalInfo);
253
254                                 ReadCustomAttributes (field);
255                         }
256                 }
257
258                 static void ReadMethods (TypeDefinition type)
259                 {
260                         var methods = type.Methods;
261
262                         for (int i = 0; i < methods.Count; i++) {
263                                 var method = methods [i];
264
265                                 ReadGenericParameters (method);
266
267                                 if (method.HasParameters)
268                                         ReadParameters (method);
269
270                                 if (method.HasOverrides)
271                                         Read (method.Overrides);
272
273                                 if (method.IsPInvokeImpl)
274                                         Read (method.PInvokeInfo);
275
276                                 ReadSecurityDeclarations (method);
277                                 ReadCustomAttributes (method);
278
279                                 var return_type = method.MethodReturnType;
280                                 if (return_type.HasConstant)
281                                         Read (return_type.Constant);
282
283                                 if (return_type.HasMarshalInfo)
284                                         Read (return_type.MarshalInfo);
285
286                                 ReadCustomAttributes (return_type);
287                         }
288                 }
289
290                 static void ReadParameters (MethodDefinition method)
291                 {
292                         var parameters = method.Parameters;
293
294                         for (int i = 0; i < parameters.Count; i++) {
295                                 var parameter = parameters [i];
296
297                                 if (parameter.HasConstant)
298                                         Read (parameter.Constant);
299
300                                 if (parameter.HasMarshalInfo)
301                                         Read (parameter.MarshalInfo);
302
303                                 ReadCustomAttributes (parameter);
304                         }
305                 }
306
307                 static void ReadProperties (TypeDefinition type)
308                 {
309                         var properties = type.Properties;
310
311                         for (int i = 0; i < properties.Count; i++) {
312                                 var property = properties [i];
313
314                                 Read (property.GetMethod);
315
316                                 if (property.HasConstant)
317                                         Read (property.Constant);
318
319                                 ReadCustomAttributes (property);
320                         }
321                 }
322
323                 static void ReadEvents (TypeDefinition type)
324                 {
325                         var events = type.Events;
326
327                         for (int i = 0; i < events.Count; i++) {
328                                 var @event = events [i];
329
330                                 Read (@event.AddMethod);
331
332                                 ReadCustomAttributes (@event);
333                         }
334                 }
335
336                 static void Read (object collection)
337                 {
338                 }
339         }
340
341         sealed class DeferredModuleReader : ModuleReader {
342
343                 public DeferredModuleReader (Image image)
344                         : base (image, ReadingMode.Deferred)
345                 {
346                 }
347
348                 protected override void ReadModule ()
349                 {
350                         this.module.Read (this.module, (module, reader) => {
351                                 ReadModuleManifest (reader);
352                                 return module;
353                         });
354                 }
355         }
356
357         sealed class MetadataReader : ByteBuffer {
358
359                 readonly internal Image image;
360                 readonly internal ModuleDefinition module;
361                 readonly internal MetadataSystem metadata;
362
363                 internal IGenericContext context;
364                 internal CodeReader code;
365
366                 uint Position {
367                         get { return (uint) base.position; }
368                         set { base.position = (int) value; }
369                 }
370
371                 public MetadataReader (ModuleDefinition module)
372                         : base (module.Image.MetadataSection.Data)
373                 {
374                         this.image = module.Image;
375                         this.module = module;
376                         this.metadata = module.MetadataSystem;
377                         this.code = CodeReader.CreateCodeReader (this);
378                 }
379
380                 int GetCodedIndexSize (CodedIndex index)
381                 {
382                         return image.GetCodedIndexSize (index);
383                 }
384
385                 uint ReadByIndexSize (int size)
386                 {
387                         if (size == 4)
388                                 return ReadUInt32 ();
389                         else
390                                 return ReadUInt16 ();
391                 }
392
393                 byte [] ReadBlob ()
394                 {
395                         var blob_heap = image.BlobHeap;
396                         if (blob_heap == null) {
397                                 position += 2;
398                                 return Empty<byte>.Array;
399                         }
400
401                         return blob_heap.Read (ReadBlobIndex ());
402                 }
403
404                 byte [] ReadBlob (uint signature)
405                 {
406                         var blob_heap = image.BlobHeap;
407                         if (blob_heap == null)
408                                 return Empty<byte>.Array;
409
410                         return blob_heap.Read (signature);
411                 }
412
413                 uint ReadBlobIndex ()
414                 {
415                         var blob_heap = image.BlobHeap;
416                         return ReadByIndexSize (blob_heap != null ? blob_heap.IndexSize : 2);
417                 }
418
419                 string ReadString ()
420                 {
421                         return image.StringHeap.Read (ReadByIndexSize (image.StringHeap.IndexSize));
422                 }
423
424                 uint ReadStringIndex ()
425                 {
426                         return ReadByIndexSize (image.StringHeap.IndexSize);
427                 }
428
429                 uint ReadTableIndex (Table table)
430                 {
431                         return ReadByIndexSize (image.GetTableIndexSize (table));
432                 }
433
434                 MetadataToken ReadMetadataToken (CodedIndex index)
435                 {
436                         return index.GetMetadataToken (ReadByIndexSize (GetCodedIndexSize (index)));
437                 }
438
439                 int MoveTo (Table table)
440                 {
441                         var info = image.TableHeap [table];
442                         if (info.Length != 0)
443                                 Position = info.Offset;
444
445                         return (int) info.Length;
446                 }
447
448                 bool MoveTo (Table table, uint row)
449                 {
450                         var info = image.TableHeap [table];
451                         var length = info.Length;
452                         if (length == 0 || row > length)
453                                 return false;
454
455                         Position = info.Offset + (info.RowSize * (row - 1));
456                         return true;
457                 }
458
459                 public AssemblyNameDefinition ReadAssemblyNameDefinition ()
460                 {
461                         if (MoveTo (Table.Assembly) == 0)
462                                 return null;
463
464                         var name = new AssemblyNameDefinition ();
465
466                         name.HashAlgorithm = (AssemblyHashAlgorithm) ReadUInt32 ();
467
468                         PopulateVersionAndFlags (name);
469
470                         name.PublicKey = ReadBlob ();
471
472                         PopulateNameAndCulture (name);
473
474                         return name;
475                 }
476
477                 public ModuleDefinition Populate (ModuleDefinition module)
478                 {
479                         if (MoveTo (Table.Module) == 0)
480                                 return module;
481
482                         Advance (2); // Generation
483
484                         module.Name = ReadString ();
485                         module.Mvid = image.GuidHeap.Read (ReadByIndexSize (image.GuidHeap.IndexSize));
486
487                         return module;
488                 }
489
490                 public Collection<AssemblyNameReference> ReadAssemblyReferences ()
491                 {
492                         int length = MoveTo (Table.AssemblyRef);
493                         var references = new Collection<AssemblyNameReference> (length);
494
495                         for (uint i = 1; i <= length; i++) {
496                                 var reference = new AssemblyNameReference ();
497                                 reference.token = new MetadataToken (TokenType.AssemblyRef, i);
498
499                                 PopulateVersionAndFlags (reference);
500
501                                 reference.PublicKeyToken = ReadBlob ();
502
503                                 PopulateNameAndCulture (reference);
504
505                                 reference.Hash = ReadBlob ();
506
507                                 references.Add (reference);
508                         }
509
510                         return references;
511                 }
512
513                 public MethodDefinition ReadEntryPoint ()
514                 {
515                         if (module.Kind != ModuleKind.Console && module.Kind != ModuleKind.Windows)
516                                 return null;
517
518                         var token = new MetadataToken (module.Image.EntryPointToken);
519
520                         return GetMethodDefinition (token.RID);
521                 }
522
523                 public Collection<ModuleDefinition> ReadModules ()
524                 {
525                         var modules = new Collection<ModuleDefinition> (1);
526                         modules.Add (this.module);
527
528                         int length = MoveTo (Table.File);
529                         for (uint i = 1; i <= length; i++) {
530                                 var attributes = (FileAttributes) ReadUInt32 ();
531                                 var name = ReadString ();
532                                 ReadBlobIndex ();
533
534                                 if (attributes != FileAttributes.ContainsMetaData)
535                                         continue;
536
537                                 var parameters = new ReaderParameters {
538                                         ReadingMode = module.ReadingMode,
539                                         SymbolReaderProvider = module.SymbolReaderProvider,
540                                 };
541
542                                 modules.Add (ModuleDefinition.ReadModule (
543                                         GetModuleFileName (name), parameters));
544                         }
545
546                         return modules;
547                 }
548
549                 string GetModuleFileName (string name)
550                 {
551                         if (module.FullyQualifiedName == null)
552                                 throw new NotSupportedException ();
553
554                         var path = Path.GetDirectoryName (module.FullyQualifiedName);
555                         return Path.Combine (path, name);
556                 }
557
558                 public Collection<ModuleReference> ReadModuleReferences ()
559                 {
560                         int length = MoveTo (Table.ModuleRef);
561                         var references = new Collection<ModuleReference> (length);
562
563                         for (uint i = 1; i <= length; i++) {
564                                 var reference = new ModuleReference (ReadString ());
565                                 reference.token = new MetadataToken (TokenType.ModuleRef, i);
566
567                                 references.Add (reference);
568                         }
569
570                         return references;
571                 }
572
573                 public bool HasFileResource ()
574                 {
575                         int length = MoveTo (Table.File);
576                         if (length == 0)
577                                 return false;
578
579                         for (uint i = 1; i <= length; i++)
580                                 if (ReadFileRecord (i).Col1 == FileAttributes.ContainsNoMetaData)
581                                         return true;
582
583                         return false;
584                 }
585
586                 public Collection<Resource> ReadResources ()
587                 {
588                         int length = MoveTo (Table.ManifestResource);
589                         var resources = new Collection<Resource> (length);
590
591                         for (int i = 1; i <= length; i++) {
592                                 var offset = ReadUInt32 ();
593                                 var flags = (ManifestResourceAttributes) ReadUInt32 ();
594                                 var name = ReadString ();
595                                 var implementation = ReadMetadataToken (CodedIndex.Implementation);
596
597                                 Resource resource;
598
599                                 if (implementation.RID == 0) {
600                                         resource = new EmbeddedResource (name, flags, offset, this);
601                                 } else if (implementation.TokenType == TokenType.AssemblyRef) {
602                                         resource = new AssemblyLinkedResource (name, flags) {
603                                                 Assembly = (AssemblyNameReference) GetTypeReferenceScope (implementation),
604                                         };
605                                 } else if (implementation.TokenType == TokenType.File) {
606                                         var file_record = ReadFileRecord (implementation.RID);
607
608                                         resource = new LinkedResource (name, flags) {
609                                                 File = file_record.Col2,
610                                                 hash = ReadBlob (file_record.Col3)
611                                         };
612                                 } else
613                                         throw new NotSupportedException ();
614
615                                 resources.Add (resource);
616                         }
617
618                         return resources;
619                 }
620
621                 Row<FileAttributes, string, uint> ReadFileRecord (uint rid)
622                 {
623                         var position = this.position;
624
625                         if (!MoveTo (Table.File, rid))
626                                 throw new ArgumentException ();
627
628                         var record = new Row<FileAttributes, string, uint> (
629                                 (FileAttributes) ReadUInt32 (),
630                                 ReadString (),
631                                 ReadBlobIndex ());
632
633                         this.position = position;
634
635                         return record;
636                 }
637
638                 public MemoryStream GetManagedResourceStream (uint offset)
639                 {
640                         var rva = image.Resources.VirtualAddress;
641                         var section = image.GetSectionAtVirtualAddress (rva);
642                         var position = (rva - section.VirtualAddress) + offset;
643                         var buffer = section.Data;
644
645                         var length = buffer [position]
646                                 | (buffer [position + 1] << 8)
647                                 | (buffer [position + 2] << 16)
648                                 | (buffer [position + 3] << 24);
649
650                         return new MemoryStream (buffer, (int) position + 4, length);
651                 }
652
653                 void PopulateVersionAndFlags (AssemblyNameReference name)
654                 {
655                         name.Version = new Version (
656                                 ReadUInt16 (),
657                                 ReadUInt16 (),
658                                 ReadUInt16 (),
659                                 ReadUInt16 ());
660
661                         name.Attributes = (AssemblyAttributes) ReadUInt32 ();
662                 }
663
664                 void PopulateNameAndCulture (AssemblyNameReference name)
665                 {
666                         name.Name = ReadString ();
667                         name.Culture = ReadString ();
668                 }
669
670                 public TypeDefinitionCollection ReadTypes ()
671                 {
672                         InitializeTypeDefinitions ();
673                         var mtypes = metadata.Types;
674                         var type_count = mtypes.Length - metadata.NestedTypes.Count;
675                         var types = new TypeDefinitionCollection (module, type_count);
676
677                         for (int i = 0; i < mtypes.Length; i++) {
678                                 var type = mtypes [i];
679                                 if (IsNested (type.Attributes))
680                                         continue;
681
682                                 types.Add (type);
683                         }
684
685                         return types;
686                 }
687
688                 void InitializeTypeDefinitions ()
689                 {
690                         if (metadata.Types != null)
691                                 return;
692
693                         InitializeNestedTypes ();
694                         InitializeFields ();
695                         InitializeMethods ();
696
697                         int length = MoveTo (Table.TypeDef);
698                         var types = metadata.Types = new TypeDefinition [length];
699
700                         for (uint i = 0; i < length; i++) {
701                                 if (types [i] != null)
702                                         continue;
703
704                                 types [i] = ReadType (i + 1);
705                         }
706                 }
707
708                 static bool IsNested (TypeAttributes attributes)
709                 {
710                         switch (attributes & TypeAttributes.VisibilityMask) {
711                         case TypeAttributes.NestedAssembly:
712                         case TypeAttributes.NestedFamANDAssem:
713                         case TypeAttributes.NestedFamily:
714                         case TypeAttributes.NestedFamORAssem:
715                         case TypeAttributes.NestedPrivate:
716                         case TypeAttributes.NestedPublic:
717                                 return true;
718                         default:
719                                 return false;
720                         }
721                 }
722
723                 public bool HasNestedTypes (TypeDefinition type)
724                 {
725                         uint [] mapping;
726                         InitializeNestedTypes ();
727
728                         if (!metadata.TryGetNestedTypeMapping (type, out mapping))
729                                 return false;
730
731                         return mapping.Length > 0;
732                 }
733
734                 public Collection<TypeDefinition> ReadNestedTypes (TypeDefinition type)
735                 {
736                         InitializeNestedTypes ();
737                         uint [] mapping;
738                         if (!metadata.TryGetNestedTypeMapping (type, out mapping))
739                                 return new MemberDefinitionCollection<TypeDefinition> (type);
740
741                         var nested_types = new MemberDefinitionCollection<TypeDefinition> (type, mapping.Length);
742
743                         for (int i = 0; i < mapping.Length; i++)
744                                 nested_types.Add (GetTypeDefinition (mapping [i]));
745
746                         metadata.RemoveNestedTypeMapping (type);
747
748                         return nested_types;
749                 }
750
751                 void InitializeNestedTypes ()
752                 {
753                         if (metadata.NestedTypes != null)
754                                 return;
755
756                         var length = MoveTo (Table.NestedClass);
757
758                         metadata.NestedTypes = new Dictionary<uint, uint []> (length);
759                         metadata.ReverseNestedTypes = new Dictionary<uint, uint> (length);
760
761                         if (length == 0)
762                                 return;
763
764                         for (int i = 1; i <= length; i++) {
765                                 var nested = ReadTableIndex (Table.TypeDef);
766                                 var declaring = ReadTableIndex (Table.TypeDef);
767
768                                 AddNestedMapping (declaring, nested);
769                         }
770                 }
771
772                 void AddNestedMapping (uint declaring, uint nested)
773                 {
774                         metadata.SetNestedTypeMapping (declaring, AddMapping (metadata.NestedTypes, declaring, nested));
775                         metadata.SetReverseNestedTypeMapping (nested, declaring);
776                 }
777
778                 static TValue [] AddMapping<TKey, TValue> (Dictionary<TKey, TValue []> cache, TKey key, TValue value)
779                 {
780                         TValue [] mapped;
781                         if (!cache.TryGetValue (key, out mapped)) {
782                                 mapped = new [] { value };
783                                 return mapped;
784                         }
785
786                         var new_mapped = new TValue [mapped.Length + 1];
787                         Array.Copy (mapped, new_mapped, mapped.Length);
788                         new_mapped [mapped.Length] = value;
789                         return new_mapped;
790                 }
791
792                 TypeDefinition ReadType (uint rid)
793                 {
794                         if (!MoveTo (Table.TypeDef, rid))
795                                 return null;
796
797                         var attributes = (TypeAttributes) ReadUInt32 ();
798                         var name = ReadString ();
799                         var @namespace = ReadString ();
800                         var type = new TypeDefinition (@namespace, name, attributes);
801                         type.token = new MetadataToken (TokenType.TypeDef, rid);
802                         type.scope = module;
803                         type.module = module;
804
805                         metadata.AddTypeDefinition (type);
806
807                         this.context = type;
808
809                         type.BaseType = GetTypeDefOrRef (ReadMetadataToken (CodedIndex.TypeDefOrRef));
810
811                         type.fields_range = ReadFieldsRange (rid);
812                         type.methods_range = ReadMethodsRange (rid);
813
814                         if (IsNested (attributes))
815                                 type.DeclaringType = GetNestedTypeDeclaringType (type);
816
817                         return type;
818                 }
819
820                 TypeDefinition GetNestedTypeDeclaringType (TypeDefinition type)
821                 {
822                         uint declaring_rid;
823                         if (!metadata.TryGetReverseNestedTypeMapping (type, out declaring_rid))
824                                 return null;
825
826                         metadata.RemoveReverseNestedTypeMapping (type);
827                         return GetTypeDefinition (declaring_rid);
828                 }
829
830                 Range ReadFieldsRange (uint type_index)
831                 {
832                         return ReadListRange (type_index, Table.TypeDef, Table.Field);
833                 }
834
835                 Range ReadMethodsRange (uint type_index)
836                 {
837                         return ReadListRange (type_index, Table.TypeDef, Table.Method);
838                 }
839
840                 Range ReadListRange (uint current_index, Table current, Table target)
841                 {
842                         var list = new Range ();
843
844                         list.Start = ReadTableIndex (target);
845
846                         uint next_index;
847                         var current_table = image.TableHeap [current];
848
849                         if (current_index == current_table.Length)
850                                 next_index = image.TableHeap [target].Length + 1;
851                         else {
852                                 var position = Position;
853                                 Position += (uint) (current_table.RowSize - image.GetTableIndexSize (target));
854                                 next_index = ReadTableIndex (target);
855                                 Position = position;
856                         }
857
858                         list.Length = next_index - list.Start;
859
860                         return list;
861                 }
862
863                 public Row<short, int> ReadTypeLayout (TypeDefinition type)
864                 {
865                         InitializeTypeLayouts ();
866                         Row<ushort, uint> class_layout;
867                         var rid = type.token.RID;
868                         if (!metadata.ClassLayouts.TryGetValue (rid, out class_layout))
869                                 return new Row<short, int> (Mixin.NoDataMarker, Mixin.NoDataMarker);
870
871                         type.PackingSize = (short) class_layout.Col1;
872                         type.ClassSize = (int) class_layout.Col2;
873
874                         metadata.ClassLayouts.Remove (rid);
875
876                         return new Row<short, int> ((short) class_layout.Col1, (int) class_layout.Col2);
877                 }
878
879                 void InitializeTypeLayouts ()
880                 {
881                         if (metadata.ClassLayouts != null)
882                                 return;
883
884                         int length = MoveTo (Table.ClassLayout);
885
886                         var class_layouts = metadata.ClassLayouts = new Dictionary<uint, Row<ushort, uint>> (length);
887
888                         for (uint i = 0; i < length; i++) {
889                                 var packing_size = ReadUInt16 ();
890                                 var class_size = ReadUInt32 ();
891
892                                 var parent = ReadTableIndex (Table.TypeDef);
893
894                                 class_layouts.Add (parent, new Row<ushort, uint> (packing_size, class_size));
895                         }
896                 }
897
898                 public TypeReference GetTypeDefOrRef (MetadataToken token)
899                 {
900                         return (TypeReference) LookupToken (token);
901                 }
902
903                 public TypeDefinition GetTypeDefinition (uint rid)
904                 {
905                         InitializeTypeDefinitions ();
906
907                         var type = metadata.GetTypeDefinition (rid);
908                         if (type != null)
909                                 return type;
910
911                         return ReadTypeDefinition (rid);
912                 }
913
914                 TypeDefinition ReadTypeDefinition (uint rid)
915                 {
916                         if (!MoveTo (Table.TypeDef, rid))
917                                 return null;
918
919                         return ReadType (rid);
920                 }
921
922                 void InitializeTypeReferences ()
923                 {
924                         if (metadata.TypeReferences != null)
925                                 return;
926
927                         metadata.TypeReferences = new TypeReference [image.GetTableLength (Table.TypeRef)];
928                 }
929
930                 public TypeReference GetTypeReference (string scope, string full_name)
931                 {
932                         InitializeTypeReferences ();
933
934                         var length = metadata.TypeReferences.Length;
935
936                         for (uint i = 1; i <= length; i++) {
937                                 var type = GetTypeReference (i);
938
939                                 if (type.FullName != full_name)
940                                         continue;
941
942                                 if (string.IsNullOrEmpty (scope))
943                                         return type;
944
945                                 if (type.Scope.Name == scope)
946                                         return type;
947                         }
948
949                         return null;
950                 }
951
952                 TypeReference GetTypeReference (uint rid)
953                 {
954                         InitializeTypeReferences ();
955
956                         var type = metadata.GetTypeReference (rid);
957                         if (type != null)
958                                 return type;
959
960                         type = ReadTypeReference (rid);
961                         if (type != null)
962                                  metadata.AddTypeReference (type);
963
964                         return type;
965                 }
966
967                 TypeReference ReadTypeReference (uint rid)
968                 {
969                         if (!MoveTo (Table.TypeRef, rid))
970                                 return null;
971
972                         TypeReference declaring_type = null;
973                         IMetadataScope scope;
974
975                         var scope_token = ReadMetadataToken (CodedIndex.ResolutionScope);
976
977                         if (scope_token.TokenType == TokenType.TypeRef) {
978                                 declaring_type = GetTypeDefOrRef (scope_token);
979
980                                 scope = declaring_type != null
981                                         ? declaring_type.Scope
982                                         : module;
983                         } else
984                                 scope = GetTypeReferenceScope (scope_token);
985
986                         var name = ReadString ();
987                         var @namespace = ReadString ();
988
989                         var type = new TypeReference (
990                                 @namespace,
991                                 name,
992                                 module,
993                                 scope);
994
995                         type.DeclaringType = declaring_type;
996                         type.token = new MetadataToken (TokenType.TypeRef, rid);
997
998                         MetadataSystem.TryProcessPrimitiveType (type);
999
1000                         return type;
1001                 }
1002
1003                 IMetadataScope GetTypeReferenceScope (MetadataToken scope)
1004                 {
1005                         switch (scope.TokenType) {
1006                         // FIXME: both assembly refs and module refs should be in their
1007                         // own arrays, in case of someone modify the collections before
1008                         // this code is called
1009                         case TokenType.AssemblyRef:
1010                                 return module.AssemblyReferences [(int) scope.RID - 1];
1011                         case TokenType.ModuleRef:
1012                                 return module.ModuleReferences [(int) scope.RID - 1];
1013                         case TokenType.Module:
1014                                 return module;
1015                         default:
1016                                 throw new NotSupportedException ();
1017                         }
1018                 }
1019
1020                 public IEnumerable<TypeReference> GetTypeReferences ()
1021                 {
1022                         InitializeTypeReferences ();
1023
1024                         var length = image.GetTableLength (Table.TypeRef);
1025
1026                         var type_references = new TypeReference [length];
1027
1028                         for (uint i = 1; i <= length; i++)
1029                                 type_references [i - 1] = GetTypeReference (i);
1030
1031                         return type_references;
1032                 }
1033
1034                 TypeReference GetTypeSpecification (uint rid)
1035                 {
1036                         if (!MoveTo (Table.TypeSpec, rid))
1037                                 return null;
1038
1039                         var reader = ReadSignature (ReadBlobIndex ());
1040                         return reader.ReadTypeSignature ();
1041                 }
1042
1043                 SignatureReader ReadSignature (uint signature)
1044                 {
1045                         return new SignatureReader (signature, this);
1046                 }
1047
1048                 public bool HasInterfaces (TypeDefinition type)
1049                 {
1050                         InitializeInterfaces ();
1051                         MetadataToken [] mapping;
1052
1053                         return metadata.TryGetInterfaceMapping (type, out mapping);
1054                 }
1055
1056                 public Collection<TypeReference> ReadInterfaces (TypeDefinition type)
1057                 {
1058                         InitializeInterfaces ();
1059                         MetadataToken [] mapping;
1060
1061                         if (!metadata.TryGetInterfaceMapping (type, out mapping))
1062                                 return new Collection<TypeReference> ();
1063
1064                         var interfaces = new Collection<TypeReference> (mapping.Length);
1065
1066                         this.context = type;
1067
1068                         for (int i = 0; i < mapping.Length; i++)
1069                                 interfaces.Add (GetTypeDefOrRef (mapping [i]));
1070
1071                         metadata.RemoveInterfaceMapping (type);
1072
1073                         return interfaces;
1074                 }
1075
1076                 void InitializeInterfaces ()
1077                 {
1078                         if (metadata.Interfaces != null)
1079                                 return;
1080
1081                         int length = MoveTo (Table.InterfaceImpl);
1082
1083                         metadata.Interfaces = new Dictionary<uint, MetadataToken []> (length);
1084
1085                         for (int i = 0; i < length; i++) {
1086                                 var type = ReadTableIndex (Table.TypeDef);
1087                                 var @interface = ReadMetadataToken (CodedIndex.TypeDefOrRef);
1088
1089                                 AddInterfaceMapping (type, @interface);
1090                         }
1091                 }
1092
1093                 void AddInterfaceMapping (uint type, MetadataToken @interface)
1094                 {
1095                         metadata.SetInterfaceMapping (type, AddMapping (metadata.Interfaces, type, @interface));
1096                 }
1097
1098                 public Collection<FieldDefinition> ReadFields (TypeDefinition type)
1099                 {
1100                         var fields_range = type.fields_range;
1101                         if (fields_range.Length == 0)
1102                                 return new MemberDefinitionCollection<FieldDefinition> (type);
1103
1104                         var fields = new MemberDefinitionCollection<FieldDefinition> (type, (int) fields_range.Length);
1105                         this.context = type;
1106
1107                         MoveTo (Table.Field, fields_range.Start);
1108                         for (uint i = 0; i < fields_range.Length; i++)
1109                                 fields.Add (ReadField (fields_range.Start + i));
1110
1111                         return fields;
1112                 }
1113
1114                 FieldDefinition ReadField (uint field_rid)
1115                 {
1116                         var attributes = (FieldAttributes) ReadUInt16 ();
1117                         var name = ReadString ();
1118                         var signature = ReadBlobIndex ();
1119
1120                         var field = new FieldDefinition (name, attributes, ReadFieldType (signature));
1121                         field.token = new MetadataToken (TokenType.Field, field_rid);
1122                         metadata.AddFieldDefinition (field);
1123
1124                         return field;
1125                 }
1126
1127                 void InitializeFields ()
1128                 {
1129                         if (metadata.Fields != null)
1130                                 return;
1131
1132                         metadata.Fields = new FieldDefinition [image.GetTableLength (Table.Field)];
1133                 }
1134
1135                 TypeReference ReadFieldType (uint signature)
1136                 {
1137                         var reader = ReadSignature (signature);
1138
1139                         const byte field_sig = 0x6;
1140
1141                         if (reader.ReadByte () != field_sig)
1142                                 throw new NotSupportedException ();
1143
1144                         return reader.ReadTypeSignature ();
1145                 }
1146
1147                 public int ReadFieldRVA (FieldDefinition field)
1148                 {
1149                         InitializeFieldRVAs ();
1150                         var rid = field.token.RID;
1151
1152                         RVA rva;
1153                         if (!metadata.FieldRVAs.TryGetValue (rid, out rva))
1154                                 return 0;
1155
1156                         var size = GetFieldTypeSize (field.FieldType);
1157
1158                         if (size == 0 || rva == 0)
1159                                 return 0;
1160
1161                         metadata.FieldRVAs.Remove (rid);
1162
1163                         field.InitialValue = GetFieldInitializeValue (size, rva);
1164
1165                         return (int) rva;
1166                 }
1167
1168                 byte [] GetFieldInitializeValue (int size, RVA rva)
1169                 {
1170                         var section = image.GetSectionAtVirtualAddress (rva);
1171                         if (section == null)
1172                                 return Empty<byte>.Array;
1173
1174                         var value = new byte [size];
1175                         Buffer.BlockCopy (section.Data, (int) (rva - section.VirtualAddress), value, 0, size);
1176                         return value;
1177                 }
1178
1179                 static int GetFieldTypeSize (TypeReference type)
1180                 {
1181                         int size = 0;
1182
1183                         switch (type.etype) {
1184                         case ElementType.Boolean:
1185                         case ElementType.U1:
1186                         case ElementType.I1:
1187                                 size = 1;
1188                                 break;
1189                         case ElementType.U2:
1190                         case ElementType.I2:
1191                         case ElementType.Char:
1192                                 size = 2;
1193                                 break;
1194                         case ElementType.U4:
1195                         case ElementType.I4:
1196                         case ElementType.R4:
1197                                 size = 4;
1198                                 break;
1199                         case ElementType.U8:
1200                         case ElementType.I8:
1201                         case ElementType.R8:
1202                                 size = 8;
1203                                 break;
1204                         case ElementType.Ptr:
1205                         case ElementType.FnPtr:
1206                                 size = IntPtr.Size;
1207                                 break;
1208                         case ElementType.CModOpt:
1209                         case ElementType.CModReqD:
1210                                 return GetFieldTypeSize (((IModifierType) type).ElementType);
1211                         default:
1212                                 var field_type = type.CheckedResolve ();
1213                                 if (field_type.HasLayoutInfo)
1214                                         size = field_type.ClassSize;
1215
1216                                 break;
1217                         }
1218
1219                         return size;
1220                 }
1221
1222                 void InitializeFieldRVAs ()
1223                 {
1224                         if (metadata.FieldRVAs != null)
1225                                 return;
1226
1227                         int length = MoveTo (Table.FieldRVA);
1228
1229                         var field_rvas = metadata.FieldRVAs = new Dictionary<uint, uint> (length);
1230
1231                         for (int i = 0; i < length; i++) {
1232                                 var rva = ReadUInt32 ();
1233                                 var field = ReadTableIndex (Table.Field);
1234
1235                                 field_rvas.Add (field, rva);
1236                         }
1237                 }
1238
1239                 public int ReadFieldLayout (FieldDefinition field)
1240                 {
1241                         InitializeFieldLayouts ();
1242                         var rid = field.token.RID;
1243                         uint offset;
1244                         if (!metadata.FieldLayouts.TryGetValue (rid, out offset))
1245                                 return Mixin.NoDataMarker;
1246
1247                         metadata.FieldLayouts.Remove (rid);
1248
1249                         return (int) offset;
1250                 }
1251
1252                 void InitializeFieldLayouts ()
1253                 {
1254                         if (metadata.FieldLayouts != null)
1255                                 return;
1256
1257                         int length = MoveTo (Table.FieldLayout);
1258
1259                         var field_layouts = metadata.FieldLayouts = new Dictionary<uint, uint> (length);
1260
1261                         for (int i = 0; i < length; i++) {
1262                                 var offset = ReadUInt32 ();
1263                                 var field = ReadTableIndex (Table.Field);
1264
1265                                 field_layouts.Add (field, offset);
1266                         }
1267                 }
1268
1269                 public bool HasEvents (TypeDefinition type)
1270                 {
1271                         InitializeEvents ();
1272
1273                         Range range;
1274                         if (!metadata.TryGetEventsRange (type, out range))
1275                                 return false;
1276
1277                         return range.Length > 0;
1278                 }
1279
1280                 public Collection<EventDefinition> ReadEvents (TypeDefinition type)
1281                 {
1282                         InitializeEvents ();
1283                         Range range;
1284
1285                         if (!metadata.TryGetEventsRange (type, out range))
1286                                 return new MemberDefinitionCollection<EventDefinition> (type);
1287
1288                         var events = new MemberDefinitionCollection<EventDefinition> (type, (int) range.Length);
1289
1290                         metadata.RemoveEventsRange (type);
1291
1292                         if (range.Length == 0 || !MoveTo (Table.Event, range.Start))
1293                                 return events;
1294
1295                         this.context = type;
1296
1297                         for (uint i = 0; i < range.Length; i++)
1298                                 events.Add (ReadEvent (range.Start + i));
1299
1300                         return events;
1301                 }
1302
1303                 EventDefinition ReadEvent (uint event_rid)
1304                 {
1305                         var attributes = (EventAttributes) ReadUInt16 ();
1306                         var name = ReadString ();
1307                         var event_type = GetTypeDefOrRef (ReadMetadataToken (CodedIndex.TypeDefOrRef));
1308
1309                         var @event = new EventDefinition (name, attributes, event_type);
1310                         @event.token = new MetadataToken (TokenType.Event, event_rid);
1311                         return @event;
1312                 }
1313
1314                 void InitializeEvents ()
1315                 {
1316                         if (metadata.Events != null)
1317                                 return;
1318
1319                         int length = MoveTo (Table.EventMap);
1320
1321                         metadata.Events = new Dictionary<uint, Range> (length);
1322
1323                         for (uint i = 1; i <= length; i++) {
1324                                 var type_rid = ReadTableIndex (Table.TypeDef);
1325                                 Range events_range = ReadEventsRange (i);
1326                                 metadata.AddEventsRange (type_rid, events_range);
1327                         }
1328                 }
1329
1330                 Range ReadEventsRange (uint rid)
1331                 {
1332                         return ReadListRange (rid, Table.EventMap, Table.Event);
1333                 }
1334
1335                 public bool HasProperties (TypeDefinition type)
1336                 {
1337                         InitializeProperties ();
1338
1339                         Range range;
1340                         if (!metadata.TryGetPropertiesRange (type, out range))
1341                                 return false;
1342
1343                         return range.Length > 0;
1344                 }
1345
1346                 public Collection<PropertyDefinition> ReadProperties (TypeDefinition type)
1347                 {
1348                         InitializeProperties ();
1349
1350                         Range range;
1351
1352                         if (!metadata.TryGetPropertiesRange (type, out range))
1353                                 return new MemberDefinitionCollection<PropertyDefinition> (type);
1354
1355                         metadata.RemovePropertiesRange (type);
1356
1357                         var properties = new MemberDefinitionCollection<PropertyDefinition> (type, (int) range.Length);
1358
1359                         if (range.Length == 0 || !MoveTo (Table.Property, range.Start))
1360                                 return properties;
1361
1362                         this.context = type;
1363
1364                         for (uint i = 0; i < range.Length; i++)
1365                                 properties.Add (ReadProperty (range.Start + i));
1366
1367                         return properties;
1368                 }
1369
1370                 PropertyDefinition ReadProperty (uint property_rid)
1371                 {
1372                         var attributes = (PropertyAttributes) ReadUInt16 ();
1373                         var name = ReadString ();
1374                         var signature = ReadBlobIndex ();
1375
1376                         var reader = ReadSignature (signature);
1377                         const byte property_signature = 0x8;
1378
1379                         var calling_convention = reader.ReadByte ();
1380
1381                         if ((calling_convention & property_signature) == 0)
1382                                 throw new NotSupportedException ();
1383
1384                         var has_this = (calling_convention & 0x20) != 0;
1385
1386                         reader.ReadCompressedUInt32 (); // count
1387
1388                         var property = new PropertyDefinition (name, attributes, reader.ReadTypeSignature ());
1389                         property.HasThis = has_this;
1390                         property.token = new MetadataToken (TokenType.Property, property_rid);
1391
1392                         return property;
1393                 }
1394
1395                 void InitializeProperties ()
1396                 {
1397                         if (metadata.Properties != null)
1398                                 return;
1399
1400                         int length = MoveTo (Table.PropertyMap);
1401
1402                         metadata.Properties = new Dictionary<uint, Range> (length);
1403
1404                         for (uint i = 1; i <= length; i++) {
1405                                 var type_rid = ReadTableIndex (Table.TypeDef);
1406                                 var properties_range = ReadPropertiesRange (i);
1407                                 metadata.AddPropertiesRange (type_rid, properties_range);
1408                         }
1409                 }
1410
1411                 Range ReadPropertiesRange (uint rid)
1412                 {
1413                         return ReadListRange (rid, Table.PropertyMap, Table.Property);
1414                 }
1415
1416                 MethodSemanticsAttributes ReadMethodSemantics (MethodDefinition method)
1417                 {
1418                         InitializeMethodSemantics ();
1419                         Row<MethodSemanticsAttributes, MetadataToken> row;
1420                         if (!metadata.Semantics.TryGetValue (method.token.RID, out row))
1421                                 return MethodSemanticsAttributes.None;
1422
1423                         var type = method.DeclaringType;
1424
1425                         switch (row.Col1) {
1426                         case MethodSemanticsAttributes.AddOn:
1427                                 GetEvent (type, row.Col2).add_method = method;
1428                                 break;
1429                         case MethodSemanticsAttributes.Fire:
1430                                 GetEvent (type, row.Col2).invoke_method = method;
1431                                 break;
1432                         case MethodSemanticsAttributes.RemoveOn:
1433                                 GetEvent (type, row.Col2).remove_method = method;
1434                                 break;
1435                         case MethodSemanticsAttributes.Getter:
1436                                 GetProperty (type, row.Col2).get_method = method;
1437                                 break;
1438                         case MethodSemanticsAttributes.Setter:
1439                                 GetProperty (type, row.Col2).set_method = method;
1440                                 break;
1441                         case MethodSemanticsAttributes.Other:
1442                                 switch (row.Col2.TokenType) {
1443                                 case TokenType.Event: {
1444                                         var @event = GetEvent (type, row.Col2);
1445                                         if (@event.other_methods == null)
1446                                                 @event.other_methods = new Collection<MethodDefinition> ();
1447
1448                                         @event.other_methods.Add (method);
1449                                         break;
1450                                 }
1451                                 case TokenType.Property: {
1452                                         var property = GetProperty (type, row.Col2);
1453                                         if (property.other_methods == null)
1454                                                 property.other_methods = new Collection<MethodDefinition> ();
1455
1456                                         property.other_methods.Add (method);
1457
1458                                         break;
1459                                 }
1460                                 default:
1461                                         throw new NotSupportedException ();
1462                                 }
1463                                 break;
1464                         default:
1465                                 throw new NotSupportedException ();
1466                         }
1467
1468                         metadata.Semantics.Remove (method.token.RID);
1469
1470                         return row.Col1;
1471                 }
1472
1473                 static EventDefinition GetEvent (TypeDefinition type, MetadataToken token)
1474                 {
1475                         if (token.TokenType != TokenType.Event)
1476                                 throw new ArgumentException ();
1477
1478                         return GetMember (type.Events, token);
1479                 }
1480
1481                 static PropertyDefinition GetProperty (TypeDefinition type, MetadataToken token)
1482                 {
1483                         if (token.TokenType != TokenType.Property)
1484                                 throw new ArgumentException ();
1485
1486                         return GetMember (type.Properties, token);
1487                 }
1488
1489                 static TMember GetMember<TMember> (Collection<TMember> members, MetadataToken token) where TMember : IMemberDefinition
1490                 {
1491                         for (int i = 0; i < members.Count; i++) {
1492                                 var member = members [i];
1493                                 if (member.MetadataToken == token)
1494                                         return member;
1495                         }
1496
1497                         throw new ArgumentException ();
1498                 }
1499
1500                 void InitializeMethodSemantics ()
1501                 {
1502                         if (metadata.Semantics != null)
1503                                 return;
1504
1505                         int length = MoveTo (Table.MethodSemantics);
1506
1507                         var semantics = metadata.Semantics = new Dictionary<uint, Row<MethodSemanticsAttributes, MetadataToken>> (0);
1508
1509                         for (uint i = 0; i < length; i++) {
1510                                 var attributes = (MethodSemanticsAttributes) ReadUInt16 ();
1511                                 var method_rid = ReadTableIndex (Table.Method);
1512                                 var association = ReadMetadataToken (CodedIndex.HasSemantics);
1513
1514                                 semantics [method_rid] = new Row<MethodSemanticsAttributes, MetadataToken> (attributes, association);
1515                         }
1516                 }
1517
1518                 public PropertyDefinition ReadMethods (PropertyDefinition property)
1519                 {
1520                         ReadAllSemantics (property.DeclaringType);
1521                         return property;
1522                 }
1523
1524                 public EventDefinition ReadMethods (EventDefinition @event)
1525                 {
1526                         ReadAllSemantics (@event.DeclaringType);
1527                         return @event;
1528                 }
1529
1530                 public MethodSemanticsAttributes ReadAllSemantics (MethodDefinition method)
1531                 {
1532                         ReadAllSemantics (method.DeclaringType);
1533
1534                         return method.SemanticsAttributes;
1535                 }
1536
1537                 void ReadAllSemantics (TypeDefinition type)
1538                 {
1539                         var methods = type.Methods;
1540                         for (int i = 0; i < methods.Count; i++) {
1541                                 var method = methods [i];
1542                                 if (method.sem_attrs.HasValue)
1543                                         continue;
1544
1545                                 method.sem_attrs = ReadMethodSemantics (method);
1546                         }
1547                 }
1548
1549                 Range ReadParametersRange (uint method_rid)
1550                 {
1551                         return ReadListRange (method_rid, Table.Method, Table.Param);
1552                 }
1553
1554                 public Collection<MethodDefinition> ReadMethods (TypeDefinition type)
1555                 {
1556                         var methods_range = type.methods_range;
1557                         if (methods_range.Length == 0)
1558                                 return new MemberDefinitionCollection<MethodDefinition> (type);
1559
1560                         var methods = new MemberDefinitionCollection<MethodDefinition> (type, (int) methods_range.Length);
1561
1562                         MoveTo (Table.Method, methods_range.Start);
1563                         for (uint i = 0; i < methods_range.Length; i++)
1564                                 ReadMethod (methods_range.Start + i, methods);
1565
1566                         return methods;
1567                 }
1568
1569                 void InitializeMethods ()
1570                 {
1571                         if (metadata.Methods != null)
1572                                 return;
1573
1574                         metadata.Methods = new MethodDefinition [image.GetTableLength (Table.Method)];
1575                 }
1576
1577                 void ReadMethod (uint method_rid, Collection<MethodDefinition> methods)
1578                 {
1579                         var method = new MethodDefinition ();
1580                         method.rva = ReadUInt32 ();
1581                         method.ImplAttributes = (MethodImplAttributes) ReadUInt16 ();
1582                         method.Attributes = (MethodAttributes) ReadUInt16 ();
1583                         method.Name = ReadString ();
1584                         method.token = new MetadataToken (TokenType.Method, method_rid);
1585
1586                         methods.Add (method); // attach method
1587
1588                         var signature = ReadBlobIndex ();
1589                         var param_range = ReadParametersRange (method_rid);
1590
1591                         this.context = method;
1592
1593                         ReadMethodSignature (signature, method);
1594                         metadata.AddMethodDefinition (method);
1595
1596                         if (param_range.Length == 0)
1597                                 return;
1598
1599                         var position = base.position;
1600                         ReadParameters (method, param_range);
1601                         base.position = position;
1602                 }
1603
1604                 void ReadParameters (MethodDefinition method, Range param_range)
1605                 {
1606                         MoveTo (Table.Param, param_range.Start);
1607                         for (uint i = 0; i < param_range.Length; i++) {
1608                                 var attributes = (ParameterAttributes) ReadUInt16 ();
1609                                 var sequence = ReadUInt16 ();
1610                                 var name = ReadString ();
1611
1612                                 var parameter = sequence == 0
1613                                         ? method.MethodReturnType.Parameter
1614                                         : method.Parameters [sequence - 1];
1615
1616                                 parameter.token = new MetadataToken (TokenType.Param, param_range.Start + i);
1617                                 parameter.Name = name;
1618                                 parameter.Attributes = attributes;
1619                         }
1620                 }
1621
1622                 void ReadMethodSignature (uint signature, IMethodSignature method)
1623                 {
1624                         var reader = ReadSignature (signature);
1625                         reader.ReadMethodSignature (method);
1626                 }
1627
1628                 public PInvokeInfo ReadPInvokeInfo (MethodDefinition method)
1629                 {
1630                         InitializePInvokes ();
1631                         Row<PInvokeAttributes, uint, uint> row;
1632
1633                         var rid = method.token.RID;
1634
1635                         if (!metadata.PInvokes.TryGetValue (rid, out row))
1636                                 return null;
1637
1638                         metadata.PInvokes.Remove (rid);
1639
1640                         return new PInvokeInfo (
1641                                 row.Col1,
1642                                 image.StringHeap.Read (row.Col2),
1643                                 module.ModuleReferences [(int) row.Col3 - 1]);
1644                 }
1645
1646                 void InitializePInvokes ()
1647                 {
1648                         if (metadata.PInvokes != null)
1649                                 return;
1650
1651                         int length = MoveTo (Table.ImplMap);
1652
1653                         var pinvokes = metadata.PInvokes = new Dictionary<uint, Row<PInvokeAttributes, uint, uint>> (length);
1654
1655                         for (int i = 1; i <= length; i++) {
1656                                 var attributes = (PInvokeAttributes) ReadUInt16 ();
1657                                 var method = ReadMetadataToken (CodedIndex.MemberForwarded);
1658                                 var name = ReadStringIndex ();
1659                                 var scope = ReadTableIndex (Table.File);
1660
1661                                 if (method.TokenType != TokenType.Method)
1662                                         continue;
1663
1664                                 pinvokes.Add (method.RID, new Row<PInvokeAttributes, uint, uint> (attributes, name, scope));
1665                         }
1666                 }
1667
1668                 public bool HasGenericParameters (IGenericParameterProvider provider)
1669                 {
1670                         InitializeGenericParameters ();
1671
1672                         Range range;
1673                         if (!metadata.TryGetGenericParameterRange (provider, out range))
1674                                 return false;
1675
1676                         return range.Length > 0;
1677                 }
1678
1679                 public Collection<GenericParameter> ReadGenericParameters (IGenericParameterProvider provider)
1680                 {
1681                         InitializeGenericParameters ();
1682
1683                         Range range;
1684                         if (!metadata.TryGetGenericParameterRange (provider, out range)
1685                                 || !MoveTo (Table.GenericParam, range.Start))
1686                                 return new Collection<GenericParameter> ();
1687
1688                         metadata.RemoveGenericParameterRange (provider);
1689
1690                         var generic_parameters = new Collection<GenericParameter> ((int) range.Length);
1691
1692                         for (uint i = 0; i < range.Length; i++) {
1693                                 ReadUInt16 (); // index
1694                                 var flags = (GenericParameterAttributes) ReadUInt16 ();
1695                                 ReadMetadataToken (CodedIndex.TypeOrMethodDef);
1696                                 var name = ReadString ();
1697
1698                                 var parameter = new GenericParameter (name, provider);
1699                                 parameter.token = new MetadataToken (TokenType.GenericParam, range.Start + i);
1700                                 parameter.Attributes = flags;
1701
1702                                 generic_parameters.Add (parameter);
1703                         }
1704
1705                         return generic_parameters;
1706                 }
1707
1708                 void InitializeGenericParameters ()
1709                 {
1710                         if (metadata.GenericParameters != null)
1711                                 return;
1712
1713                         metadata.GenericParameters = InitializeRanges (
1714                                 Table.GenericParam, () => {
1715                                         Advance (4);
1716                                         var next = ReadMetadataToken (CodedIndex.TypeOrMethodDef);
1717                                         ReadStringIndex ();
1718                                         return next;
1719                         });
1720                 }
1721
1722                 Dictionary<MetadataToken, Range> InitializeRanges (Table table, Func<MetadataToken> get_next)
1723                 {
1724                         int length = MoveTo (table);
1725                         var ranges = new Dictionary<MetadataToken, Range> (length);
1726
1727                         if (length == 0)
1728                                 return ranges;
1729
1730                         MetadataToken owner = MetadataToken.Zero;
1731                         Range range = new Range (1, 0);
1732
1733                         for (uint i = 1; i <= length; i++) {
1734                                 var next = get_next ();
1735
1736                                 if (i == 1) {
1737                                         owner = next;
1738                                         range.Length++;
1739                                 } else if (next != owner) {
1740                                         if (owner.RID != 0)
1741                                                 ranges.Add (owner, range);
1742                                         range = new Range (i, 1);
1743                                         owner = next;
1744                                 } else
1745                                         range.Length++;
1746                         }
1747
1748                         if (owner != MetadataToken.Zero)
1749                                 ranges.Add (owner, range);
1750
1751                         return ranges;
1752                 }
1753
1754                 public bool HasGenericConstraints (GenericParameter generic_parameter)
1755                 {
1756                         InitializeGenericConstraints ();
1757
1758                         MetadataToken [] mapping;
1759                         if (!metadata.TryGetGenericConstraintMapping (generic_parameter, out mapping))
1760                                 return false;
1761
1762                         return mapping.Length > 0;
1763                 }
1764
1765                 public Collection<TypeReference> ReadGenericConstraints (GenericParameter generic_parameter)
1766                 {
1767                         InitializeGenericConstraints ();
1768
1769                         MetadataToken [] mapping;
1770                         if (!metadata.TryGetGenericConstraintMapping (generic_parameter, out mapping))
1771                                 return new Collection<TypeReference> ();
1772
1773                         var constraints = new Collection<TypeReference> (mapping.Length);
1774
1775                         this.context = (IGenericContext) generic_parameter.Owner;
1776
1777                         for (int i = 0; i < mapping.Length; i++)
1778                                 constraints.Add (GetTypeDefOrRef (mapping [i]));
1779
1780                         metadata.RemoveGenericConstraintMapping (generic_parameter);
1781
1782                         return constraints;
1783                 }
1784
1785                 void InitializeGenericConstraints ()
1786                 {
1787                         if (metadata.GenericConstraints != null)
1788                                 return;
1789
1790                         var length = MoveTo (Table.GenericParamConstraint);
1791
1792                         metadata.GenericConstraints = new Dictionary<uint, MetadataToken []> (length);
1793
1794                         for (int i = 1; i <= length; i++)
1795                                 AddGenericConstraintMapping (
1796                                         ReadTableIndex (Table.GenericParam),
1797                                         ReadMetadataToken (CodedIndex.TypeDefOrRef));
1798                 }
1799
1800                 void AddGenericConstraintMapping (uint generic_parameter, MetadataToken constraint)
1801                 {
1802                         metadata.SetGenericConstraintMapping (
1803                                 generic_parameter,
1804                                 AddMapping (metadata.GenericConstraints, generic_parameter, constraint));
1805                 }
1806
1807                 public bool HasOverrides (MethodDefinition method)
1808                 {
1809                         InitializeOverrides ();
1810                         MetadataToken [] mapping;
1811
1812                         if (!metadata.TryGetOverrideMapping (method, out mapping))
1813                                 return false;
1814
1815                         return mapping.Length > 0;
1816                 }
1817
1818                 public Collection<MethodReference> ReadOverrides (MethodDefinition method)
1819                 {
1820                         InitializeOverrides ();
1821
1822                         MetadataToken [] mapping;
1823                         if (!metadata.TryGetOverrideMapping (method, out mapping))
1824                                 return new Collection<MethodReference> ();
1825
1826                         var overrides = new Collection<MethodReference> (mapping.Length);
1827
1828                         this.context = method;
1829
1830                         for (int i = 0; i < mapping.Length; i++)
1831                                 overrides.Add ((MethodReference) LookupToken (mapping [i]));
1832
1833                         metadata.RemoveOverrideMapping (method);
1834
1835                         return overrides;
1836                 }
1837
1838                 void InitializeOverrides ()
1839                 {
1840                         if (metadata.Overrides != null)
1841                                 return;
1842
1843                         var length = MoveTo (Table.MethodImpl);
1844
1845                         metadata.Overrides = new Dictionary<uint, MetadataToken []> (length);
1846
1847                         for (int i = 1; i <= length; i++) {
1848                                 ReadTableIndex (Table.TypeDef);
1849
1850                                 var method = ReadMetadataToken (CodedIndex.MethodDefOrRef);
1851                                 if (method.TokenType != TokenType.Method)
1852                                         throw new NotSupportedException ();
1853
1854                                 var @override = ReadMetadataToken (CodedIndex.MethodDefOrRef);
1855
1856                                 AddOverrideMapping (method.RID, @override);
1857                         }
1858                 }
1859
1860                 void AddOverrideMapping (uint method_rid, MetadataToken @override)
1861                 {
1862                         metadata.SetOverrideMapping (
1863                                 method_rid,
1864                                 AddMapping (metadata.Overrides, method_rid, @override));
1865                 }
1866
1867                 public MethodBody ReadMethodBody (MethodDefinition method)
1868                 {
1869                         return code.ReadMethodBody (method);
1870                 }
1871
1872                 public CallSite ReadCallSite (MetadataToken token)
1873                 {
1874                         if (!MoveTo (Table.StandAloneSig, token.RID))
1875                                 return null;
1876
1877                         var signature = ReadBlobIndex ();
1878
1879                         var call_site = new CallSite ();
1880
1881                         ReadMethodSignature (signature, call_site);
1882
1883                         return call_site;
1884                 }
1885
1886                 public VariableDefinitionCollection ReadVariables (MetadataToken local_var_token)
1887                 {
1888                         if (!MoveTo (Table.StandAloneSig, local_var_token.RID))
1889                                 return null;
1890
1891                         var reader = ReadSignature (ReadBlobIndex ());
1892                         const byte local_sig = 0x7;
1893
1894                         if (reader.ReadByte () != local_sig)
1895                                 throw new NotSupportedException ();
1896
1897                         var count = reader.ReadCompressedUInt32 ();
1898                         if (count == 0)
1899                                 return null;
1900
1901                         var variables = new VariableDefinitionCollection ((int) count);
1902
1903                         for (int i = 0; i < count; i++)
1904                                 variables.Add (new VariableDefinition (reader.ReadTypeSignature ()));
1905
1906                         return variables;
1907                 }
1908
1909                 public IMetadataTokenProvider LookupToken (MetadataToken token)
1910                 {
1911                         var rid = token.RID;
1912
1913                         if (rid == 0)
1914                                 return null;
1915
1916                         IMetadataTokenProvider element;
1917                         var position = this.position;
1918                         var context = this.context;
1919
1920                         switch (token.TokenType) {
1921                         case TokenType.TypeDef:
1922                                 element = GetTypeDefinition (rid);
1923                                 break;
1924                         case TokenType.TypeRef:
1925                                 element = GetTypeReference (rid);
1926                                 break;
1927                         case TokenType.TypeSpec:
1928                                 element = GetTypeSpecification (rid);
1929                                 break;
1930                         case TokenType.Field:
1931                                 element = GetFieldDefinition (rid);
1932                                 break;
1933                         case TokenType.Method:
1934                                 element = GetMethodDefinition (rid);
1935                                 break;
1936                         case TokenType.MemberRef:
1937                                 element = GetMemberReference (rid);
1938                                 break;
1939                         case TokenType.MethodSpec:
1940                                 element = GetMethodSpecification (rid);
1941                                 break;
1942                         default:
1943                                 throw new NotSupportedException ();
1944                         }
1945
1946                         this.position = position;
1947                         this.context = context;
1948
1949                         return element;
1950                 }
1951
1952                 public FieldDefinition GetFieldDefinition (uint rid)
1953                 {
1954                         InitializeTypeDefinitions ();
1955
1956                         var field = metadata.GetFieldDefinition (rid);
1957                         if (field != null)
1958                                 return field;
1959
1960                         return LookupField (rid);
1961                 }
1962
1963                 FieldDefinition LookupField (uint rid)
1964                 {
1965                         var type = metadata.GetFieldDeclaringType (rid);
1966                         if (type == null)
1967                                 throw new NotSupportedException ();
1968
1969                         InitializeCollection (type.Fields);
1970
1971                         return metadata.GetFieldDefinition (rid);
1972                 }
1973
1974                 public MethodDefinition GetMethodDefinition (uint rid)
1975                 {
1976                         InitializeTypeDefinitions ();
1977
1978                         var method = metadata.GetMethodDefinition (rid);
1979                         if (method != null)
1980                                 return method;
1981
1982                         return LookupMethod (rid);
1983                 }
1984
1985                 MethodDefinition LookupMethod (uint rid)
1986                 {
1987                         var type = metadata.GetMethodDeclaringType (rid);
1988                         if (type == null)
1989                                 throw new NotSupportedException ();
1990
1991                         InitializeCollection (type.Methods);
1992
1993                         return metadata.GetMethodDefinition (rid);
1994                 }
1995
1996                 MethodSpecification GetMethodSpecification (uint rid)
1997                 {
1998                         if (!MoveTo (Table.MethodSpec, rid))
1999                                 return null;
2000
2001                         var method = (MethodReference) LookupToken (
2002                                 ReadMetadataToken (CodedIndex.MethodDefOrRef));
2003                         var signature = ReadBlobIndex ();
2004
2005                         return ReadMethodSpecSignature (signature, method);
2006                 }
2007
2008                 MethodSpecification ReadMethodSpecSignature (uint signature, MethodReference method)
2009                 {
2010                         var reader = ReadSignature (signature);
2011                         const byte methodspec_sig = 0x0a;
2012
2013                         var call_conv = reader.ReadByte ();
2014
2015                         if (call_conv != methodspec_sig)
2016                                 throw new NotSupportedException ();
2017
2018                         var instance = new GenericInstanceMethod (method);
2019
2020                         reader.ReadGenericInstanceSignature (method, instance);
2021
2022                         return instance;
2023                 }
2024
2025                 MemberReference GetMemberReference (uint rid)
2026                 {
2027                         InitializeMemberReferences ();
2028
2029                         var member = metadata.GetMemberReference (rid);
2030                         if (member != null)
2031                                 return member;
2032
2033                         member = ReadMemberReference (rid);
2034                         if (!member.ContainsGenericParameter)
2035                                 metadata.AddMemberReference (member);
2036                         return member;
2037                 }
2038
2039                 MemberReference ReadMemberReference (uint rid)
2040                 {
2041                         if (!MoveTo (Table.MemberRef, rid))
2042                                 return null;
2043
2044                         var token = ReadMetadataToken (CodedIndex.MemberRefParent);
2045                         var name = ReadString ();
2046                         var signature = ReadBlobIndex ();
2047
2048                         MemberReference member;
2049
2050                         switch (token.TokenType) {
2051                         case TokenType.TypeDef:
2052                         case TokenType.TypeRef:
2053                         case TokenType.TypeSpec:
2054                                 member = ReadTypeMemberReference (token, name, signature);
2055                                 break;
2056                         case TokenType.Method:
2057                                 member = ReadMethodMemberReference (token, name, signature);
2058                                 break;
2059                         default:
2060                                 throw new NotSupportedException ();
2061                         }
2062
2063                         member.token = new MetadataToken (TokenType.MemberRef, rid);
2064
2065                         return member;
2066                 }
2067
2068                 MemberReference ReadTypeMemberReference (MetadataToken type, string name, uint signature)
2069                 {
2070                         var declaring_type = GetTypeDefOrRef (type);
2071
2072                         this.context = declaring_type;
2073
2074                         var member = ReadMemberReferenceSignature (signature, declaring_type);
2075                         member.Name = name;
2076
2077                         return member;
2078                 }
2079
2080                 MemberReference ReadMemberReferenceSignature (uint signature, TypeReference declaring_type)
2081                 {
2082                         var reader = ReadSignature (signature);
2083                         const byte field_sig = 0x6;
2084
2085                         if (reader.buffer [reader.position] == field_sig) {
2086                                 reader.position++;
2087                                 var field = new FieldReference ();
2088                                 field.DeclaringType = declaring_type;
2089                                 field.FieldType = reader.ReadTypeSignature ();
2090                                 return field;
2091                         } else {
2092                                 var method = new MethodReference ();
2093                                 method.DeclaringType = declaring_type;
2094                                 reader.ReadMethodSignature (method);
2095                                 return method;
2096                         }
2097                 }
2098
2099                 MemberReference ReadMethodMemberReference (MetadataToken token, string name, uint signature)
2100                 {
2101                         var method = GetMethodDefinition (token.RID);
2102
2103                         this.context = method;
2104
2105                         var member = ReadMemberReferenceSignature (signature, method.DeclaringType);
2106                         member.Name = name;
2107
2108                         return member;
2109                 }
2110
2111                 void InitializeMemberReferences ()
2112                 {
2113                         if (metadata.MemberReferences != null)
2114                                 return;
2115
2116                         metadata.MemberReferences = new MemberReference [image.GetTableLength (Table.MemberRef)];
2117                 }
2118
2119                 public IEnumerable<MemberReference> GetMemberReferences ()
2120                 {
2121                         InitializeMemberReferences ();
2122
2123                         var length = image.GetTableLength (Table.MemberRef);
2124
2125                         var type_system = module.TypeSystem;
2126
2127                         var context = new MethodReference (string.Empty, type_system.Void);
2128                         context.DeclaringType = new TypeReference (string.Empty, string.Empty, module, type_system.Corlib);
2129
2130                         var member_references = new MemberReference [length];
2131
2132                         for (uint i = 1; i <= length; i++) {
2133                                 this.context = context;
2134                                 member_references [i - 1] = GetMemberReference (i);
2135                         }
2136
2137                         return member_references;
2138                 }
2139
2140                 void InitializeConstants ()
2141                 {
2142                         if (metadata.Constants != null)
2143                                 return;
2144
2145                         var length = MoveTo (Table.Constant);
2146
2147                         var constants = metadata.Constants = new Dictionary<MetadataToken, Row<ElementType, uint>> (length);
2148
2149                         for (uint i = 1; i <= length; i++) {
2150                                 var type = (ElementType) ReadUInt16 ();
2151                                 var owner = ReadMetadataToken (CodedIndex.HasConstant);
2152                                 var signature = ReadBlobIndex ();
2153
2154                                 constants.Add (owner, new Row<ElementType, uint> (type, signature));
2155                         }
2156                 }
2157
2158                 public object ReadConstant (IConstantProvider owner)
2159                 {
2160                         InitializeConstants ();
2161
2162                         Row<ElementType, uint> row;
2163                         if (!metadata.Constants.TryGetValue (owner.MetadataToken, out row))
2164                                 return Mixin.NoValue;
2165
2166                         metadata.Constants.Remove (owner.MetadataToken);
2167
2168                         switch (row.Col1) {
2169                         case ElementType.Class:
2170                         case ElementType.Object:
2171                                 return null;
2172                         case ElementType.String:
2173                                 return ReadConstantString (ReadBlob (row.Col2));
2174                         default:
2175                                 return ReadConstantPrimitive (row.Col1, row.Col2);
2176                         }
2177                 }
2178
2179                 static string ReadConstantString (byte [] blob)
2180                 {
2181                         var length = blob.Length;
2182                         if ((length & 1) == 1)
2183                                 length--;
2184
2185                         return Encoding.Unicode.GetString (blob, 0, length);
2186                 }
2187
2188                 object ReadConstantPrimitive (ElementType type, uint signature)
2189                 {
2190                         var reader = ReadSignature (signature);
2191                         return reader.ReadConstantSignature (type);
2192                 }
2193
2194                 void InitializeCustomAttributes ()
2195                 {
2196                         if (metadata.CustomAttributes != null)
2197                                 return;
2198
2199                         metadata.CustomAttributes = InitializeRanges (
2200                                 Table.CustomAttribute, () => {
2201                                         var next = ReadMetadataToken (CodedIndex.HasCustomAttribute);
2202                                         ReadMetadataToken (CodedIndex.CustomAttributeType);
2203                                         ReadBlobIndex ();
2204                                         return next;
2205                         });
2206                 }
2207
2208                 public bool HasCustomAttributes (ICustomAttributeProvider owner)
2209                 {
2210                         InitializeCustomAttributes ();
2211
2212                         Range range;
2213                         if (!metadata.TryGetCustomAttributeRange (owner, out range))
2214                                 return false;
2215
2216                         return range.Length > 0;
2217                 }
2218
2219                 public Collection<CustomAttribute> ReadCustomAttributes (ICustomAttributeProvider owner)
2220                 {
2221                         InitializeCustomAttributes ();
2222
2223                         Range range;
2224                         if (!metadata.TryGetCustomAttributeRange (owner, out range)
2225                                 || !MoveTo (Table.CustomAttribute, range.Start))
2226                                 return new Collection<CustomAttribute> ();
2227
2228                         var custom_attributes = new Collection<CustomAttribute> ((int) range.Length);
2229
2230                         for (int i = 0; i < range.Length; i++) {
2231                                 ReadMetadataToken (CodedIndex.HasCustomAttribute);
2232
2233                                 var constructor = (MethodReference) LookupToken (
2234                                         ReadMetadataToken (CodedIndex.CustomAttributeType));
2235
2236                                 var signature = ReadBlobIndex ();
2237
2238                                 custom_attributes.Add (new CustomAttribute (signature, constructor));
2239                         }
2240
2241                         metadata.RemoveCustomAttributeRange (owner);
2242
2243                         return custom_attributes;
2244                 }
2245
2246                 public byte [] ReadCustomAttributeBlob (uint signature)
2247                 {
2248                         return ReadBlob (signature);
2249                 }
2250
2251                 public void ReadCustomAttributeSignature (CustomAttribute attribute)
2252                 {
2253                         var reader = ReadSignature (attribute.signature);
2254                         if (reader.ReadUInt16 () != 0x0001)
2255                             throw new InvalidOperationException ();
2256
2257                         var constructor = attribute.Constructor;
2258                         if (constructor.HasParameters)
2259                                 reader.ReadCustomAttributeConstructorArguments (attribute, constructor.Parameters);
2260
2261                         if (!reader.CanReadMore ())
2262                                 return;
2263
2264                         var named = reader.ReadUInt16 ();
2265
2266                         if (named == 0)
2267                                 return;
2268
2269                         reader.ReadCustomAttributeNamedArguments (named, ref attribute.fields, ref attribute.properties);
2270                 }
2271
2272                 void InitializeMarshalInfos ()
2273                 {
2274                         if (metadata.FieldMarshals != null)
2275                                 return;
2276
2277                         var length = MoveTo (Table.FieldMarshal);
2278
2279                         var marshals = metadata.FieldMarshals = new Dictionary<MetadataToken, uint> (length);
2280
2281                         for (int i = 0; i < length; i++) {
2282                                 var token = ReadMetadataToken (CodedIndex.HasFieldMarshal);
2283                                 var signature = ReadBlobIndex ();
2284                                 if (token.RID == 0)
2285                                         continue;
2286
2287                                 marshals.Add (token, signature);
2288                         }
2289                 }
2290
2291                 public bool HasMarshalInfo (IMarshalInfoProvider owner)
2292                 {
2293                         InitializeMarshalInfos ();
2294
2295                         return metadata.FieldMarshals.ContainsKey (owner.MetadataToken);
2296                 }
2297
2298                 public MarshalInfo ReadMarshalInfo (IMarshalInfoProvider owner)
2299                 {
2300                         InitializeMarshalInfos ();
2301
2302                         uint signature;
2303                         if (!metadata.FieldMarshals.TryGetValue (owner.MetadataToken, out signature))
2304                                 return null;
2305
2306                         var reader = ReadSignature (signature);
2307
2308                         metadata.FieldMarshals.Remove (owner.MetadataToken);
2309
2310                         return reader.ReadMarshalInfo ();
2311                 }
2312
2313                 void InitializeSecurityDeclarations ()
2314                 {
2315                         if (metadata.SecurityDeclarations != null)
2316                                 return;
2317
2318                         metadata.SecurityDeclarations = InitializeRanges (
2319                                 Table.DeclSecurity, () => {
2320                                         ReadUInt16 ();
2321                                         var next = ReadMetadataToken (CodedIndex.HasDeclSecurity);
2322                                         ReadBlobIndex ();
2323                                         return next;
2324                         });
2325                 }
2326
2327                 public bool HasSecurityDeclarations (ISecurityDeclarationProvider owner)
2328                 {
2329                         InitializeSecurityDeclarations ();
2330
2331                         Range range;
2332                         if (!metadata.TryGetSecurityDeclarationRange (owner, out range))
2333                                 return false;
2334
2335                         return range.Length > 0;
2336                 }
2337
2338                 public Collection<SecurityDeclaration> ReadSecurityDeclarations (ISecurityDeclarationProvider owner)
2339                 {
2340                         InitializeSecurityDeclarations ();
2341
2342                         Range range;
2343                         if (!metadata.TryGetSecurityDeclarationRange (owner, out range)
2344                                 || !MoveTo (Table.DeclSecurity, range.Start))
2345                                 return new Collection<SecurityDeclaration> ();
2346
2347                         var security_declarations = new Collection<SecurityDeclaration> ((int) range.Length);
2348
2349                         for (int i = 0; i < range.Length; i++) {
2350                                 var action = (SecurityAction) ReadUInt16 ();
2351                                 ReadMetadataToken (CodedIndex.HasDeclSecurity);
2352                                 var signature = ReadBlobIndex ();
2353
2354                                 security_declarations.Add (new SecurityDeclaration (action, signature, module));
2355                         }
2356
2357                         metadata.RemoveSecurityDeclarationRange (owner);
2358
2359                         return security_declarations;
2360                 }
2361
2362                 public byte [] ReadSecurityDeclarationBlob (uint signature)
2363                 {
2364                         return ReadBlob (signature);
2365                 }
2366
2367                 public void ReadSecurityDeclarationSignature (SecurityDeclaration declaration)
2368                 {
2369                         var signature = declaration.signature;
2370                         var reader = ReadSignature (signature);
2371
2372                         if (reader.buffer [reader.position] != '.') {
2373                                 ReadXmlSecurityDeclaration (signature, declaration);
2374                                 return;
2375                         }
2376
2377                         reader.ReadByte ();
2378                         var count = reader.ReadCompressedUInt32 ();
2379                         var attributes = new Collection<SecurityAttribute> ((int) count);
2380
2381                         for (int i = 0; i < count; i++)
2382                                 attributes.Add (reader.ReadSecurityAttribute ());
2383
2384                         declaration.security_attributes = attributes;
2385                 }
2386
2387                 void ReadXmlSecurityDeclaration (uint signature, SecurityDeclaration declaration)
2388                 {
2389                         var blob = ReadBlob (signature);
2390                         var attributes = new Collection<SecurityAttribute> (1);
2391
2392                         var attribute = new SecurityAttribute (
2393                                 module.TypeSystem.LookupType ("System.Security.Permissions", "PermissionSetAttribute"));
2394
2395                         attribute.properties = new Collection<CustomAttributeNamedArgument> (1);
2396                         attribute.properties.Add (
2397                                 new CustomAttributeNamedArgument (
2398                                         "XML",
2399                                         new CustomAttributeArgument (
2400                                                 module.TypeSystem.String,
2401                                                 Encoding.Unicode.GetString (blob, 0, blob.Length))));
2402
2403                         attributes.Add (attribute);
2404
2405                         declaration.security_attributes = attributes;
2406                 }
2407
2408                 public Collection<ExportedType> ReadExportedTypes ()
2409                 {
2410                         var length = MoveTo (Table.ExportedType);
2411                         if (length == 0)
2412                                 return new Collection<ExportedType> ();
2413
2414                         var exported_types = new Collection<ExportedType> (length);
2415
2416                         for (int i = 1; i <= length; i++) {
2417                                 var attributes = (TypeAttributes) ReadUInt32 ();
2418                                 var identifier = ReadUInt32 ();
2419                                 var name = ReadString ();
2420                                 var @namespace = ReadString ();
2421                                 var implementation = ReadMetadataToken (CodedIndex.Implementation);
2422
2423                                 ExportedType declaring_type = null;
2424                                 IMetadataScope scope = null;
2425
2426                                 switch (implementation.TokenType) {
2427                                 case TokenType.AssemblyRef:
2428                                 case TokenType.File:
2429                                         scope = GetExportedTypeScope (implementation);
2430                                         break;
2431                                 case TokenType.ExportedType:
2432                                         // FIXME: if the table is not properly sorted
2433                                         declaring_type = exported_types [(int) implementation.RID - 1];
2434                                         break;
2435                                 }
2436
2437                                 var exported_type = new ExportedType (@namespace, name, scope) {
2438                                         Attributes = attributes,
2439                                         Identifier = (int) identifier,
2440                                         DeclaringType = declaring_type,
2441                                 };
2442                                 exported_type.token = new MetadataToken (TokenType.ExportedType, i);
2443
2444                                 exported_types.Add (exported_type);
2445                         }
2446
2447                         return exported_types;
2448                 }
2449
2450                 IMetadataScope GetExportedTypeScope (MetadataToken token)
2451                 {
2452                         switch (token.TokenType) {
2453                         case TokenType.AssemblyRef:
2454                                 return module.AssemblyReferences [(int) token.RID - 1];
2455                         case TokenType.File:
2456                                 var position = this.position;
2457                                 var reference = GetModuleReferenceFromFile (token);
2458                                 this.position = position;
2459
2460                                 if (reference == null)
2461                                         throw new NotSupportedException ();
2462
2463                                 return reference;
2464                         default:
2465                                 throw new NotSupportedException ();
2466                         }
2467                 }
2468
2469                 ModuleReference GetModuleReferenceFromFile (MetadataToken token)
2470                 {
2471                         if (!MoveTo (Table.File, token.RID))
2472                                 return null;
2473
2474                         ReadUInt32 ();
2475                         var file_name = ReadString ();
2476                         var modules = module.ModuleReferences;
2477
2478                         ModuleReference reference = null;
2479                         for (int i = 0; i < modules.Count; i++) {
2480                                 var module_reference = modules [i];
2481                                 if (module_reference.Name != file_name)
2482                                         continue;
2483
2484                                 reference = module_reference;
2485                                 break;
2486                         }
2487
2488                         return reference;
2489                 }
2490
2491                 static void InitializeCollection (object o)
2492                 {
2493                 }
2494         }
2495
2496         sealed class SignatureReader : ByteBuffer {
2497
2498                 readonly MetadataReader reader;
2499                 readonly uint start, sig_length;
2500
2501                 TypeSystem TypeSystem {
2502                         get { return reader.module.TypeSystem; }
2503                 }
2504
2505                 public SignatureReader (uint blob, MetadataReader reader)
2506                         : base (reader.buffer)
2507                 {
2508                         this.reader = reader;
2509
2510                         MoveToBlob (blob);
2511
2512                         this.sig_length = ReadCompressedUInt32 ();
2513                         this.start = (uint) position;
2514                 }
2515
2516                 void MoveToBlob (uint blob)
2517                 {
2518                         position = (int) (reader.image.BlobHeap.Offset + blob);
2519                 }
2520
2521                 MetadataToken ReadTypeTokenSignature ()
2522                 {
2523                         return CodedIndex.TypeDefOrRef.GetMetadataToken (ReadCompressedUInt32 ());
2524                 }
2525
2526                 GenericParameter GetGenericParameter (GenericParameterType type, uint var)
2527                 {
2528                         var context = reader.context;
2529
2530                         if (context == null)
2531                                 throw new NotSupportedException ();
2532
2533                         IGenericParameterProvider provider;
2534
2535                         switch (type) {
2536                         case GenericParameterType.Type:
2537                                 provider = context.Type;
2538                                 break;
2539                         case GenericParameterType.Method:
2540                                 provider = context.Method;
2541                                 break;
2542                         default:
2543                                 throw new NotSupportedException ();
2544                         }
2545
2546                         int index = (int) var;
2547
2548                         if (!context.IsDefinition)
2549                                 CheckGenericContext (provider, index);
2550
2551                         return provider.GenericParameters [index];
2552                 }
2553
2554                 static void CheckGenericContext (IGenericParameterProvider owner, int index)
2555                 {
2556                         var owner_parameters = owner.GenericParameters;
2557
2558                         for (int i = owner_parameters.Count; i <= index; i++)
2559                                 owner_parameters.Add (new GenericParameter (owner));
2560                 }
2561
2562                 public void ReadGenericInstanceSignature (IGenericParameterProvider provider, IGenericInstance instance)
2563                 {
2564                         var arity = ReadCompressedUInt32 ();
2565
2566                         if (!provider.IsDefinition)
2567                                 CheckGenericContext (provider, (int) arity - 1);
2568
2569                         var instance_arguments = instance.GenericArguments;
2570
2571                         for (int i = 0; i < arity; i++)
2572                                 instance_arguments.Add (ReadTypeSignature ());
2573                 }
2574
2575                 ArrayType ReadArrayTypeSignature ()
2576                 {
2577                         var array = new ArrayType (ReadTypeSignature ());
2578
2579                         var rank = ReadCompressedUInt32 ();
2580
2581                         var sizes = new uint [ReadCompressedUInt32 ()];
2582                         for (int i = 0; i < sizes.Length; i++)
2583                                 sizes [i] = ReadCompressedUInt32 ();
2584
2585                         var low_bounds = new int [ReadCompressedUInt32 ()];
2586                         for (int i = 0; i < low_bounds.Length; i++)
2587                                 low_bounds [i] = ReadCompressedInt32 ();
2588
2589                         array.Dimensions.Clear ();
2590
2591                         for (int i = 0; i < rank; i++) {
2592                                 int? lower = null, upper = null;
2593
2594                                 if (i < low_bounds.Length)
2595                                         lower = low_bounds [i];
2596
2597                                 if (i < sizes.Length)
2598                                         upper = lower + (int) sizes [i] - 1;
2599
2600                                 array.Dimensions.Add (new ArrayDimension (lower, upper));
2601                         }
2602
2603                         return array;
2604                 }
2605
2606                 TypeReference GetTypeDefOrRef (MetadataToken token)
2607                 {
2608                         return reader.GetTypeDefOrRef (token);
2609                 }
2610
2611                 public TypeReference ReadTypeSignature ()
2612                 {
2613                         return ReadTypeSignature ((ElementType) ReadByte ());
2614                 }
2615
2616                 TypeReference ReadTypeSignature (ElementType etype)
2617                 {
2618                         switch (etype) {
2619                         case ElementType.ValueType: {
2620                                 var value_type = GetTypeDefOrRef (ReadTypeTokenSignature ());
2621                                 value_type.IsValueType = true;
2622                                 return value_type;
2623                         }
2624                         case ElementType.Class:
2625                                 return GetTypeDefOrRef (ReadTypeTokenSignature ());
2626                         case ElementType.Ptr:
2627                                 return new PointerType (ReadTypeSignature ());
2628                         case ElementType.FnPtr: {
2629                                 var fptr = new FunctionPointerType ();
2630                                 ReadMethodSignature (fptr);
2631                                 return fptr;
2632                         }
2633                         case ElementType.ByRef:
2634                                 return new ByReferenceType (ReadTypeSignature ());
2635                         case ElementType.Pinned:
2636                                 return new PinnedType (ReadTypeSignature ());
2637                         case ElementType.SzArray:
2638                                 return new ArrayType (ReadTypeSignature ());
2639                         case ElementType.Array:
2640                                 return ReadArrayTypeSignature ();
2641                         case ElementType.CModOpt:
2642                                 return new OptionalModifierType (
2643                                         GetTypeDefOrRef (ReadTypeTokenSignature ()), ReadTypeSignature ());
2644                         case ElementType.CModReqD:
2645                                 return new RequiredModifierType (
2646                                         GetTypeDefOrRef (ReadTypeTokenSignature ()), ReadTypeSignature ());
2647                         case ElementType.Sentinel:
2648                                 return new SentinelType (ReadTypeSignature ());
2649                         case ElementType.Var:
2650                                 return GetGenericParameter (GenericParameterType.Type, ReadCompressedUInt32 ());
2651                         case ElementType.MVar:
2652                                 return GetGenericParameter (GenericParameterType.Method, ReadCompressedUInt32 ());
2653                         case ElementType.GenericInst: {
2654                                 var is_value_type = ReadByte () == (byte) ElementType.ValueType;
2655                                 var element_type = GetTypeDefOrRef (ReadTypeTokenSignature ());
2656                                 var generic_instance = new GenericInstanceType (element_type);
2657
2658                                 ReadGenericInstanceSignature (element_type, generic_instance);
2659
2660                                 if (is_value_type) {
2661                                         generic_instance.IsValueType = true;
2662                                         element_type.GetElementType ().IsValueType = true;
2663                                 }
2664
2665                                 return generic_instance;
2666                         }
2667                         case ElementType.Object: return TypeSystem.Object;
2668                         case ElementType.Void: return TypeSystem.Void;
2669                         case ElementType.TypedByRef: return TypeSystem.TypedReference;
2670                         case ElementType.I: return TypeSystem.IntPtr;
2671                         case ElementType.U: return TypeSystem.UIntPtr;
2672                         default: return GetPrimitiveType (etype);
2673                         }
2674                 }
2675
2676                 public void ReadMethodSignature (IMethodSignature method)
2677                 {
2678                         var calling_convention = ReadByte ();
2679                         method.CallingConvention = (MethodCallingConvention) calling_convention;
2680                         method.HasThis = (calling_convention & 0x20) != 0;
2681                         method.ExplicitThis = (calling_convention & 0x40) != 0;
2682
2683                         var generic_context = method as MethodReference;
2684                         if (generic_context != null)
2685                                 reader.context = generic_context;
2686
2687                         if ((calling_convention & 0x10) != 0) {
2688                                 var arity = ReadCompressedUInt32 ();
2689
2690                                 if (generic_context != null && !generic_context.IsDefinition)
2691                                         CheckGenericContext (generic_context, (int) arity -1 );
2692                         }
2693
2694                         // TODO: more call_conv
2695
2696                         var param_count = ReadCompressedUInt32 ();
2697
2698                         method.MethodReturnType.ReturnType = ReadTypeSignature ();
2699
2700                         if (param_count == 0)
2701                                 return;
2702
2703                         Collection<ParameterDefinition> parameters;
2704
2705                         var method_ref = method as MethodReference;
2706                         if (method_ref != null)
2707                                 parameters = method_ref.parameters = new ParameterDefinitionCollection (method, (int) param_count);
2708                         else
2709                                 parameters = method.Parameters;
2710
2711                         for (int i = 0; i < param_count; i++)
2712                                 parameters.Add (new ParameterDefinition (ReadTypeSignature ()));
2713                 }
2714
2715                 public object ReadConstantSignature (ElementType type)
2716                 {
2717                         return ReadPrimitiveValue (type);
2718                 }
2719
2720                 public void ReadCustomAttributeConstructorArguments (CustomAttribute attribute, Collection<ParameterDefinition> parameters)
2721                 {
2722                         var count = parameters.Count;
2723                         if (count == 0)
2724                                 return;
2725
2726                         attribute.arguments = new Collection<CustomAttributeArgument> (count);
2727
2728                         for (int i = 0; i < count; i++)
2729                                 attribute.arguments.Add (
2730                                         ReadCustomAttributeFixedArgument (parameters [i].ParameterType));
2731                 }
2732
2733                 CustomAttributeArgument ReadCustomAttributeFixedArgument (TypeReference type)
2734                 {
2735                         if (type.IsArray)
2736                                 return ReadCustomAttributeFixedArrayArgument ((ArrayType) type);
2737
2738                         return ReadCustomAttributeElement (type);
2739                 }
2740
2741                 public void ReadCustomAttributeNamedArguments (ushort count, ref Collection<CustomAttributeNamedArgument> fields, ref Collection<CustomAttributeNamedArgument> properties)
2742                 {
2743                         for (int i = 0; i < count; i++)
2744                                 ReadCustomAttributeNamedArgument (ref fields, ref properties);
2745                 }
2746
2747                 void ReadCustomAttributeNamedArgument (ref Collection<CustomAttributeNamedArgument> fields, ref Collection<CustomAttributeNamedArgument> properties)
2748                 {
2749                         var kind = ReadByte ();
2750                         var type = ReadCustomAttributeFieldOrPropType ();
2751                         var name = ReadUTF8String ();
2752
2753                         Collection<CustomAttributeNamedArgument> container;
2754                         switch (kind) {
2755                         case 0x53:
2756                                 container = GetCustomAttributeNamedArgumentCollection (ref fields);
2757                                 break;
2758                         case 0x54:
2759                                 container = GetCustomAttributeNamedArgumentCollection (ref properties);
2760                                 break;
2761                         default:
2762                                 throw new NotSupportedException ();
2763                         }
2764
2765                         container.Add (new CustomAttributeNamedArgument (name, ReadCustomAttributeFixedArgument (type)));
2766                 }
2767
2768                 static Collection<CustomAttributeNamedArgument> GetCustomAttributeNamedArgumentCollection (ref Collection<CustomAttributeNamedArgument> collection)
2769                 {
2770                         if (collection != null)
2771                                 return collection;
2772
2773                         return collection = new Collection<CustomAttributeNamedArgument> ();
2774                 }
2775
2776                 CustomAttributeArgument ReadCustomAttributeFixedArrayArgument (ArrayType type)
2777                 {
2778                         var length = ReadUInt32 ();
2779
2780                         if (length == 0xffffffff)
2781                                 return new CustomAttributeArgument (type, null);
2782
2783                         if (length == 0)
2784                                 return new CustomAttributeArgument (type, Empty<CustomAttributeArgument>.Array);
2785
2786                         var arguments = new CustomAttributeArgument [length];
2787                         var element_type = type.ElementType;
2788
2789                         for (int i = 0; i < length; i++)
2790                                 arguments [i] = ReadCustomAttributeElement (element_type);
2791
2792                         return new CustomAttributeArgument (type, arguments);
2793                 }
2794
2795                 CustomAttributeArgument ReadCustomAttributeElement (TypeReference type)
2796                 {
2797                         if (type.IsArray)
2798                                 return ReadCustomAttributeFixedArrayArgument ((ArrayType) type);
2799
2800                         if (type.etype == ElementType.Object)
2801                                 return ReadCustomAttributeElement (ReadCustomAttributeFieldOrPropType ());
2802
2803                         return new CustomAttributeArgument (type, ReadCustomAttributeElementValue (type));
2804                 }
2805
2806                 object ReadCustomAttributeElementValue (TypeReference type)
2807                 {
2808                         var etype = type.etype;
2809
2810                         switch (etype) {
2811                         case ElementType.String:
2812                                 return ReadUTF8String ();
2813                         case ElementType.None:
2814                                 if (type.IsTypeOf ("System", "Type"))
2815                                         return ReadTypeReference ();
2816
2817                                 return ReadCustomAttributeEnum (type);
2818                         default:
2819                                 return ReadPrimitiveValue (etype);
2820                         }
2821                 }
2822
2823                 object ReadPrimitiveValue (ElementType type)
2824                 {
2825                         switch (type) {
2826                         case ElementType.Boolean:
2827                                 return ReadByte () == 1;
2828                         case ElementType.I1:
2829                                 return (sbyte) ReadByte ();
2830                         case ElementType.U1:
2831                                 return ReadByte ();
2832                         case ElementType.Char:
2833                                 return (char) ReadUInt16 ();
2834                         case ElementType.I2:
2835                                 return ReadInt16 ();
2836                         case ElementType.U2:
2837                                 return ReadUInt16 ();
2838                         case ElementType.I4:
2839                                 return ReadInt32 ();
2840                         case ElementType.U4:
2841                                 return ReadUInt32 ();
2842                         case ElementType.I8:
2843                                 return ReadInt64 ();
2844                         case ElementType.U8:
2845                                 return ReadUInt64 ();
2846                         case ElementType.R4:
2847                                 return ReadSingle ();
2848                         case ElementType.R8:
2849                                 return ReadDouble ();
2850                         default:
2851                                 throw new NotImplementedException (type.ToString ());
2852                         }
2853                 }
2854
2855                 TypeReference GetPrimitiveType (ElementType etype)
2856                 {
2857                         switch (etype) {
2858                         case ElementType.Boolean:
2859                                 return TypeSystem.Boolean;
2860                         case ElementType.Char:
2861                                 return TypeSystem.Char;
2862                         case ElementType.I1:
2863                                 return TypeSystem.SByte;
2864                         case ElementType.U1:
2865                                 return TypeSystem.Byte;
2866                         case ElementType.I2:
2867                                 return TypeSystem.Int16;
2868                         case ElementType.U2:
2869                                 return TypeSystem.UInt16;
2870                         case ElementType.I4:
2871                                 return TypeSystem.Int32;
2872                         case ElementType.U4:
2873                                 return TypeSystem.UInt32;
2874                         case ElementType.I8:
2875                                 return TypeSystem.Int64;
2876                         case ElementType.U8:
2877                                 return TypeSystem.UInt64;
2878                         case ElementType.R4:
2879                                 return TypeSystem.Single;
2880                         case ElementType.R8:
2881                                 return TypeSystem.Double;
2882                         case ElementType.String:
2883                                 return TypeSystem.String;
2884                         default:
2885                                 throw new NotImplementedException (etype.ToString ());
2886                         }
2887                 }
2888
2889                 TypeReference ReadCustomAttributeFieldOrPropType ()
2890                 {
2891                         var etype = (ElementType) ReadByte ();
2892
2893                         switch (etype) {
2894                         case ElementType.Boxed:
2895                                 return TypeSystem.Object;
2896                         case ElementType.SzArray:
2897                                 return new ArrayType (ReadCustomAttributeFieldOrPropType ());
2898                         case ElementType.Enum:
2899                                 return ReadTypeReference ();
2900                         case ElementType.Type:
2901                                 return TypeSystem.LookupType ("System", "Type");
2902                         default:
2903                                 return GetPrimitiveType (etype);
2904                         }
2905                 }
2906
2907                 public TypeReference ReadTypeReference ()
2908                 {
2909                         return TypeParser.ParseType (reader.module, ReadUTF8String ());
2910                 }
2911
2912                 object ReadCustomAttributeEnum (TypeReference enum_type)
2913                 {
2914                         var type = enum_type.CheckedResolve ();
2915                         if (!type.IsEnum)
2916                                 throw new ArgumentException ();
2917
2918                         return ReadCustomAttributeElementValue (type.GetEnumUnderlyingType ());
2919                 }
2920
2921                 public SecurityAttribute ReadSecurityAttribute ()
2922                 {
2923                         var attribute = new SecurityAttribute (ReadTypeReference ());
2924
2925                         ReadCompressedUInt32 ();
2926
2927                         ReadCustomAttributeNamedArguments (
2928                                 (ushort) ReadCompressedUInt32 (),
2929                                 ref attribute.fields,
2930                                 ref attribute.properties);
2931
2932                         return attribute;
2933                 }
2934
2935                 public MarshalInfo ReadMarshalInfo ()
2936                 {
2937                         var native = ReadNativeType ();
2938                         switch (native) {
2939                         case NativeType.Array: {
2940                                 var array = new ArrayMarshalInfo ();
2941                                 if (CanReadMore ())
2942                                         array.element_type = ReadNativeType ();
2943                                 if (CanReadMore ())
2944                                         array.size_parameter_index = (int) ReadCompressedUInt32 ();
2945                                 if (CanReadMore ())
2946                                         array.size = (int) ReadCompressedUInt32 ();
2947                                 if (CanReadMore ())
2948                                         array.size_parameter_multiplier = (int) ReadCompressedUInt32 ();
2949                                 return array;
2950                         }
2951                         case NativeType.SafeArray: {
2952                                 var array = new SafeArrayMarshalInfo ();
2953                                 if (CanReadMore ())
2954                                         array.element_type = ReadVariantType ();
2955                                 return array;
2956                         }
2957                         case NativeType.FixedArray: {
2958                                 var array = new FixedArrayMarshalInfo ();
2959                                 if (CanReadMore ())
2960                                         array.size = (int) ReadCompressedUInt32 ();
2961                                 if (CanReadMore ())
2962                                         array.element_type = ReadNativeType ();
2963                                 return array;
2964                         }
2965                         case NativeType.FixedSysString: {
2966                                 var sys_string = new FixedSysStringMarshalInfo ();
2967                                 if (CanReadMore ())
2968                                         sys_string.size = (int) ReadCompressedUInt32 ();
2969                                 return sys_string;
2970                         }
2971                         case NativeType.CustomMarshaler: {
2972                                 var marshaler = new CustomMarshalInfo ();
2973                                 var guid_value = ReadUTF8String ();
2974                                 marshaler.guid = !string.IsNullOrEmpty (guid_value) ? new Guid (guid_value) : Guid.Empty;
2975                                 marshaler.unmanaged_type = ReadUTF8String ();
2976                                 marshaler.managed_type = ReadTypeReference ();
2977                                 marshaler.cookie = ReadUTF8String ();
2978                                 return marshaler;
2979                         }
2980                         default:
2981                                 return new MarshalInfo (native);
2982                         }
2983                 }
2984
2985                 NativeType ReadNativeType ()
2986                 {
2987                         return (NativeType) ReadByte ();
2988                 }
2989
2990                 VariantType ReadVariantType ()
2991                 {
2992                         return (VariantType) ReadByte ();
2993                 }
2994
2995                 string ReadUTF8String ()
2996                 {
2997                         if (buffer [position] == 0xff) {
2998                                 position++;
2999                                 return null;
3000                         }
3001
3002                         var length = (int) ReadCompressedUInt32 ();
3003                         if (length == 0)
3004                                 return string.Empty;
3005
3006                         var @string = Encoding.UTF8.GetString (buffer, position,
3007                                 buffer [position + length - 1] == 0 ? length - 1 : length);
3008
3009                         position += length;
3010                         return @string;
3011                 }
3012
3013                 public bool CanReadMore ()
3014                 {
3015                         return position - start < sig_length;
3016                 }
3017         }
3018 }