~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to external/ikvm/reflect/Reader/ModuleReader.cs

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

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