57c3c15a8e2d59dc2a50ee47091a76f74ad7a62b
[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                         call_site.MetadataToken = token;
1888
1889                         return call_site;
1890                 }
1891
1892                 public VariableDefinitionCollection ReadVariables (MetadataToken local_var_token)
1893                 {
1894                         if (!MoveTo (Table.StandAloneSig, local_var_token.RID))
1895                                 return null;
1896
1897                         var reader = ReadSignature (ReadBlobIndex ());
1898                         const byte local_sig = 0x7;
1899
1900                         if (reader.ReadByte () != local_sig)
1901                                 throw new NotSupportedException ();
1902
1903                         var count = reader.ReadCompressedUInt32 ();
1904                         if (count == 0)
1905                                 return null;
1906
1907                         var variables = new VariableDefinitionCollection ((int) count);
1908
1909                         for (int i = 0; i < count; i++)
1910                                 variables.Add (new VariableDefinition (reader.ReadTypeSignature ()));
1911
1912                         return variables;
1913                 }
1914
1915                 public IMetadataTokenProvider LookupToken (MetadataToken token)
1916                 {
1917                         var rid = token.RID;
1918
1919                         if (rid == 0)
1920                                 return null;
1921
1922                         IMetadataTokenProvider element;
1923                         var position = this.position;
1924                         var context = this.context;
1925
1926                         switch (token.TokenType) {
1927                         case TokenType.TypeDef:
1928                                 element = GetTypeDefinition (rid);
1929                                 break;
1930                         case TokenType.TypeRef:
1931                                 element = GetTypeReference (rid);
1932                                 break;
1933                         case TokenType.TypeSpec:
1934                                 element = GetTypeSpecification (rid);
1935                                 break;
1936                         case TokenType.Field:
1937                                 element = GetFieldDefinition (rid);
1938                                 break;
1939                         case TokenType.Method:
1940                                 element = GetMethodDefinition (rid);
1941                                 break;
1942                         case TokenType.MemberRef:
1943                                 element = GetMemberReference (rid);
1944                                 break;
1945                         case TokenType.MethodSpec:
1946                                 element = GetMethodSpecification (rid);
1947                                 break;
1948                         default:
1949                                 return null;
1950                         }
1951
1952                         this.position = position;
1953                         this.context = context;
1954
1955                         return element;
1956                 }
1957
1958                 public FieldDefinition GetFieldDefinition (uint rid)
1959                 {
1960                         InitializeTypeDefinitions ();
1961
1962                         var field = metadata.GetFieldDefinition (rid);
1963                         if (field != null)
1964                                 return field;
1965
1966                         return LookupField (rid);
1967                 }
1968
1969                 FieldDefinition LookupField (uint rid)
1970                 {
1971                         var type = metadata.GetFieldDeclaringType (rid);
1972                         if (type == null)
1973                                 return null;
1974
1975                         InitializeCollection (type.Fields);
1976
1977                         return metadata.GetFieldDefinition (rid);
1978                 }
1979
1980                 public MethodDefinition GetMethodDefinition (uint rid)
1981                 {
1982                         InitializeTypeDefinitions ();
1983
1984                         var method = metadata.GetMethodDefinition (rid);
1985                         if (method != null)
1986                                 return method;
1987
1988                         return LookupMethod (rid);
1989                 }
1990
1991                 MethodDefinition LookupMethod (uint rid)
1992                 {
1993                         var type = metadata.GetMethodDeclaringType (rid);
1994                         if (type == null)
1995                                 return null;
1996
1997                         InitializeCollection (type.Methods);
1998
1999                         return metadata.GetMethodDefinition (rid);
2000                 }
2001
2002                 MethodSpecification GetMethodSpecification (uint rid)
2003                 {
2004                         if (!MoveTo (Table.MethodSpec, rid))
2005                                 return null;
2006
2007                         var element_method = (MethodReference) LookupToken (
2008                                 ReadMetadataToken (CodedIndex.MethodDefOrRef));
2009                         var signature = ReadBlobIndex ();
2010
2011                         var method_spec = ReadMethodSpecSignature (signature, element_method);
2012                         method_spec.token = new MetadataToken (TokenType.MethodSpec, rid);
2013                         return method_spec;
2014                 }
2015
2016                 MethodSpecification ReadMethodSpecSignature (uint signature, MethodReference method)
2017                 {
2018                         var reader = ReadSignature (signature);
2019                         const byte methodspec_sig = 0x0a;
2020
2021                         var call_conv = reader.ReadByte ();
2022
2023                         if (call_conv != methodspec_sig)
2024                                 throw new NotSupportedException ();
2025
2026                         var instance = new GenericInstanceMethod (method);
2027
2028                         reader.ReadGenericInstanceSignature (method, instance);
2029
2030                         return instance;
2031                 }
2032
2033                 MemberReference GetMemberReference (uint rid)
2034                 {
2035                         InitializeMemberReferences ();
2036
2037                         var member = metadata.GetMemberReference (rid);
2038                         if (member != null)
2039                                 return member;
2040
2041                         member = ReadMemberReference (rid);
2042                         if (member != null && !member.ContainsGenericParameter)
2043                                 metadata.AddMemberReference (member);
2044                         return member;
2045                 }
2046
2047                 MemberReference ReadMemberReference (uint rid)
2048                 {
2049                         if (!MoveTo (Table.MemberRef, rid))
2050                                 return null;
2051
2052                         var token = ReadMetadataToken (CodedIndex.MemberRefParent);
2053                         var name = ReadString ();
2054                         var signature = ReadBlobIndex ();
2055
2056                         MemberReference member;
2057
2058                         switch (token.TokenType) {
2059                         case TokenType.TypeDef:
2060                         case TokenType.TypeRef:
2061                         case TokenType.TypeSpec:
2062                                 member = ReadTypeMemberReference (token, name, signature);
2063                                 break;
2064                         case TokenType.Method:
2065                                 member = ReadMethodMemberReference (token, name, signature);
2066                                 break;
2067                         default:
2068                                 throw new NotSupportedException ();
2069                         }
2070
2071                         member.token = new MetadataToken (TokenType.MemberRef, rid);
2072
2073                         return member;
2074                 }
2075
2076                 MemberReference ReadTypeMemberReference (MetadataToken type, string name, uint signature)
2077                 {
2078                         var declaring_type = GetTypeDefOrRef (type);
2079
2080                         this.context = declaring_type;
2081
2082                         var member = ReadMemberReferenceSignature (signature, declaring_type);
2083                         member.Name = name;
2084
2085                         return member;
2086                 }
2087
2088                 MemberReference ReadMemberReferenceSignature (uint signature, TypeReference declaring_type)
2089                 {
2090                         var reader = ReadSignature (signature);
2091                         const byte field_sig = 0x6;
2092
2093                         if (reader.buffer [reader.position] == field_sig) {
2094                                 reader.position++;
2095                                 var field = new FieldReference ();
2096                                 field.DeclaringType = declaring_type;
2097                                 field.FieldType = reader.ReadTypeSignature ();
2098                                 return field;
2099                         } else {
2100                                 var method = new MethodReference ();
2101                                 method.DeclaringType = declaring_type;
2102                                 reader.ReadMethodSignature (method);
2103                                 return method;
2104                         }
2105                 }
2106
2107                 MemberReference ReadMethodMemberReference (MetadataToken token, string name, uint signature)
2108                 {
2109                         var method = GetMethodDefinition (token.RID);
2110
2111                         this.context = method;
2112
2113                         var member = ReadMemberReferenceSignature (signature, method.DeclaringType);
2114                         member.Name = name;
2115
2116                         return member;
2117                 }
2118
2119                 void InitializeMemberReferences ()
2120                 {
2121                         if (metadata.MemberReferences != null)
2122                                 return;
2123
2124                         metadata.MemberReferences = new MemberReference [image.GetTableLength (Table.MemberRef)];
2125                 }
2126
2127                 public IEnumerable<MemberReference> GetMemberReferences ()
2128                 {
2129                         InitializeMemberReferences ();
2130
2131                         var length = image.GetTableLength (Table.MemberRef);
2132
2133                         var type_system = module.TypeSystem;
2134
2135                         var context = new MethodReference (string.Empty, type_system.Void);
2136                         context.DeclaringType = new TypeReference (string.Empty, string.Empty, module, type_system.Corlib);
2137
2138                         var member_references = new MemberReference [length];
2139
2140                         for (uint i = 1; i <= length; i++) {
2141                                 this.context = context;
2142                                 member_references [i - 1] = GetMemberReference (i);
2143                         }
2144
2145                         return member_references;
2146                 }
2147
2148                 void InitializeConstants ()
2149                 {
2150                         if (metadata.Constants != null)
2151                                 return;
2152
2153                         var length = MoveTo (Table.Constant);
2154
2155                         var constants = metadata.Constants = new Dictionary<MetadataToken, Row<ElementType, uint>> (length);
2156
2157                         for (uint i = 1; i <= length; i++) {
2158                                 var type = (ElementType) ReadUInt16 ();
2159                                 var owner = ReadMetadataToken (CodedIndex.HasConstant);
2160                                 var signature = ReadBlobIndex ();
2161
2162                                 constants.Add (owner, new Row<ElementType, uint> (type, signature));
2163                         }
2164                 }
2165
2166                 public object ReadConstant (IConstantProvider owner)
2167                 {
2168                         InitializeConstants ();
2169
2170                         Row<ElementType, uint> row;
2171                         if (!metadata.Constants.TryGetValue (owner.MetadataToken, out row))
2172                                 return Mixin.NoValue;
2173
2174                         metadata.Constants.Remove (owner.MetadataToken);
2175
2176                         switch (row.Col1) {
2177                         case ElementType.Class:
2178                         case ElementType.Object:
2179                                 return null;
2180                         case ElementType.String:
2181                                 return ReadConstantString (ReadBlob (row.Col2));
2182                         default:
2183                                 return ReadConstantPrimitive (row.Col1, row.Col2);
2184                         }
2185                 }
2186
2187                 static string ReadConstantString (byte [] blob)
2188                 {
2189                         var length = blob.Length;
2190                         if ((length & 1) == 1)
2191                                 length--;
2192
2193                         return Encoding.Unicode.GetString (blob, 0, length);
2194                 }
2195
2196                 object ReadConstantPrimitive (ElementType type, uint signature)
2197                 {
2198                         var reader = ReadSignature (signature);
2199                         return reader.ReadConstantSignature (type);
2200                 }
2201
2202                 void InitializeCustomAttributes ()
2203                 {
2204                         if (metadata.CustomAttributes != null)
2205                                 return;
2206
2207                         metadata.CustomAttributes = InitializeRanges (
2208                                 Table.CustomAttribute, () => {
2209                                         var next = ReadMetadataToken (CodedIndex.HasCustomAttribute);
2210                                         ReadMetadataToken (CodedIndex.CustomAttributeType);
2211                                         ReadBlobIndex ();
2212                                         return next;
2213                         });
2214                 }
2215
2216                 public bool HasCustomAttributes (ICustomAttributeProvider owner)
2217                 {
2218                         InitializeCustomAttributes ();
2219
2220                         Range range;
2221                         if (!metadata.TryGetCustomAttributeRange (owner, out range))
2222                                 return false;
2223
2224                         return range.Length > 0;
2225                 }
2226
2227                 public Collection<CustomAttribute> ReadCustomAttributes (ICustomAttributeProvider owner)
2228                 {
2229                         InitializeCustomAttributes ();
2230
2231                         Range range;
2232                         if (!metadata.TryGetCustomAttributeRange (owner, out range)
2233                                 || !MoveTo (Table.CustomAttribute, range.Start))
2234                                 return new Collection<CustomAttribute> ();
2235
2236                         var custom_attributes = new Collection<CustomAttribute> ((int) range.Length);
2237
2238                         for (int i = 0; i < range.Length; i++) {
2239                                 ReadMetadataToken (CodedIndex.HasCustomAttribute);
2240
2241                                 var constructor = (MethodReference) LookupToken (
2242                                         ReadMetadataToken (CodedIndex.CustomAttributeType));
2243
2244                                 var signature = ReadBlobIndex ();
2245
2246                                 custom_attributes.Add (new CustomAttribute (signature, constructor));
2247                         }
2248
2249                         metadata.RemoveCustomAttributeRange (owner);
2250
2251                         return custom_attributes;
2252                 }
2253
2254                 public byte [] ReadCustomAttributeBlob (uint signature)
2255                 {
2256                         return ReadBlob (signature);
2257                 }
2258
2259                 public void ReadCustomAttributeSignature (CustomAttribute attribute)
2260                 {
2261                         var reader = ReadSignature (attribute.signature);
2262                         if (reader.ReadUInt16 () != 0x0001)
2263                             throw new InvalidOperationException ();
2264
2265                         var constructor = attribute.Constructor;
2266                         if (constructor.HasParameters)
2267                                 reader.ReadCustomAttributeConstructorArguments (attribute, constructor.Parameters);
2268
2269                         if (!reader.CanReadMore ())
2270                                 return;
2271
2272                         var named = reader.ReadUInt16 ();
2273
2274                         if (named == 0)
2275                                 return;
2276
2277                         reader.ReadCustomAttributeNamedArguments (named, ref attribute.fields, ref attribute.properties);
2278                 }
2279
2280                 void InitializeMarshalInfos ()
2281                 {
2282                         if (metadata.FieldMarshals != null)
2283                                 return;
2284
2285                         var length = MoveTo (Table.FieldMarshal);
2286
2287                         var marshals = metadata.FieldMarshals = new Dictionary<MetadataToken, uint> (length);
2288
2289                         for (int i = 0; i < length; i++) {
2290                                 var token = ReadMetadataToken (CodedIndex.HasFieldMarshal);
2291                                 var signature = ReadBlobIndex ();
2292                                 if (token.RID == 0)
2293                                         continue;
2294
2295                                 marshals.Add (token, signature);
2296                         }
2297                 }
2298
2299                 public bool HasMarshalInfo (IMarshalInfoProvider owner)
2300                 {
2301                         InitializeMarshalInfos ();
2302
2303                         return metadata.FieldMarshals.ContainsKey (owner.MetadataToken);
2304                 }
2305
2306                 public MarshalInfo ReadMarshalInfo (IMarshalInfoProvider owner)
2307                 {
2308                         InitializeMarshalInfos ();
2309
2310                         uint signature;
2311                         if (!metadata.FieldMarshals.TryGetValue (owner.MetadataToken, out signature))
2312                                 return null;
2313
2314                         var reader = ReadSignature (signature);
2315
2316                         metadata.FieldMarshals.Remove (owner.MetadataToken);
2317
2318                         return reader.ReadMarshalInfo ();
2319                 }
2320
2321                 void InitializeSecurityDeclarations ()
2322                 {
2323                         if (metadata.SecurityDeclarations != null)
2324                                 return;
2325
2326                         metadata.SecurityDeclarations = InitializeRanges (
2327                                 Table.DeclSecurity, () => {
2328                                         ReadUInt16 ();
2329                                         var next = ReadMetadataToken (CodedIndex.HasDeclSecurity);
2330                                         ReadBlobIndex ();
2331                                         return next;
2332                         });
2333                 }
2334
2335                 public bool HasSecurityDeclarations (ISecurityDeclarationProvider owner)
2336                 {
2337                         InitializeSecurityDeclarations ();
2338
2339                         Range range;
2340                         if (!metadata.TryGetSecurityDeclarationRange (owner, out range))
2341                                 return false;
2342
2343                         return range.Length > 0;
2344                 }
2345
2346                 public Collection<SecurityDeclaration> ReadSecurityDeclarations (ISecurityDeclarationProvider owner)
2347                 {
2348                         InitializeSecurityDeclarations ();
2349
2350                         Range range;
2351                         if (!metadata.TryGetSecurityDeclarationRange (owner, out range)
2352                                 || !MoveTo (Table.DeclSecurity, range.Start))
2353                                 return new Collection<SecurityDeclaration> ();
2354
2355                         var security_declarations = new Collection<SecurityDeclaration> ((int) range.Length);
2356
2357                         for (int i = 0; i < range.Length; i++) {
2358                                 var action = (SecurityAction) ReadUInt16 ();
2359                                 ReadMetadataToken (CodedIndex.HasDeclSecurity);
2360                                 var signature = ReadBlobIndex ();
2361
2362                                 security_declarations.Add (new SecurityDeclaration (action, signature, module));
2363                         }
2364
2365                         metadata.RemoveSecurityDeclarationRange (owner);
2366
2367                         return security_declarations;
2368                 }
2369
2370                 public byte [] ReadSecurityDeclarationBlob (uint signature)
2371                 {
2372                         return ReadBlob (signature);
2373                 }
2374
2375                 public void ReadSecurityDeclarationSignature (SecurityDeclaration declaration)
2376                 {
2377                         var signature = declaration.signature;
2378                         var reader = ReadSignature (signature);
2379
2380                         if (reader.buffer [reader.position] != '.') {
2381                                 ReadXmlSecurityDeclaration (signature, declaration);
2382                                 return;
2383                         }
2384
2385                         reader.ReadByte ();
2386                         var count = reader.ReadCompressedUInt32 ();
2387                         var attributes = new Collection<SecurityAttribute> ((int) count);
2388
2389                         for (int i = 0; i < count; i++)
2390                                 attributes.Add (reader.ReadSecurityAttribute ());
2391
2392                         declaration.security_attributes = attributes;
2393                 }
2394
2395                 void ReadXmlSecurityDeclaration (uint signature, SecurityDeclaration declaration)
2396                 {
2397                         var blob = ReadBlob (signature);
2398                         var attributes = new Collection<SecurityAttribute> (1);
2399
2400                         var attribute = new SecurityAttribute (
2401                                 module.TypeSystem.LookupType ("System.Security.Permissions", "PermissionSetAttribute"));
2402
2403                         attribute.properties = new Collection<CustomAttributeNamedArgument> (1);
2404                         attribute.properties.Add (
2405                                 new CustomAttributeNamedArgument (
2406                                         "XML",
2407                                         new CustomAttributeArgument (
2408                                                 module.TypeSystem.String,
2409                                                 Encoding.Unicode.GetString (blob, 0, blob.Length))));
2410
2411                         attributes.Add (attribute);
2412
2413                         declaration.security_attributes = attributes;
2414                 }
2415
2416                 public Collection<ExportedType> ReadExportedTypes ()
2417                 {
2418                         var length = MoveTo (Table.ExportedType);
2419                         if (length == 0)
2420                                 return new Collection<ExportedType> ();
2421
2422                         var exported_types = new Collection<ExportedType> (length);
2423
2424                         for (int i = 1; i <= length; i++) {
2425                                 var attributes = (TypeAttributes) ReadUInt32 ();
2426                                 var identifier = ReadUInt32 ();
2427                                 var name = ReadString ();
2428                                 var @namespace = ReadString ();
2429                                 var implementation = ReadMetadataToken (CodedIndex.Implementation);
2430
2431                                 ExportedType declaring_type = null;
2432                                 IMetadataScope scope = null;
2433
2434                                 switch (implementation.TokenType) {
2435                                 case TokenType.AssemblyRef:
2436                                 case TokenType.File:
2437                                         scope = GetExportedTypeScope (implementation);
2438                                         break;
2439                                 case TokenType.ExportedType:
2440                                         // FIXME: if the table is not properly sorted
2441                                         declaring_type = exported_types [(int) implementation.RID - 1];
2442                                         break;
2443                                 }
2444
2445                                 var exported_type = new ExportedType (@namespace, name, scope) {
2446                                         Attributes = attributes,
2447                                         Identifier = (int) identifier,
2448                                         DeclaringType = declaring_type,
2449                                 };
2450                                 exported_type.token = new MetadataToken (TokenType.ExportedType, i);
2451
2452                                 exported_types.Add (exported_type);
2453                         }
2454
2455                         return exported_types;
2456                 }
2457
2458                 IMetadataScope GetExportedTypeScope (MetadataToken token)
2459                 {
2460                         switch (token.TokenType) {
2461                         case TokenType.AssemblyRef:
2462                                 return module.AssemblyReferences [(int) token.RID - 1];
2463                         case TokenType.File:
2464                                 var position = this.position;
2465                                 var reference = GetModuleReferenceFromFile (token);
2466                                 this.position = position;
2467
2468                                 if (reference == null)
2469                                         throw new NotSupportedException ();
2470
2471                                 return reference;
2472                         default:
2473                                 throw new NotSupportedException ();
2474                         }
2475                 }
2476
2477                 ModuleReference GetModuleReferenceFromFile (MetadataToken token)
2478                 {
2479                         if (!MoveTo (Table.File, token.RID))
2480                                 return null;
2481
2482                         ReadUInt32 ();
2483                         var file_name = ReadString ();
2484                         var modules = module.ModuleReferences;
2485
2486                         ModuleReference reference = null;
2487                         for (int i = 0; i < modules.Count; i++) {
2488                                 var module_reference = modules [i];
2489                                 if (module_reference.Name != file_name)
2490                                         continue;
2491
2492                                 reference = module_reference;
2493                                 break;
2494                         }
2495
2496                         return reference;
2497                 }
2498
2499                 static void InitializeCollection (object o)
2500                 {
2501                 }
2502         }
2503
2504         sealed class SignatureReader : ByteBuffer {
2505
2506                 readonly MetadataReader reader;
2507                 readonly uint start, sig_length;
2508
2509                 TypeSystem TypeSystem {
2510                         get { return reader.module.TypeSystem; }
2511                 }
2512
2513                 public SignatureReader (uint blob, MetadataReader reader)
2514                         : base (reader.buffer)
2515                 {
2516                         this.reader = reader;
2517
2518                         MoveToBlob (blob);
2519
2520                         this.sig_length = ReadCompressedUInt32 ();
2521                         this.start = (uint) position;
2522                 }
2523
2524                 void MoveToBlob (uint blob)
2525                 {
2526                         position = (int) (reader.image.BlobHeap.Offset + blob);
2527                 }
2528
2529                 MetadataToken ReadTypeTokenSignature ()
2530                 {
2531                         return CodedIndex.TypeDefOrRef.GetMetadataToken (ReadCompressedUInt32 ());
2532                 }
2533
2534                 GenericParameter GetGenericParameter (GenericParameterType type, uint var)
2535                 {
2536                         var context = reader.context;
2537
2538                         if (context == null)
2539                                 throw new NotSupportedException ();
2540
2541                         IGenericParameterProvider provider;
2542
2543                         switch (type) {
2544                         case GenericParameterType.Type:
2545                                 provider = context.Type;
2546                                 break;
2547                         case GenericParameterType.Method:
2548                                 provider = context.Method;
2549                                 break;
2550                         default:
2551                                 throw new NotSupportedException ();
2552                         }
2553
2554                         int index = (int) var;
2555
2556                         if (!context.IsDefinition)
2557                                 CheckGenericContext (provider, index);
2558
2559                         return provider.GenericParameters [index];
2560                 }
2561
2562                 static void CheckGenericContext (IGenericParameterProvider owner, int index)
2563                 {
2564                         var owner_parameters = owner.GenericParameters;
2565
2566                         for (int i = owner_parameters.Count; i <= index; i++)
2567                                 owner_parameters.Add (new GenericParameter (owner));
2568                 }
2569
2570                 public void ReadGenericInstanceSignature (IGenericParameterProvider provider, IGenericInstance instance)
2571                 {
2572                         var arity = ReadCompressedUInt32 ();
2573
2574                         if (!provider.IsDefinition)
2575                                 CheckGenericContext (provider, (int) arity - 1);
2576
2577                         var instance_arguments = instance.GenericArguments;
2578
2579                         for (int i = 0; i < arity; i++)
2580                                 instance_arguments.Add (ReadTypeSignature ());
2581                 }
2582
2583                 ArrayType ReadArrayTypeSignature ()
2584                 {
2585                         var array = new ArrayType (ReadTypeSignature ());
2586
2587                         var rank = ReadCompressedUInt32 ();
2588
2589                         var sizes = new uint [ReadCompressedUInt32 ()];
2590                         for (int i = 0; i < sizes.Length; i++)
2591                                 sizes [i] = ReadCompressedUInt32 ();
2592
2593                         var low_bounds = new int [ReadCompressedUInt32 ()];
2594                         for (int i = 0; i < low_bounds.Length; i++)
2595                                 low_bounds [i] = ReadCompressedInt32 ();
2596
2597                         array.Dimensions.Clear ();
2598
2599                         for (int i = 0; i < rank; i++) {
2600                                 int? lower = null, upper = null;
2601
2602                                 if (i < low_bounds.Length)
2603                                         lower = low_bounds [i];
2604
2605                                 if (i < sizes.Length)
2606                                         upper = lower + (int) sizes [i] - 1;
2607
2608                                 array.Dimensions.Add (new ArrayDimension (lower, upper));
2609                         }
2610
2611                         return array;
2612                 }
2613
2614                 TypeReference GetTypeDefOrRef (MetadataToken token)
2615                 {
2616                         return reader.GetTypeDefOrRef (token);
2617                 }
2618
2619                 public TypeReference ReadTypeSignature ()
2620                 {
2621                         return ReadTypeSignature ((ElementType) ReadByte ());
2622                 }
2623
2624                 TypeReference ReadTypeSignature (ElementType etype)
2625                 {
2626                         switch (etype) {
2627                         case ElementType.ValueType: {
2628                                 var value_type = GetTypeDefOrRef (ReadTypeTokenSignature ());
2629                                 value_type.IsValueType = true;
2630                                 return value_type;
2631                         }
2632                         case ElementType.Class:
2633                                 return GetTypeDefOrRef (ReadTypeTokenSignature ());
2634                         case ElementType.Ptr:
2635                                 return new PointerType (ReadTypeSignature ());
2636                         case ElementType.FnPtr: {
2637                                 var fptr = new FunctionPointerType ();
2638                                 ReadMethodSignature (fptr);
2639                                 return fptr;
2640                         }
2641                         case ElementType.ByRef:
2642                                 return new ByReferenceType (ReadTypeSignature ());
2643                         case ElementType.Pinned:
2644                                 return new PinnedType (ReadTypeSignature ());
2645                         case ElementType.SzArray:
2646                                 return new ArrayType (ReadTypeSignature ());
2647                         case ElementType.Array:
2648                                 return ReadArrayTypeSignature ();
2649                         case ElementType.CModOpt:
2650                                 return new OptionalModifierType (
2651                                         GetTypeDefOrRef (ReadTypeTokenSignature ()), ReadTypeSignature ());
2652                         case ElementType.CModReqD:
2653                                 return new RequiredModifierType (
2654                                         GetTypeDefOrRef (ReadTypeTokenSignature ()), ReadTypeSignature ());
2655                         case ElementType.Sentinel:
2656                                 return new SentinelType (ReadTypeSignature ());
2657                         case ElementType.Var:
2658                                 return GetGenericParameter (GenericParameterType.Type, ReadCompressedUInt32 ());
2659                         case ElementType.MVar:
2660                                 return GetGenericParameter (GenericParameterType.Method, ReadCompressedUInt32 ());
2661                         case ElementType.GenericInst: {
2662                                 var is_value_type = ReadByte () == (byte) ElementType.ValueType;
2663                                 var element_type = GetTypeDefOrRef (ReadTypeTokenSignature ());
2664                                 var generic_instance = new GenericInstanceType (element_type);
2665
2666                                 ReadGenericInstanceSignature (element_type, generic_instance);
2667
2668                                 if (is_value_type) {
2669                                         generic_instance.IsValueType = true;
2670                                         element_type.GetElementType ().IsValueType = true;
2671                                 }
2672
2673                                 return generic_instance;
2674                         }
2675                         case ElementType.Object: return TypeSystem.Object;
2676                         case ElementType.Void: return TypeSystem.Void;
2677                         case ElementType.TypedByRef: return TypeSystem.TypedReference;
2678                         case ElementType.I: return TypeSystem.IntPtr;
2679                         case ElementType.U: return TypeSystem.UIntPtr;
2680                         default: return GetPrimitiveType (etype);
2681                         }
2682                 }
2683
2684                 public void ReadMethodSignature (IMethodSignature method)
2685                 {
2686                         var calling_convention = ReadByte ();
2687                         method.CallingConvention = (MethodCallingConvention) calling_convention;
2688                         method.HasThis = (calling_convention & 0x20) != 0;
2689                         method.ExplicitThis = (calling_convention & 0x40) != 0;
2690
2691                         var generic_context = method as MethodReference;
2692                         if (generic_context != null)
2693                                 reader.context = generic_context;
2694
2695                         if ((calling_convention & 0x10) != 0) {
2696                                 var arity = ReadCompressedUInt32 ();
2697
2698                                 if (generic_context != null && !generic_context.IsDefinition)
2699                                         CheckGenericContext (generic_context, (int) arity -1 );
2700                         }
2701
2702                         // TODO: more call_conv
2703
2704                         var param_count = ReadCompressedUInt32 ();
2705
2706                         method.MethodReturnType.ReturnType = ReadTypeSignature ();
2707
2708                         if (param_count == 0)
2709                                 return;
2710
2711                         Collection<ParameterDefinition> parameters;
2712
2713                         var method_ref = method as MethodReference;
2714                         if (method_ref != null)
2715                                 parameters = method_ref.parameters = new ParameterDefinitionCollection (method, (int) param_count);
2716                         else
2717                                 parameters = method.Parameters;
2718
2719                         for (int i = 0; i < param_count; i++)
2720                                 parameters.Add (new ParameterDefinition (ReadTypeSignature ()));
2721                 }
2722
2723                 public object ReadConstantSignature (ElementType type)
2724                 {
2725                         return ReadPrimitiveValue (type);
2726                 }
2727
2728                 public void ReadCustomAttributeConstructorArguments (CustomAttribute attribute, Collection<ParameterDefinition> parameters)
2729                 {
2730                         var count = parameters.Count;
2731                         if (count == 0)
2732                                 return;
2733
2734                         attribute.arguments = new Collection<CustomAttributeArgument> (count);
2735
2736                         for (int i = 0; i < count; i++)
2737                                 attribute.arguments.Add (
2738                                         ReadCustomAttributeFixedArgument (parameters [i].ParameterType));
2739                 }
2740
2741                 CustomAttributeArgument ReadCustomAttributeFixedArgument (TypeReference type)
2742                 {
2743                         if (type.IsArray)
2744                                 return ReadCustomAttributeFixedArrayArgument ((ArrayType) type);
2745
2746                         return ReadCustomAttributeElement (type);
2747                 }
2748
2749                 public void ReadCustomAttributeNamedArguments (ushort count, ref Collection<CustomAttributeNamedArgument> fields, ref Collection<CustomAttributeNamedArgument> properties)
2750                 {
2751                         for (int i = 0; i < count; i++)
2752                                 ReadCustomAttributeNamedArgument (ref fields, ref properties);
2753                 }
2754
2755                 void ReadCustomAttributeNamedArgument (ref Collection<CustomAttributeNamedArgument> fields, ref Collection<CustomAttributeNamedArgument> properties)
2756                 {
2757                         var kind = ReadByte ();
2758                         var type = ReadCustomAttributeFieldOrPropType ();
2759                         var name = ReadUTF8String ();
2760
2761                         Collection<CustomAttributeNamedArgument> container;
2762                         switch (kind) {
2763                         case 0x53:
2764                                 container = GetCustomAttributeNamedArgumentCollection (ref fields);
2765                                 break;
2766                         case 0x54:
2767                                 container = GetCustomAttributeNamedArgumentCollection (ref properties);
2768                                 break;
2769                         default:
2770                                 throw new NotSupportedException ();
2771                         }
2772
2773                         container.Add (new CustomAttributeNamedArgument (name, ReadCustomAttributeFixedArgument (type)));
2774                 }
2775
2776                 static Collection<CustomAttributeNamedArgument> GetCustomAttributeNamedArgumentCollection (ref Collection<CustomAttributeNamedArgument> collection)
2777                 {
2778                         if (collection != null)
2779                                 return collection;
2780
2781                         return collection = new Collection<CustomAttributeNamedArgument> ();
2782                 }
2783
2784                 CustomAttributeArgument ReadCustomAttributeFixedArrayArgument (ArrayType type)
2785                 {
2786                         var length = ReadUInt32 ();
2787
2788                         if (length == 0xffffffff)
2789                                 return new CustomAttributeArgument (type, null);
2790
2791                         if (length == 0)
2792                                 return new CustomAttributeArgument (type, Empty<CustomAttributeArgument>.Array);
2793
2794                         var arguments = new CustomAttributeArgument [length];
2795                         var element_type = type.ElementType;
2796
2797                         for (int i = 0; i < length; i++)
2798                                 arguments [i] = ReadCustomAttributeElement (element_type);
2799
2800                         return new CustomAttributeArgument (type, arguments);
2801                 }
2802
2803                 CustomAttributeArgument ReadCustomAttributeElement (TypeReference type)
2804                 {
2805                         if (type.IsArray)
2806                                 return ReadCustomAttributeFixedArrayArgument ((ArrayType) type);
2807
2808                         return new CustomAttributeArgument (
2809                                 type,
2810                                 type.etype == ElementType.Object
2811                                         ? ReadCustomAttributeElement (ReadCustomAttributeFieldOrPropType ())
2812                                         : ReadCustomAttributeElementValue (type));
2813                 }
2814
2815                 object ReadCustomAttributeElementValue (TypeReference type)
2816                 {
2817                         var etype = type.etype;
2818
2819                         switch (etype) {
2820                         case ElementType.String:
2821                                 return ReadUTF8String ();
2822                         case ElementType.None:
2823                                 if (type.IsTypeOf ("System", "Type"))
2824                                         return ReadTypeReference ();
2825
2826                                 return ReadCustomAttributeEnum (type);
2827                         default:
2828                                 return ReadPrimitiveValue (etype);
2829                         }
2830                 }
2831
2832                 object ReadPrimitiveValue (ElementType type)
2833                 {
2834                         switch (type) {
2835                         case ElementType.Boolean:
2836                                 return ReadByte () == 1;
2837                         case ElementType.I1:
2838                                 return (sbyte) ReadByte ();
2839                         case ElementType.U1:
2840                                 return ReadByte ();
2841                         case ElementType.Char:
2842                                 return (char) ReadUInt16 ();
2843                         case ElementType.I2:
2844                                 return ReadInt16 ();
2845                         case ElementType.U2:
2846                                 return ReadUInt16 ();
2847                         case ElementType.I4:
2848                                 return ReadInt32 ();
2849                         case ElementType.U4:
2850                                 return ReadUInt32 ();
2851                         case ElementType.I8:
2852                                 return ReadInt64 ();
2853                         case ElementType.U8:
2854                                 return ReadUInt64 ();
2855                         case ElementType.R4:
2856                                 return ReadSingle ();
2857                         case ElementType.R8:
2858                                 return ReadDouble ();
2859                         default:
2860                                 throw new NotImplementedException (type.ToString ());
2861                         }
2862                 }
2863
2864                 TypeReference GetPrimitiveType (ElementType etype)
2865                 {
2866                         switch (etype) {
2867                         case ElementType.Boolean:
2868                                 return TypeSystem.Boolean;
2869                         case ElementType.Char:
2870                                 return TypeSystem.Char;
2871                         case ElementType.I1:
2872                                 return TypeSystem.SByte;
2873                         case ElementType.U1:
2874                                 return TypeSystem.Byte;
2875                         case ElementType.I2:
2876                                 return TypeSystem.Int16;
2877                         case ElementType.U2:
2878                                 return TypeSystem.UInt16;
2879                         case ElementType.I4:
2880                                 return TypeSystem.Int32;
2881                         case ElementType.U4:
2882                                 return TypeSystem.UInt32;
2883                         case ElementType.I8:
2884                                 return TypeSystem.Int64;
2885                         case ElementType.U8:
2886                                 return TypeSystem.UInt64;
2887                         case ElementType.R4:
2888                                 return TypeSystem.Single;
2889                         case ElementType.R8:
2890                                 return TypeSystem.Double;
2891                         case ElementType.String:
2892                                 return TypeSystem.String;
2893                         default:
2894                                 throw new NotImplementedException (etype.ToString ());
2895                         }
2896                 }
2897
2898                 TypeReference ReadCustomAttributeFieldOrPropType ()
2899                 {
2900                         var etype = (ElementType) ReadByte ();
2901
2902                         switch (etype) {
2903                         case ElementType.Boxed:
2904                                 return TypeSystem.Object;
2905                         case ElementType.SzArray:
2906                                 return new ArrayType (ReadCustomAttributeFieldOrPropType ());
2907                         case ElementType.Enum:
2908                                 return ReadTypeReference ();
2909                         case ElementType.Type:
2910                                 return TypeSystem.LookupType ("System", "Type");
2911                         default:
2912                                 return GetPrimitiveType (etype);
2913                         }
2914                 }
2915
2916                 public TypeReference ReadTypeReference ()
2917                 {
2918                         return TypeParser.ParseType (reader.module, ReadUTF8String ());
2919                 }
2920
2921                 object ReadCustomAttributeEnum (TypeReference enum_type)
2922                 {
2923                         var type = enum_type.CheckedResolve ();
2924                         if (!type.IsEnum)
2925                                 throw new ArgumentException ();
2926
2927                         return ReadCustomAttributeElementValue (type.GetEnumUnderlyingType ());
2928                 }
2929
2930                 public SecurityAttribute ReadSecurityAttribute ()
2931                 {
2932                         var attribute = new SecurityAttribute (ReadTypeReference ());
2933
2934                         ReadCompressedUInt32 ();
2935
2936                         ReadCustomAttributeNamedArguments (
2937                                 (ushort) ReadCompressedUInt32 (),
2938                                 ref attribute.fields,
2939                                 ref attribute.properties);
2940
2941                         return attribute;
2942                 }
2943
2944                 public MarshalInfo ReadMarshalInfo ()
2945                 {
2946                         var native = ReadNativeType ();
2947                         switch (native) {
2948                         case NativeType.Array: {
2949                                 var array = new ArrayMarshalInfo ();
2950                                 if (CanReadMore ())
2951                                         array.element_type = ReadNativeType ();
2952                                 if (CanReadMore ())
2953                                         array.size_parameter_index = (int) ReadCompressedUInt32 ();
2954                                 if (CanReadMore ())
2955                                         array.size = (int) ReadCompressedUInt32 ();
2956                                 if (CanReadMore ())
2957                                         array.size_parameter_multiplier = (int) ReadCompressedUInt32 ();
2958                                 return array;
2959                         }
2960                         case NativeType.SafeArray: {
2961                                 var array = new SafeArrayMarshalInfo ();
2962                                 if (CanReadMore ())
2963                                         array.element_type = ReadVariantType ();
2964                                 return array;
2965                         }
2966                         case NativeType.FixedArray: {
2967                                 var array = new FixedArrayMarshalInfo ();
2968                                 if (CanReadMore ())
2969                                         array.size = (int) ReadCompressedUInt32 ();
2970                                 if (CanReadMore ())
2971                                         array.element_type = ReadNativeType ();
2972                                 return array;
2973                         }
2974                         case NativeType.FixedSysString: {
2975                                 var sys_string = new FixedSysStringMarshalInfo ();
2976                                 if (CanReadMore ())
2977                                         sys_string.size = (int) ReadCompressedUInt32 ();
2978                                 return sys_string;
2979                         }
2980                         case NativeType.CustomMarshaler: {
2981                                 var marshaler = new CustomMarshalInfo ();
2982                                 var guid_value = ReadUTF8String ();
2983                                 marshaler.guid = !string.IsNullOrEmpty (guid_value) ? new Guid (guid_value) : Guid.Empty;
2984                                 marshaler.unmanaged_type = ReadUTF8String ();
2985                                 marshaler.managed_type = ReadTypeReference ();
2986                                 marshaler.cookie = ReadUTF8String ();
2987                                 return marshaler;
2988                         }
2989                         default:
2990                                 return new MarshalInfo (native);
2991                         }
2992                 }
2993
2994                 NativeType ReadNativeType ()
2995                 {
2996                         return (NativeType) ReadByte ();
2997                 }
2998
2999                 VariantType ReadVariantType ()
3000                 {
3001                         return (VariantType) ReadByte ();
3002                 }
3003
3004                 string ReadUTF8String ()
3005                 {
3006                         if (buffer [position] == 0xff) {
3007                                 position++;
3008                                 return null;
3009                         }
3010
3011                         var length = (int) ReadCompressedUInt32 ();
3012                         if (length == 0)
3013                                 return string.Empty;
3014
3015                         var @string = Encoding.UTF8.GetString (buffer, position,
3016                                 buffer [position + length - 1] == 0 ? length - 1 : length);
3017
3018                         position += length;
3019                         return @string;
3020                 }
3021
3022                 public bool CanReadMore ()
3023                 {
3024                         return position - start < sig_length;
3025                 }
3026         }
3027 }