update cecil from upstream
[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                         return ReadTypeReference (rid);
961                 }
962
963                 TypeReference ReadTypeReference (uint rid)
964                 {
965                         if (!MoveTo (Table.TypeRef, rid))
966                                 return null;
967
968                         TypeReference declaring_type = null;
969                         IMetadataScope scope;
970
971                         var scope_token = ReadMetadataToken (CodedIndex.ResolutionScope);
972
973                         var name = ReadString ();
974                         var @namespace = ReadString ();
975
976                         var type = new TypeReference (
977                                 @namespace,
978                                 name,
979                                 module,
980                                 null);
981
982                         type.token = new MetadataToken (TokenType.TypeRef, rid);
983
984                         metadata.AddTypeReference (type);
985
986                         if (scope_token.TokenType == TokenType.TypeRef) {
987                                 declaring_type = GetTypeDefOrRef (scope_token);
988
989                                 scope = declaring_type != null
990                                         ? declaring_type.Scope
991                                         : module;
992                         } else
993                                 scope = GetTypeReferenceScope (scope_token);
994
995                         type.scope = scope;
996                         type.DeclaringType = declaring_type;
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                         var type = reader.ReadTypeSignature ();
1041                         if (type.token.RID == 0)
1042                                 type.token = new MetadataToken (TokenType.TypeSpec, rid);
1043
1044                         return type;
1045                 }
1046
1047                 SignatureReader ReadSignature (uint signature)
1048                 {
1049                         return new SignatureReader (signature, this);
1050                 }
1051
1052                 public bool HasInterfaces (TypeDefinition type)
1053                 {
1054                         InitializeInterfaces ();
1055                         MetadataToken [] mapping;
1056
1057                         return metadata.TryGetInterfaceMapping (type, out mapping);
1058                 }
1059
1060                 public Collection<TypeReference> ReadInterfaces (TypeDefinition type)
1061                 {
1062                         InitializeInterfaces ();
1063                         MetadataToken [] mapping;
1064
1065                         if (!metadata.TryGetInterfaceMapping (type, out mapping))
1066                                 return new Collection<TypeReference> ();
1067
1068                         var interfaces = new Collection<TypeReference> (mapping.Length);
1069
1070                         this.context = type;
1071
1072                         for (int i = 0; i < mapping.Length; i++)
1073                                 interfaces.Add (GetTypeDefOrRef (mapping [i]));
1074
1075                         metadata.RemoveInterfaceMapping (type);
1076
1077                         return interfaces;
1078                 }
1079
1080                 void InitializeInterfaces ()
1081                 {
1082                         if (metadata.Interfaces != null)
1083                                 return;
1084
1085                         int length = MoveTo (Table.InterfaceImpl);
1086
1087                         metadata.Interfaces = new Dictionary<uint, MetadataToken []> (length);
1088
1089                         for (int i = 0; i < length; i++) {
1090                                 var type = ReadTableIndex (Table.TypeDef);
1091                                 var @interface = ReadMetadataToken (CodedIndex.TypeDefOrRef);
1092
1093                                 AddInterfaceMapping (type, @interface);
1094                         }
1095                 }
1096
1097                 void AddInterfaceMapping (uint type, MetadataToken @interface)
1098                 {
1099                         metadata.SetInterfaceMapping (type, AddMapping (metadata.Interfaces, type, @interface));
1100                 }
1101
1102                 public Collection<FieldDefinition> ReadFields (TypeDefinition type)
1103                 {
1104                         var fields_range = type.fields_range;
1105                         if (fields_range.Length == 0)
1106                                 return new MemberDefinitionCollection<FieldDefinition> (type);
1107
1108                         var fields = new MemberDefinitionCollection<FieldDefinition> (type, (int) fields_range.Length);
1109                         this.context = type;
1110
1111                         MoveTo (Table.Field, fields_range.Start);
1112                         for (uint i = 0; i < fields_range.Length; i++)
1113                                 fields.Add (ReadField (fields_range.Start + i));
1114
1115                         return fields;
1116                 }
1117
1118                 FieldDefinition ReadField (uint field_rid)
1119                 {
1120                         var attributes = (FieldAttributes) ReadUInt16 ();
1121                         var name = ReadString ();
1122                         var signature = ReadBlobIndex ();
1123
1124                         var field = new FieldDefinition (name, attributes, ReadFieldType (signature));
1125                         field.token = new MetadataToken (TokenType.Field, field_rid);
1126                         metadata.AddFieldDefinition (field);
1127
1128                         return field;
1129                 }
1130
1131                 void InitializeFields ()
1132                 {
1133                         if (metadata.Fields != null)
1134                                 return;
1135
1136                         metadata.Fields = new FieldDefinition [image.GetTableLength (Table.Field)];
1137                 }
1138
1139                 TypeReference ReadFieldType (uint signature)
1140                 {
1141                         var reader = ReadSignature (signature);
1142
1143                         const byte field_sig = 0x6;
1144
1145                         if (reader.ReadByte () != field_sig)
1146                                 throw new NotSupportedException ();
1147
1148                         return reader.ReadTypeSignature ();
1149                 }
1150
1151                 public int ReadFieldRVA (FieldDefinition field)
1152                 {
1153                         InitializeFieldRVAs ();
1154                         var rid = field.token.RID;
1155
1156                         RVA rva;
1157                         if (!metadata.FieldRVAs.TryGetValue (rid, out rva))
1158                                 return 0;
1159
1160                         var size = GetFieldTypeSize (field.FieldType);
1161
1162                         if (size == 0 || rva == 0)
1163                                 return 0;
1164
1165                         metadata.FieldRVAs.Remove (rid);
1166
1167                         field.InitialValue = GetFieldInitializeValue (size, rva);
1168
1169                         return (int) rva;
1170                 }
1171
1172                 byte [] GetFieldInitializeValue (int size, RVA rva)
1173                 {
1174                         var section = image.GetSectionAtVirtualAddress (rva);
1175                         if (section == null)
1176                                 return Empty<byte>.Array;
1177
1178                         var value = new byte [size];
1179                         Buffer.BlockCopy (section.Data, (int) (rva - section.VirtualAddress), value, 0, size);
1180                         return value;
1181                 }
1182
1183                 static int GetFieldTypeSize (TypeReference type)
1184                 {
1185                         int size = 0;
1186
1187                         switch (type.etype) {
1188                         case ElementType.Boolean:
1189                         case ElementType.U1:
1190                         case ElementType.I1:
1191                                 size = 1;
1192                                 break;
1193                         case ElementType.U2:
1194                         case ElementType.I2:
1195                         case ElementType.Char:
1196                                 size = 2;
1197                                 break;
1198                         case ElementType.U4:
1199                         case ElementType.I4:
1200                         case ElementType.R4:
1201                                 size = 4;
1202                                 break;
1203                         case ElementType.U8:
1204                         case ElementType.I8:
1205                         case ElementType.R8:
1206                                 size = 8;
1207                                 break;
1208                         case ElementType.Ptr:
1209                         case ElementType.FnPtr:
1210                                 size = IntPtr.Size;
1211                                 break;
1212                         case ElementType.CModOpt:
1213                         case ElementType.CModReqD:
1214                                 return GetFieldTypeSize (((IModifierType) type).ElementType);
1215                         default:
1216                                 var field_type = type.CheckedResolve ();
1217                                 if (field_type.HasLayoutInfo)
1218                                         size = field_type.ClassSize;
1219
1220                                 break;
1221                         }
1222
1223                         return size;
1224                 }
1225
1226                 void InitializeFieldRVAs ()
1227                 {
1228                         if (metadata.FieldRVAs != null)
1229                                 return;
1230
1231                         int length = MoveTo (Table.FieldRVA);
1232
1233                         var field_rvas = metadata.FieldRVAs = new Dictionary<uint, uint> (length);
1234
1235                         for (int i = 0; i < length; i++) {
1236                                 var rva = ReadUInt32 ();
1237                                 var field = ReadTableIndex (Table.Field);
1238
1239                                 field_rvas.Add (field, rva);
1240                         }
1241                 }
1242
1243                 public int ReadFieldLayout (FieldDefinition field)
1244                 {
1245                         InitializeFieldLayouts ();
1246                         var rid = field.token.RID;
1247                         uint offset;
1248                         if (!metadata.FieldLayouts.TryGetValue (rid, out offset))
1249                                 return Mixin.NoDataMarker;
1250
1251                         metadata.FieldLayouts.Remove (rid);
1252
1253                         return (int) offset;
1254                 }
1255
1256                 void InitializeFieldLayouts ()
1257                 {
1258                         if (metadata.FieldLayouts != null)
1259                                 return;
1260
1261                         int length = MoveTo (Table.FieldLayout);
1262
1263                         var field_layouts = metadata.FieldLayouts = new Dictionary<uint, uint> (length);
1264
1265                         for (int i = 0; i < length; i++) {
1266                                 var offset = ReadUInt32 ();
1267                                 var field = ReadTableIndex (Table.Field);
1268
1269                                 field_layouts.Add (field, offset);
1270                         }
1271                 }
1272
1273                 public bool HasEvents (TypeDefinition type)
1274                 {
1275                         InitializeEvents ();
1276
1277                         Range range;
1278                         if (!metadata.TryGetEventsRange (type, out range))
1279                                 return false;
1280
1281                         return range.Length > 0;
1282                 }
1283
1284                 public Collection<EventDefinition> ReadEvents (TypeDefinition type)
1285                 {
1286                         InitializeEvents ();
1287                         Range range;
1288
1289                         if (!metadata.TryGetEventsRange (type, out range))
1290                                 return new MemberDefinitionCollection<EventDefinition> (type);
1291
1292                         var events = new MemberDefinitionCollection<EventDefinition> (type, (int) range.Length);
1293
1294                         metadata.RemoveEventsRange (type);
1295
1296                         if (range.Length == 0 || !MoveTo (Table.Event, range.Start))
1297                                 return events;
1298
1299                         this.context = type;
1300
1301                         for (uint i = 0; i < range.Length; i++)
1302                                 events.Add (ReadEvent (range.Start + i));
1303
1304                         return events;
1305                 }
1306
1307                 EventDefinition ReadEvent (uint event_rid)
1308                 {
1309                         var attributes = (EventAttributes) ReadUInt16 ();
1310                         var name = ReadString ();
1311                         var event_type = GetTypeDefOrRef (ReadMetadataToken (CodedIndex.TypeDefOrRef));
1312
1313                         var @event = new EventDefinition (name, attributes, event_type);
1314                         @event.token = new MetadataToken (TokenType.Event, event_rid);
1315                         return @event;
1316                 }
1317
1318                 void InitializeEvents ()
1319                 {
1320                         if (metadata.Events != null)
1321                                 return;
1322
1323                         int length = MoveTo (Table.EventMap);
1324
1325                         metadata.Events = new Dictionary<uint, Range> (length);
1326
1327                         for (uint i = 1; i <= length; i++) {
1328                                 var type_rid = ReadTableIndex (Table.TypeDef);
1329                                 Range events_range = ReadEventsRange (i);
1330                                 metadata.AddEventsRange (type_rid, events_range);
1331                         }
1332                 }
1333
1334                 Range ReadEventsRange (uint rid)
1335                 {
1336                         return ReadListRange (rid, Table.EventMap, Table.Event);
1337                 }
1338
1339                 public bool HasProperties (TypeDefinition type)
1340                 {
1341                         InitializeProperties ();
1342
1343                         Range range;
1344                         if (!metadata.TryGetPropertiesRange (type, out range))
1345                                 return false;
1346
1347                         return range.Length > 0;
1348                 }
1349
1350                 public Collection<PropertyDefinition> ReadProperties (TypeDefinition type)
1351                 {
1352                         InitializeProperties ();
1353
1354                         Range range;
1355
1356                         if (!metadata.TryGetPropertiesRange (type, out range))
1357                                 return new MemberDefinitionCollection<PropertyDefinition> (type);
1358
1359                         metadata.RemovePropertiesRange (type);
1360
1361                         var properties = new MemberDefinitionCollection<PropertyDefinition> (type, (int) range.Length);
1362
1363                         if (range.Length == 0 || !MoveTo (Table.Property, range.Start))
1364                                 return properties;
1365
1366                         this.context = type;
1367
1368                         for (uint i = 0; i < range.Length; i++)
1369                                 properties.Add (ReadProperty (range.Start + i));
1370
1371                         return properties;
1372                 }
1373
1374                 PropertyDefinition ReadProperty (uint property_rid)
1375                 {
1376                         var attributes = (PropertyAttributes) ReadUInt16 ();
1377                         var name = ReadString ();
1378                         var signature = ReadBlobIndex ();
1379
1380                         var reader = ReadSignature (signature);
1381                         const byte property_signature = 0x8;
1382
1383                         var calling_convention = reader.ReadByte ();
1384
1385                         if ((calling_convention & property_signature) == 0)
1386                                 throw new NotSupportedException ();
1387
1388                         var has_this = (calling_convention & 0x20) != 0;
1389
1390                         reader.ReadCompressedUInt32 (); // count
1391
1392                         var property = new PropertyDefinition (name, attributes, reader.ReadTypeSignature ());
1393                         property.HasThis = has_this;
1394                         property.token = new MetadataToken (TokenType.Property, property_rid);
1395
1396                         return property;
1397                 }
1398
1399                 void InitializeProperties ()
1400                 {
1401                         if (metadata.Properties != null)
1402                                 return;
1403
1404                         int length = MoveTo (Table.PropertyMap);
1405
1406                         metadata.Properties = new Dictionary<uint, Range> (length);
1407
1408                         for (uint i = 1; i <= length; i++) {
1409                                 var type_rid = ReadTableIndex (Table.TypeDef);
1410                                 var properties_range = ReadPropertiesRange (i);
1411                                 metadata.AddPropertiesRange (type_rid, properties_range);
1412                         }
1413                 }
1414
1415                 Range ReadPropertiesRange (uint rid)
1416                 {
1417                         return ReadListRange (rid, Table.PropertyMap, Table.Property);
1418                 }
1419
1420                 MethodSemanticsAttributes ReadMethodSemantics (MethodDefinition method)
1421                 {
1422                         InitializeMethodSemantics ();
1423                         Row<MethodSemanticsAttributes, MetadataToken> row;
1424                         if (!metadata.Semantics.TryGetValue (method.token.RID, out row))
1425                                 return MethodSemanticsAttributes.None;
1426
1427                         var type = method.DeclaringType;
1428
1429                         switch (row.Col1) {
1430                         case MethodSemanticsAttributes.AddOn:
1431                                 GetEvent (type, row.Col2).add_method = method;
1432                                 break;
1433                         case MethodSemanticsAttributes.Fire:
1434                                 GetEvent (type, row.Col2).invoke_method = method;
1435                                 break;
1436                         case MethodSemanticsAttributes.RemoveOn:
1437                                 GetEvent (type, row.Col2).remove_method = method;
1438                                 break;
1439                         case MethodSemanticsAttributes.Getter:
1440                                 GetProperty (type, row.Col2).get_method = method;
1441                                 break;
1442                         case MethodSemanticsAttributes.Setter:
1443                                 GetProperty (type, row.Col2).set_method = method;
1444                                 break;
1445                         case MethodSemanticsAttributes.Other:
1446                                 switch (row.Col2.TokenType) {
1447                                 case TokenType.Event: {
1448                                         var @event = GetEvent (type, row.Col2);
1449                                         if (@event.other_methods == null)
1450                                                 @event.other_methods = new Collection<MethodDefinition> ();
1451
1452                                         @event.other_methods.Add (method);
1453                                         break;
1454                                 }
1455                                 case TokenType.Property: {
1456                                         var property = GetProperty (type, row.Col2);
1457                                         if (property.other_methods == null)
1458                                                 property.other_methods = new Collection<MethodDefinition> ();
1459
1460                                         property.other_methods.Add (method);
1461
1462                                         break;
1463                                 }
1464                                 default:
1465                                         throw new NotSupportedException ();
1466                                 }
1467                                 break;
1468                         default:
1469                                 throw new NotSupportedException ();
1470                         }
1471
1472                         metadata.Semantics.Remove (method.token.RID);
1473
1474                         return row.Col1;
1475                 }
1476
1477                 static EventDefinition GetEvent (TypeDefinition type, MetadataToken token)
1478                 {
1479                         if (token.TokenType != TokenType.Event)
1480                                 throw new ArgumentException ();
1481
1482                         return GetMember (type.Events, token);
1483                 }
1484
1485                 static PropertyDefinition GetProperty (TypeDefinition type, MetadataToken token)
1486                 {
1487                         if (token.TokenType != TokenType.Property)
1488                                 throw new ArgumentException ();
1489
1490                         return GetMember (type.Properties, token);
1491                 }
1492
1493                 static TMember GetMember<TMember> (Collection<TMember> members, MetadataToken token) where TMember : IMemberDefinition
1494                 {
1495                         for (int i = 0; i < members.Count; i++) {
1496                                 var member = members [i];
1497                                 if (member.MetadataToken == token)
1498                                         return member;
1499                         }
1500
1501                         throw new ArgumentException ();
1502                 }
1503
1504                 void InitializeMethodSemantics ()
1505                 {
1506                         if (metadata.Semantics != null)
1507                                 return;
1508
1509                         int length = MoveTo (Table.MethodSemantics);
1510
1511                         var semantics = metadata.Semantics = new Dictionary<uint, Row<MethodSemanticsAttributes, MetadataToken>> (0);
1512
1513                         for (uint i = 0; i < length; i++) {
1514                                 var attributes = (MethodSemanticsAttributes) ReadUInt16 ();
1515                                 var method_rid = ReadTableIndex (Table.Method);
1516                                 var association = ReadMetadataToken (CodedIndex.HasSemantics);
1517
1518                                 semantics [method_rid] = new Row<MethodSemanticsAttributes, MetadataToken> (attributes, association);
1519                         }
1520                 }
1521
1522                 public PropertyDefinition ReadMethods (PropertyDefinition property)
1523                 {
1524                         ReadAllSemantics (property.DeclaringType);
1525                         return property;
1526                 }
1527
1528                 public EventDefinition ReadMethods (EventDefinition @event)
1529                 {
1530                         ReadAllSemantics (@event.DeclaringType);
1531                         return @event;
1532                 }
1533
1534                 public MethodSemanticsAttributes ReadAllSemantics (MethodDefinition method)
1535                 {
1536                         ReadAllSemantics (method.DeclaringType);
1537
1538                         return method.SemanticsAttributes;
1539                 }
1540
1541                 void ReadAllSemantics (TypeDefinition type)
1542                 {
1543                         var methods = type.Methods;
1544                         for (int i = 0; i < methods.Count; i++) {
1545                                 var method = methods [i];
1546                                 if (method.sem_attrs.HasValue)
1547                                         continue;
1548
1549                                 method.sem_attrs = ReadMethodSemantics (method);
1550                         }
1551                 }
1552
1553                 Range ReadParametersRange (uint method_rid)
1554                 {
1555                         return ReadListRange (method_rid, Table.Method, Table.Param);
1556                 }
1557
1558                 public Collection<MethodDefinition> ReadMethods (TypeDefinition type)
1559                 {
1560                         var methods_range = type.methods_range;
1561                         if (methods_range.Length == 0)
1562                                 return new MemberDefinitionCollection<MethodDefinition> (type);
1563
1564                         var methods = new MemberDefinitionCollection<MethodDefinition> (type, (int) methods_range.Length);
1565
1566                         MoveTo (Table.Method, methods_range.Start);
1567                         for (uint i = 0; i < methods_range.Length; i++)
1568                                 ReadMethod (methods_range.Start + i, methods);
1569
1570                         return methods;
1571                 }
1572
1573                 void InitializeMethods ()
1574                 {
1575                         if (metadata.Methods != null)
1576                                 return;
1577
1578                         metadata.Methods = new MethodDefinition [image.GetTableLength (Table.Method)];
1579                 }
1580
1581                 void ReadMethod (uint method_rid, Collection<MethodDefinition> methods)
1582                 {
1583                         var method = new MethodDefinition ();
1584                         method.rva = ReadUInt32 ();
1585                         method.ImplAttributes = (MethodImplAttributes) ReadUInt16 ();
1586                         method.Attributes = (MethodAttributes) ReadUInt16 ();
1587                         method.Name = ReadString ();
1588                         method.token = new MetadataToken (TokenType.Method, method_rid);
1589
1590                         methods.Add (method); // attach method
1591
1592                         var signature = ReadBlobIndex ();
1593                         var param_range = ReadParametersRange (method_rid);
1594
1595                         this.context = method;
1596
1597                         ReadMethodSignature (signature, method);
1598                         metadata.AddMethodDefinition (method);
1599
1600                         if (param_range.Length == 0)
1601                                 return;
1602
1603                         var position = base.position;
1604                         ReadParameters (method, param_range);
1605                         base.position = position;
1606                 }
1607
1608                 void ReadParameters (MethodDefinition method, Range param_range)
1609                 {
1610                         MoveTo (Table.Param, param_range.Start);
1611                         for (uint i = 0; i < param_range.Length; i++) {
1612                                 var attributes = (ParameterAttributes) ReadUInt16 ();
1613                                 var sequence = ReadUInt16 ();
1614                                 var name = ReadString ();
1615
1616                                 var parameter = sequence == 0
1617                                         ? method.MethodReturnType.Parameter
1618                                         : method.Parameters [sequence - 1];
1619
1620                                 parameter.token = new MetadataToken (TokenType.Param, param_range.Start + i);
1621                                 parameter.Name = name;
1622                                 parameter.Attributes = attributes;
1623                         }
1624                 }
1625
1626                 void ReadMethodSignature (uint signature, IMethodSignature method)
1627                 {
1628                         var reader = ReadSignature (signature);
1629                         reader.ReadMethodSignature (method);
1630                 }
1631
1632                 public PInvokeInfo ReadPInvokeInfo (MethodDefinition method)
1633                 {
1634                         InitializePInvokes ();
1635                         Row<PInvokeAttributes, uint, uint> row;
1636
1637                         var rid = method.token.RID;
1638
1639                         if (!metadata.PInvokes.TryGetValue (rid, out row))
1640                                 return null;
1641
1642                         metadata.PInvokes.Remove (rid);
1643
1644                         return new PInvokeInfo (
1645                                 row.Col1,
1646                                 image.StringHeap.Read (row.Col2),
1647                                 module.ModuleReferences [(int) row.Col3 - 1]);
1648                 }
1649
1650                 void InitializePInvokes ()
1651                 {
1652                         if (metadata.PInvokes != null)
1653                                 return;
1654
1655                         int length = MoveTo (Table.ImplMap);
1656
1657                         var pinvokes = metadata.PInvokes = new Dictionary<uint, Row<PInvokeAttributes, uint, uint>> (length);
1658
1659                         for (int i = 1; i <= length; i++) {
1660                                 var attributes = (PInvokeAttributes) ReadUInt16 ();
1661                                 var method = ReadMetadataToken (CodedIndex.MemberForwarded);
1662                                 var name = ReadStringIndex ();
1663                                 var scope = ReadTableIndex (Table.File);
1664
1665                                 if (method.TokenType != TokenType.Method)
1666                                         continue;
1667
1668                                 pinvokes.Add (method.RID, new Row<PInvokeAttributes, uint, uint> (attributes, name, scope));
1669                         }
1670                 }
1671
1672                 public bool HasGenericParameters (IGenericParameterProvider provider)
1673                 {
1674                         InitializeGenericParameters ();
1675
1676                         Range range;
1677                         if (!metadata.TryGetGenericParameterRange (provider, out range))
1678                                 return false;
1679
1680                         return range.Length > 0;
1681                 }
1682
1683                 public Collection<GenericParameter> ReadGenericParameters (IGenericParameterProvider provider)
1684                 {
1685                         InitializeGenericParameters ();
1686
1687                         Range range;
1688                         if (!metadata.TryGetGenericParameterRange (provider, out range)
1689                                 || !MoveTo (Table.GenericParam, range.Start))
1690                                 return new Collection<GenericParameter> ();
1691
1692                         metadata.RemoveGenericParameterRange (provider);
1693
1694                         var generic_parameters = new Collection<GenericParameter> ((int) range.Length);
1695
1696                         for (uint i = 0; i < range.Length; i++) {
1697                                 ReadUInt16 (); // index
1698                                 var flags = (GenericParameterAttributes) ReadUInt16 ();
1699                                 ReadMetadataToken (CodedIndex.TypeOrMethodDef);
1700                                 var name = ReadString ();
1701
1702                                 var parameter = new GenericParameter (name, provider);
1703                                 parameter.token = new MetadataToken (TokenType.GenericParam, range.Start + i);
1704                                 parameter.Attributes = flags;
1705
1706                                 generic_parameters.Add (parameter);
1707                         }
1708
1709                         return generic_parameters;
1710                 }
1711
1712                 void InitializeGenericParameters ()
1713                 {
1714                         if (metadata.GenericParameters != null)
1715                                 return;
1716
1717                         metadata.GenericParameters = InitializeRanges (
1718                                 Table.GenericParam, () => {
1719                                         Advance (4);
1720                                         var next = ReadMetadataToken (CodedIndex.TypeOrMethodDef);
1721                                         ReadStringIndex ();
1722                                         return next;
1723                         });
1724                 }
1725
1726                 Dictionary<MetadataToken, Range> InitializeRanges (Table table, Func<MetadataToken> get_next)
1727                 {
1728                         int length = MoveTo (table);
1729                         var ranges = new Dictionary<MetadataToken, Range> (length);
1730
1731                         if (length == 0)
1732                                 return ranges;
1733
1734                         MetadataToken owner = MetadataToken.Zero;
1735                         Range range = new Range (1, 0);
1736
1737                         for (uint i = 1; i <= length; i++) {
1738                                 var next = get_next ();
1739
1740                                 if (i == 1) {
1741                                         owner = next;
1742                                         range.Length++;
1743                                 } else if (next != owner) {
1744                                         if (owner.RID != 0)
1745                                                 ranges.Add (owner, range);
1746                                         range = new Range (i, 1);
1747                                         owner = next;
1748                                 } else
1749                                         range.Length++;
1750                         }
1751
1752                         if (owner != MetadataToken.Zero)
1753                                 ranges.Add (owner, range);
1754
1755                         return ranges;
1756                 }
1757
1758                 public bool HasGenericConstraints (GenericParameter generic_parameter)
1759                 {
1760                         InitializeGenericConstraints ();
1761
1762                         MetadataToken [] mapping;
1763                         if (!metadata.TryGetGenericConstraintMapping (generic_parameter, out mapping))
1764                                 return false;
1765
1766                         return mapping.Length > 0;
1767                 }
1768
1769                 public Collection<TypeReference> ReadGenericConstraints (GenericParameter generic_parameter)
1770                 {
1771                         InitializeGenericConstraints ();
1772
1773                         MetadataToken [] mapping;
1774                         if (!metadata.TryGetGenericConstraintMapping (generic_parameter, out mapping))
1775                                 return new Collection<TypeReference> ();
1776
1777                         var constraints = new Collection<TypeReference> (mapping.Length);
1778
1779                         this.context = (IGenericContext) generic_parameter.Owner;
1780
1781                         for (int i = 0; i < mapping.Length; i++)
1782                                 constraints.Add (GetTypeDefOrRef (mapping [i]));
1783
1784                         metadata.RemoveGenericConstraintMapping (generic_parameter);
1785
1786                         return constraints;
1787                 }
1788
1789                 void InitializeGenericConstraints ()
1790                 {
1791                         if (metadata.GenericConstraints != null)
1792                                 return;
1793
1794                         var length = MoveTo (Table.GenericParamConstraint);
1795
1796                         metadata.GenericConstraints = new Dictionary<uint, MetadataToken []> (length);
1797
1798                         for (int i = 1; i <= length; i++)
1799                                 AddGenericConstraintMapping (
1800                                         ReadTableIndex (Table.GenericParam),
1801                                         ReadMetadataToken (CodedIndex.TypeDefOrRef));
1802                 }
1803
1804                 void AddGenericConstraintMapping (uint generic_parameter, MetadataToken constraint)
1805                 {
1806                         metadata.SetGenericConstraintMapping (
1807                                 generic_parameter,
1808                                 AddMapping (metadata.GenericConstraints, generic_parameter, constraint));
1809                 }
1810
1811                 public bool HasOverrides (MethodDefinition method)
1812                 {
1813                         InitializeOverrides ();
1814                         MetadataToken [] mapping;
1815
1816                         if (!metadata.TryGetOverrideMapping (method, out mapping))
1817                                 return false;
1818
1819                         return mapping.Length > 0;
1820                 }
1821
1822                 public Collection<MethodReference> ReadOverrides (MethodDefinition method)
1823                 {
1824                         InitializeOverrides ();
1825
1826                         MetadataToken [] mapping;
1827                         if (!metadata.TryGetOverrideMapping (method, out mapping))
1828                                 return new Collection<MethodReference> ();
1829
1830                         var overrides = new Collection<MethodReference> (mapping.Length);
1831
1832                         this.context = method;
1833
1834                         for (int i = 0; i < mapping.Length; i++)
1835                                 overrides.Add ((MethodReference) LookupToken (mapping [i]));
1836
1837                         metadata.RemoveOverrideMapping (method);
1838
1839                         return overrides;
1840                 }
1841
1842                 void InitializeOverrides ()
1843                 {
1844                         if (metadata.Overrides != null)
1845                                 return;
1846
1847                         var length = MoveTo (Table.MethodImpl);
1848
1849                         metadata.Overrides = new Dictionary<uint, MetadataToken []> (length);
1850
1851                         for (int i = 1; i <= length; i++) {
1852                                 ReadTableIndex (Table.TypeDef);
1853
1854                                 var method = ReadMetadataToken (CodedIndex.MethodDefOrRef);
1855                                 if (method.TokenType != TokenType.Method)
1856                                         throw new NotSupportedException ();
1857
1858                                 var @override = ReadMetadataToken (CodedIndex.MethodDefOrRef);
1859
1860                                 AddOverrideMapping (method.RID, @override);
1861                         }
1862                 }
1863
1864                 void AddOverrideMapping (uint method_rid, MetadataToken @override)
1865                 {
1866                         metadata.SetOverrideMapping (
1867                                 method_rid,
1868                                 AddMapping (metadata.Overrides, method_rid, @override));
1869                 }
1870
1871                 public MethodBody ReadMethodBody (MethodDefinition method)
1872                 {
1873                         return code.ReadMethodBody (method);
1874                 }
1875
1876                 public CallSite ReadCallSite (MetadataToken token)
1877                 {
1878                         if (!MoveTo (Table.StandAloneSig, token.RID))
1879                                 return null;
1880
1881                         var signature = ReadBlobIndex ();
1882
1883                         var call_site = new CallSite ();
1884
1885                         ReadMethodSignature (signature, call_site);
1886
1887                         return call_site;
1888                 }
1889
1890                 public VariableDefinitionCollection ReadVariables (MetadataToken local_var_token)
1891                 {
1892                         if (!MoveTo (Table.StandAloneSig, local_var_token.RID))
1893                                 return null;
1894
1895                         var reader = ReadSignature (ReadBlobIndex ());
1896                         const byte local_sig = 0x7;
1897
1898                         if (reader.ReadByte () != local_sig)
1899                                 throw new NotSupportedException ();
1900
1901                         var count = reader.ReadCompressedUInt32 ();
1902                         if (count == 0)
1903                                 return null;
1904
1905                         var variables = new VariableDefinitionCollection ((int) count);
1906
1907                         for (int i = 0; i < count; i++)
1908                                 variables.Add (new VariableDefinition (reader.ReadTypeSignature ()));
1909
1910                         return variables;
1911                 }
1912
1913                 public IMetadataTokenProvider LookupToken (MetadataToken token)
1914                 {
1915                         var rid = token.RID;
1916
1917                         if (rid == 0)
1918                                 return null;
1919
1920                         IMetadataTokenProvider element;
1921                         var position = this.position;
1922                         var context = this.context;
1923
1924                         switch (token.TokenType) {
1925                         case TokenType.TypeDef:
1926                                 element = GetTypeDefinition (rid);
1927                                 break;
1928                         case TokenType.TypeRef:
1929                                 element = GetTypeReference (rid);
1930                                 break;
1931                         case TokenType.TypeSpec:
1932                                 element = GetTypeSpecification (rid);
1933                                 break;
1934                         case TokenType.Field:
1935                                 element = GetFieldDefinition (rid);
1936                                 break;
1937                         case TokenType.Method:
1938                                 element = GetMethodDefinition (rid);
1939                                 break;
1940                         case TokenType.MemberRef:
1941                                 element = GetMemberReference (rid);
1942                                 break;
1943                         case TokenType.MethodSpec:
1944                                 element = GetMethodSpecification (rid);
1945                                 break;
1946                         default:
1947                                 return null;
1948                         }
1949
1950                         this.position = position;
1951                         this.context = context;
1952
1953                         return element;
1954                 }
1955
1956                 public FieldDefinition GetFieldDefinition (uint rid)
1957                 {
1958                         InitializeTypeDefinitions ();
1959
1960                         var field = metadata.GetFieldDefinition (rid);
1961                         if (field != null)
1962                                 return field;
1963
1964                         return LookupField (rid);
1965                 }
1966
1967                 FieldDefinition LookupField (uint rid)
1968                 {
1969                         var type = metadata.GetFieldDeclaringType (rid);
1970                         if (type == null)
1971                                 return null;
1972
1973                         InitializeCollection (type.Fields);
1974
1975                         return metadata.GetFieldDefinition (rid);
1976                 }
1977
1978                 public MethodDefinition GetMethodDefinition (uint rid)
1979                 {
1980                         InitializeTypeDefinitions ();
1981
1982                         var method = metadata.GetMethodDefinition (rid);
1983                         if (method != null)
1984                                 return method;
1985
1986                         return LookupMethod (rid);
1987                 }
1988
1989                 MethodDefinition LookupMethod (uint rid)
1990                 {
1991                         var type = metadata.GetMethodDeclaringType (rid);
1992                         if (type == null)
1993                                 return null;
1994
1995                         InitializeCollection (type.Methods);
1996
1997                         return metadata.GetMethodDefinition (rid);
1998                 }
1999
2000                 MethodSpecification GetMethodSpecification (uint rid)
2001                 {
2002                         if (!MoveTo (Table.MethodSpec, rid))
2003                                 return null;
2004
2005                         var element_method = (MethodReference) LookupToken (
2006                                 ReadMetadataToken (CodedIndex.MethodDefOrRef));
2007                         var signature = ReadBlobIndex ();
2008
2009                         var method_spec = ReadMethodSpecSignature (signature, element_method);
2010                         method_spec.token = new MetadataToken (TokenType.MethodSpec, rid);
2011                         return method_spec;
2012                 }
2013
2014                 MethodSpecification ReadMethodSpecSignature (uint signature, MethodReference method)
2015                 {
2016                         var reader = ReadSignature (signature);
2017                         const byte methodspec_sig = 0x0a;
2018
2019                         var call_conv = reader.ReadByte ();
2020
2021                         if (call_conv != methodspec_sig)
2022                                 throw new NotSupportedException ();
2023
2024                         var instance = new GenericInstanceMethod (method);
2025
2026                         reader.ReadGenericInstanceSignature (method, instance);
2027
2028                         return instance;
2029                 }
2030
2031                 MemberReference GetMemberReference (uint rid)
2032                 {
2033                         InitializeMemberReferences ();
2034
2035                         var member = metadata.GetMemberReference (rid);
2036                         if (member != null)
2037                                 return member;
2038
2039                         member = ReadMemberReference (rid);
2040                         if (member != null && !member.ContainsGenericParameter)
2041                                 metadata.AddMemberReference (member);
2042                         return member;
2043                 }
2044
2045                 MemberReference ReadMemberReference (uint rid)
2046                 {
2047                         if (!MoveTo (Table.MemberRef, rid))
2048                                 return null;
2049
2050                         var token = ReadMetadataToken (CodedIndex.MemberRefParent);
2051                         var name = ReadString ();
2052                         var signature = ReadBlobIndex ();
2053
2054                         MemberReference member;
2055
2056                         switch (token.TokenType) {
2057                         case TokenType.TypeDef:
2058                         case TokenType.TypeRef:
2059                         case TokenType.TypeSpec:
2060                                 member = ReadTypeMemberReference (token, name, signature);
2061                                 break;
2062                         case TokenType.Method:
2063                                 member = ReadMethodMemberReference (token, name, signature);
2064                                 break;
2065                         default:
2066                                 throw new NotSupportedException ();
2067                         }
2068
2069                         member.token = new MetadataToken (TokenType.MemberRef, rid);
2070
2071                         return member;
2072                 }
2073
2074                 MemberReference ReadTypeMemberReference (MetadataToken type, string name, uint signature)
2075                 {
2076                         var declaring_type = GetTypeDefOrRef (type);
2077
2078                         this.context = declaring_type;
2079
2080                         var member = ReadMemberReferenceSignature (signature, declaring_type);
2081                         member.Name = name;
2082
2083                         return member;
2084                 }
2085
2086                 MemberReference ReadMemberReferenceSignature (uint signature, TypeReference declaring_type)
2087                 {
2088                         var reader = ReadSignature (signature);
2089                         const byte field_sig = 0x6;
2090
2091                         if (reader.buffer [reader.position] == field_sig) {
2092                                 reader.position++;
2093                                 var field = new FieldReference ();
2094                                 field.DeclaringType = declaring_type;
2095                                 field.FieldType = reader.ReadTypeSignature ();
2096                                 return field;
2097                         } else {
2098                                 var method = new MethodReference ();
2099                                 method.DeclaringType = declaring_type;
2100                                 reader.ReadMethodSignature (method);
2101                                 return method;
2102                         }
2103                 }
2104
2105                 MemberReference ReadMethodMemberReference (MetadataToken token, string name, uint signature)
2106                 {
2107                         var method = GetMethodDefinition (token.RID);
2108
2109                         this.context = method;
2110
2111                         var member = ReadMemberReferenceSignature (signature, method.DeclaringType);
2112                         member.Name = name;
2113
2114                         return member;
2115                 }
2116
2117                 void InitializeMemberReferences ()
2118                 {
2119                         if (metadata.MemberReferences != null)
2120                                 return;
2121
2122                         metadata.MemberReferences = new MemberReference [image.GetTableLength (Table.MemberRef)];
2123                 }
2124
2125                 public IEnumerable<MemberReference> GetMemberReferences ()
2126                 {
2127                         InitializeMemberReferences ();
2128
2129                         var length = image.GetTableLength (Table.MemberRef);
2130
2131                         var type_system = module.TypeSystem;
2132
2133                         var context = new MethodReference (string.Empty, type_system.Void);
2134                         context.DeclaringType = new TypeReference (string.Empty, string.Empty, module, type_system.Corlib);
2135
2136                         var member_references = new MemberReference [length];
2137
2138                         for (uint i = 1; i <= length; i++) {
2139                                 this.context = context;
2140                                 member_references [i - 1] = GetMemberReference (i);
2141                         }
2142
2143                         return member_references;
2144                 }
2145
2146                 void InitializeConstants ()
2147                 {
2148                         if (metadata.Constants != null)
2149                                 return;
2150
2151                         var length = MoveTo (Table.Constant);
2152
2153                         var constants = metadata.Constants = new Dictionary<MetadataToken, Row<ElementType, uint>> (length);
2154
2155                         for (uint i = 1; i <= length; i++) {
2156                                 var type = (ElementType) ReadUInt16 ();
2157                                 var owner = ReadMetadataToken (CodedIndex.HasConstant);
2158                                 var signature = ReadBlobIndex ();
2159
2160                                 constants.Add (owner, new Row<ElementType, uint> (type, signature));
2161                         }
2162                 }
2163
2164                 public object ReadConstant (IConstantProvider owner)
2165                 {
2166                         InitializeConstants ();
2167
2168                         Row<ElementType, uint> row;
2169                         if (!metadata.Constants.TryGetValue (owner.MetadataToken, out row))
2170                                 return Mixin.NoValue;
2171
2172                         metadata.Constants.Remove (owner.MetadataToken);
2173
2174                         switch (row.Col1) {
2175                         case ElementType.Class:
2176                         case ElementType.Object:
2177                                 return null;
2178                         case ElementType.String:
2179                                 return ReadConstantString (ReadBlob (row.Col2));
2180                         default:
2181                                 return ReadConstantPrimitive (row.Col1, row.Col2);
2182                         }
2183                 }
2184
2185                 static string ReadConstantString (byte [] blob)
2186                 {
2187                         var length = blob.Length;
2188                         if ((length & 1) == 1)
2189                                 length--;
2190
2191                         return Encoding.Unicode.GetString (blob, 0, length);
2192                 }
2193
2194                 object ReadConstantPrimitive (ElementType type, uint signature)
2195                 {
2196                         var reader = ReadSignature (signature);
2197                         return reader.ReadConstantSignature (type);
2198                 }
2199
2200                 void InitializeCustomAttributes ()
2201                 {
2202                         if (metadata.CustomAttributes != null)
2203                                 return;
2204
2205                         metadata.CustomAttributes = InitializeRanges (
2206                                 Table.CustomAttribute, () => {
2207                                         var next = ReadMetadataToken (CodedIndex.HasCustomAttribute);
2208                                         ReadMetadataToken (CodedIndex.CustomAttributeType);
2209                                         ReadBlobIndex ();
2210                                         return next;
2211                         });
2212                 }
2213
2214                 public bool HasCustomAttributes (ICustomAttributeProvider owner)
2215                 {
2216                         InitializeCustomAttributes ();
2217
2218                         Range range;
2219                         if (!metadata.TryGetCustomAttributeRange (owner, out range))
2220                                 return false;
2221
2222                         return range.Length > 0;
2223                 }
2224
2225                 public Collection<CustomAttribute> ReadCustomAttributes (ICustomAttributeProvider owner)
2226                 {
2227                         InitializeCustomAttributes ();
2228
2229                         Range range;
2230                         if (!metadata.TryGetCustomAttributeRange (owner, out range)
2231                                 || !MoveTo (Table.CustomAttribute, range.Start))
2232                                 return new Collection<CustomAttribute> ();
2233
2234                         var custom_attributes = new Collection<CustomAttribute> ((int) range.Length);
2235
2236                         for (int i = 0; i < range.Length; i++) {
2237                                 ReadMetadataToken (CodedIndex.HasCustomAttribute);
2238
2239                                 var constructor = (MethodReference) LookupToken (
2240                                         ReadMetadataToken (CodedIndex.CustomAttributeType));
2241
2242                                 var signature = ReadBlobIndex ();
2243
2244                                 custom_attributes.Add (new CustomAttribute (signature, constructor));
2245                         }
2246
2247                         metadata.RemoveCustomAttributeRange (owner);
2248
2249                         return custom_attributes;
2250                 }
2251
2252                 public byte [] ReadCustomAttributeBlob (uint signature)
2253                 {
2254                         return ReadBlob (signature);
2255                 }
2256
2257                 public void ReadCustomAttributeSignature (CustomAttribute attribute)
2258                 {
2259                         var reader = ReadSignature (attribute.signature);
2260                         if (reader.ReadUInt16 () != 0x0001)
2261                             throw new InvalidOperationException ();
2262
2263                         var constructor = attribute.Constructor;
2264                         if (constructor.HasParameters)
2265                                 reader.ReadCustomAttributeConstructorArguments (attribute, constructor.Parameters);
2266
2267                         if (!reader.CanReadMore ())
2268                                 return;
2269
2270                         var named = reader.ReadUInt16 ();
2271
2272                         if (named == 0)
2273                                 return;
2274
2275                         reader.ReadCustomAttributeNamedArguments (named, ref attribute.fields, ref attribute.properties);
2276                 }
2277
2278                 void InitializeMarshalInfos ()
2279                 {
2280                         if (metadata.FieldMarshals != null)
2281                                 return;
2282
2283                         var length = MoveTo (Table.FieldMarshal);
2284
2285                         var marshals = metadata.FieldMarshals = new Dictionary<MetadataToken, uint> (length);
2286
2287                         for (int i = 0; i < length; i++) {
2288                                 var token = ReadMetadataToken (CodedIndex.HasFieldMarshal);
2289                                 var signature = ReadBlobIndex ();
2290                                 if (token.RID == 0)
2291                                         continue;
2292
2293                                 marshals.Add (token, signature);
2294                         }
2295                 }
2296
2297                 public bool HasMarshalInfo (IMarshalInfoProvider owner)
2298                 {
2299                         InitializeMarshalInfos ();
2300
2301                         return metadata.FieldMarshals.ContainsKey (owner.MetadataToken);
2302                 }
2303
2304                 public MarshalInfo ReadMarshalInfo (IMarshalInfoProvider owner)
2305                 {
2306                         InitializeMarshalInfos ();
2307
2308                         uint signature;
2309                         if (!metadata.FieldMarshals.TryGetValue (owner.MetadataToken, out signature))
2310                                 return null;
2311
2312                         var reader = ReadSignature (signature);
2313
2314                         metadata.FieldMarshals.Remove (owner.MetadataToken);
2315
2316                         return reader.ReadMarshalInfo ();
2317                 }
2318
2319                 void InitializeSecurityDeclarations ()
2320                 {
2321                         if (metadata.SecurityDeclarations != null)
2322                                 return;
2323
2324                         metadata.SecurityDeclarations = InitializeRanges (
2325                                 Table.DeclSecurity, () => {
2326                                         ReadUInt16 ();
2327                                         var next = ReadMetadataToken (CodedIndex.HasDeclSecurity);
2328                                         ReadBlobIndex ();
2329                                         return next;
2330                         });
2331                 }
2332
2333                 public bool HasSecurityDeclarations (ISecurityDeclarationProvider owner)
2334                 {
2335                         InitializeSecurityDeclarations ();
2336
2337                         Range range;
2338                         if (!metadata.TryGetSecurityDeclarationRange (owner, out range))
2339                                 return false;
2340
2341                         return range.Length > 0;
2342                 }
2343
2344                 public Collection<SecurityDeclaration> ReadSecurityDeclarations (ISecurityDeclarationProvider owner)
2345                 {
2346                         InitializeSecurityDeclarations ();
2347
2348                         Range range;
2349                         if (!metadata.TryGetSecurityDeclarationRange (owner, out range)
2350                                 || !MoveTo (Table.DeclSecurity, range.Start))
2351                                 return new Collection<SecurityDeclaration> ();
2352
2353                         var security_declarations = new Collection<SecurityDeclaration> ((int) range.Length);
2354
2355                         for (int i = 0; i < range.Length; i++) {
2356                                 var action = (SecurityAction) ReadUInt16 ();
2357                                 ReadMetadataToken (CodedIndex.HasDeclSecurity);
2358                                 var signature = ReadBlobIndex ();
2359
2360                                 security_declarations.Add (new SecurityDeclaration (action, signature, module));
2361                         }
2362
2363                         metadata.RemoveSecurityDeclarationRange (owner);
2364
2365                         return security_declarations;
2366                 }
2367
2368                 public byte [] ReadSecurityDeclarationBlob (uint signature)
2369                 {
2370                         return ReadBlob (signature);
2371                 }
2372
2373                 public void ReadSecurityDeclarationSignature (SecurityDeclaration declaration)
2374                 {
2375                         var signature = declaration.signature;
2376                         var reader = ReadSignature (signature);
2377
2378                         if (reader.buffer [reader.position] != '.') {
2379                                 ReadXmlSecurityDeclaration (signature, declaration);
2380                                 return;
2381                         }
2382
2383                         reader.ReadByte ();
2384                         var count = reader.ReadCompressedUInt32 ();
2385                         var attributes = new Collection<SecurityAttribute> ((int) count);
2386
2387                         for (int i = 0; i < count; i++)
2388                                 attributes.Add (reader.ReadSecurityAttribute ());
2389
2390                         declaration.security_attributes = attributes;
2391                 }
2392
2393                 void ReadXmlSecurityDeclaration (uint signature, SecurityDeclaration declaration)
2394                 {
2395                         var blob = ReadBlob (signature);
2396                         var attributes = new Collection<SecurityAttribute> (1);
2397
2398                         var attribute = new SecurityAttribute (
2399                                 module.TypeSystem.LookupType ("System.Security.Permissions", "PermissionSetAttribute"));
2400
2401                         attribute.properties = new Collection<CustomAttributeNamedArgument> (1);
2402                         attribute.properties.Add (
2403                                 new CustomAttributeNamedArgument (
2404                                         "XML",
2405                                         new CustomAttributeArgument (
2406                                                 module.TypeSystem.String,
2407                                                 Encoding.Unicode.GetString (blob, 0, blob.Length))));
2408
2409                         attributes.Add (attribute);
2410
2411                         declaration.security_attributes = attributes;
2412                 }
2413
2414                 public Collection<ExportedType> ReadExportedTypes ()
2415                 {
2416                         var length = MoveTo (Table.ExportedType);
2417                         if (length == 0)
2418                                 return new Collection<ExportedType> ();
2419
2420                         var exported_types = new Collection<ExportedType> (length);
2421
2422                         for (int i = 1; i <= length; i++) {
2423                                 var attributes = (TypeAttributes) ReadUInt32 ();
2424                                 var identifier = ReadUInt32 ();
2425                                 var name = ReadString ();
2426                                 var @namespace = ReadString ();
2427                                 var implementation = ReadMetadataToken (CodedIndex.Implementation);
2428
2429                                 ExportedType declaring_type = null;
2430                                 IMetadataScope scope = null;
2431
2432                                 switch (implementation.TokenType) {
2433                                 case TokenType.AssemblyRef:
2434                                 case TokenType.File:
2435                                         scope = GetExportedTypeScope (implementation);
2436                                         break;
2437                                 case TokenType.ExportedType:
2438                                         // FIXME: if the table is not properly sorted
2439                                         declaring_type = exported_types [(int) implementation.RID - 1];
2440                                         break;
2441                                 }
2442
2443                                 var exported_type = new ExportedType (@namespace, name, scope) {
2444                                         Attributes = attributes,
2445                                         Identifier = (int) identifier,
2446                                         DeclaringType = declaring_type,
2447                                 };
2448                                 exported_type.token = new MetadataToken (TokenType.ExportedType, i);
2449
2450                                 exported_types.Add (exported_type);
2451                         }
2452
2453                         return exported_types;
2454                 }
2455
2456                 IMetadataScope GetExportedTypeScope (MetadataToken token)
2457                 {
2458                         switch (token.TokenType) {
2459                         case TokenType.AssemblyRef:
2460                                 return module.AssemblyReferences [(int) token.RID - 1];
2461                         case TokenType.File:
2462                                 var position = this.position;
2463                                 var reference = GetModuleReferenceFromFile (token);
2464                                 this.position = position;
2465
2466                                 if (reference == null)
2467                                         throw new NotSupportedException ();
2468
2469                                 return reference;
2470                         default:
2471                                 throw new NotSupportedException ();
2472                         }
2473                 }
2474
2475                 ModuleReference GetModuleReferenceFromFile (MetadataToken token)
2476                 {
2477                         if (!MoveTo (Table.File, token.RID))
2478                                 return null;
2479
2480                         ReadUInt32 ();
2481                         var file_name = ReadString ();
2482                         var modules = module.ModuleReferences;
2483
2484                         ModuleReference reference = null;
2485                         for (int i = 0; i < modules.Count; i++) {
2486                                 var module_reference = modules [i];
2487                                 if (module_reference.Name != file_name)
2488                                         continue;
2489
2490                                 reference = module_reference;
2491                                 break;
2492                         }
2493
2494                         return reference;
2495                 }
2496
2497                 static void InitializeCollection (object o)
2498                 {
2499                 }
2500         }
2501
2502         sealed class SignatureReader : ByteBuffer {
2503
2504                 readonly MetadataReader reader;
2505                 readonly uint start, sig_length;
2506
2507                 TypeSystem TypeSystem {
2508                         get { return reader.module.TypeSystem; }
2509                 }
2510
2511                 public SignatureReader (uint blob, MetadataReader reader)
2512                         : base (reader.buffer)
2513                 {
2514                         this.reader = reader;
2515
2516                         MoveToBlob (blob);
2517
2518                         this.sig_length = ReadCompressedUInt32 ();
2519                         this.start = (uint) position;
2520                 }
2521
2522                 void MoveToBlob (uint blob)
2523                 {
2524                         position = (int) (reader.image.BlobHeap.Offset + blob);
2525                 }
2526
2527                 MetadataToken ReadTypeTokenSignature ()
2528                 {
2529                         return CodedIndex.TypeDefOrRef.GetMetadataToken (ReadCompressedUInt32 ());
2530                 }
2531
2532                 GenericParameter GetGenericParameter (GenericParameterType type, uint var)
2533                 {
2534                         var context = reader.context;
2535
2536                         if (context == null)
2537                                 throw new NotSupportedException ();
2538
2539                         IGenericParameterProvider provider;
2540
2541                         switch (type) {
2542                         case GenericParameterType.Type:
2543                                 provider = context.Type;
2544                                 break;
2545                         case GenericParameterType.Method:
2546                                 provider = context.Method;
2547                                 break;
2548                         default:
2549                                 throw new NotSupportedException ();
2550                         }
2551
2552                         int index = (int) var;
2553
2554                         if (!context.IsDefinition)
2555                                 CheckGenericContext (provider, index);
2556
2557                         return provider.GenericParameters [index];
2558                 }
2559
2560                 static void CheckGenericContext (IGenericParameterProvider owner, int index)
2561                 {
2562                         var owner_parameters = owner.GenericParameters;
2563
2564                         for (int i = owner_parameters.Count; i <= index; i++)
2565                                 owner_parameters.Add (new GenericParameter (owner));
2566                 }
2567
2568                 public void ReadGenericInstanceSignature (IGenericParameterProvider provider, IGenericInstance instance)
2569                 {
2570                         var arity = ReadCompressedUInt32 ();
2571
2572                         if (!provider.IsDefinition)
2573                                 CheckGenericContext (provider, (int) arity - 1);
2574
2575                         var instance_arguments = instance.GenericArguments;
2576
2577                         for (int i = 0; i < arity; i++)
2578                                 instance_arguments.Add (ReadTypeSignature ());
2579                 }
2580
2581                 ArrayType ReadArrayTypeSignature ()
2582                 {
2583                         var array = new ArrayType (ReadTypeSignature ());
2584
2585                         var rank = ReadCompressedUInt32 ();
2586
2587                         var sizes = new uint [ReadCompressedUInt32 ()];
2588                         for (int i = 0; i < sizes.Length; i++)
2589                                 sizes [i] = ReadCompressedUInt32 ();
2590
2591                         var low_bounds = new int [ReadCompressedUInt32 ()];
2592                         for (int i = 0; i < low_bounds.Length; i++)
2593                                 low_bounds [i] = ReadCompressedInt32 ();
2594
2595                         array.Dimensions.Clear ();
2596
2597                         for (int i = 0; i < rank; i++) {
2598                                 int? lower = null, upper = null;
2599
2600                                 if (i < low_bounds.Length)
2601                                         lower = low_bounds [i];
2602
2603                                 if (i < sizes.Length)
2604                                         upper = lower + (int) sizes [i] - 1;
2605
2606                                 array.Dimensions.Add (new ArrayDimension (lower, upper));
2607                         }
2608
2609                         return array;
2610                 }
2611
2612                 TypeReference GetTypeDefOrRef (MetadataToken token)
2613                 {
2614                         return reader.GetTypeDefOrRef (token);
2615                 }
2616
2617                 public TypeReference ReadTypeSignature ()
2618                 {
2619                         return ReadTypeSignature ((ElementType) ReadByte ());
2620                 }
2621
2622                 TypeReference ReadTypeSignature (ElementType etype)
2623                 {
2624                         switch (etype) {
2625                         case ElementType.ValueType: {
2626                                 var value_type = GetTypeDefOrRef (ReadTypeTokenSignature ());
2627                                 value_type.IsValueType = true;
2628                                 return value_type;
2629                         }
2630                         case ElementType.Class:
2631                                 return GetTypeDefOrRef (ReadTypeTokenSignature ());
2632                         case ElementType.Ptr:
2633                                 return new PointerType (ReadTypeSignature ());
2634                         case ElementType.FnPtr: {
2635                                 var fptr = new FunctionPointerType ();
2636                                 ReadMethodSignature (fptr);
2637                                 return fptr;
2638                         }
2639                         case ElementType.ByRef:
2640                                 return new ByReferenceType (ReadTypeSignature ());
2641                         case ElementType.Pinned:
2642                                 return new PinnedType (ReadTypeSignature ());
2643                         case ElementType.SzArray:
2644                                 return new ArrayType (ReadTypeSignature ());
2645                         case ElementType.Array:
2646                                 return ReadArrayTypeSignature ();
2647                         case ElementType.CModOpt:
2648                                 return new OptionalModifierType (
2649                                         GetTypeDefOrRef (ReadTypeTokenSignature ()), ReadTypeSignature ());
2650                         case ElementType.CModReqD:
2651                                 return new RequiredModifierType (
2652                                         GetTypeDefOrRef (ReadTypeTokenSignature ()), ReadTypeSignature ());
2653                         case ElementType.Sentinel:
2654                                 return new SentinelType (ReadTypeSignature ());
2655                         case ElementType.Var:
2656                                 return GetGenericParameter (GenericParameterType.Type, ReadCompressedUInt32 ());
2657                         case ElementType.MVar:
2658                                 return GetGenericParameter (GenericParameterType.Method, ReadCompressedUInt32 ());
2659                         case ElementType.GenericInst: {
2660                                 var is_value_type = ReadByte () == (byte) ElementType.ValueType;
2661                                 var element_type = GetTypeDefOrRef (ReadTypeTokenSignature ());
2662                                 var generic_instance = new GenericInstanceType (element_type);
2663
2664                                 ReadGenericInstanceSignature (element_type, generic_instance);
2665
2666                                 if (is_value_type) {
2667                                         generic_instance.IsValueType = true;
2668                                         element_type.GetElementType ().IsValueType = true;
2669                                 }
2670
2671                                 return generic_instance;
2672                         }
2673                         case ElementType.Object: return TypeSystem.Object;
2674                         case ElementType.Void: return TypeSystem.Void;
2675                         case ElementType.TypedByRef: return TypeSystem.TypedReference;
2676                         case ElementType.I: return TypeSystem.IntPtr;
2677                         case ElementType.U: return TypeSystem.UIntPtr;
2678                         default: return GetPrimitiveType (etype);
2679                         }
2680                 }
2681
2682                 public void ReadMethodSignature (IMethodSignature method)
2683                 {
2684                         var calling_convention = ReadByte ();
2685                         method.CallingConvention = (MethodCallingConvention) calling_convention;
2686                         method.HasThis = (calling_convention & 0x20) != 0;
2687                         method.ExplicitThis = (calling_convention & 0x40) != 0;
2688
2689                         var generic_context = method as MethodReference;
2690                         if (generic_context != null)
2691                                 reader.context = generic_context;
2692
2693                         if ((calling_convention & 0x10) != 0) {
2694                                 var arity = ReadCompressedUInt32 ();
2695
2696                                 if (generic_context != null && !generic_context.IsDefinition)
2697                                         CheckGenericContext (generic_context, (int) arity -1 );
2698                         }
2699
2700                         // TODO: more call_conv
2701
2702                         var param_count = ReadCompressedUInt32 ();
2703
2704                         method.MethodReturnType.ReturnType = ReadTypeSignature ();
2705
2706                         if (param_count == 0)
2707                                 return;
2708
2709                         Collection<ParameterDefinition> parameters;
2710
2711                         var method_ref = method as MethodReference;
2712                         if (method_ref != null)
2713                                 parameters = method_ref.parameters = new ParameterDefinitionCollection (method, (int) param_count);
2714                         else
2715                                 parameters = method.Parameters;
2716
2717                         for (int i = 0; i < param_count; i++)
2718                                 parameters.Add (new ParameterDefinition (ReadTypeSignature ()));
2719                 }
2720
2721                 public object ReadConstantSignature (ElementType type)
2722                 {
2723                         return ReadPrimitiveValue (type);
2724                 }
2725
2726                 public void ReadCustomAttributeConstructorArguments (CustomAttribute attribute, Collection<ParameterDefinition> parameters)
2727                 {
2728                         var count = parameters.Count;
2729                         if (count == 0)
2730                                 return;
2731
2732                         attribute.arguments = new Collection<CustomAttributeArgument> (count);
2733
2734                         for (int i = 0; i < count; i++)
2735                                 attribute.arguments.Add (
2736                                         ReadCustomAttributeFixedArgument (parameters [i].ParameterType));
2737                 }
2738
2739                 CustomAttributeArgument ReadCustomAttributeFixedArgument (TypeReference type)
2740                 {
2741                         if (type.IsArray)
2742                                 return ReadCustomAttributeFixedArrayArgument ((ArrayType) type);
2743
2744                         return ReadCustomAttributeElement (type);
2745                 }
2746
2747                 public void ReadCustomAttributeNamedArguments (ushort count, ref Collection<CustomAttributeNamedArgument> fields, ref Collection<CustomAttributeNamedArgument> properties)
2748                 {
2749                         for (int i = 0; i < count; i++)
2750                                 ReadCustomAttributeNamedArgument (ref fields, ref properties);
2751                 }
2752
2753                 void ReadCustomAttributeNamedArgument (ref Collection<CustomAttributeNamedArgument> fields, ref Collection<CustomAttributeNamedArgument> properties)
2754                 {
2755                         var kind = ReadByte ();
2756                         var type = ReadCustomAttributeFieldOrPropType ();
2757                         var name = ReadUTF8String ();
2758
2759                         Collection<CustomAttributeNamedArgument> container;
2760                         switch (kind) {
2761                         case 0x53:
2762                                 container = GetCustomAttributeNamedArgumentCollection (ref fields);
2763                                 break;
2764                         case 0x54:
2765                                 container = GetCustomAttributeNamedArgumentCollection (ref properties);
2766                                 break;
2767                         default:
2768                                 throw new NotSupportedException ();
2769                         }
2770
2771                         container.Add (new CustomAttributeNamedArgument (name, ReadCustomAttributeFixedArgument (type)));
2772                 }
2773
2774                 static Collection<CustomAttributeNamedArgument> GetCustomAttributeNamedArgumentCollection (ref Collection<CustomAttributeNamedArgument> collection)
2775                 {
2776                         if (collection != null)
2777                                 return collection;
2778
2779                         return collection = new Collection<CustomAttributeNamedArgument> ();
2780                 }
2781
2782                 CustomAttributeArgument ReadCustomAttributeFixedArrayArgument (ArrayType type)
2783                 {
2784                         var length = ReadUInt32 ();
2785
2786                         if (length == 0xffffffff)
2787                                 return new CustomAttributeArgument (type, null);
2788
2789                         if (length == 0)
2790                                 return new CustomAttributeArgument (type, Empty<CustomAttributeArgument>.Array);
2791
2792                         var arguments = new CustomAttributeArgument [length];
2793                         var element_type = type.ElementType;
2794
2795                         for (int i = 0; i < length; i++)
2796                                 arguments [i] = ReadCustomAttributeElement (element_type);
2797
2798                         return new CustomAttributeArgument (type, arguments);
2799                 }
2800
2801                 CustomAttributeArgument ReadCustomAttributeElement (TypeReference type)
2802                 {
2803                         if (type.IsArray)
2804                                 return ReadCustomAttributeFixedArrayArgument ((ArrayType) type);
2805
2806                         if (type.etype == ElementType.Object)
2807                                 return ReadCustomAttributeElement (ReadCustomAttributeFieldOrPropType ());
2808
2809                         return new CustomAttributeArgument (type, ReadCustomAttributeElementValue (type));
2810                 }
2811
2812                 object ReadCustomAttributeElementValue (TypeReference type)
2813                 {
2814                         var etype = type.etype;
2815
2816                         switch (etype) {
2817                         case ElementType.String:
2818                                 return ReadUTF8String ();
2819                         case ElementType.None:
2820                                 if (type.IsTypeOf ("System", "Type"))
2821                                         return ReadTypeReference ();
2822
2823                                 return ReadCustomAttributeEnum (type);
2824                         default:
2825                                 return ReadPrimitiveValue (etype);
2826                         }
2827                 }
2828
2829                 object ReadPrimitiveValue (ElementType type)
2830                 {
2831                         switch (type) {
2832                         case ElementType.Boolean:
2833                                 return ReadByte () == 1;
2834                         case ElementType.I1:
2835                                 return (sbyte) ReadByte ();
2836                         case ElementType.U1:
2837                                 return ReadByte ();
2838                         case ElementType.Char:
2839                                 return (char) ReadUInt16 ();
2840                         case ElementType.I2:
2841                                 return ReadInt16 ();
2842                         case ElementType.U2:
2843                                 return ReadUInt16 ();
2844                         case ElementType.I4:
2845                                 return ReadInt32 ();
2846                         case ElementType.U4:
2847                                 return ReadUInt32 ();
2848                         case ElementType.I8:
2849                                 return ReadInt64 ();
2850                         case ElementType.U8:
2851                                 return ReadUInt64 ();
2852                         case ElementType.R4:
2853                                 return ReadSingle ();
2854                         case ElementType.R8:
2855                                 return ReadDouble ();
2856                         default:
2857                                 throw new NotImplementedException (type.ToString ());
2858                         }
2859                 }
2860
2861                 TypeReference GetPrimitiveType (ElementType etype)
2862                 {
2863                         switch (etype) {
2864                         case ElementType.Boolean:
2865                                 return TypeSystem.Boolean;
2866                         case ElementType.Char:
2867                                 return TypeSystem.Char;
2868                         case ElementType.I1:
2869                                 return TypeSystem.SByte;
2870                         case ElementType.U1:
2871                                 return TypeSystem.Byte;
2872                         case ElementType.I2:
2873                                 return TypeSystem.Int16;
2874                         case ElementType.U2:
2875                                 return TypeSystem.UInt16;
2876                         case ElementType.I4:
2877                                 return TypeSystem.Int32;
2878                         case ElementType.U4:
2879                                 return TypeSystem.UInt32;
2880                         case ElementType.I8:
2881                                 return TypeSystem.Int64;
2882                         case ElementType.U8:
2883                                 return TypeSystem.UInt64;
2884                         case ElementType.R4:
2885                                 return TypeSystem.Single;
2886                         case ElementType.R8:
2887                                 return TypeSystem.Double;
2888                         case ElementType.String:
2889                                 return TypeSystem.String;
2890                         default:
2891                                 throw new NotImplementedException (etype.ToString ());
2892                         }
2893                 }
2894
2895                 TypeReference ReadCustomAttributeFieldOrPropType ()
2896                 {
2897                         var etype = (ElementType) ReadByte ();
2898
2899                         switch (etype) {
2900                         case ElementType.Boxed:
2901                                 return TypeSystem.Object;
2902                         case ElementType.SzArray:
2903                                 return new ArrayType (ReadCustomAttributeFieldOrPropType ());
2904                         case ElementType.Enum:
2905                                 return ReadTypeReference ();
2906                         case ElementType.Type:
2907                                 return TypeSystem.LookupType ("System", "Type");
2908                         default:
2909                                 return GetPrimitiveType (etype);
2910                         }
2911                 }
2912
2913                 public TypeReference ReadTypeReference ()
2914                 {
2915                         return TypeParser.ParseType (reader.module, ReadUTF8String ());
2916                 }
2917
2918                 object ReadCustomAttributeEnum (TypeReference enum_type)
2919                 {
2920                         var type = enum_type.CheckedResolve ();
2921                         if (!type.IsEnum)
2922                                 throw new ArgumentException ();
2923
2924                         return ReadCustomAttributeElementValue (type.GetEnumUnderlyingType ());
2925                 }
2926
2927                 public SecurityAttribute ReadSecurityAttribute ()
2928                 {
2929                         var attribute = new SecurityAttribute (ReadTypeReference ());
2930
2931                         ReadCompressedUInt32 ();
2932
2933                         ReadCustomAttributeNamedArguments (
2934                                 (ushort) ReadCompressedUInt32 (),
2935                                 ref attribute.fields,
2936                                 ref attribute.properties);
2937
2938                         return attribute;
2939                 }
2940
2941                 public MarshalInfo ReadMarshalInfo ()
2942                 {
2943                         var native = ReadNativeType ();
2944                         switch (native) {
2945                         case NativeType.Array: {
2946                                 var array = new ArrayMarshalInfo ();
2947                                 if (CanReadMore ())
2948                                         array.element_type = ReadNativeType ();
2949                                 if (CanReadMore ())
2950                                         array.size_parameter_index = (int) ReadCompressedUInt32 ();
2951                                 if (CanReadMore ())
2952                                         array.size = (int) ReadCompressedUInt32 ();
2953                                 if (CanReadMore ())
2954                                         array.size_parameter_multiplier = (int) ReadCompressedUInt32 ();
2955                                 return array;
2956                         }
2957                         case NativeType.SafeArray: {
2958                                 var array = new SafeArrayMarshalInfo ();
2959                                 if (CanReadMore ())
2960                                         array.element_type = ReadVariantType ();
2961                                 return array;
2962                         }
2963                         case NativeType.FixedArray: {
2964                                 var array = new FixedArrayMarshalInfo ();
2965                                 if (CanReadMore ())
2966                                         array.size = (int) ReadCompressedUInt32 ();
2967                                 if (CanReadMore ())
2968                                         array.element_type = ReadNativeType ();
2969                                 return array;
2970                         }
2971                         case NativeType.FixedSysString: {
2972                                 var sys_string = new FixedSysStringMarshalInfo ();
2973                                 if (CanReadMore ())
2974                                         sys_string.size = (int) ReadCompressedUInt32 ();
2975                                 return sys_string;
2976                         }
2977                         case NativeType.CustomMarshaler: {
2978                                 var marshaler = new CustomMarshalInfo ();
2979                                 var guid_value = ReadUTF8String ();
2980                                 marshaler.guid = !string.IsNullOrEmpty (guid_value) ? new Guid (guid_value) : Guid.Empty;
2981                                 marshaler.unmanaged_type = ReadUTF8String ();
2982                                 marshaler.managed_type = ReadTypeReference ();
2983                                 marshaler.cookie = ReadUTF8String ();
2984                                 return marshaler;
2985                         }
2986                         default:
2987                                 return new MarshalInfo (native);
2988                         }
2989                 }
2990
2991                 NativeType ReadNativeType ()
2992                 {
2993                         return (NativeType) ReadByte ();
2994                 }
2995
2996                 VariantType ReadVariantType ()
2997                 {
2998                         return (VariantType) ReadByte ();
2999                 }
3000
3001                 string ReadUTF8String ()
3002                 {
3003                         if (buffer [position] == 0xff) {
3004                                 position++;
3005                                 return null;
3006                         }
3007
3008                         var length = (int) ReadCompressedUInt32 ();
3009                         if (length == 0)
3010                                 return string.Empty;
3011
3012                         var @string = Encoding.UTF8.GetString (buffer, position,
3013                                 buffer [position + length - 1] == 0 ? length - 1 : length);
3014
3015                         position += length;
3016                         return @string;
3017                 }
3018
3019                 public bool CanReadMore ()
3020                 {
3021                         return position - start < sig_length;
3022                 }
3023         }
3024 }