ImageReader.cs 20 KB

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