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

« back to all changes in this revision

Viewing changes to external/mono-addins/Mono.Addins.CecilReflector/Mono.Cecil/Mono.Cecil.PE/ImageReader.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
// ImageReader.cs
 
3
//
 
4
// Author:
 
5
//   Jb Evain (jbevain@gmail.com)
 
6
//
 
7
// Copyright (c) 2008 - 2010 Jb Evain
 
8
//
 
9
// Permission is hereby granted, free of charge, to any person obtaining
 
10
// a copy of this software and associated documentation files (the
 
11
// "Software"), to deal in the Software without restriction, including
 
12
// without limitation the rights to use, copy, modify, merge, publish,
 
13
// distribute, sublicense, and/or sell copies of the Software, and to
 
14
// permit persons to whom the Software is furnished to do so, subject to
 
15
// the following conditions:
 
16
//
 
17
// The above copyright notice and this permission notice shall be
 
18
// included in all copies or substantial portions of the Software.
 
19
//
 
20
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 
21
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 
22
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 
23
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 
24
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 
25
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 
26
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
27
//
 
28
 
 
29
using System;
 
30
using System.IO;
 
31
 
 
32
using Mono.Cecil.Metadata;
 
33
 
 
34
using RVA = System.UInt32;
 
35
 
 
36
namespace Mono.Cecil.PE {
 
37
 
 
38
        sealed class ImageReader : BinaryStreamReader {
 
39
 
 
40
                readonly Image image;
 
41
 
 
42
                DataDirectory cli;
 
43
                DataDirectory metadata;
 
44
 
 
45
                public ImageReader (Stream stream)
 
46
                        : base (stream)
 
47
                {
 
48
                        image = new Image ();
 
49
 
 
50
                        image.FileName = stream.GetFullyQualifiedName ();
 
51
                }
 
52
 
 
53
                void MoveTo (DataDirectory directory)
 
54
                {
 
55
                        BaseStream.Position = image.ResolveVirtualAddress (directory.VirtualAddress);
 
56
                }
 
57
 
 
58
                void MoveTo (uint position)
 
59
                {
 
60
                        BaseStream.Position = position;
 
61
                }
 
62
 
 
63
                void ReadImage ()
 
64
                {
 
65
                        if (BaseStream.Length < 128)
 
66
                                throw new BadImageFormatException ();
 
67
 
 
68
                        // - DOSHeader
 
69
 
 
70
                        // PE                                   2
 
71
                        // Start                                58
 
72
                        // Lfanew                               4
 
73
                        // End                                  64
 
74
 
 
75
                        if (ReadUInt16 () != 0x5a4d)
 
76
                                throw new BadImageFormatException ();
 
77
 
 
78
                        Advance (58);
 
79
 
 
80
                        MoveTo (ReadUInt32 ());
 
81
 
 
82
                        if (ReadUInt32 () != 0x00004550)
 
83
                                throw new BadImageFormatException ();
 
84
 
 
85
                        // - PEFileHeader
 
86
 
 
87
                        // Machine                              2
 
88
                        image.Architecture = ReadArchitecture ();
 
89
 
 
90
                        // NumberOfSections             2
 
91
                        ushort sections = ReadUInt16 ();
 
92
 
 
93
                        // TimeDateStamp                4
 
94
                        // PointerToSymbolTable 4
 
95
                        // NumberOfSymbols              4
 
96
                        // OptionalHeaderSize   2
 
97
                        Advance (14);
 
98
 
 
99
                        // Characteristics              2
 
100
                        ushort characteristics = ReadUInt16 ();
 
101
 
 
102
                        ushort subsystem;
 
103
                        ReadOptionalHeaders (out subsystem);
 
104
                        ReadSections (sections);
 
105
                        ReadCLIHeader ();
 
106
                        ReadMetadata ();
 
107
 
 
108
                        image.Kind = GetModuleKind (characteristics, subsystem);
 
109
                }
 
110
 
 
111
                TargetArchitecture ReadArchitecture ()
 
112
                {
 
113
                        var machine = ReadUInt16 ();
 
114
                        switch (machine) {
 
115
                        case 0x014c:
 
116
                                return TargetArchitecture.I386;
 
117
                        case 0x8664:
 
118
                                return TargetArchitecture.AMD64;
 
119
                        case 0x0200:
 
120
                                return TargetArchitecture.IA64;
 
121
                        }
 
122
 
 
123
                        throw new NotSupportedException ();
 
124
                }
 
125
 
 
126
                static ModuleKind GetModuleKind (ushort characteristics, ushort subsystem)
 
127
                {
 
128
                        if ((characteristics & 0x2000) != 0) // ImageCharacteristics.Dll
 
129
                                return ModuleKind.Dll;
 
130
 
 
131
                        if (subsystem == 0x2 || subsystem == 0x9) // SubSystem.WindowsGui || SubSystem.WindowsCeGui
 
132
                                return ModuleKind.Windows;
 
133
 
 
134
                        return ModuleKind.Console;
 
135
                }
 
136
 
 
137
                void ReadOptionalHeaders (out ushort subsystem)
 
138
                {
 
139
                        // - PEOptionalHeader
 
140
                        //   - StandardFieldsHeader
 
141
 
 
142
                        // Magic                                2
 
143
                        bool pe64 = ReadUInt16 () == 0x20b;
 
144
 
 
145
                        //                                              pe32 || pe64
 
146
 
 
147
                        // LMajor                               1
 
148
                        // LMinor                               1
 
149
                        // CodeSize                             4
 
150
                        // InitializedDataSize  4
 
151
                        // UninitializedDataSize4
 
152
                        // EntryPointRVA                4
 
153
                        // BaseOfCode                   4
 
154
                        // BaseOfData                   4 || 0
 
155
 
 
156
                        //   - NTSpecificFieldsHeader
 
157
 
 
158
                        // ImageBase                    4 || 8
 
159
                        // SectionAlignment             4
 
160
                        // FileAlignement               4
 
161
                        // OSMajor                              2
 
162
                        // OSMinor                              2
 
163
                        // UserMajor                    2
 
164
                        // UserMinor                    2
 
165
                        // SubSysMajor                  2
 
166
                        // SubSysMinor                  2
 
167
                        // Reserved                             4
 
168
                        // ImageSize                    4
 
169
                        // HeaderSize                   4
 
170
                        // FileChecksum                 4
 
171
                        Advance (66);
 
172
 
 
173
                        // SubSystem                    2
 
174
                        subsystem = ReadUInt16 ();
 
175
 
 
176
                        // DLLFlags                             2
 
177
                        // StackReserveSize             4 || 8
 
178
                        // StackCommitSize              4 || 8
 
179
                        // HeapReserveSize              4 || 8
 
180
                        // HeapCommitSize               4 || 8
 
181
                        // LoaderFlags                  4
 
182
                        // NumberOfDataDir              4
 
183
 
 
184
                        //   - DataDirectoriesHeader
 
185
 
 
186
                        // ExportTable                  8
 
187
                        // ImportTable                  8
 
188
                        // ResourceTable                8
 
189
                        // ExceptionTable               8
 
190
                        // CertificateTable             8
 
191
                        // BaseRelocationTable  8
 
192
 
 
193
                        Advance (pe64 ? 90 : 74);
 
194
 
 
195
                        // Debug                                8
 
196
                        image.Debug = ReadDataDirectory ();
 
197
 
 
198
                        // Copyright                    8
 
199
                        // GlobalPtr                    8
 
200
                        // TLSTable                             8
 
201
                        // LoadConfigTable              8
 
202
                        // BoundImport                  8
 
203
                        // IAT                                  8
 
204
                        // DelayImportDescriptor8
 
205
                        Advance (56);
 
206
 
 
207
                        // CLIHeader                    8
 
208
                        cli = ReadDataDirectory ();
 
209
 
 
210
                        if (cli.IsZero)
 
211
                                throw new BadImageFormatException ();
 
212
 
 
213
                        // Reserved                             8
 
214
                        Advance (8);
 
215
                }
 
216
 
 
217
                string ReadAlignedString (int length)
 
218
                {
 
219
                        int read = 0;
 
220
                        var buffer = new char [length];
 
221
                        while (read < length) {
 
222
                                var current = ReadByte ();
 
223
                                if (current == 0)
 
224
                                        break;
 
225
 
 
226
                                buffer [read++] = (char) current;
 
227
                        }
 
228
 
 
229
                        Advance (-1 + ((read + 4) & ~3) - read);
 
230
 
 
231
                        return new string (buffer, 0, read);
 
232
                }
 
233
 
 
234
                string ReadZeroTerminatedString (int length)
 
235
                {
 
236
                        int read = 0;
 
237
                        var buffer = new char [length];
 
238
                        var bytes = ReadBytes (length);
 
239
                        while (read < length) {
 
240
                                var current = bytes [read];
 
241
                                if (current == 0)
 
242
                                        break;
 
243
 
 
244
                                buffer [read++] = (char) current;
 
245
                        }
 
246
 
 
247
                        return new string (buffer, 0, read);
 
248
                }
 
249
 
 
250
                void ReadSections (ushort count)
 
251
                {
 
252
                        var sections = new Section [count];
 
253
 
 
254
                        for (int i = 0; i < count; i++) {
 
255
                                var section = new Section ();
 
256
 
 
257
                                // Name
 
258
                                section.Name = ReadZeroTerminatedString (8);
 
259
 
 
260
                                // VirtualSize          4
 
261
                                Advance (4);
 
262
 
 
263
                                // VirtualAddress       4
 
264
                                section.VirtualAddress = ReadUInt32 ();
 
265
                                // SizeOfRawData        4
 
266
                                section.SizeOfRawData = ReadUInt32 ();
 
267
                                // PointerToRawData     4
 
268
                                section.PointerToRawData = ReadUInt32 ();
 
269
 
 
270
                                // PointerToRelocations         4
 
271
                                // PointerToLineNumbers         4
 
272
                                // NumberOfRelocations          2
 
273
                                // NumberOfLineNumbers          2
 
274
                                // Characteristics                      4
 
275
                                Advance (16);
 
276
 
 
277
                                sections [i] = section;
 
278
 
 
279
                                if (section.Name == ".reloc")
 
280
                                        continue;
 
281
 
 
282
                                ReadSectionData (section);
 
283
                        }
 
284
 
 
285
                        image.Sections = sections;
 
286
                }
 
287
 
 
288
                void ReadSectionData (Section section)
 
289
                {
 
290
                        var position = BaseStream.Position;
 
291
 
 
292
                        MoveTo (section.PointerToRawData);
 
293
 
 
294
                        var length = (int) section.SizeOfRawData;
 
295
                        var data = new byte [length];
 
296
                        int offset = 0, read;
 
297
 
 
298
                        while ((read = Read (data, offset, length - offset)) > 0)
 
299
                                offset += read;
 
300
 
 
301
                        section.Data = data;
 
302
 
 
303
                        BaseStream.Position = position;
 
304
                }
 
305
 
 
306
                void ReadCLIHeader ()
 
307
                {
 
308
                        MoveTo (cli);
 
309
 
 
310
                        // - CLIHeader
 
311
 
 
312
                        // Cb                                           4
 
313
                        // MajorRuntimeVersion          2
 
314
                        // MinorRuntimeVersion          2
 
315
                        Advance (8);
 
316
 
 
317
                        // Metadata                                     8
 
318
                        metadata = ReadDataDirectory ();
 
319
                        // Flags                                        4
 
320
                        image.Attributes = (ModuleAttributes) ReadUInt32 ();
 
321
                        // EntryPointToken                      4
 
322
                        image.EntryPointToken = ReadUInt32 ();
 
323
                        // Resources                            8
 
324
                        image.Resources = ReadDataDirectory ();
 
325
                        // StrongNameSignature          8
 
326
                        // CodeManagerTable                     8
 
327
                        // VTableFixups                         8
 
328
                        // ExportAddressTableJumps      8
 
329
                        // ManagedNativeHeader          8
 
330
                }
 
331
 
 
332
                void ReadMetadata ()
 
333
                {
 
334
                        MoveTo (metadata);
 
335
 
 
336
                        if (ReadUInt32 () != 0x424a5342)
 
337
                                throw new BadImageFormatException ();
 
338
 
 
339
                        // MajorVersion                 2
 
340
                        // MinorVersion                 2
 
341
                        // Reserved                             4
 
342
                        Advance (8);
 
343
 
 
344
                        var version = ReadZeroTerminatedString (ReadInt32 ());
 
345
                        image.Runtime = version.ParseRuntime ();
 
346
 
 
347
                        // Flags                2
 
348
                        Advance (2);
 
349
 
 
350
                        var streams = ReadUInt16 ();
 
351
 
 
352
                        var section = image.GetSectionAtVirtualAddress (metadata.VirtualAddress);
 
353
                        if (section == null)
 
354
                                throw new BadImageFormatException ();
 
355
 
 
356
                        image.MetadataSection = section;
 
357
 
 
358
                        for (int i = 0; i < streams; i++)
 
359
                                ReadMetadataStream (section);
 
360
 
 
361
                        if (image.TableHeap != null)
 
362
                                ReadTableHeap ();
 
363
                }
 
364
 
 
365
                void ReadMetadataStream (Section section)
 
366
                {
 
367
                        // Offset               4
 
368
                        uint start = metadata.VirtualAddress - section.VirtualAddress + ReadUInt32 (); // relative to the section start
 
369
 
 
370
                        // Size                 4
 
371
                        uint size = ReadUInt32 ();
 
372
 
 
373
                        var name = ReadAlignedString (16);
 
374
                        switch (name) {
 
375
                        case "#~":
 
376
                        case "#-":
 
377
                                image.TableHeap = new TableHeap (section, start, size);
 
378
                                break;
 
379
                        case "#Strings":
 
380
                                image.StringHeap = new StringHeap (section, start, size);
 
381
                                break;
 
382
                        case "#Blob":
 
383
                                image.BlobHeap = new BlobHeap (section, start, size);
 
384
                                break;
 
385
                        case "#GUID":
 
386
                                image.GuidHeap = new GuidHeap (section, start, size);
 
387
                                break;
 
388
                        case "#US":
 
389
                                image.UserStringHeap = new UserStringHeap (section, start, size);
 
390
                                break;
 
391
                        }
 
392
                }
 
393
 
 
394
                void ReadTableHeap ()
 
395
                {
 
396
                        var heap = image.TableHeap;
 
397
 
 
398
                        uint start = heap.Section.PointerToRawData;
 
399
 
 
400
                        MoveTo (heap.Offset + start);
 
401
 
 
402
                        // Reserved                     4
 
403
                        // MajorVersion         1
 
404
                        // MinorVersion         1
 
405
                        Advance (6);
 
406
 
 
407
                        // HeapSizes            1
 
408
                        var sizes = ReadByte ();
 
409
 
 
410
                        // Reserved2            1
 
411
                        Advance (1);
 
412
 
 
413
                        // Valid                        8
 
414
                        heap.Valid = ReadInt64 ();
 
415
 
 
416
                        // Sorted                       8
 
417
                        heap.Sorted = ReadInt64 ();
 
418
 
 
419
                        for (int i = 0; i < TableHeap.TableIdentifiers.Length; i++) {
 
420
                                var table = TableHeap.TableIdentifiers [i];
 
421
                                if (!heap.HasTable (table))
 
422
                                        continue;
 
423
 
 
424
                                heap.Tables [(int) table].Length = ReadUInt32 ();
 
425
                        }
 
426
 
 
427
                        SetIndexSize (image.StringHeap, sizes, 0x1);
 
428
                        SetIndexSize (image.GuidHeap, sizes, 0x2);
 
429
                        SetIndexSize (image.BlobHeap, sizes, 0x4);
 
430
 
 
431
                        ComputeTableInformations ();
 
432
                }
 
433
 
 
434
                static void SetIndexSize (Heap heap, uint sizes, byte flag)
 
435
                {
 
436
                        if (heap == null)
 
437
                                return;
 
438
 
 
439
                        heap.IndexSize = (sizes & flag) > 0 ? 4 : 2;
 
440
                }
 
441
 
 
442
                int GetTableIndexSize (Table table)
 
443
                {
 
444
                        return image.GetTableIndexSize (table);
 
445
                }
 
446
 
 
447
                int GetCodedIndexSize (CodedIndex index)
 
448
                {
 
449
                        return image.GetCodedIndexSize (index);
 
450
                }
 
451
 
 
452
                void ComputeTableInformations ()
 
453
                {
 
454
                        uint offset = (uint) BaseStream.Position - image.MetadataSection.PointerToRawData; // header
 
455
 
 
456
                        int stridx_size = image.StringHeap.IndexSize;
 
457
                        int blobidx_size = image.BlobHeap != null ? image.BlobHeap.IndexSize : 2;
 
458
 
 
459
                        var heap = image.TableHeap;
 
460
                        var tables = heap.Tables;
 
461
 
 
462
                        for (int i = 0; i < TableHeap.TableIdentifiers.Length; i++) {
 
463
                                var table = TableHeap.TableIdentifiers [i];
 
464
                                if (!heap.HasTable (table))
 
465
                                        continue;
 
466
 
 
467
                                int size;
 
468
                                switch (table) {
 
469
                                case Table.Module:
 
470
                                        size = 2        // Generation
 
471
                                                + stridx_size   // Name
 
472
                                                + (image.GuidHeap.IndexSize * 3);       // Mvid, EncId, EncBaseId
 
473
                                        break;
 
474
                                case Table.TypeRef:
 
475
                                        size = GetCodedIndexSize (CodedIndex.ResolutionScope)   // ResolutionScope
 
476
                                                + (stridx_size * 2);    // Name, Namespace
 
477
                                        break;
 
478
                                case Table.TypeDef:
 
479
                                        size = 4        // Flags
 
480
                                                + (stridx_size * 2)     // Name, Namespace
 
481
                                                + GetCodedIndexSize (CodedIndex.TypeDefOrRef)   // BaseType
 
482
                                                + GetTableIndexSize (Table.Field)       // FieldList
 
483
                                                + GetTableIndexSize (Table.Method);     // MethodList
 
484
                                        break;
 
485
                                case Table.FieldPtr:
 
486
                                        size = GetTableIndexSize (Table.Field); // Field
 
487
                                        break;
 
488
                                case Table.Field:
 
489
                                        size = 2        // Flags
 
490
                                                + stridx_size   // Name
 
491
                                                + blobidx_size; // Signature
 
492
                                        break;
 
493
                                case Table.MethodPtr:
 
494
                                        size = GetTableIndexSize (Table.Method);        // Method
 
495
                                        break;
 
496
                                case Table.Method:
 
497
                                        size = 8        // Rva 4, ImplFlags 2, Flags 2
 
498
                                                + stridx_size   // Name
 
499
                                                + blobidx_size  // Signature
 
500
                                                + GetTableIndexSize (Table.Param); // ParamList
 
501
                                        break;
 
502
                                case Table.ParamPtr:
 
503
                                        size = GetTableIndexSize (Table.Param); // Param
 
504
                                        break;
 
505
                                case Table.Param:
 
506
                                        size = 4        // Flags 2, Sequence 2
 
507
                                                + stridx_size;  // Name
 
508
                                        break;
 
509
                                case Table.InterfaceImpl:
 
510
                                        size = GetTableIndexSize (Table.TypeDef)        // Class
 
511
                                                + GetCodedIndexSize (CodedIndex.TypeDefOrRef);  // Interface
 
512
                                        break;
 
513
                                case Table.MemberRef:
 
514
                                        size = GetCodedIndexSize (CodedIndex.MemberRefParent)   // Class
 
515
                                                + stridx_size   // Name
 
516
                                                + blobidx_size; // Signature
 
517
                                        break;
 
518
                                case Table.Constant:
 
519
                                        size = 2        // Type
 
520
                                                + GetCodedIndexSize (CodedIndex.HasConstant)    // Parent
 
521
                                                + blobidx_size; // Value
 
522
                                        break;
 
523
                                case Table.CustomAttribute:
 
524
                                        size = GetCodedIndexSize (CodedIndex.HasCustomAttribute)        // Parent
 
525
                                                + GetCodedIndexSize (CodedIndex.CustomAttributeType)    // Type
 
526
                                                + blobidx_size; // Value
 
527
                                        break;
 
528
                                case Table.FieldMarshal:
 
529
                                        size = GetCodedIndexSize (CodedIndex.HasFieldMarshal)   // Parent
 
530
                                                + blobidx_size; // NativeType
 
531
                                        break;
 
532
                                case Table.DeclSecurity:
 
533
                                        size = 2        // Action
 
534
                                                + GetCodedIndexSize (CodedIndex.HasDeclSecurity)        // Parent
 
535
                                                + blobidx_size; // PermissionSet
 
536
                                        break;
 
537
                                case Table.ClassLayout:
 
538
                                        size = 6        // PackingSize 2, ClassSize 4
 
539
                                                + GetTableIndexSize (Table.TypeDef);    // Parent
 
540
                                        break;
 
541
                                case Table.FieldLayout:
 
542
                                        size = 4        // Offset
 
543
                                                + GetTableIndexSize (Table.Field);      // Field
 
544
                                        break;
 
545
                                case Table.StandAloneSig:
 
546
                                        size = blobidx_size;    // Signature
 
547
                                        break;
 
548
                                case Table.EventMap:
 
549
                                        size = GetTableIndexSize (Table.TypeDef)        // Parent
 
550
                                                + GetTableIndexSize (Table.Event);      // EventList
 
551
                                        break;
 
552
                                case Table.EventPtr:
 
553
                                        size = GetTableIndexSize (Table.Event); // Event
 
554
                                        break;
 
555
                                case Table.Event:
 
556
                                        size = 2        // Flags
 
557
                                                + stridx_size // Name
 
558
                                                + GetCodedIndexSize (CodedIndex.TypeDefOrRef);  // EventType
 
559
                                        break;
 
560
                                case Table.PropertyMap:
 
561
                                        size = GetTableIndexSize (Table.TypeDef)        // Parent
 
562
                                                + GetTableIndexSize (Table.Property);   // PropertyList
 
563
                                        break;
 
564
                                case Table.PropertyPtr:
 
565
                                        size = GetTableIndexSize (Table.Property);      // Property
 
566
                                        break;
 
567
                                case Table.Property:
 
568
                                        size = 2        // Flags
 
569
                                                + stridx_size   // Name
 
570
                                                + blobidx_size; // Type
 
571
                                        break;
 
572
                                case Table.MethodSemantics:
 
573
                                        size = 2        // Semantics
 
574
                                                + GetTableIndexSize (Table.Method)      // Method
 
575
                                                + GetCodedIndexSize (CodedIndex.HasSemantics);  // Association
 
576
                                        break;
 
577
                                case Table.MethodImpl:
 
578
                                        size = GetTableIndexSize (Table.TypeDef)        // Class
 
579
                                                + GetCodedIndexSize (CodedIndex.MethodDefOrRef) // MethodBody
 
580
                                                + GetCodedIndexSize (CodedIndex.MethodDefOrRef);        // MethodDeclaration
 
581
                                        break;
 
582
                                case Table.ModuleRef:
 
583
                                        size = stridx_size;     // Name
 
584
                                        break;
 
585
                                case Table.TypeSpec:
 
586
                                        size = blobidx_size;    // Signature
 
587
                                        break;
 
588
                                case Table.ImplMap:
 
589
                                        size = 2        // MappingFlags
 
590
                                                + GetCodedIndexSize (CodedIndex.MemberForwarded)        // MemberForwarded
 
591
                                                + stridx_size   // ImportName
 
592
                                                + GetTableIndexSize (Table.ModuleRef);  // ImportScope
 
593
                                        break;
 
594
                                case Table.FieldRVA:
 
595
                                        size = 4        // RVA
 
596
                                                + GetTableIndexSize (Table.Field);      // Field
 
597
                                        break;
 
598
                                case Table.Assembly:
 
599
                                        size = 16 // HashAlgId 4, Version 4 * 2, Flags 4
 
600
                                                + blobidx_size  // PublicKey
 
601
                                                + (stridx_size * 2);    // Name, Culture
 
602
                                        break;
 
603
                                case Table.AssemblyProcessor:
 
604
                                        size = 4;       // Processor
 
605
                                        break;
 
606
                                case Table.AssemblyOS:
 
607
                                        size = 12;      // Platform 4, Version 2 * 4
 
608
                                        break;
 
609
                                case Table.AssemblyRef:
 
610
                                        size = 12       // Version 2 * 4 + Flags 4
 
611
                                                + (blobidx_size * 2)    // PublicKeyOrToken, HashValue
 
612
                                                + (stridx_size * 2);    // Name, Culture
 
613
                                        break;
 
614
                                case Table.AssemblyRefProcessor:
 
615
                                        size = 4        // Processor
 
616
                                                + GetTableIndexSize (Table.AssemblyRef);        // AssemblyRef
 
617
                                        break;
 
618
                                case Table.AssemblyRefOS:
 
619
                                        size = 12       // Platform 4, Version 2 * 4
 
620
                                                + GetTableIndexSize (Table.AssemblyRef);        // AssemblyRef
 
621
                                        break;
 
622
                                case Table.File:
 
623
                                        size = 4        // Flags
 
624
                                                + stridx_size   // Name
 
625
                                                + blobidx_size; // HashValue
 
626
                                        break;
 
627
                                case Table.ExportedType:
 
628
                                        size = 8        // Flags 4, TypeDefId 4
 
629
                                                + (stridx_size * 2)     // Name, Namespace
 
630
                                                + GetCodedIndexSize (CodedIndex.Implementation);        // Implementation
 
631
                                        break;
 
632
                                case Table.ManifestResource:
 
633
                                        size = 8        // Offset, Flags
 
634
                                                + stridx_size   // Name
 
635
                                                + GetCodedIndexSize (CodedIndex.Implementation);        // Implementation
 
636
                                        break;
 
637
                                case Table.NestedClass:
 
638
                                        size = GetTableIndexSize (Table.TypeDef)        // NestedClass
 
639
                                                + GetTableIndexSize (Table.TypeDef);    // EnclosingClass
 
640
                                        break;
 
641
                                case Table.GenericParam:
 
642
                                        size = 4        // Number, Flags
 
643
                                                + GetCodedIndexSize (CodedIndex.TypeOrMethodDef)        // Owner
 
644
                                                + stridx_size;  // Name
 
645
                                        break;
 
646
                                case Table.MethodSpec:
 
647
                                        size = GetCodedIndexSize (CodedIndex.MethodDefOrRef)    // Method
 
648
                                                + blobidx_size; // Instantiation
 
649
                                        break;
 
650
                                case Table.GenericParamConstraint:
 
651
                                        size = GetTableIndexSize (Table.GenericParam)   // Owner
 
652
                                                + GetCodedIndexSize (CodedIndex.TypeDefOrRef);  // Constraint
 
653
                                        break;
 
654
                                default:
 
655
                                        throw new NotSupportedException ();
 
656
                                }
 
657
 
 
658
                                int index = (int) table;
 
659
 
 
660
                                tables [index].RowSize = (uint) size;
 
661
                                tables [index].Offset = offset;
 
662
 
 
663
                                offset += (uint) size * tables [index].Length;
 
664
                        }
 
665
                }
 
666
 
 
667
                public static Image ReadImageFrom (Stream stream)
 
668
                {
 
669
                        try {
 
670
                                var reader = new ImageReader (stream);
 
671
                                reader.ReadImage ();
 
672
                                return reader.image;
 
673
                        } catch (EndOfStreamException e) {
 
674
                                throw new BadImageFormatException (stream.GetFullyQualifiedName (), e);
 
675
                        }
 
676
                }
 
677
        }
 
678
}