507dd5e0e8c4ca06021dc011eb66d295e40497f6
[mono.git] / mcs / tools / cil-strip / Mono.Cecil.Binary / Image.cs
1 //
2 // Image.cs
3 //
4 // Author:
5 //   Jb Evain (jbevain@gmail.com)
6 //
7 // (C) 2005 - 2007 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 namespace Mono.Cecil.Binary {
30
31         using System;
32         using System.IO;
33
34         using Mono.Cecil.Metadata;
35
36         internal sealed class Image : IBinaryVisitable {
37
38                 DOSHeader m_dosHeader;
39                 PEFileHeader m_peFileHeader;
40                 PEOptionalHeader m_peOptionalHeader;
41
42                 SectionCollection m_sections;
43                 Section m_textSection;
44
45                 ImportAddressTable m_importAddressTable;
46                 CLIHeader m_cliHeader;
47                 ImportTable m_importTable;
48                 ImportLookupTable m_importLookupTable;
49                 HintNameTable m_hintNameTable;
50                 ExportTable m_exportTable;
51
52                 DebugHeader m_debugHeader;
53                 MetadataRoot m_mdRoot;
54
55                 ResourceDirectoryTable m_rsrcRoot;
56
57                 FileInfo m_img;
58
59                 public DOSHeader DOSHeader {
60                         get { return m_dosHeader; }
61                 }
62
63                 public PEFileHeader PEFileHeader {
64                         get { return m_peFileHeader; }
65                 }
66
67                 public PEOptionalHeader PEOptionalHeader {
68                         get { return m_peOptionalHeader; }
69                 }
70
71                 public SectionCollection Sections {
72                         get { return m_sections; }
73                 }
74
75                 public Section TextSection {
76                         get { return m_textSection; }
77                         set { m_textSection = value; }
78                 }
79
80                 public ImportAddressTable ImportAddressTable {
81                         get { return m_importAddressTable; }
82                 }
83
84                 public CLIHeader CLIHeader {
85                         get { return m_cliHeader; }
86                         set { m_cliHeader = value; }
87                 }
88
89                 public DebugHeader DebugHeader {
90                         get { return m_debugHeader; }
91                         set { m_debugHeader = value; }
92                 }
93
94                 public MetadataRoot MetadataRoot {
95                         get { return m_mdRoot; }
96                 }
97
98                 public ImportTable ImportTable {
99                         get { return m_importTable; }
100                 }
101
102                 public ImportLookupTable ImportLookupTable {
103                         get { return m_importLookupTable; }
104                 }
105
106                 public HintNameTable HintNameTable {
107                         get { return m_hintNameTable; }
108                 }
109
110                 public ExportTable ExportTable {
111                         get { return m_exportTable; }
112                         set { m_exportTable = value; }
113                 }
114
115                 internal ResourceDirectoryTable ResourceDirectoryRoot {
116                         get { return m_rsrcRoot; }
117                         set { m_rsrcRoot = value; }
118                 }
119
120                 public FileInfo FileInformation {
121                         get { return m_img; }
122                 }
123
124                 internal Image ()
125                 {
126                         m_dosHeader = new DOSHeader ();
127                         m_peFileHeader = new PEFileHeader ();
128                         m_peOptionalHeader = new PEOptionalHeader ();
129                         m_sections = new SectionCollection ();
130                         m_importAddressTable = new ImportAddressTable ();
131                         m_importTable = new ImportTable ();
132                         m_importLookupTable = new ImportLookupTable ();
133                         m_hintNameTable = new HintNameTable ();
134                         m_mdRoot = new MetadataRoot (this);
135                 }
136
137                 internal Image (FileInfo img) : this ()
138                 {
139                         m_img = img;
140                 }
141
142                 public long ResolveVirtualAddress (RVA rva)
143                 {
144                         foreach (Section sect in this.Sections) {
145                                 if (rva >= sect.VirtualAddress &&
146                                         rva < sect.VirtualAddress + sect.SizeOfRawData)
147
148                                         return rva + sect.PointerToRawData - sect.VirtualAddress;
149                         }
150
151                         throw new ArgumentOutOfRangeException ("Cannot map the rva to any section");
152                 }
153
154                 internal Section GetSectionAtVirtualAddress (RVA rva)
155                 {
156                         foreach (Section sect in this.Sections) {
157                                 if (rva >= sect.VirtualAddress &&
158                                         rva < sect.VirtualAddress + sect.SizeOfRawData) {
159                                         return sect;
160                                 }
161                         }
162                         return null;
163                 }
164
165                 public BinaryReader GetReaderAtVirtualAddress (RVA rva)
166                 {
167                         Section sect = GetSectionAtVirtualAddress (rva);
168                         if (sect == null)
169                                 return null;
170
171                         BinaryReader br = new BinaryReader (new MemoryStream (sect.Data));
172                         br.BaseStream.Position = rva - sect.VirtualAddress;
173                         return br;
174                 }
175
176                 public void AddDebugHeader ()
177                 {
178                         m_debugHeader = new DebugHeader ();
179                         m_debugHeader.SetDefaultValues ();
180                 }
181
182                 internal void SetFileInfo (FileInfo file)
183                 {
184                         m_img = file;
185                 }
186
187                 public void Accept (IBinaryVisitor visitor)
188                 {
189                         visitor.VisitImage (this);
190
191                         m_dosHeader.Accept (visitor);
192                         m_peFileHeader.Accept (visitor);
193                         m_peOptionalHeader.Accept (visitor);
194
195                         m_sections.Accept (visitor);
196
197                         m_importAddressTable.Accept (visitor);
198
199                         AcceptIfNotNull (m_cliHeader, visitor);
200                         AcceptIfNotNull (m_debugHeader, visitor);
201
202                         m_importTable.Accept (visitor);
203                         m_importLookupTable.Accept (visitor);
204                         m_hintNameTable.Accept (visitor);
205                         AcceptIfNotNull (m_exportTable, visitor);
206
207                         visitor.TerminateImage (this);
208                 }
209
210                 static void AcceptIfNotNull (IBinaryVisitable visitable, IBinaryVisitor visitor)
211                 {
212                         if (visitable == null)
213                                 return;
214
215                         visitable.Accept (visitor);
216                 }
217
218                 public static Image CreateImage ()
219                 {
220                         Image img = new Image ();
221
222                         ImageInitializer init = new ImageInitializer (img);
223                         img.Accept (init);
224
225                         return img;
226                 }
227
228                 public static Image GetImage (string file)
229                 {
230                         return ImageReader.Read (file).Image;
231                 }
232
233                 public static Image GetImage (byte [] image)
234                 {
235                         return ImageReader.Read (image).Image;
236                 }
237
238                 public static Image GetImage (Stream stream)
239                 {
240                         return ImageReader.Read (stream).Image;
241                 }
242         }
243 }