1 | // |
---|
2 | // ImageReader.cs |
---|
3 | // |
---|
4 | // Author: |
---|
5 | // Jb Evain (jbevain@gmail.com) |
---|
6 | // |
---|
7 | // Copyright (c) 2008 - 2011 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.TableCount; i++) { |
---|
420 | if (!heap.HasTable ((Table) i)) |
---|
421 | continue; |
---|
422 | |
---|
423 | heap.Tables [i].Length = ReadUInt32 (); |
---|
424 | } |
---|
425 | |
---|
426 | SetIndexSize (image.StringHeap, sizes, 0x1); |
---|
427 | SetIndexSize (image.GuidHeap, sizes, 0x2); |
---|
428 | SetIndexSize (image.BlobHeap, sizes, 0x4); |
---|
429 | |
---|
430 | ComputeTableInformations (); |
---|
431 | } |
---|
432 | |
---|
433 | static void SetIndexSize (Heap heap, uint sizes, byte flag) |
---|
434 | { |
---|
435 | if (heap == null) |
---|
436 | return; |
---|
437 | |
---|
438 | heap.IndexSize = (sizes & flag) > 0 ? 4 : 2; |
---|
439 | } |
---|
440 | |
---|
441 | int GetTableIndexSize (Table table) |
---|
442 | { |
---|
443 | return image.GetTableIndexSize (table); |
---|
444 | } |
---|
445 | |
---|
446 | int GetCodedIndexSize (CodedIndex index) |
---|
447 | { |
---|
448 | return image.GetCodedIndexSize (index); |
---|
449 | } |
---|
450 | |
---|
451 | void ComputeTableInformations () |
---|
452 | { |
---|
453 | uint offset = (uint) BaseStream.Position - image.MetadataSection.PointerToRawData; // header |
---|
454 | |
---|
455 | int stridx_size = image.StringHeap.IndexSize; |
---|
456 | int blobidx_size = image.BlobHeap != null ? image.BlobHeap.IndexSize : 2; |
---|
457 | |
---|
458 | var heap = image.TableHeap; |
---|
459 | var tables = heap.Tables; |
---|
460 | |
---|
461 | for (int i = 0; i < TableHeap.TableCount; i++) { |
---|
462 | var table = (Table) i; |
---|
463 | if (!heap.HasTable (table)) |
---|
464 | continue; |
---|
465 | |
---|
466 | int size; |
---|
467 | switch (table) { |
---|
468 | case Table.Module: |
---|
469 | size = 2 // Generation |
---|
470 | + stridx_size // Name |
---|
471 | + (image.GuidHeap.IndexSize * 3); // Mvid, EncId, EncBaseId |
---|
472 | break; |
---|
473 | case Table.TypeRef: |
---|
474 | size = GetCodedIndexSize (CodedIndex.ResolutionScope) // ResolutionScope |
---|
475 | + (stridx_size * 2); // Name, Namespace |
---|
476 | break; |
---|
477 | case Table.TypeDef: |
---|
478 | size = 4 // Flags |
---|
479 | + (stridx_size * 2) // Name, Namespace |
---|
480 | + GetCodedIndexSize (CodedIndex.TypeDefOrRef) // BaseType |
---|
481 | + GetTableIndexSize (Table.Field) // FieldList |
---|
482 | + GetTableIndexSize (Table.Method); // MethodList |
---|
483 | break; |
---|
484 | case Table.FieldPtr: |
---|
485 | size = GetTableIndexSize (Table.Field); // Field |
---|
486 | break; |
---|
487 | case Table.Field: |
---|
488 | size = 2 // Flags |
---|
489 | + stridx_size // Name |
---|
490 | + blobidx_size; // Signature |
---|
491 | break; |
---|
492 | case Table.MethodPtr: |
---|
493 | size = GetTableIndexSize (Table.Method); // Method |
---|
494 | break; |
---|
495 | case Table.Method: |
---|
496 | size = 8 // Rva 4, ImplFlags 2, Flags 2 |
---|
497 | + stridx_size // Name |
---|
498 | + blobidx_size // Signature |
---|
499 | + GetTableIndexSize (Table.Param); // ParamList |
---|
500 | break; |
---|
501 | case Table.ParamPtr: |
---|
502 | size = GetTableIndexSize (Table.Param); // Param |
---|
503 | break; |
---|
504 | case Table.Param: |
---|
505 | size = 4 // Flags 2, Sequence 2 |
---|
506 | + stridx_size; // Name |
---|
507 | break; |
---|
508 | case Table.InterfaceImpl: |
---|
509 | size = GetTableIndexSize (Table.TypeDef) // Class |
---|
510 | + GetCodedIndexSize (CodedIndex.TypeDefOrRef); // Interface |
---|
511 | break; |
---|
512 | case Table.MemberRef: |
---|
513 | size = GetCodedIndexSize (CodedIndex.MemberRefParent) // Class |
---|
514 | + stridx_size // Name |
---|
515 | + blobidx_size; // Signature |
---|
516 | break; |
---|
517 | case Table.Constant: |
---|
518 | size = 2 // Type |
---|
519 | + GetCodedIndexSize (CodedIndex.HasConstant) // Parent |
---|
520 | + blobidx_size; // Value |
---|
521 | break; |
---|
522 | case Table.CustomAttribute: |
---|
523 | size = GetCodedIndexSize (CodedIndex.HasCustomAttribute) // Parent |
---|
524 | + GetCodedIndexSize (CodedIndex.CustomAttributeType) // Type |
---|
525 | + blobidx_size; // Value |
---|
526 | break; |
---|
527 | case Table.FieldMarshal: |
---|
528 | size = GetCodedIndexSize (CodedIndex.HasFieldMarshal) // Parent |
---|
529 | + blobidx_size; // NativeType |
---|
530 | break; |
---|
531 | case Table.DeclSecurity: |
---|
532 | size = 2 // Action |
---|
533 | + GetCodedIndexSize (CodedIndex.HasDeclSecurity) // Parent |
---|
534 | + blobidx_size; // PermissionSet |
---|
535 | break; |
---|
536 | case Table.ClassLayout: |
---|
537 | size = 6 // PackingSize 2, ClassSize 4 |
---|
538 | + GetTableIndexSize (Table.TypeDef); // Parent |
---|
539 | break; |
---|
540 | case Table.FieldLayout: |
---|
541 | size = 4 // Offset |
---|
542 | + GetTableIndexSize (Table.Field); // Field |
---|
543 | break; |
---|
544 | case Table.StandAloneSig: |
---|
545 | size = blobidx_size; // Signature |
---|
546 | break; |
---|
547 | case Table.EventMap: |
---|
548 | size = GetTableIndexSize (Table.TypeDef) // Parent |
---|
549 | + GetTableIndexSize (Table.Event); // EventList |
---|
550 | break; |
---|
551 | case Table.EventPtr: |
---|
552 | size = GetTableIndexSize (Table.Event); // Event |
---|
553 | break; |
---|
554 | case Table.Event: |
---|
555 | size = 2 // Flags |
---|
556 | + stridx_size // Name |
---|
557 | + GetCodedIndexSize (CodedIndex.TypeDefOrRef); // EventType |
---|
558 | break; |
---|
559 | case Table.PropertyMap: |
---|
560 | size = GetTableIndexSize (Table.TypeDef) // Parent |
---|
561 | + GetTableIndexSize (Table.Property); // PropertyList |
---|
562 | break; |
---|
563 | case Table.PropertyPtr: |
---|
564 | size = GetTableIndexSize (Table.Property); // Property |
---|
565 | break; |
---|
566 | case Table.Property: |
---|
567 | size = 2 // Flags |
---|
568 | + stridx_size // Name |
---|
569 | + blobidx_size; // Type |
---|
570 | break; |
---|
571 | case Table.MethodSemantics: |
---|
572 | size = 2 // Semantics |
---|
573 | + GetTableIndexSize (Table.Method) // Method |
---|
574 | + GetCodedIndexSize (CodedIndex.HasSemantics); // Association |
---|
575 | break; |
---|
576 | case Table.MethodImpl: |
---|
577 | size = GetTableIndexSize (Table.TypeDef) // Class |
---|
578 | + GetCodedIndexSize (CodedIndex.MethodDefOrRef) // MethodBody |
---|
579 | + GetCodedIndexSize (CodedIndex.MethodDefOrRef); // MethodDeclaration |
---|
580 | break; |
---|
581 | case Table.ModuleRef: |
---|
582 | size = stridx_size; // Name |
---|
583 | break; |
---|
584 | case Table.TypeSpec: |
---|
585 | size = blobidx_size; // Signature |
---|
586 | break; |
---|
587 | case Table.ImplMap: |
---|
588 | size = 2 // MappingFlags |
---|
589 | + GetCodedIndexSize (CodedIndex.MemberForwarded) // MemberForwarded |
---|
590 | + stridx_size // ImportName |
---|
591 | + GetTableIndexSize (Table.ModuleRef); // ImportScope |
---|
592 | break; |
---|
593 | case Table.FieldRVA: |
---|
594 | size = 4 // RVA |
---|
595 | + GetTableIndexSize (Table.Field); // Field |
---|
596 | break; |
---|
597 | case Table.EncLog: |
---|
598 | case Table.EncMap: |
---|
599 | size = 4; |
---|
600 | break; |
---|
601 | case Table.Assembly: |
---|
602 | size = 16 // HashAlgId 4, Version 4 * 2, Flags 4 |
---|
603 | + blobidx_size // PublicKey |
---|
604 | + (stridx_size * 2); // Name, Culture |
---|
605 | break; |
---|
606 | case Table.AssemblyProcessor: |
---|
607 | size = 4; // Processor |
---|
608 | break; |
---|
609 | case Table.AssemblyOS: |
---|
610 | size = 12; // Platform 4, Version 2 * 4 |
---|
611 | break; |
---|
612 | case Table.AssemblyRef: |
---|
613 | size = 12 // Version 2 * 4 + Flags 4 |
---|
614 | + (blobidx_size * 2) // PublicKeyOrToken, HashValue |
---|
615 | + (stridx_size * 2); // Name, Culture |
---|
616 | break; |
---|
617 | case Table.AssemblyRefProcessor: |
---|
618 | size = 4 // Processor |
---|
619 | + GetTableIndexSize (Table.AssemblyRef); // AssemblyRef |
---|
620 | break; |
---|
621 | case Table.AssemblyRefOS: |
---|
622 | size = 12 // Platform 4, Version 2 * 4 |
---|
623 | + GetTableIndexSize (Table.AssemblyRef); // AssemblyRef |
---|
624 | break; |
---|
625 | case Table.File: |
---|
626 | size = 4 // Flags |
---|
627 | + stridx_size // Name |
---|
628 | + blobidx_size; // HashValue |
---|
629 | break; |
---|
630 | case Table.ExportedType: |
---|
631 | size = 8 // Flags 4, TypeDefId 4 |
---|
632 | + (stridx_size * 2) // Name, Namespace |
---|
633 | + GetCodedIndexSize (CodedIndex.Implementation); // Implementation |
---|
634 | break; |
---|
635 | case Table.ManifestResource: |
---|
636 | size = 8 // Offset, Flags |
---|
637 | + stridx_size // Name |
---|
638 | + GetCodedIndexSize (CodedIndex.Implementation); // Implementation |
---|
639 | break; |
---|
640 | case Table.NestedClass: |
---|
641 | size = GetTableIndexSize (Table.TypeDef) // NestedClass |
---|
642 | + GetTableIndexSize (Table.TypeDef); // EnclosingClass |
---|
643 | break; |
---|
644 | case Table.GenericParam: |
---|
645 | size = 4 // Number, Flags |
---|
646 | + GetCodedIndexSize (CodedIndex.TypeOrMethodDef) // Owner |
---|
647 | + stridx_size; // Name |
---|
648 | break; |
---|
649 | case Table.MethodSpec: |
---|
650 | size = GetCodedIndexSize (CodedIndex.MethodDefOrRef) // Method |
---|
651 | + blobidx_size; // Instantiation |
---|
652 | break; |
---|
653 | case Table.GenericParamConstraint: |
---|
654 | size = GetTableIndexSize (Table.GenericParam) // Owner |
---|
655 | + GetCodedIndexSize (CodedIndex.TypeDefOrRef); // Constraint |
---|
656 | break; |
---|
657 | default: |
---|
658 | throw new NotSupportedException (); |
---|
659 | } |
---|
660 | |
---|
661 | tables [i].RowSize = (uint) size; |
---|
662 | tables [i].Offset = offset; |
---|
663 | |
---|
664 | offset += (uint) size * tables [i].Length; |
---|
665 | } |
---|
666 | } |
---|
667 | |
---|
668 | public static Image ReadImageFrom (Stream stream) |
---|
669 | { |
---|
670 | try { |
---|
671 | var reader = new ImageReader (stream); |
---|
672 | reader.ReadImage (); |
---|
673 | return reader.image; |
---|
674 | } catch (EndOfStreamException e) { |
---|
675 | throw new BadImageFormatException (stream.GetFullyQualifiedName (), e); |
---|
676 | } |
---|
677 | } |
---|
678 | } |
---|
679 | } |
---|