Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Release 1.0
[palacios.git] / misc / decoder_test / XED2 / examples / xed-disas-pecoff.cpp
1 /*BEGIN_LEGAL 
2 Intel Open Source License 
3
4 Copyright (c) 2002-2007 Intel Corporation 
5 All rights reserved. 
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are
8 met:
9
10 Redistributions of source code must retain the above copyright notice,
11 this list of conditions and the following disclaimer.  Redistributions
12 in binary form must reproduce the above copyright notice, this list of
13 conditions and the following disclaimer in the documentation and/or
14 other materials provided with the distribution.  Neither the name of
15 the Intel Corporation nor the names of its contributors may be used to
16 endorse or promote products derived from this software without
17 specific prior written permission.
18  
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE INTEL OR
23 ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 END_LEGAL */
31 /// @file xed-disas-pecoff.cpp
32 /// @author Mark Charney   <mark.charney@intel.com>
33
34 //// ONLY COMPILES IF -mno-cygwin is thrown on to GCC compilations
35
36 #include "xed-disas-pecoff.H"
37
38 #if defined(XED_PECOFF_FILE_READER)
39 #include <sstream>
40 #include <iostream>
41 #include <iomanip>
42
43
44 // windows specific headers
45 #include <windows.h>
46 #include <winnt.h>
47
48 // xed headers -- THESE MUST BE AFTER THE WINDOWS HEADERS
49
50
51 extern "C" {
52 #include "xed-interface.h"
53 #include "xed-examples-util.h"
54 #include "xed-portability.h" // This really must be after the windows.h include
55 }
56
57 #include "xed-disas-pecoff.h"
58 #include "xed-examples-ostreams.h"
59 using namespace std;
60
61 // Pronto
62 static std::string
63 windows_error(const char* syscall, 
64               const char* filename)
65 {
66   std::ostringstream os;
67   os << "Mapped file:: " << syscall
68      << " for file " << filename << " failed: ";
69   switch (GetLastError())
70     {
71     case 2:
72       os << "File not found";
73       break;
74     case 3:
75       os << "Path not found";
76       break;
77     case 5:
78       os <<  "Access denied";
79       break;
80     case 15:
81       os << "Invalid drive";
82       break;
83     default:
84       os << "error code " << STATIC_CAST(xed_uint32_t,GetLastError());
85       break;
86     }
87
88   return os.str();
89 }
90
91 class pecoff_reader_t
92 {
93   /// NT handle for the open file.
94   void* file_handle_;
95
96   /// NT handle for the memory mapping.
97   void* map_handle_;
98
99   void* base_;
100   xed_bool_t okay_;
101   xed_bool_t sixty_four_bit_;
102
103   const IMAGE_SECTION_HEADER* hdr;
104   const IMAGE_SECTION_HEADER* orig_hdr;
105   unsigned int nsections;
106   xed_uint64_t image_base;
107     
108
109 public:
110   xed_uint32_t section_index;
111
112   pecoff_reader_t()
113   {
114     init();
115   }
116   ~pecoff_reader_t()
117   {
118     close();
119   }
120
121   void* base() const { return base_; }
122   xed_bool_t okay() const { return okay_; }
123   xed_bool_t sixty_four_bit() const { return sixty_four_bit_; }
124
125   void
126   init()
127   {
128     file_handle_ = INVALID_HANDLE_VALUE;
129     map_handle_ = INVALID_HANDLE_VALUE;
130     okay_ = false;
131     sixty_four_bit_ = false;
132     
133     hdr=0;
134     orig_hdr=0;
135     nsections=0;
136     image_base=0;
137     section_index=0;
138   }
139
140   void
141   close()
142   {
143     if (base_)
144       {
145         UnmapViewOfFile(base_);
146       }
147     if (map_handle_ != INVALID_HANDLE_VALUE)
148       {
149         CloseHandle(map_handle_);
150       }
151     if (file_handle_ != INVALID_HANDLE_VALUE)
152       {
153         CloseHandle(file_handle_);
154       }
155         
156     init();
157   }
158
159
160   xed_bool_t
161   map_region(const char* input_file_name, 
162              void*& vregion,
163              xed_uint32_t& len)
164   {
165     std::string error_msg;
166     okay_ = false;
167
168     file_handle_ = CreateFile(input_file_name,
169                               GENERIC_READ,
170                               FILE_SHARE_READ,
171                               NULL,
172                               OPEN_EXISTING,
173                               FILE_FLAG_NO_BUFFERING + FILE_ATTRIBUTE_READONLY,
174                               NULL);
175     if (file_handle_ == INVALID_HANDLE_VALUE)  {
176       error_msg = windows_error("CreateFile", input_file_name);
177       xedex_derror(error_msg.c_str());
178     }
179
180     map_handle_ = CreateFileMapping(file_handle_,
181                                     NULL,
182                                     PAGE_READONLY,
183                                     0,
184                                     0,
185                                     NULL);
186
187     if (map_handle_ == INVALID_HANDLE_VALUE)   {
188       error_msg = windows_error("CreateFileMapping", input_file_name);
189       xedex_derror(error_msg.c_str());
190     }
191
192     base_ = MapViewOfFile(map_handle_,
193                           FILE_MAP_READ, 0, 0, 0);
194     if (base_ != NULL)   {
195       okay_ = true;
196       vregion = base_;
197       len = 0; //FIXME
198       return true;
199     }
200     error_msg = windows_error("MapViewOfFile", input_file_name);
201     CloseHandle(map_handle_);
202     map_handle_ = INVALID_HANDLE_VALUE;
203         
204     CloseHandle(file_handle_);
205     file_handle_ = INVALID_HANDLE_VALUE;
206     return false;
207   }
208
209
210   xed_bool_t read_header() {
211     if (! parse_nt_file_header(&nsections, &image_base, &hdr)) {
212       xedex_derror("Could not read nt file header");
213       return false;
214     }
215
216     orig_hdr=hdr;
217     return true;
218   }
219   void print_section_headers() { 
220     const IMAGE_SECTION_HEADER* jhdr = orig_hdr;
221     for (unsigned int j = 0; j < nsections; j++, jhdr++)   {
222         cout << "# SECNAME  " << j << " "
223              << reinterpret_cast<const char*>(jhdr->Name) 
224              << endl;
225     }
226   }
227
228   xed_bool_t
229   module_section_info(
230                       const char* secname,
231                       xed_uint8_t*& section_start,
232                       xed_uint32_t& section_size,
233                       xed_uint64_t& virtual_addr)
234   {
235     unsigned int i,ii;
236         
237     if (secname == 0)
238         secname = ".text";
239
240     // Extract the name into a 0-padded 8 byte string.
241     char my_name[IMAGE_SIZEOF_SHORT_NAME];
242     memset(my_name,0,IMAGE_SIZEOF_SHORT_NAME);
243     for( i=0;i<IMAGE_SIZEOF_SHORT_NAME;i++)   {
244       my_name[i] = secname[i];
245       if (secname[i] == 0)
246         break;
247     }
248
249     // There are section names that LOOK like .text$x but they really have
250     // a null string embedded in them. So when you strcmp, you hit the
251     // null.
252     
253     // match the substring that starts with the given target_section_name
254     unsigned int match_len = static_cast<unsigned int>(strlen(secname));
255     if (match_len > IMAGE_SIZEOF_SHORT_NAME)
256         match_len = IMAGE_SIZEOF_SHORT_NAME;
257
258     for ( ii = section_index; ii < nsections; ii++, hdr++)   {
259         if (strncmp(reinterpret_cast<const char*>(hdr->Name), my_name,
260                     match_len) == 0) {
261             // Found it.  Extract the info and return.
262             virtual_addr  = hdr->VirtualAddress  + image_base;
263             section_size = (hdr->Misc.VirtualSize > 0 ? 
264                             hdr->Misc.VirtualSize
265                             : hdr->SizeOfRawData);
266             section_start = (xed_uint8_t*)ptr_add(base_, hdr->PointerToRawData);
267             section_index = ii+1;
268             hdr++;
269             return true;
270           }
271       }
272
273     return false;
274   }
275
276 private:
277   static inline const void*
278   ptr_add(const void* ptr, unsigned int n)  {
279     return static_cast<const char*>(ptr)+n;
280   }
281
282   xed_bool_t
283   is_valid_module()  {
284     // Point to the DOS header and check it.
285     const IMAGE_DOS_HEADER* dh = static_cast<const IMAGE_DOS_HEADER*>(base_);
286     if (dh->e_magic != IMAGE_DOS_SIGNATURE)
287         return false;
288         
289     // Point to the PE signature word and check it.
290     const DWORD* sig = static_cast<const DWORD*>(ptr_add(base_, dh->e_lfanew));
291         
292     // This must be a valid PE file with a valid DOS header.
293     if (*sig != IMAGE_NT_SIGNATURE)
294         return false;
295
296     return true;
297   }
298
299
300   xed_bool_t
301   parse_nt_file_header(unsigned int* pnsections,
302                        xed_uint64_t* pimage_base,
303                        const IMAGE_SECTION_HEADER** phdr)
304   {
305     // Oh joy - the format of a .obj file on Windows is *different*
306     // from the format of a .exe file.  Deal with that.
307     const IMAGE_FILE_HEADER* ifh;
308         
309     // Check the header to see if this is a valid .exe file
310     if (is_valid_module())
311       {
312         // Point to the DOS header.
313         const IMAGE_DOS_HEADER* dh = static_cast<const IMAGE_DOS_HEADER*>(base_);
314             
315         // Point to the COFF File Header (just after the signature)
316         ifh = static_cast<const IMAGE_FILE_HEADER*>(ptr_add(base_, dh->e_lfanew + 4));
317       }
318     else
319       {
320         // Maybe this is a .obj file, which starts with the image file header
321         ifh = static_cast<const IMAGE_FILE_HEADER*>(base_);
322       }
323         
324 #if !defined(IMAGE_FILE_MACHINE_AMD64)
325 # define IMAGE_FILE_MACHINE_AMD64 0x8664
326 #endif
327
328     if (ifh->Machine == IMAGE_FILE_MACHINE_I386) {
329         cout << "# IA32 format" << endl;
330         sixty_four_bit_ = false;
331     }
332     else if (ifh->Machine == IMAGE_FILE_MACHINE_AMD64) {
333         cout << "# Intel64 format" << endl;
334         sixty_four_bit_ = true;
335     }
336     else  {
337         // We only support Windows formats on IA32 and Intel64
338         return false;
339     }
340         
341     *pimage_base = 0;
342         
343     // Very important to use the 32b header here because the
344     // unqualified IMAGE_OPTIONAL_HEADER gets the wrong version on
345     // win64!
346     const IMAGE_OPTIONAL_HEADER32* opthdr32
347       = static_cast<const IMAGE_OPTIONAL_HEADER32*>(ptr_add(ifh, sizeof(*ifh)));
348
349     // Cygwin's w32api winnt.h header doesn't distinguish 32 and 64b.
350 #if !defined(IMAGE_NT_OPTIONAL_HDR32_MAGIC)
351 # define IMAGE_NT_OPTIONAL_HDR32_MAGIC IMAGE_NT_OPTIONAL_HDR_MAGIC
352 #endif
353     // And it lacks the definition for 64b headers
354 #if !defined(IMAGE_NT_OPTIONAL_HDR64_MAGIC)
355 # define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b
356 #endif
357
358     if (ifh->SizeOfOptionalHeader > 0)
359       {
360         if (opthdr32->Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
361           {
362             *pimage_base = opthdr32->ImageBase;
363             //cerr << hex << "IMAGE BASE 32b: " << *pimage_base << dec << endl;
364           }
365         else if (opthdr32->Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
366           {
367 #if defined(_MSC_VER)
368 # if _MSC_VER >= 1400
369             const IMAGE_OPTIONAL_HEADER64* opthdr64 =
370               static_cast<const IMAGE_OPTIONAL_HEADER64*>(ptr_add(ifh, sizeof(*ifh)));
371             *pimage_base = opthdr64->ImageBase;
372             //cerr << hex << "IMAGE BASE 64b: " << *pimage_base << dec << endl;
373 # else
374             xedex_derror("No support for 64b optional headers because older MS compilers do not have the type yet");
375 # endif
376 #else
377             xedex_derror("No support for 64b optional headers because cygwin does nt have the type yet");
378             return false;
379 #endif
380           }
381         else 
382           {
383             // Optional header is not a form we recognize, so punt.
384             return false;
385           }
386       }
387         
388     // Point to the first of the Section Headers
389     *phdr = static_cast<const IMAGE_SECTION_HEADER*>(ptr_add(opthdr32,
390                                                              ifh->SizeOfOptionalHeader));
391     *pnsections = ifh->NumberOfSections;
392     return true;
393   }
394
395
396
397 };
398
399 ////////////////////////////////////////////////////////////////////////////
400
401
402
403 void
404 process_pecoff(xed_uint8_t* start,
405                unsigned int length,
406                xed_decode_file_info_t& decode_info,
407                pecoff_reader_t& reader,
408                const char* target_section)
409 {
410   xed_uint8_t* section_start = 0;
411   xed_uint32_t section_size = 0;
412   xed_uint64_t runtime_vaddr  = 0;
413     
414   xed_bool_t okay = true;
415   xed_bool_t found = false;
416   while(okay) {
417       okay = reader.module_section_info(target_section,
418                                         section_start,
419                                         section_size,
420                                         runtime_vaddr);
421       if (okay) { 
422           printf ("# SECTION %d\n", reader.section_index-1);
423           found = true;
424           xed_disas_test(&decode_info.dstate, 
425                          REINTERPRET_CAST(unsigned char*,start),
426                          REINTERPRET_CAST(unsigned char*,section_start), 
427                          REINTERPRET_CAST(unsigned char*,section_start + section_size),
428                          decode_info.ninst,
429                          runtime_vaddr,
430                          decode_info.decode_only,0);
431       }
432   }
433   if (!found)
434       xedex_derror("text section not found");
435   (void) length;
436 }
437
438 void
439 xed_disas_pecoff(const char* input_file_name,
440                  const xed_state_t* dstate,
441                  int ninst,
442                  xed_bool_t sixty_four_bit,
443                  xed_bool_t decode_only,
444                  const char* target_section)
445 {
446   xed_uint8_t* region = 0;
447   void* vregion = 0;
448   xed_uint32_t len = 0;
449   pecoff_reader_t image_reader;
450   xed_bool_t okay = image_reader.map_region(input_file_name, vregion, len);
451   if (!okay)
452     xedex_derror("image read failed");
453   if (CLIENT_VERBOSE1)
454     printf("Mapped image\n");
455   image_reader.read_header();
456   region = REINTERPRET_CAST(xed_uint8_t*,vregion);
457
458   xed_state_t local_dstate = *dstate;
459   if (image_reader.sixty_four_bit() && sixty_four_bit == 0) {
460       /* modify the default dstate values because we were not expecting a
461        * 64b binary */
462       local_dstate.mmode = XED_MACHINE_MODE_LONG_64;
463       local_dstate.addr_width = XED_ADDRESS_WIDTH_64b;
464   }
465   
466   xed_decode_file_info_t decode_info;
467   xed_decode_file_info_init(&decode_info, &local_dstate, ninst, decode_only);    
468   process_pecoff(region, len,  decode_info, image_reader, target_section);
469   xed_print_decode_stats();
470 }
471  
472
473
474 #endif
475 //Local Variables:
476 //pref: "xed-disas-pecoff.H"
477 //End: