2 Intel Open Source License
4 Copyright (c) 2002-2007 Intel Corporation
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are
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.
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.
31 /// @file xed-disas-pecoff.cpp
32 /// @author Mark Charney <mark.charney@intel.com>
34 //// ONLY COMPILES IF -mno-cygwin is thrown on to GCC compilations
36 #include "xed-disas-pecoff.H"
38 #if defined(XED_PECOFF_FILE_READER)
44 // windows specific headers
48 // xed headers -- THESE MUST BE AFTER THE WINDOWS HEADERS
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
57 #include "xed-disas-pecoff.h"
58 #include "xed-examples-ostreams.h"
63 windows_error(const char* syscall,
66 std::ostringstream os;
67 os << "Mapped file:: " << syscall
68 << " for file " << filename << " failed: ";
69 switch (GetLastError())
72 os << "File not found";
75 os << "Path not found";
78 os << "Access denied";
81 os << "Invalid drive";
84 os << "error code " << STATIC_CAST(xed_uint32_t,GetLastError());
93 /// NT handle for the open file.
96 /// NT handle for the memory mapping.
101 xed_bool_t sixty_four_bit_;
103 const IMAGE_SECTION_HEADER* hdr;
104 const IMAGE_SECTION_HEADER* orig_hdr;
105 unsigned int nsections;
106 xed_uint64_t image_base;
110 xed_uint32_t section_index;
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_; }
128 file_handle_ = INVALID_HANDLE_VALUE;
129 map_handle_ = INVALID_HANDLE_VALUE;
131 sixty_four_bit_ = false;
145 UnmapViewOfFile(base_);
147 if (map_handle_ != INVALID_HANDLE_VALUE)
149 CloseHandle(map_handle_);
151 if (file_handle_ != INVALID_HANDLE_VALUE)
153 CloseHandle(file_handle_);
161 map_region(const char* input_file_name,
165 std::string error_msg;
168 file_handle_ = CreateFile(input_file_name,
173 FILE_FLAG_NO_BUFFERING + FILE_ATTRIBUTE_READONLY,
175 if (file_handle_ == INVALID_HANDLE_VALUE) {
176 error_msg = windows_error("CreateFile", input_file_name);
177 xedex_derror(error_msg.c_str());
180 map_handle_ = CreateFileMapping(file_handle_,
187 if (map_handle_ == INVALID_HANDLE_VALUE) {
188 error_msg = windows_error("CreateFileMapping", input_file_name);
189 xedex_derror(error_msg.c_str());
192 base_ = MapViewOfFile(map_handle_,
193 FILE_MAP_READ, 0, 0, 0);
200 error_msg = windows_error("MapViewOfFile", input_file_name);
201 CloseHandle(map_handle_);
202 map_handle_ = INVALID_HANDLE_VALUE;
204 CloseHandle(file_handle_);
205 file_handle_ = INVALID_HANDLE_VALUE;
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");
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)
231 xed_uint8_t*& section_start,
232 xed_uint32_t& section_size,
233 xed_uint64_t& virtual_addr)
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];
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
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;
258 for ( ii = section_index; ii < nsections; ii++, hdr++) {
259 if (strncmp(reinterpret_cast<const char*>(hdr->Name), my_name,
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;
277 static inline const void*
278 ptr_add(const void* ptr, unsigned int n) {
279 return static_cast<const char*>(ptr)+n;
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)
289 // Point to the PE signature word and check it.
290 const DWORD* sig = static_cast<const DWORD*>(ptr_add(base_, dh->e_lfanew));
292 // This must be a valid PE file with a valid DOS header.
293 if (*sig != IMAGE_NT_SIGNATURE)
301 parse_nt_file_header(unsigned int* pnsections,
302 xed_uint64_t* pimage_base,
303 const IMAGE_SECTION_HEADER** phdr)
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;
309 // Check the header to see if this is a valid .exe file
310 if (is_valid_module())
312 // Point to the DOS header.
313 const IMAGE_DOS_HEADER* dh = static_cast<const IMAGE_DOS_HEADER*>(base_);
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));
320 // Maybe this is a .obj file, which starts with the image file header
321 ifh = static_cast<const IMAGE_FILE_HEADER*>(base_);
324 #if !defined(IMAGE_FILE_MACHINE_AMD64)
325 # define IMAGE_FILE_MACHINE_AMD64 0x8664
328 if (ifh->Machine == IMAGE_FILE_MACHINE_I386) {
329 cout << "# IA32 format" << endl;
330 sixty_four_bit_ = false;
332 else if (ifh->Machine == IMAGE_FILE_MACHINE_AMD64) {
333 cout << "# Intel64 format" << endl;
334 sixty_four_bit_ = true;
337 // We only support Windows formats on IA32 and Intel64
343 // Very important to use the 32b header here because the
344 // unqualified IMAGE_OPTIONAL_HEADER gets the wrong version on
346 const IMAGE_OPTIONAL_HEADER32* opthdr32
347 = static_cast<const IMAGE_OPTIONAL_HEADER32*>(ptr_add(ifh, sizeof(*ifh)));
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
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
358 if (ifh->SizeOfOptionalHeader > 0)
360 if (opthdr32->Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
362 *pimage_base = opthdr32->ImageBase;
363 //cerr << hex << "IMAGE BASE 32b: " << *pimage_base << dec << endl;
365 else if (opthdr32->Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
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;
374 xedex_derror("No support for 64b optional headers because older MS compilers do not have the type yet");
377 xedex_derror("No support for 64b optional headers because cygwin does nt have the type yet");
383 // Optional header is not a form we recognize, so punt.
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;
399 ////////////////////////////////////////////////////////////////////////////
404 process_pecoff(xed_uint8_t* start,
406 xed_decode_file_info_t& decode_info,
407 pecoff_reader_t& reader,
408 const char* target_section)
410 xed_uint8_t* section_start = 0;
411 xed_uint32_t section_size = 0;
412 xed_uint64_t runtime_vaddr = 0;
414 xed_bool_t okay = true;
415 xed_bool_t found = false;
417 okay = reader.module_section_info(target_section,
422 printf ("# SECTION %d\n", reader.section_index-1);
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),
430 decode_info.decode_only,0);
434 xedex_derror("text section not found");
439 xed_disas_pecoff(const char* input_file_name,
440 const xed_state_t* dstate,
442 xed_bool_t sixty_four_bit,
443 xed_bool_t decode_only,
444 const char* target_section)
446 xed_uint8_t* region = 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);
452 xedex_derror("image read failed");
454 printf("Mapped image\n");
455 image_reader.read_header();
456 region = REINTERPRET_CAST(xed_uint8_t*,vregion);
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
462 local_dstate.mmode = XED_MACHINE_MODE_LONG_64;
463 local_dstate.addr_width = XED_ADDRESS_WIDTH_64b;
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();
476 //pref: "xed-disas-pecoff.H"