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 	sealed class Image {
40 
41 		public ModuleKind Kind;
42 		public TargetRuntime Runtime;
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