1 // 2 // Image.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 31 using Mono; 32 using Mono.Cecil.Cil; 33 using Mono.Cecil.Metadata; 34 35 using RVA = System.UInt32; 36 37 namespace Mono.Cecil.PE { 38 39 public sealed class Image { 40 41 public ModuleKind Kind; 42 public string RuntimeVersion; 43 public TargetArchitecture Architecture; 44 public ModuleCharacteristics Characteristics; 45 public string FileName; 46 47 public Section [] Sections; 48 49 public Section MetadataSection; 50 51 public uint EntryPointToken; 52 public ModuleAttributes Attributes; 53 54 public DataDirectory Debug; 55 public DataDirectory Resources; 56 public DataDirectory StrongName; 57 58 public StringHeap StringHeap; 59 public BlobHeap BlobHeap; 60 public UserStringHeap UserStringHeap; 61 public GuidHeap GuidHeap; 62 public TableHeap TableHeap; 63 64 readonly int [] coded_index_sizes = new int [13]; 65 66 readonly Func<Table, int> counter; 67 Image()68 public Image () 69 { 70 counter = GetTableLength; 71 } 72 HasTable(Table table)73 public bool HasTable (Table table) 74 { 75 return GetTableLength (table) > 0; 76 } 77 GetTableLength(Table table)78 public int GetTableLength (Table table) 79 { 80 return (int) TableHeap [table].Length; 81 } 82 GetTableIndexSize(Table table)83 public int GetTableIndexSize (Table table) 84 { 85 return GetTableLength (table) < 65536 ? 2 : 4; 86 } 87 GetCodedIndexSize(CodedIndex coded_index)88 public int GetCodedIndexSize (CodedIndex coded_index) 89 { 90 var index = (int) coded_index; 91 var size = coded_index_sizes [index]; 92 if (size != 0) 93 return size; 94 95 return coded_index_sizes [index] = coded_index.GetSize (counter); 96 } 97 ResolveVirtualAddress(RVA rva)98 public uint ResolveVirtualAddress (RVA rva) 99 { 100 var section = GetSectionAtVirtualAddress (rva); 101 if (section == null) 102 throw new ArgumentOutOfRangeException (); 103 104 return ResolveVirtualAddressInSection (rva, section); 105 } 106 ResolveVirtualAddressInSection(RVA rva, Section section)107 public uint ResolveVirtualAddressInSection (RVA rva, Section section) 108 { 109 return rva + section.PointerToRawData - section.VirtualAddress; 110 } 111 GetSection(string name)112 public Section GetSection (string name) 113 { 114 var sections = this.Sections; 115 for (int i = 0; i < sections.Length; i++) { 116 var section = sections [i]; 117 if (section.Name == name) 118 return section; 119 } 120 121 return null; 122 } 123 GetSectionAtVirtualAddress(RVA rva)124 public Section GetSectionAtVirtualAddress (RVA rva) 125 { 126 var sections = this.Sections; 127 for (int i = 0; i < sections.Length; i++) { 128 var section = sections [i]; 129 if (rva >= section.VirtualAddress && rva < section.VirtualAddress + section.SizeOfRawData) 130 return section; 131 } 132 133 return null; 134 } 135 GetDebugHeader(out byte [] header)136 public ImageDebugDirectory GetDebugHeader (out byte [] header) 137 { 138 var section = GetSectionAtVirtualAddress (Debug.VirtualAddress); 139 var buffer = new ByteBuffer (section.Data); 140 buffer.position = (int) (Debug.VirtualAddress - section.VirtualAddress); 141 142 var directory = new ImageDebugDirectory { 143 Characteristics = buffer.ReadInt32 (), 144 TimeDateStamp = buffer.ReadInt32 (), 145 MajorVersion = buffer.ReadInt16 (), 146 MinorVersion = buffer.ReadInt16 (), 147 Type = buffer.ReadInt32 (), 148 SizeOfData = buffer.ReadInt32 (), 149 AddressOfRawData = buffer.ReadInt32 (), 150 PointerToRawData = buffer.ReadInt32 (), 151 }; 152 153 if (directory.SizeOfData == 0 || directory.PointerToRawData == 0) { 154 header = Empty<byte>.Array; 155 return directory; 156 } 157 158 buffer.position = (int) (directory.PointerToRawData - section.PointerToRawData); 159 160 header = new byte [directory.SizeOfData]; 161 Buffer.BlockCopy (buffer.buffer, buffer.position, header, 0, header.Length); 162 163 return directory; 164 } 165 } 166 } 167