Merge pull request #347 from JamesB7/master
[mono.git] / mcs / class / IKVM.Reflection / Reader / ModuleReader.cs
1 /*
2   Copyright (C) 2009-2012 Jeroen Frijters
3
4   This software is provided 'as-is', without any express or implied
5   warranty.  In no event will the authors be held liable for any damages
6   arising from the use of this software.
7
8   Permission is granted to anyone to use this software for any purpose,
9   including commercial applications, and to alter it and redistribute it
10   freely, subject to the following restrictions:
11
12   1. The origin of this software must not be misrepresented; you must not
13      claim that you wrote the original software. If you use this software
14      in a product, an acknowledgment in the product documentation would be
15      appreciated but is not required.
16   2. Altered source versions must be plainly marked as such, and must not be
17      misrepresented as being the original software.
18   3. This notice may not be removed or altered from any source distribution.
19
20   Jeroen Frijters
21   jeroen@frijters.net
22   
23 */
24 using System;
25 using System.IO;
26 using System.Text;
27 using System.Collections.Generic;
28 using IKVM.Reflection.Metadata;
29
30 namespace IKVM.Reflection.Reader
31 {
32         sealed class StreamHeader
33         {
34                 internal uint Offset;
35                 internal uint Size;
36                 internal string Name;
37
38                 internal void Read(BinaryReader br)
39                 {
40                         Offset = br.ReadUInt32();
41                         Size = br.ReadUInt32();
42                         byte[] buf = new byte[32];
43                         byte b;
44                         int len = 0;
45                         while ((b = br.ReadByte()) != 0)
46                         {
47                                 buf[len++] = b;
48                         }
49                         Name = Encoding.UTF8.GetString(buf, 0, len); ;
50                         int padding = -1 + ((len + 4) & ~3) - len;
51                         br.BaseStream.Seek(padding, SeekOrigin.Current);
52                 }
53         }
54
55         sealed class ModuleReader : Module
56         {
57                 internal readonly Stream stream;
58                 private readonly string location;
59                 private Assembly assembly;
60                 private readonly PEReader peFile = new PEReader();
61                 private readonly CliHeader cliHeader = new CliHeader();
62                 private string imageRuntimeVersion;
63                 private int metadataStreamVersion;
64                 private byte[] stringHeap;
65                 private byte[] blobHeap;
66                 private byte[] userStringHeap;
67                 private byte[] guidHeap;
68                 private TypeDefImpl[] typeDefs;
69                 private TypeDefImpl moduleType;
70                 private Assembly[] assemblyRefs;
71                 private Type[] typeRefs;
72                 private Type[] typeSpecs;
73                 private FieldInfo[] fields;
74                 private MethodBase[] methods;
75                 private MemberInfo[] memberRefs;
76                 private Dictionary<int, string> strings = new Dictionary<int, string>();
77                 private Dictionary<TypeName, Type> types = new Dictionary<TypeName, Type>();
78                 private Dictionary<TypeName, LazyForwardedType> forwardedTypes = new Dictionary<TypeName, LazyForwardedType>();
79
80                 private sealed class LazyForwardedType
81                 {
82                         private readonly int assemblyRef;
83                         private Type type;
84
85                         internal LazyForwardedType(int assemblyRef)
86                         {
87                                 this.assemblyRef = assemblyRef;
88                         }
89
90                         internal Type GetType(ModuleReader module, TypeName typeName)
91                         {
92                                 if (type == null)
93                                 {
94                                         Assembly asm = module.ResolveAssemblyRef(assemblyRef);
95                                         type = asm.ResolveType(typeName);
96                                         if (type == null)
97                                         {
98                                                 throw new TypeLoadException(typeName.ToString());
99                                         }
100                                 }
101                                 return type;
102                         }
103                 }
104
105                 internal ModuleReader(AssemblyReader assembly, Universe universe, Stream stream, string location)
106                         : base(universe)
107                 {
108                         this.stream = stream;
109                         this.location = location;
110                         Read();
111                         if (assembly == null && AssemblyTable.records.Length != 0)
112                         {
113                                 assembly = new AssemblyReader(location, this);
114                         }
115                         this.assembly = assembly;
116                 }
117
118                 private void Read()
119                 {
120                         BinaryReader br = new BinaryReader(stream);
121                         peFile.Read(br);
122                         stream.Seek(peFile.RvaToFileOffset(peFile.GetComDescriptorVirtualAddress()), SeekOrigin.Begin);
123                         cliHeader.Read(br);
124                         stream.Seek(peFile.RvaToFileOffset(cliHeader.MetaData.VirtualAddress), SeekOrigin.Begin);
125                         foreach (StreamHeader sh in ReadStreamHeaders(br, out imageRuntimeVersion))
126                         {
127                                 switch (sh.Name)
128                                 {
129                                         case "#Strings":
130                                                 stringHeap = ReadHeap(stream, sh);
131                                                 break;
132                                         case "#Blob":
133                                                 blobHeap = ReadHeap(stream, sh);
134                                                 break;
135                                         case "#US":
136                                                 userStringHeap = ReadHeap(stream, sh);
137                                                 break;
138                                         case "#GUID":
139                                                 guidHeap = ReadHeap(stream, sh);
140                                                 break;
141                                         case "#~":
142                                         case "#-":
143                                                 stream.Seek(peFile.RvaToFileOffset(cliHeader.MetaData.VirtualAddress + sh.Offset), SeekOrigin.Begin);
144                                                 ReadTables(br);
145                                                 break;
146                                         default:
147                                                 throw new BadImageFormatException("Unsupported stream: " + sh.Name);
148                                 }
149                         }
150                 }
151
152                 internal void SetAssembly(Assembly assembly)
153                 {
154                         this.assembly = assembly;
155                 }
156
157                 private static StreamHeader[] ReadStreamHeaders(BinaryReader br, out string Version)
158                 {
159                         uint Signature = br.ReadUInt32();
160                         if (Signature != 0x424A5342)
161                         {
162                                 throw new BadImageFormatException("Invalid metadata signature");
163                         }
164                         /*ushort MajorVersion =*/ br.ReadUInt16();
165                         /*ushort MinorVersion =*/ br.ReadUInt16();
166                         /*uint Reserved =*/ br.ReadUInt32();
167                         uint Length = br.ReadUInt32();
168                         byte[] buf = br.ReadBytes((int)Length);
169                         Version = Encoding.UTF8.GetString(buf).TrimEnd('\u0000');
170                         /*ushort Flags =*/ br.ReadUInt16();
171                         ushort Streams = br.ReadUInt16();
172                         StreamHeader[] streamHeaders = new StreamHeader[Streams];
173                         for (int i = 0; i < streamHeaders.Length; i++)
174                         {
175                                 streamHeaders[i] = new StreamHeader();
176                                 streamHeaders[i].Read(br);
177                         }
178                         return streamHeaders;
179                 }
180
181                 private void ReadTables(BinaryReader br)
182                 {
183                         Table[] tables = GetTables();
184                         /*uint Reserved0 =*/ br.ReadUInt32();
185                         byte MajorVersion = br.ReadByte();
186                         byte MinorVersion = br.ReadByte();
187                         metadataStreamVersion = MajorVersion << 16 | MinorVersion;
188                         byte HeapSizes = br.ReadByte();
189                         /*byte Reserved7 =*/ br.ReadByte();
190                         ulong Valid = br.ReadUInt64();
191                         ulong Sorted = br.ReadUInt64();
192                         for (int i = 0; i < 64; i++)
193                         {
194                                 if ((Valid & (1UL << i)) != 0)
195                                 {
196                                         tables[i].Sorted = (Sorted & (1UL << i)) != 0;
197                                         tables[i].RowCount = br.ReadInt32();
198                                 }
199                                 else if (tables[i] != null)
200                                 {
201                                         tables[i].RowCount = 0;
202                                 }
203                         }
204                         MetadataReader mr = new MetadataReader(this, br.BaseStream, HeapSizes);
205                         for (int i = 0; i < 64; i++)
206                         {
207                                 if ((Valid & (1UL << i)) != 0)
208                                 {
209                                         tables[i].Read(mr);
210                                 }
211                         }
212                         if (ParamPtr.RowCount != 0)
213                         {
214                                 throw new NotImplementedException("ParamPtr table support has not yet been implemented.");
215                         }
216                 }
217
218                 private byte[] ReadHeap(Stream stream, StreamHeader sh)
219                 {
220                         byte[] buf = new byte[sh.Size];
221                         stream.Seek(peFile.RvaToFileOffset(cliHeader.MetaData.VirtualAddress + sh.Offset), SeekOrigin.Begin);
222                         for (int pos = 0; pos < buf.Length; )
223                         {
224                                 int read = stream.Read(buf, pos, buf.Length - pos);
225                                 if (read == 0)
226                                 {
227                                         throw new BadImageFormatException();
228                                 }
229                                 pos += read;
230                         }
231                         return buf;
232                 }
233
234                 internal void SeekRVA(int rva)
235                 {
236                         stream.Seek(peFile.RvaToFileOffset((uint)rva), SeekOrigin.Begin);
237                 }
238
239                 internal override void GetTypesImpl(List<Type> list)
240                 {
241                         PopulateTypeDef();
242                         foreach (TypeDefImpl type in typeDefs)
243                         {
244                                 if (type != moduleType)
245                                 {
246                                         list.Add(type);
247                                 }
248                         }
249                 }
250
251                 private void PopulateTypeDef()
252                 {
253                         if (typeDefs == null)
254                         {
255                                 typeDefs = new TypeDefImpl[TypeDef.records.Length];
256                                 for (int i = 0; i < typeDefs.Length; i++)
257                                 {
258                                         TypeDefImpl type = new TypeDefImpl(this, i);
259                                         typeDefs[i] = type;
260                                         if (type.IsModulePseudoType)
261                                         {
262                                                 moduleType = type;
263                                         }
264                                         else if (!type.IsNestedByFlags)
265                                         {
266                                                 types.Add(new TypeName(type.__Namespace, type.__Name), type);
267                                         }
268                                 }
269                                 // add forwarded types to forwardedTypes dictionary (because Module.GetType(string) should return them)
270                                 for (int i = 0; i < ExportedType.records.Length; i++)
271                                 {
272                                         int implementation = ExportedType.records[i].Implementation;
273                                         if (implementation >> 24 == AssemblyRefTable.Index)
274                                         {
275                                                 TypeName typeName = GetTypeName(ExportedType.records[i].TypeNamespace, ExportedType.records[i].TypeName);
276                                                 forwardedTypes.Add(typeName, new LazyForwardedType((implementation & 0xFFFFFF) - 1));
277                                         }
278                                 }
279                         }
280                 }
281
282                 internal string GetString(int index)
283                 {
284                         if (index == 0)
285                         {
286                                 return null;
287                         }
288                         string str;
289                         if (!strings.TryGetValue(index, out str))
290                         {
291                                 int len = 0;
292                                 while (stringHeap[index + len] != 0)
293                                 {
294                                         len++;
295                                 }
296                                 str = Encoding.UTF8.GetString(stringHeap, index, len);
297                                 strings.Add(index, str);
298                         }
299                         return str;
300                 }
301
302                 private static int ReadCompressedInt(byte[] buffer, ref int offset)
303                 {
304                         byte b1 = buffer[offset++];
305                         if (b1 <= 0x7F)
306                         {
307                                 return b1;
308                         }
309                         else if ((b1 & 0xC0) == 0x80)
310                         {
311                                 byte b2 = buffer[offset++];
312                                 return ((b1 & 0x3F) << 8) | b2;
313                         }
314                         else
315                         {
316                                 byte b2 = buffer[offset++];
317                                 byte b3 = buffer[offset++];
318                                 byte b4 = buffer[offset++];
319                                 return ((b1 & 0x3F) << 24) + (b2 << 16) + (b3 << 8) + b4;
320                         }
321                 }
322
323                 internal byte[] GetBlobCopy(int blobIndex)
324                 {
325                         int len = ReadCompressedInt(blobHeap, ref blobIndex);
326                         byte[] buf = new byte[len];
327                         Buffer.BlockCopy(blobHeap, blobIndex, buf, 0, len);
328                         return buf;
329                 }
330
331                 internal override ByteReader GetBlob(int blobIndex)
332                 {
333                         return ByteReader.FromBlob(blobHeap, blobIndex);
334                 }
335
336                 public override string ResolveString(int metadataToken)
337                 {
338                         string str;
339                         if (!strings.TryGetValue(metadataToken, out str))
340                         {
341                                 if ((metadataToken >> 24) != 0x70)
342                                 {
343                                         throw TokenOutOfRangeException(metadataToken);
344                                 }
345                                 int index = metadataToken & 0xFFFFFF;
346                                 int len = ReadCompressedInt(userStringHeap, ref index) & ~1;
347                                 StringBuilder sb = new StringBuilder(len / 2);
348                                 for (int i = 0; i < len; i += 2)
349                                 {
350                                         char ch = (char)(userStringHeap[index + i] | userStringHeap[index + i + 1] << 8);
351                                         sb.Append(ch);
352                                 }
353                                 str = sb.ToString();
354                                 strings.Add(metadataToken, str);
355                         }
356                         return str;
357                 }
358
359                 internal Type ResolveType(int metadataToken, IGenericContext context)
360                 {
361                         int index = (metadataToken & 0xFFFFFF) - 1;
362                         if (index < 0)
363                         {
364                                 throw TokenOutOfRangeException(metadataToken);
365                         }
366                         else if ((metadataToken >> 24) == TypeDefTable.Index && index < TypeDef.RowCount)
367                         {
368                                 PopulateTypeDef();
369                                 return typeDefs[index];
370                         }
371                         else if ((metadataToken >> 24) == TypeRefTable.Index && index < TypeRef.RowCount)
372                         {
373                                 if (typeRefs == null)
374                                 {
375                                         typeRefs = new Type[TypeRef.records.Length];
376                                 }
377                                 if (typeRefs[index] == null)
378                                 {
379                                         int scope = TypeRef.records[index].ResolutionScope;
380                                         switch (scope >> 24)
381                                         {
382                                                 case AssemblyRefTable.Index:
383                                                         {
384                                                                 Assembly assembly = ResolveAssemblyRef((scope & 0xFFFFFF) - 1);
385                                                                 TypeName typeName = GetTypeName(TypeRef.records[index].TypeNameSpace, TypeRef.records[index].TypeName);
386                                                                 typeRefs[index] = assembly.ResolveType(typeName);
387                                                                 break;
388                                                         }
389                                                 case TypeRefTable.Index:
390                                                         {
391                                                                 Type outer = ResolveType(scope, null);
392                                                                 TypeName typeName = GetTypeName(TypeRef.records[index].TypeNameSpace, TypeRef.records[index].TypeName);
393                                                                 typeRefs[index] = outer.ResolveNestedType(typeName);
394                                                                 break;
395                                                         }
396                                                 case ModuleTable.Index:
397                                                 case ModuleRefTable.Index:
398                                                         {
399                                                                 Module module;
400                                                                 if (scope >> 24 == ModuleTable.Index)
401                                                                 {
402                                                                         if (scope == 0 || scope == 1)
403                                                                         {
404                                                                                 module = this;
405                                                                         }
406                                                                         else
407                                                                         {
408                                                                                 throw new NotImplementedException("self reference scope?");
409                                                                         }
410                                                                 }
411                                                                 else
412                                                                 {
413                                                                         module = ResolveModuleRef(ModuleRef.records[(scope & 0xFFFFFF) - 1]);
414                                                                 }
415                                                                 TypeName typeName = GetTypeName(TypeRef.records[index].TypeNameSpace, TypeRef.records[index].TypeName);
416                                                                 typeRefs[index] = module.FindType(typeName) ?? module.universe.GetMissingTypeOrThrow(module, null, typeName);
417                                                                 break;
418                                                         }
419                                                 default:
420                                                         throw new NotImplementedException("ResolutionScope = " + scope.ToString("X"));
421                                         }
422                                 }
423                                 return typeRefs[index];
424                         }
425                         else if ((metadataToken >> 24) == TypeSpecTable.Index && index < TypeSpec.RowCount)
426                         {
427                                 if (typeSpecs == null)
428                                 {
429                                         typeSpecs = new Type[TypeSpec.records.Length];
430                                 }
431                                 Type type = typeSpecs[index];
432                                 if (type == null)
433                                 {
434                                         TrackingGenericContext tc = context == null ? null : new TrackingGenericContext(context);
435                                         type = Signature.ReadTypeSpec(this, ByteReader.FromBlob(blobHeap, TypeSpec.records[index]), tc);
436                                         if (tc == null || !tc.IsUsed)
437                                         {
438                                                 typeSpecs[index] = type;
439                                         }
440                                 }
441                                 return type;
442                         }
443                         else
444                         {
445                                 throw TokenOutOfRangeException(metadataToken);
446                         }
447                 }
448
449                 private Module ResolveModuleRef(int moduleNameIndex)
450                 {
451                         string moduleName = GetString(moduleNameIndex);
452                         Module module = assembly.GetModule(moduleName);
453                         if (module == null)
454                         {
455                                 throw new FileNotFoundException(moduleName);
456                         }
457                         return module;
458                 }
459
460                 private sealed class TrackingGenericContext : IGenericContext
461                 {
462                         private readonly IGenericContext context;
463                         private bool used;
464
465                         internal TrackingGenericContext(IGenericContext context)
466                         {
467                                 this.context = context;
468                         }
469
470                         internal bool IsUsed
471                         {
472                                 get { return used; }
473                         }
474
475                         public Type GetGenericTypeArgument(int index)
476                         {
477                                 used = true;
478                                 return context.GetGenericTypeArgument(index);
479                         }
480
481                         public Type GetGenericMethodArgument(int index)
482                         {
483                                 used = true;
484                                 return context.GetGenericMethodArgument(index);
485                         }
486                 }
487
488                 public override Type ResolveType(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
489                 {
490                         if ((metadataToken >> 24) == TypeSpecTable.Index)
491                         {
492                                 return ResolveType(metadataToken, new GenericContext(genericTypeArguments, genericMethodArguments));
493                         }
494                         else
495                         {
496                                 return ResolveType(metadataToken, null);
497                         }
498                 }
499
500                 private TypeName GetTypeName(int typeNamespace, int typeName)
501                 {
502                         return new TypeName(GetString(typeNamespace), GetString(typeName));
503                 }
504
505                 internal Assembly ResolveAssemblyRef(int index)
506                 {
507                         if (assemblyRefs == null)
508                         {
509                                 assemblyRefs = new Assembly[AssemblyRef.RowCount];
510                         }
511                         if (assemblyRefs[index] == null)
512                         {
513                                 assemblyRefs[index] = ResolveAssemblyRefImpl(ref AssemblyRef.records[index]);
514                         }
515                         return assemblyRefs[index];
516                 }
517
518                 private Assembly ResolveAssemblyRefImpl(ref AssemblyRefTable.Record rec)
519                 {
520                         const int PublicKey = 0x0001;
521                         string name = String.Format("{0}, Version={1}.{2}.{3}.{4}, Culture={5}, {6}={7}",
522                                 GetString(rec.Name),
523                                 rec.MajorVersion,
524                                 rec.MinorVersion,
525                                 rec.BuildNumber,
526                                 rec.RevisionNumber,
527                                 rec.Culture == 0 ? "neutral" : GetString(rec.Culture),
528                                 (rec.Flags & PublicKey) == 0 ? "PublicKeyToken" : "PublicKey",
529                                 PublicKeyOrTokenToString(rec.PublicKeyOrToken));
530                         return universe.Load(name, this.Assembly, true);
531                 }
532
533                 private string PublicKeyOrTokenToString(int publicKeyOrToken)
534                 {
535                         if (publicKeyOrToken == 0)
536                         {
537                                 return "null";
538                         }
539                         ByteReader br = GetBlob(publicKeyOrToken);
540                         if (br.Length == 0)
541                         {
542                                 return "null";
543                         }
544                         StringBuilder sb = new StringBuilder(br.Length * 2);
545                         while (br.Length > 0)
546                         {
547                                 sb.AppendFormat("{0:x2}", br.ReadByte());
548                         }
549                         return sb.ToString();
550                 }
551
552                 public override Guid ModuleVersionId
553                 {
554                         get
555                         {
556                                 byte[] buf = new byte[16];
557                                 Buffer.BlockCopy(guidHeap, 16 * (ModuleTable.records[0].Mvid - 1), buf, 0, 16);
558                                 return new Guid(buf);
559                         }
560                 }
561
562                 public override string FullyQualifiedName
563                 {
564                         get { return location ?? "<Unknown>"; }
565                 }
566
567                 public override string Name
568                 {
569                         get { return location == null ? "<Unknown>" : System.IO.Path.GetFileName(location); }
570                 }
571
572                 public override Assembly Assembly
573                 {
574                         get { return assembly; }
575                 }
576
577                 internal override Type FindType(TypeName typeName)
578                 {
579                         PopulateTypeDef();
580                         Type type;
581                         if (!types.TryGetValue(typeName, out type))
582                         {
583                                 LazyForwardedType fw;
584                                 if (forwardedTypes.TryGetValue(typeName, out fw))
585                                 {
586                                         return fw.GetType(this, typeName);
587                                 }
588                         }
589                         return type;
590                 }
591
592                 internal override Type FindTypeIgnoreCase(TypeName lowerCaseName)
593                 {
594                         PopulateTypeDef();
595                         foreach (Type type in types.Values)
596                         {
597                                 if (new TypeName(type.__Namespace, type.__Name).ToLowerInvariant() == lowerCaseName)
598                                 {
599                                         return type;
600                                 }
601                         }
602                         foreach (TypeName name in forwardedTypes.Keys)
603                         {
604                                 if (name.ToLowerInvariant() == lowerCaseName)
605                                 {
606                                         return forwardedTypes[name].GetType(this, name);
607                                 }
608                         }
609                         return null;
610                 }
611
612                 private Exception TokenOutOfRangeException(int metadataToken)
613                 {
614                         return new ArgumentOutOfRangeException("metadataToken", String.Format("Token 0x{0:x8} is not valid in the scope of module {1}.", metadataToken, this.Name));
615                 }
616
617                 public override MemberInfo ResolveMember(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
618                 {
619                         switch (metadataToken >> 24)
620                         {
621                                 case FieldTable.Index:
622                                         return ResolveField(metadataToken, genericTypeArguments, genericMethodArguments);
623                                 case MemberRefTable.Index:
624                                         int index = (metadataToken & 0xFFFFFF) - 1;
625                                         if (index < 0 || index >= MemberRef.RowCount)
626                                         {
627                                                 goto default;
628                                         }
629                                         return GetMemberRef(index, genericTypeArguments, genericMethodArguments);
630                                 case MethodDefTable.Index:
631                                 case MethodSpecTable.Index:
632                                         return ResolveMethod(metadataToken, genericTypeArguments, genericMethodArguments);
633                                 default:
634                                         throw TokenOutOfRangeException(metadataToken);
635                         }
636                 }
637
638                 internal FieldInfo GetFieldAt(TypeDefImpl owner, int index)
639                 {
640                         if (fields == null)
641                         {
642                                 fields = new FieldInfo[Field.records.Length];
643                         }
644                         if (fields[index] == null)
645                         {
646                                 fields[index] = new FieldDefImpl(this, owner ?? FindFieldOwner(index), index);
647                         }
648                         return fields[index];
649                 }
650
651                 public override FieldInfo ResolveField(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
652                 {
653                         int index = (metadataToken & 0xFFFFFF) - 1;
654                         if (index < 0)
655                         {
656                                 throw TokenOutOfRangeException(metadataToken);
657                         }
658                         else if ((metadataToken >> 24) == FieldTable.Index && index < Field.RowCount)
659                         {
660                                 return GetFieldAt(null, index);
661                         }
662                         else if ((metadataToken >> 24) == MemberRefTable.Index && index < MemberRef.RowCount)
663                         {
664                                 FieldInfo field = GetMemberRef(index, genericTypeArguments, genericMethodArguments) as FieldInfo;
665                                 if (field != null)
666                                 {
667                                         return field;
668                                 }
669                                 throw new ArgumentException(String.Format("Token 0x{0:x8} is not a valid FieldInfo token in the scope of module {1}.", metadataToken, this.Name), "metadataToken");
670                         }
671                         else
672                         {
673                                 throw TokenOutOfRangeException(metadataToken);
674                         }
675                 }
676
677                 private TypeDefImpl FindFieldOwner(int fieldIndex)
678                 {
679                         // TODO use binary search?
680                         for (int i = 0; i < TypeDef.records.Length; i++)
681                         {
682                                 int field = TypeDef.records[i].FieldList - 1;
683                                 int end = TypeDef.records.Length > i + 1 ? TypeDef.records[i + 1].FieldList - 1 : Field.records.Length;
684                                 if (field <= fieldIndex && fieldIndex < end)
685                                 {
686                                         PopulateTypeDef();
687                                         return typeDefs[i];
688                                 }
689                         }
690                         throw new InvalidOperationException();
691                 }
692
693                 internal MethodBase GetMethodAt(TypeDefImpl owner, int index)
694                 {
695                         if (methods == null)
696                         {
697                                 methods = new MethodBase[MethodDef.records.Length];
698                         }
699                         if (methods[index] == null)
700                         {
701                                 MethodDefImpl method = new MethodDefImpl(this, owner ?? FindMethodOwner(index), index);
702                                 methods[index] = method.IsConstructor ? new ConstructorInfoImpl(method) : (MethodBase)method;
703                         }
704                         return methods[index];
705                 }
706
707                 private sealed class GenericContext : IGenericContext
708                 {
709                         private readonly Type[] genericTypeArguments;
710                         private readonly Type[] genericMethodArguments;
711
712                         internal GenericContext(Type[] genericTypeArguments, Type[] genericMethodArguments)
713                         {
714                                 this.genericTypeArguments = genericTypeArguments;
715                                 this.genericMethodArguments = genericMethodArguments;
716                         }
717
718                         public Type GetGenericTypeArgument(int index)
719                         {
720                                 return genericTypeArguments[index];
721                         }
722
723                         public Type GetGenericMethodArgument(int index)
724                         {
725                                 return genericMethodArguments[index];
726                         }
727                 }
728
729                 public override MethodBase ResolveMethod(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
730                 {
731                         int index = (metadataToken & 0xFFFFFF) - 1;
732                         if (index < 0)
733                         {
734                                 throw TokenOutOfRangeException(metadataToken);
735                         }
736                         else if ((metadataToken >> 24) == MethodDefTable.Index && index < MethodDef.RowCount)
737                         {
738                                 return GetMethodAt(null, index);
739                         }
740                         else if ((metadataToken >> 24) == MemberRefTable.Index && index < MemberRef.RowCount)
741                         {
742                                 MethodBase method = GetMemberRef(index, genericTypeArguments, genericMethodArguments) as MethodBase;
743                                 if (method != null)
744                                 {
745                                         return method;
746                                 }
747                                 throw new ArgumentException(String.Format("Token 0x{0:x8} is not a valid MethodBase token in the scope of module {1}.", metadataToken, this.Name), "metadataToken");
748                         }
749                         else if ((metadataToken >> 24) == MethodSpecTable.Index && index < MethodSpec.RowCount)
750                         {
751                                 MethodInfo method = (MethodInfo)ResolveMethod(MethodSpec.records[index].Method, genericTypeArguments, genericMethodArguments);
752                                 ByteReader instantiation = ByteReader.FromBlob(blobHeap, MethodSpec.records[index].Instantiation);
753                                 return method.MakeGenericMethod(Signature.ReadMethodSpec(this, instantiation, new GenericContext(genericTypeArguments, genericMethodArguments)));
754                         }
755                         else
756                         {
757                                 throw TokenOutOfRangeException(metadataToken);
758                         }
759                 }
760
761                 public override Type[] __ResolveOptionalParameterTypes(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments, out CustomModifiers[] customModifiers)
762                 {
763                         int index = (metadataToken & 0xFFFFFF) - 1;
764                         if (index < 0)
765                         {
766                                 throw TokenOutOfRangeException(metadataToken);
767                         }
768                         else if ((metadataToken >> 24) == MemberRefTable.Index && index < MemberRef.RowCount)
769                         {
770                                 int sig = MemberRef.records[index].Signature;
771                                 return Signature.ReadOptionalParameterTypes(this, GetBlob(sig), new GenericContext(genericTypeArguments, genericMethodArguments), out customModifiers);
772                         }
773                         else if ((metadataToken >> 24) == MethodDefTable.Index && index < MethodDef.RowCount)
774                         {
775                                 // for convenience, we support passing a MethodDef token as well, because in some places
776                                 // it makes sense to have a vararg method that is referred to by its methoddef (e.g. ldftn).
777                                 // Note that MethodSpec doesn't make sense, because generic methods cannot be vararg.
778                                 customModifiers = Empty<CustomModifiers>.Array;
779                                 return Type.EmptyTypes;
780                         }
781                         else
782                         {
783                                 throw TokenOutOfRangeException(metadataToken);
784                         }
785                 }
786
787                 public override string ScopeName
788                 {
789                         get { return GetString(ModuleTable.records[0].Name); }
790                 }
791
792                 private TypeDefImpl FindMethodOwner(int methodIndex)
793                 {
794                         // TODO use binary search?
795                         for (int i = 0; i < TypeDef.records.Length; i++)
796                         {
797                                 int method = TypeDef.records[i].MethodList - 1;
798                                 int end = TypeDef.records.Length > i + 1 ? TypeDef.records[i + 1].MethodList - 1 : MethodDef.records.Length;
799                                 if (method <= methodIndex && methodIndex < end)
800                                 {
801                                         PopulateTypeDef();
802                                         return typeDefs[i];
803                                 }
804                         }
805                         throw new InvalidOperationException();
806                 }
807
808                 private MemberInfo GetMemberRef(int index, Type[] genericTypeArguments, Type[] genericMethodArguments)
809                 {
810                         if (memberRefs == null)
811                         {
812                                 memberRefs = new MemberInfo[MemberRef.records.Length];
813                         }
814                         if (memberRefs[index] == null)
815                         {
816                                 int owner = MemberRef.records[index].Class;
817                                 int sig = MemberRef.records[index].Signature;
818                                 string name = GetString(MemberRef.records[index].Name);
819                                 switch (owner >> 24)
820                                 {
821                                         case MethodDefTable.Index:
822                                                 return GetMethodAt(null, (owner & 0xFFFFFF) - 1);
823                                         case ModuleRefTable.Index:
824                                                 memberRefs[index] = ResolveTypeMemberRef(ResolveModuleType(owner), name, ByteReader.FromBlob(blobHeap, sig));
825                                                 break;
826                                         case TypeDefTable.Index:
827                                         case TypeRefTable.Index:
828                                                 memberRefs[index] = ResolveTypeMemberRef(ResolveType(owner), name, ByteReader.FromBlob(blobHeap, sig));
829                                                 break;
830                                         case TypeSpecTable.Index:
831                                         {
832                                                 Type type = ResolveType(owner, genericTypeArguments, genericMethodArguments);
833                                                 if (type.IsArray)
834                                                 {
835                                                         MethodSignature methodSig = MethodSignature.ReadSig(this, ByteReader.FromBlob(blobHeap, sig), new GenericContext(genericTypeArguments, genericMethodArguments));
836                                                         return type.FindMethod(name, methodSig)
837                                                                 ?? universe.GetMissingMethodOrThrow(type, name, methodSig);
838                                                 }
839                                                 else if (type.IsGenericTypeInstance)
840                                                 {
841                                                         MemberInfo member = ResolveTypeMemberRef(type.GetGenericTypeDefinition(), name, ByteReader.FromBlob(blobHeap, sig));
842                                                         MethodBase mb = member as MethodBase;
843                                                         if (mb != null)
844                                                         {
845                                                                 member = mb.BindTypeParameters(type);
846                                                         }
847                                                         FieldInfo fi = member as FieldInfo;
848                                                         if (fi != null)
849                                                         {
850                                                                 member = fi.BindTypeParameters(type);
851                                                         }
852                                                         return member;
853                                                 }
854                                                 else
855                                                 {
856                                                         return ResolveTypeMemberRef(type, name, ByteReader.FromBlob(blobHeap, sig));
857                                                 }
858                                         }
859                                         default:
860                                                 throw new BadImageFormatException();
861                                 }
862                         }
863                         return memberRefs[index];
864                 }
865
866                 private Type ResolveModuleType(int token)
867                 {
868                         int index = (token & 0xFFFFFF) - 1;
869                         string name = GetString(ModuleRef.records[index]);
870                         Module module = assembly.GetModule(name);
871                         if (module == null || module.IsResource())
872                         {
873                                 throw new BadImageFormatException();
874                         }
875                         return module.GetModuleType();
876                 }
877
878                 private MemberInfo ResolveTypeMemberRef(Type type, string name, ByteReader sig)
879                 {
880                         if (sig.PeekByte() == Signature.FIELD)
881                         {
882                                 Type org = type;
883                                 FieldSignature fieldSig = FieldSignature.ReadSig(this, sig, type);
884                                 FieldInfo field = type.FindField(name, fieldSig);
885                                 if (field == null && universe.MissingMemberResolution)
886                                 {
887                                         return universe.GetMissingFieldOrThrow(type, name, fieldSig);
888                                 }
889                                 while (field == null && (type = type.BaseType) != null)
890                                 {
891                                         field = type.FindField(name, fieldSig);
892                                 }
893                                 if (field != null)
894                                 {
895                                         return field;
896                                 }
897                                 throw new MissingFieldException(org.ToString(), name);
898                         }
899                         else
900                         {
901                                 Type org = type;
902                                 MethodSignature methodSig = MethodSignature.ReadSig(this, sig, type);
903                                 MethodBase method = type.FindMethod(name, methodSig);
904                                 if (method == null && universe.MissingMemberResolution)
905                                 {
906                                         return universe.GetMissingMethodOrThrow(type, name, methodSig);
907                                 }
908                                 while (method == null && (type = type.BaseType) != null)
909                                 {
910                                         method = type.FindMethod(name, methodSig);
911                                 }
912                                 if (method != null)
913                                 {
914                                         return method;
915                                 }
916                                 throw new MissingMethodException(org.ToString(), name);
917                         }
918                 }
919
920                 internal ByteReader GetStandAloneSig(int index)
921                 {
922                         return ByteReader.FromBlob(blobHeap, StandAloneSig.records[index]);
923                 }
924
925                 public override byte[] ResolveSignature(int metadataToken)
926                 {
927                         int index = (metadataToken & 0xFFFFFF) - 1;
928                         if ((metadataToken >> 24) == StandAloneSigTable.Index && index >= 0 && index < StandAloneSig.RowCount)
929                         {
930                                 ByteReader br = GetStandAloneSig(index);
931                                 return br.ReadBytes(br.Length);
932                         }
933                         else
934                         {
935                                 throw TokenOutOfRangeException(metadataToken);
936                         }
937                 }
938
939                 public override __StandAloneMethodSig __ResolveStandAloneMethodSig(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
940                 {
941                         int index = (metadataToken & 0xFFFFFF) - 1;
942                         if ((metadataToken >> 24) == StandAloneSigTable.Index && index >= 0 && index < StandAloneSig.RowCount)
943                         {
944                                 return MethodSignature.ReadStandAloneMethodSig(this, GetStandAloneSig(index), new GenericContext(genericTypeArguments, genericMethodArguments));
945                         }
946                         else
947                         {
948                                 throw TokenOutOfRangeException(metadataToken);
949                         }
950                 }
951
952                 internal MethodInfo GetEntryPoint()
953                 {
954                         if (cliHeader.EntryPointToken != 0 && (cliHeader.Flags & CliHeader.COMIMAGE_FLAGS_NATIVE_ENTRYPOINT) == 0)
955                         {
956                                 return (MethodInfo)ResolveMethod((int)cliHeader.EntryPointToken);
957                         }
958                         return null;
959                 }
960
961                 internal string[] GetManifestResourceNames()
962                 {
963                         string[] names = new string[ManifestResource.records.Length];
964                         for (int i = 0; i < ManifestResource.records.Length; i++)
965                         {
966                                 names[i] = GetString(ManifestResource.records[i].Name);
967                         }
968                         return names;
969                 }
970
971                 internal ManifestResourceInfo GetManifestResourceInfo(string resourceName)
972                 {
973                         for (int i = 0; i < ManifestResource.records.Length; i++)
974                         {
975                                 if (resourceName == GetString(ManifestResource.records[i].Name))
976                                 {
977                                         ManifestResourceInfo info = new ManifestResourceInfo(this, i);
978                                         Assembly asm = info.ReferencedAssembly;
979                                         if (asm != null && !asm.__IsMissing && asm.GetManifestResourceInfo(resourceName) == null)
980                                         {
981                                                 return null;
982                                         }
983                                         return info;
984                                 }
985                         }
986                         return null;
987                 }
988
989                 internal Stream GetManifestResourceStream(string resourceName)
990                 {
991                         for (int i = 0; i < ManifestResource.records.Length; i++)
992                         {
993                                 if (resourceName == GetString(ManifestResource.records[i].Name))
994                                 {
995                                         if (ManifestResource.records[i].Implementation != 0x26000000)
996                                         {
997                                                 ManifestResourceInfo info = new ManifestResourceInfo(this, i);
998                                                 switch (ManifestResource.records[i].Implementation >> 24)
999                                                 {
1000                                                         case FileTable.Index:
1001                                                                 string fileName = Path.Combine(Path.GetDirectoryName(location), info.FileName);
1002                                                                 if (System.IO.File.Exists(fileName))
1003                                                                 {
1004                                                                         // note that, like System.Reflection, we return null for zero length files and
1005                                                                         // ManifestResource.Offset is ignored
1006                                                                         FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete);
1007                                                                         if (fs.Length == 0)
1008                                                                         {
1009                                                                                 fs.Close();
1010                                                                                 return null;
1011                                                                         }
1012                                                                         return fs;
1013                                                                 }
1014                                                                 return null;
1015                                                         case AssemblyRefTable.Index:
1016                                                                 Assembly asm = info.ReferencedAssembly;
1017                                                                 if (asm.__IsMissing)
1018                                                                 {
1019                                                                         return null;
1020                                                                 }
1021                                                                 return asm.GetManifestResourceStream(resourceName);
1022                                                         default:
1023                                                                 throw new BadImageFormatException();
1024                                                 }
1025                                         }
1026                                         SeekRVA((int)cliHeader.Resources.VirtualAddress + ManifestResource.records[i].Offset);
1027                                         BinaryReader br = new BinaryReader(stream);
1028                                         int length = br.ReadInt32();
1029                                         return new MemoryStream(br.ReadBytes(length));
1030                                 }
1031                         }
1032                         return null;
1033                 }
1034
1035                 public override AssemblyName[] __GetReferencedAssemblies()
1036                 {
1037                         List<AssemblyName> list = new List<AssemblyName>();
1038                         for (int i = 0; i < AssemblyRef.records.Length; i++)
1039                         {
1040                                 AssemblyName name = new AssemblyName();
1041                                 name.Name = GetString(AssemblyRef.records[i].Name);
1042                                 name.Version = new Version(
1043                                         AssemblyRef.records[i].MajorVersion,
1044                                         AssemblyRef.records[i].MinorVersion,
1045                                         AssemblyRef.records[i].BuildNumber,
1046                                         AssemblyRef.records[i].RevisionNumber);
1047                                 if (AssemblyRef.records[i].PublicKeyOrToken != 0)
1048                                 {
1049                                         byte[] keyOrToken = GetBlobCopy(AssemblyRef.records[i].PublicKeyOrToken);
1050                                         const int PublicKey = 0x0001;
1051                                         if ((AssemblyRef.records[i].Flags & PublicKey) != 0)
1052                                         {
1053                                                 name.SetPublicKey(keyOrToken);
1054                                         }
1055                                         else
1056                                         {
1057                                                 name.SetPublicKeyToken(keyOrToken);
1058                                         }
1059                                 }
1060                                 else
1061                                 {
1062                                         name.SetPublicKeyToken(Empty<byte>.Array);
1063                                 }
1064                                 if (AssemblyRef.records[i].Culture != 0)
1065                                 {
1066                                         name.Culture = GetString(AssemblyRef.records[i].Culture);
1067                                 }
1068                                 else
1069                                 {
1070                                         name.Culture = "";
1071                                 }
1072                                 if (AssemblyRef.records[i].HashValue != 0)
1073                                 {
1074                                         name.hash = GetBlobCopy(AssemblyRef.records[i].HashValue);
1075                                 }
1076                                 name.Flags = (AssemblyNameFlags)AssemblyRef.records[i].Flags;
1077                                 list.Add(name);
1078                         }
1079                         return list.ToArray();
1080                 }
1081
1082                 public override void __ResolveReferencedAssemblies(Assembly[] assemblies)
1083                 {
1084                         if (assemblyRefs == null)
1085                         {
1086                                 assemblyRefs = new Assembly[AssemblyRef.RowCount];
1087                         }
1088                         for (int i = 0; i < assemblies.Length; i++)
1089                         {
1090                                 if (assemblyRefs[i] == null)
1091                                 {
1092                                         assemblyRefs[i] = assemblies[i];
1093                                 }
1094                         }
1095                 }
1096
1097                 public override string[] __GetReferencedModules()
1098                 {
1099                         string[] arr = new string[this.ModuleRef.RowCount];
1100                         for (int i = 0; i < arr.Length; i++)
1101                         {
1102                                 arr[i] = GetString(this.ModuleRef.records[i]);
1103                         }
1104                         return arr;
1105                 }
1106
1107                 public override Type[] __GetReferencedTypes()
1108                 {
1109                         Type[] arr = new Type[this.TypeRef.RowCount];
1110                         for (int i = 0; i < arr.Length; i++)
1111                         {
1112                                 arr[i] = ResolveType((TypeRefTable.Index << 24) + i + 1);
1113                         }
1114                         return arr;
1115                 }
1116
1117                 public override Type[] __GetExportedTypes()
1118                 {
1119                         Type[] arr = new Type[this.ExportedType.RowCount];
1120                         for (int i = 0; i < arr.Length; i++)
1121                         {
1122                                 arr[i] = ResolveExportedType(i);
1123                         }
1124                         return arr;
1125                 }
1126
1127                 private Type ResolveExportedType(int index)
1128                 {
1129                         TypeName typeName = GetTypeName(ExportedType.records[index].TypeNamespace, ExportedType.records[index].TypeName);
1130                         int implementation = ExportedType.records[index].Implementation;
1131                         int token = ExportedType.records[index].TypeDefId;
1132                         switch (implementation >> 24)
1133                         {
1134                                 case AssemblyRefTable.Index:
1135                                         return ResolveAssemblyRef((implementation & 0xFFFFFF) - 1).ResolveType(typeName).SetMetadataTokenForMissing(token);
1136                                 case ExportedTypeTable.Index:
1137                                         return ResolveExportedType((implementation & 0xFFFFFF) - 1).ResolveNestedType(typeName).SetMetadataTokenForMissing(token);
1138                                 default:
1139                                         throw new NotImplementedException();
1140                         }
1141                 }
1142
1143                 internal override Type GetModuleType()
1144                 {
1145                         PopulateTypeDef();
1146                         return moduleType;
1147                 }
1148
1149                 public override string __ImageRuntimeVersion
1150                 {
1151                         get { return imageRuntimeVersion; }
1152                 }
1153
1154                 public override int MDStreamVersion
1155                 {
1156                         get { return metadataStreamVersion; }
1157                 }
1158
1159                 public override void __GetDataDirectoryEntry(int index, out int rva, out int length)
1160                 {
1161                         peFile.GetDataDirectoryEntry(index, out rva, out length);
1162                 }
1163
1164                 public override long __RelativeVirtualAddressToFileOffset(int rva)
1165                 {
1166                         return peFile.RvaToFileOffset((uint)rva);
1167                 }
1168
1169                 public override bool __GetSectionInfo(int rva, out string name, out int characteristics)
1170                 {
1171                         return peFile.GetSectionInfo(rva, out name, out characteristics);
1172                 }
1173
1174                 public override int __ReadDataFromRVA(int rva, byte[] data, int offset, int length)
1175                 {
1176                         SeekRVA(rva);
1177                         int totalBytesRead = 0;
1178                         while (length > 0)
1179                         {
1180                                 int read = stream.Read(data, offset, length);
1181                                 if (read == 0)
1182                                 {
1183                                         // C++ assemblies can have fields that have an RVA that lies outside of the file
1184                                         break;
1185                                 }
1186                                 offset += read;
1187                                 length -= read;
1188                                 totalBytesRead += read;
1189                         }
1190                         return totalBytesRead;
1191                 }
1192
1193                 public override void GetPEKind(out PortableExecutableKinds peKind, out ImageFileMachine machine)
1194                 {
1195                         peKind = 0;
1196                         if ((cliHeader.Flags & CliHeader.COMIMAGE_FLAGS_ILONLY) != 0)
1197                         {
1198                                 peKind |= PortableExecutableKinds.ILOnly;
1199                         }
1200                         switch (cliHeader.Flags & (CliHeader.COMIMAGE_FLAGS_32BITREQUIRED | CliHeader.COMIMAGE_FLAGS_32BITPREFERRED))
1201                         {
1202                                 case CliHeader.COMIMAGE_FLAGS_32BITREQUIRED:
1203                                         peKind |= PortableExecutableKinds.Required32Bit;
1204                                         break;
1205                                 case CliHeader.COMIMAGE_FLAGS_32BITREQUIRED | CliHeader.COMIMAGE_FLAGS_32BITPREFERRED:
1206                                         peKind |= PortableExecutableKinds.Preferred32Bit;
1207                                         break;
1208                                 default:
1209                                         // COMIMAGE_FLAGS_32BITPREFERRED by itself is illegal, so we ignore it
1210                                         // (not setting any flag is ok)
1211                                         break;
1212                         }
1213                         if (peFile.OptionalHeader.Magic == IMAGE_OPTIONAL_HEADER.IMAGE_NT_OPTIONAL_HDR64_MAGIC)
1214                         {
1215                                 peKind |= PortableExecutableKinds.PE32Plus;
1216                         }
1217
1218                         machine = (ImageFileMachine)peFile.FileHeader.Machine;
1219                 }
1220
1221                 public override int __Subsystem
1222                 {
1223                         get { return peFile.OptionalHeader.Subsystem; }
1224                 }
1225
1226                 public override IList<CustomAttributeData> __GetPlaceholderAssemblyCustomAttributes(bool multiple, bool security)
1227                 {
1228                         TypeName typeName;
1229                         switch ((multiple ? 1 : 0) + (security ? 2 : 0))
1230                         {
1231                                 case 0:
1232                                         typeName = new TypeName("System.Runtime.CompilerServices", "AssemblyAttributesGoHere");
1233                                         break;
1234                                 case 1:
1235                                         typeName = new TypeName("System.Runtime.CompilerServices", "AssemblyAttributesGoHereM");
1236                                         break;
1237                                 case 2:
1238                                         typeName = new TypeName("System.Runtime.CompilerServices", "AssemblyAttributesGoHereS");
1239                                         break;
1240                                 case 3:
1241                                 default:
1242                                         typeName = new TypeName("System.Runtime.CompilerServices", "AssemblyAttributesGoHereSM");
1243                                         break;
1244                         }
1245                         List<CustomAttributeData> list = new List<CustomAttributeData>();
1246                         for (int i = 0; i < CustomAttribute.records.Length; i++)
1247                         {
1248                                 if ((CustomAttribute.records[i].Parent >> 24) == TypeRefTable.Index)
1249                                 {
1250                                         int index = (CustomAttribute.records[i].Parent & 0xFFFFFF) - 1;
1251                                         if (typeName == GetTypeName(TypeRef.records[index].TypeNameSpace, TypeRef.records[index].TypeName))
1252                                         {
1253                                                 list.Add(new CustomAttributeData(this, i));
1254                                         }
1255                                 }
1256                         }
1257                         return list;
1258                 }
1259
1260                 internal override void Dispose()
1261                 {
1262                         stream.Close();
1263                 }
1264
1265                 internal override void ExportTypes(int fileToken, IKVM.Reflection.Emit.ModuleBuilder manifestModule)
1266                 {
1267                         PopulateTypeDef();
1268                         manifestModule.ExportTypes(typeDefs, fileToken);
1269                 }
1270
1271                 protected override long GetImageBaseImpl()
1272                 {
1273                         return (long)peFile.OptionalHeader.ImageBase;
1274                 }
1275
1276                 protected override long GetStackReserveImpl()
1277                 {
1278                         return (long)peFile.OptionalHeader.SizeOfStackReserve;
1279                 }
1280
1281                 protected override int GetFileAlignmentImpl()
1282                 {
1283                         return (int)peFile.OptionalHeader.FileAlignment;
1284                 }
1285
1286                 protected override DllCharacteristics GetDllCharacteristicsImpl()
1287                 {
1288                         return (DllCharacteristics)peFile.OptionalHeader.DllCharacteristics;
1289                 }
1290
1291                 public override int __EntryPointRVA
1292                 {
1293                         get { return (cliHeader.Flags & CliHeader.COMIMAGE_FLAGS_NATIVE_ENTRYPOINT) != 0 ? (int)cliHeader.EntryPointToken : 0; }
1294                 }
1295
1296                 public override int __EntryPointToken
1297                 {
1298                         get { return (cliHeader.Flags & CliHeader.COMIMAGE_FLAGS_NATIVE_ENTRYPOINT) == 0 ? (int)cliHeader.EntryPointToken : 0; }
1299                 }
1300         }
1301 }