168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// found in the LICENSE file.
468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "courgette/disassembler_win32_x64.h"
668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include <algorithm>
868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include <string>
968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include <vector>
1068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
1168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "base/basictypes.h"
1268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "base/logging.h"
1368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
1468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "courgette/assembly_program.h"
1568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "courgette/courgette.h"
1668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "courgette/encoded_program.h"
1768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
1868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)namespace courgette {
1968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
2068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)DisassemblerWin32X64::DisassemblerWin32X64(const void* start, size_t length)
2168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  : Disassembler(start, length),
2268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    incomplete_disassembly_(false),
2368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    is_PE32_plus_(false),
2468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    optional_header_(NULL),
2568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    size_of_optional_header_(0),
2668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    offset_of_data_directories_(0),
2768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    machine_type_(0),
2868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    number_of_sections_(0),
2968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    sections_(NULL),
3068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    has_text_section_(false),
3168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    size_of_code_(0),
3268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    size_of_initialized_data_(0),
3368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    size_of_uninitialized_data_(0),
3468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    base_of_code_(0),
3568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    base_of_data_(0),
3668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    image_base_(0),
3768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    size_of_image_(0),
3868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    number_of_data_directories_(0) {
3968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
4068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
4168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// ParseHeader attempts to match up the buffer with the Windows data
4268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// structures that exist within a Windows 'Portable Executable' format file.
4368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// Returns 'true' if the buffer matches, and 'false' if the data looks
4468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// suspicious.  Rather than try to 'map' the buffer to the numerous windows
4568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// structures, we extract the information we need into the courgette::PEInfo
4668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// structure.
4768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)//
4868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool DisassemblerWin32X64::ParseHeader() {
4968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (length() < kOffsetOfFileAddressOfNewExeHeader + 4 /*size*/)
5068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return Bad("Too small");
5168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
5268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Have 'MZ' magic for a DOS header?
5368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (start()[0] != 'M' || start()[1] != 'Z')
5468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return Bad("Not MZ");
5568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
5668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // offset from DOS header to PE header is stored in DOS header.
5768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  uint32 offset = ReadU32(start(),
5868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                          kOffsetOfFileAddressOfNewExeHeader);
5968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
6068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (offset >= length())
6168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return Bad("Bad offset to PE header");
6268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
6368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  const uint8* const pe_header = OffsetToPointer(offset);
6468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  const size_t kMinPEHeaderSize = 4 /*signature*/ + kSizeOfCoffHeader;
6568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (pe_header <= start() ||
6668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      pe_header >= end() - kMinPEHeaderSize)
6768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return Bad("Bad offset to PE header");
6868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
6968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (offset % 8 != 0)
7068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return Bad("Misaligned PE header");
7168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
7268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // The 'PE' header is an IMAGE_NT_HEADERS structure as defined in WINNT.H.
7368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // See http://msdn.microsoft.com/en-us/library/ms680336(VS.85).aspx
7468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  //
7568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // The first field of the IMAGE_NT_HEADERS is the signature.
7668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!(pe_header[0] == 'P' &&
7768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        pe_header[1] == 'E' &&
7868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        pe_header[2] == 0 &&
7968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        pe_header[3] == 0))
8068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return Bad("no PE signature");
8168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
8268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // The second field of the IMAGE_NT_HEADERS is the COFF header.
8368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // The COFF header is also called an IMAGE_FILE_HEADER
8468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  //   http://msdn.microsoft.com/en-us/library/ms680313(VS.85).aspx
8568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  const uint8* const coff_header = pe_header + 4;
8668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  machine_type_       = ReadU16(coff_header, 0);
8768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  number_of_sections_ = ReadU16(coff_header, 2);
8868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  size_of_optional_header_ = ReadU16(coff_header, 16);
8968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
9068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // The rest of the IMAGE_NT_HEADERS is the IMAGE_OPTIONAL_HEADER(32|64)
9168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  const uint8* const optional_header = coff_header + kSizeOfCoffHeader;
9268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  optional_header_ = optional_header;
9368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
9468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (optional_header + size_of_optional_header_ >= end())
9568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return Bad("optional header past end of file");
9668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
9768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Check we can read the magic.
9868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (size_of_optional_header_ < 2)
9968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return Bad("optional header no magic");
10068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
10168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  uint16 magic = ReadU16(optional_header, 0);
10268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
10368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (magic == kImageNtOptionalHdr32Magic) {
10468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    is_PE32_plus_ = false;
10568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    offset_of_data_directories_ =
10668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      kOffsetOfDataDirectoryFromImageOptionalHeader32;
10768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  } else if (magic == kImageNtOptionalHdr64Magic) {
10868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    is_PE32_plus_ = true;
10968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    offset_of_data_directories_ =
11068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      kOffsetOfDataDirectoryFromImageOptionalHeader64;
11168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  } else {
11268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return Bad("unrecognized magic");
11368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
11468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
11568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Check that we can read the rest of the the fixed fields.  Data directories
11668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // directly follow the fixed fields of the IMAGE_OPTIONAL_HEADER.
11768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (size_of_optional_header_ < offset_of_data_directories_)
11868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return Bad("optional header too short");
11968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
12068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // The optional header is either an IMAGE_OPTIONAL_HEADER32 or
12168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // IMAGE_OPTIONAL_HEADER64
12268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // http://msdn.microsoft.com/en-us/library/ms680339(VS.85).aspx
12368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  //
12468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Copy the fields we care about.
12568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  size_of_code_               = ReadU32(optional_header, 4);
12668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  size_of_initialized_data_   = ReadU32(optional_header, 8);
12768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  size_of_uninitialized_data_ = ReadU32(optional_header, 12);
12868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  base_of_code_               = ReadU32(optional_header, 20);
12968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (is_PE32_plus_) {
13068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    base_of_data_ = 0;
13168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    image_base_  = ReadU64(optional_header, 24);
13268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  } else {
13368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    base_of_data_ = ReadU32(optional_header, 24);
13468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    image_base_   = ReadU32(optional_header, 28);
13568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
13668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  size_of_image_ = ReadU32(optional_header, 56);
13768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  number_of_data_directories_ =
13868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    ReadU32(optional_header, (is_PE32_plus_ ? 108 : 92));
13968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
14068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (size_of_code_ >= length() ||
14168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      size_of_initialized_data_ >= length() ||
14268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      size_of_code_ + size_of_initialized_data_ >= length()) {
14368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // This validation fires on some perfectly fine executables.
14468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    //  return Bad("code or initialized data too big");
14568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
14668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
14768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // TODO(sra): we can probably get rid of most of the data directories.
14868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  bool b = true;
14968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // 'b &= ...' could be short circuit 'b = b && ...' but it is not necessary
15068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // for correctness and it compiles smaller this way.
15168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  b &= ReadDataDirectory(0, &export_table_);
15268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  b &= ReadDataDirectory(1, &import_table_);
15368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  b &= ReadDataDirectory(2, &resource_table_);
15468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  b &= ReadDataDirectory(3, &exception_table_);
15568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  b &= ReadDataDirectory(5, &base_relocation_table_);
15668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  b &= ReadDataDirectory(11, &bound_import_table_);
15768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  b &= ReadDataDirectory(12, &import_address_table_);
15868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  b &= ReadDataDirectory(13, &delay_import_descriptor_);
15968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  b &= ReadDataDirectory(14, &clr_runtime_header_);
16068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!b) {
16168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return Bad("malformed data directory");
16268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
16368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
16468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Sections follow the optional header.
16568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  sections_ =
16668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      reinterpret_cast<const Section*>(optional_header +
16768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                       size_of_optional_header_);
16868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  size_t detected_length = 0;
16968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
17068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  for (int i = 0;  i < number_of_sections_;  ++i) {
17168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const Section* section = &sections_[i];
17268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
17368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // TODO(sra): consider using the 'characteristics' field of the section
17468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // header to see if the section contains instructions.
17568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (memcmp(section->name, ".text", 6) == 0)
17668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      has_text_section_ = true;
17768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
17868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    uint32 section_end =
17968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        section->file_offset_of_raw_data + section->size_of_raw_data;
18068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (section_end > detected_length)
18168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      detected_length = section_end;
18268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
18368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
18468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Pretend our in-memory copy is only as long as our detected length.
18568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  ReduceLength(detected_length);
18668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
18768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (is_32bit()) {
18868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return Bad("32 bit executables are not supported by this disassembler");
18968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
19068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
19168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!has_text_section()) {
19268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return Bad("Resource-only executables are not yet supported");
19368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
19468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
19568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return Good();
19668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
19768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
19868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool DisassemblerWin32X64::Disassemble(AssemblyProgram* target) {
19968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!ok())
20068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return false;
20168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
20268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  target->set_image_base(image_base());
20368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
20468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!ParseAbs32Relocs())
20568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return false;
20668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
20768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  ParseRel32RelocsFromSections();
20868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
20968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!ParseFile(target))
21068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return false;
21168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
21268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  target->DefaultAssignIndexes();
21368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
21468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return true;
21568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
21668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
21768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
21868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
21968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool DisassemblerWin32X64::ParseRelocs(std::vector<RVA> *relocs) {
22068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  relocs->clear();
22168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
22268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  size_t relocs_size = base_relocation_table_.size_;
22368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (relocs_size == 0)
22468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return true;
22568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
22668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // The format of the base relocation table is a sequence of variable sized
22768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // IMAGE_BASE_RELOCATION blocks.  Search for
22868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  //   "The format of the base relocation data is somewhat quirky"
22968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // at http://msdn.microsoft.com/en-us/library/ms809762.aspx
23068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
23168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  const uint8* relocs_start = RVAToPointer(base_relocation_table_.address_);
23268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  const uint8* relocs_end = relocs_start + relocs_size;
23368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
23468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Make sure entire base relocation table is within the buffer.
23568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (relocs_start < start() ||
23668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      relocs_start >= end() ||
23768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      relocs_end <= start() ||
23868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      relocs_end > end()) {
23968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return Bad(".relocs outside image");
24068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
24168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
24268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  const uint8* block = relocs_start;
24368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
24468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Walk the variable sized blocks.
24568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  while (block + 8 < relocs_end) {
24668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    RVA page_rva = ReadU32(block, 0);
24768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    uint32 size = ReadU32(block, 4);
24868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (size < 8 ||        // Size includes header ...
24968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        size % 4  !=  0)   // ... and is word aligned.
25068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      return Bad("unreasonable relocs block");
25168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
25268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const uint8* end_entries = block + size;
25368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
25468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (end_entries <= block ||
25568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        end_entries <= start() ||
25668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        end_entries > end())
25768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      return Bad(".relocs block outside image");
25868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
25968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // Walk through the two-byte entries.
26068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    for (const uint8* p = block + 8;  p < end_entries;  p += 2) {
26168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      uint16 entry = ReadU16(p, 0);
26268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      int type = entry >> 12;
26368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      int offset = entry & 0xFFF;
26468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
26568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      RVA rva = page_rva + offset;
26668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      if (type == 10) {         // IMAGE_REL_BASED_DIR64
26768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        relocs->push_back(rva);
26868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      } else if (type == 0) {  // IMAGE_REL_BASED_ABSOLUTE
26968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        // Ignore, used as padding.
27068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      } else {
27168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        // Does not occur in Windows x64 executables.
27268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        return Bad("unknown type of reloc");
27368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      }
27468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
27568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
27668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    block += size;
27768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
27868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
27968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::sort(relocs->begin(), relocs->end());
28068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
28168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return true;
28268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
28368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
28468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const Section* DisassemblerWin32X64::RVAToSection(RVA rva) const {
28568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  for (int i = 0; i < number_of_sections_; i++) {
28668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const Section* section = &sections_[i];
28768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    uint32 offset = rva - section->virtual_address;
28868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (offset < section->virtual_size) {
28968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      return section;
29068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
29168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
29268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return NULL;
29368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
29468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
29568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)int DisassemblerWin32X64::RVAToFileOffset(RVA rva) const {
29668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  const Section* section = RVAToSection(rva);
29768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (section) {
29868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    uint32 offset = rva - section->virtual_address;
29968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (offset < section->size_of_raw_data) {
30068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      return section->file_offset_of_raw_data + offset;
30168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    } else {
30268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      return kNoOffset;  // In section but not in file (e.g. uninit data).
30368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
30468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
30568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
30668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Small RVA values point into the file header in the loaded image.
30768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // RVA 0 is the module load address which Windows uses as the module handle.
30868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // RVA 2 sometimes occurs, I'm not sure what it is, but it would map into the
30968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // DOS header.
31068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (rva == 0 || rva == 2)
31168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return rva;
31268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
31368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  NOTREACHED();
31468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return kNoOffset;
31568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
31668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
31768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const uint8* DisassemblerWin32X64::RVAToPointer(RVA rva) const {
31868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int file_offset = RVAToFileOffset(rva);
31968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (file_offset == kNoOffset)
32068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return NULL;
32168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  else
32268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return OffsetToPointer(file_offset);
32368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
32468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
32568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)std::string DisassemblerWin32X64::SectionName(const Section* section) {
32668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (section == NULL)
32768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return "<none>";
32868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  char name[9];
32968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  memcpy(name, section->name, 8);
33068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  name[8] = '\0';  // Ensure termination.
33168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return name;
33268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
33368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
33468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)CheckBool DisassemblerWin32X64::ParseFile(AssemblyProgram* program) {
33568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Walk all the bytes in the file, whether or not in a section.
33668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  uint32 file_offset = 0;
33768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  while (file_offset < length()) {
33868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const Section* section = FindNextSection(file_offset);
33968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (section == NULL) {
34068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      // No more sections.  There should not be extra stuff following last
34168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      // section.
34268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      //   ParseNonSectionFileRegion(file_offset, pe_info().length(), program);
34368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      break;
34468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
34568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (file_offset < section->file_offset_of_raw_data) {
34668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      uint32 section_start_offset = section->file_offset_of_raw_data;
34768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      if(!ParseNonSectionFileRegion(file_offset, section_start_offset,
34868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                    program))
34968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        return false;
35068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
35168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      file_offset = section_start_offset;
35268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
35368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    uint32 end = file_offset + section->size_of_raw_data;
35468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (!ParseFileRegion(section, file_offset, end, program))
35568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      return false;
35668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    file_offset = end;
35768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
35868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
35968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#if COURGETTE_HISTOGRAM_TARGETS
36068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  HistogramTargets("abs32 relocs", abs32_target_rvas_);
36168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  HistogramTargets("rel32 relocs", rel32_target_rvas_);
36268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#endif
36368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
36468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return true;
36568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
36668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
36768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool DisassemblerWin32X64::ParseAbs32Relocs() {
36868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  abs32_locations_.clear();
36968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!ParseRelocs(&abs32_locations_))
37068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return false;
37168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
37268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::sort(abs32_locations_.begin(), abs32_locations_.end());
37368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
37468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#if COURGETTE_HISTOGRAM_TARGETS
37568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  for (size_t i = 0;  i < abs32_locations_.size(); ++i) {
37668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    RVA rva = abs32_locations_[i];
37768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // The 4 bytes at the relocation are a reference to some address.
37868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    uint32 target_address = Read32LittleEndian(RVAToPointer(rva));
37968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    ++abs32_target_rvas_[target_address - image_base()];
38068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
38168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#endif
38268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return true;
38368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
38468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
38568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void DisassemblerWin32X64::ParseRel32RelocsFromSections() {
38668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  uint32 file_offset = 0;
38768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  while (file_offset < length()) {
38868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const Section* section = FindNextSection(file_offset);
38968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (section == NULL)
39068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      break;
39168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (file_offset < section->file_offset_of_raw_data)
39268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      file_offset = section->file_offset_of_raw_data;
39368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    ParseRel32RelocsFromSection(section);
39468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    file_offset += section->size_of_raw_data;
39568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
39668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::sort(rel32_locations_.begin(), rel32_locations_.end());
39768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
39868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#if COURGETTE_HISTOGRAM_TARGETS
39968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  VLOG(1) << "abs32_locations_ " << abs32_locations_.size()
40068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          << "\nrel32_locations_ " << rel32_locations_.size()
40168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          << "\nabs32_target_rvas_ " << abs32_target_rvas_.size()
40268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          << "\nrel32_target_rvas_ " << rel32_target_rvas_.size();
40368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
40468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int common = 0;
40568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::map<RVA, int>::iterator abs32_iter = abs32_target_rvas_.begin();
40668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::map<RVA, int>::iterator rel32_iter = rel32_target_rvas_.begin();
40768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  while (abs32_iter != abs32_target_rvas_.end() &&
40868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)         rel32_iter != rel32_target_rvas_.end()) {
40968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (abs32_iter->first < rel32_iter->first)
41068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      ++abs32_iter;
41168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    else if (rel32_iter->first < abs32_iter->first)
41268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      ++rel32_iter;
41368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    else {
41468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      ++common;
41568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      ++abs32_iter;
41668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      ++rel32_iter;
41768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
41868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
41968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  VLOG(1) << "common " << common;
42068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#endif
42168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
42268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
42368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void DisassemblerWin32X64::ParseRel32RelocsFromSection(const Section* section) {
42468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // TODO(sra): use characteristic.
42568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  bool isCode = strcmp(section->name, ".text") == 0;
42668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!isCode)
42768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return;
42868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
42968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  uint32 start_file_offset = section->file_offset_of_raw_data;
43068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  uint32 end_file_offset = start_file_offset + section->size_of_raw_data;
43168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  RVA relocs_start_rva = base_relocation_table().address_;
43268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
43368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  const uint8* start_pointer = OffsetToPointer(start_file_offset);
43468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  const uint8* end_pointer = OffsetToPointer(end_file_offset);
43568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
43668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  RVA start_rva = FileOffsetToRVA(start_file_offset);
43768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  RVA end_rva = start_rva + section->virtual_size;
43868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
43968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Quick way to convert from Pointer to RVA within a single Section is to
44068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // subtract 'pointer_to_rva'.
44168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  const uint8* const adjust_pointer_to_rva = start_pointer - start_rva;
44268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
44368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::vector<RVA>::iterator abs32_pos = abs32_locations_.begin();
44468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
44568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Find the rel32 relocations.
44668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  const uint8* p = start_pointer;
44768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  while (p < end_pointer) {
44868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    RVA current_rva = static_cast<RVA>(p - adjust_pointer_to_rva);
44968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (current_rva == relocs_start_rva) {
45068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      uint32 relocs_size = base_relocation_table().size_;
45168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      if (relocs_size) {
45268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        p += relocs_size;
45368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        continue;
45468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      }
45568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
45668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
45768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    //while (abs32_pos != abs32_locations_.end() && *abs32_pos < current_rva)
45868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    //  ++abs32_pos;
45968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
46068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // Heuristic discovery of rel32 locations in instruction stream: are the
46168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // next few bytes the start of an instruction containing a rel32
46268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // addressing mode?
46368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const uint8* rel32 = NULL;
46468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
46568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (p + 5 <= end_pointer) {
46668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      if (*p == 0xE8 || *p == 0xE9) {  // jmp rel32 and call rel32
46768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        rel32 = p + 1;
46868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      }
46968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
47068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (p + 6 <= end_pointer) {
47168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      if (*p == 0x0F  &&  (*(p+1) & 0xF0) == 0x80) {  // Jcc long form
47268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        if (p[1] != 0x8A && p[1] != 0x8B)  // JPE/JPO unlikely
47368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          rel32 = p + 2;
47468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      }
47568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
47668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (rel32) {
47768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      RVA rel32_rva = static_cast<RVA>(rel32 - adjust_pointer_to_rva);
47868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
47968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      // Is there an abs32 reloc overlapping the candidate?
48068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      while (abs32_pos != abs32_locations_.end() && *abs32_pos < rel32_rva - 3)
48168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        ++abs32_pos;
48268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      // Now: (*abs32_pos > rel32_rva - 4) i.e. the lowest addressed 4-byte
48368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      // region that could overlap rel32_rva.
48468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      if (abs32_pos != abs32_locations_.end()) {
48568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        if (*abs32_pos < rel32_rva + 4) {
48668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          // Beginning of abs32 reloc is before end of rel32 reloc so they
48768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          // overlap.  Skip four bytes past the abs32 reloc.
48868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          p += (*abs32_pos + 4) - current_rva;
48968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          continue;
49068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        }
49168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      }
49268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
49368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      RVA target_rva = rel32_rva + 4 + Read32LittleEndian(rel32);
49468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      // To be valid, rel32 target must be within image, and within this
49568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      // section.
49668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      if (IsValidRVA(target_rva) &&
49768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          start_rva <= target_rva && target_rva < end_rva) {
49868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        rel32_locations_.push_back(rel32_rva);
49968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#if COURGETTE_HISTOGRAM_TARGETS
50068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        ++rel32_target_rvas_[target_rva];
50168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#endif
50268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        p = rel32 + 4;
50368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        continue;
50468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      }
50568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
50668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    p += 1;
50768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
50868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
50968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
51068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)CheckBool DisassemblerWin32X64::ParseNonSectionFileRegion(
51168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    uint32 start_file_offset,
51268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    uint32 end_file_offset,
51368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    AssemblyProgram* program) {
51468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (incomplete_disassembly_)
51568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return true;
51668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
51768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  const uint8* start = OffsetToPointer(start_file_offset);
51868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  const uint8* end = OffsetToPointer(end_file_offset);
51968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
52068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  const uint8* p = start;
52168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
52268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  while (p < end) {
52368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (!program->EmitByteInstruction(*p))
52468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      return false;
52568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    ++p;
52668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
52768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
52868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return true;
52968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
53068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
53168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)CheckBool DisassemblerWin32X64::ParseFileRegion(
53268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const Section* section,
53368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    uint32 start_file_offset, uint32 end_file_offset,
53468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    AssemblyProgram* program) {
53568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  RVA relocs_start_rva = base_relocation_table().address_;
53668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
53768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  const uint8* start_pointer = OffsetToPointer(start_file_offset);
53868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  const uint8* end_pointer = OffsetToPointer(end_file_offset);
53968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
54068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  RVA start_rva = FileOffsetToRVA(start_file_offset);
54168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  RVA end_rva = start_rva + section->virtual_size;
54268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
54368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Quick way to convert from Pointer to RVA within a single Section is to
54468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // subtract 'pointer_to_rva'.
54568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  const uint8* const adjust_pointer_to_rva = start_pointer - start_rva;
54668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
54768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::vector<RVA>::iterator rel32_pos = rel32_locations_.begin();
54868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::vector<RVA>::iterator abs32_pos = abs32_locations_.begin();
54968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
55068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (!program->EmitOriginInstruction(start_rva))
55168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return false;
55268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
55368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  const uint8* p = start_pointer;
55468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
55568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  while (p < end_pointer) {
55668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    RVA current_rva = static_cast<RVA>(p - adjust_pointer_to_rva);
55768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
55868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // The base relocation table is usually in the .relocs section, but it could
55968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // actually be anywhere.  Make sure we skip it because we will regenerate it
56068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // during assembly.
56168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (current_rva == relocs_start_rva) {
56268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      if (!program->EmitPeRelocsInstruction())
56368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        return false;
56468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      uint32 relocs_size = base_relocation_table().size_;
56568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      if (relocs_size) {
56668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        p += relocs_size;
56768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        continue;
56868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      }
56968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
57068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
57168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    while (abs32_pos != abs32_locations_.end() && *abs32_pos < current_rva)
57268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      ++abs32_pos;
57368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
57468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (abs32_pos != abs32_locations_.end() && *abs32_pos == current_rva) {
57568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      uint32 target_address = Read32LittleEndian(p);
57668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      RVA target_rva = target_address - image_base();
57768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      // TODO(sra): target could be Label+offset.  It is not clear how to guess
57868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      // which it might be.  We assume offset==0.
57968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      if (!program->EmitAbs32(program->FindOrMakeAbs32Label(target_rva)))
58068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        return false;
58168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      p += 4;
58268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      continue;
58368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
58468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
58568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    while (rel32_pos != rel32_locations_.end() && *rel32_pos < current_rva)
58668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      ++rel32_pos;
58768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
58868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (rel32_pos != rel32_locations_.end() && *rel32_pos == current_rva) {
58968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      RVA target_rva = current_rva + 4 + Read32LittleEndian(p);
59068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      if (!program->EmitRel32(program->FindOrMakeRel32Label(target_rva)))
59168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        return false;
59268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      p += 4;
59368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      continue;
59468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
59568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
59668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (incomplete_disassembly_) {
59768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      if ((abs32_pos == abs32_locations_.end() || end_rva <= *abs32_pos) &&
59868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          (rel32_pos == rel32_locations_.end() || end_rva <= *rel32_pos) &&
59968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          (end_rva <= relocs_start_rva || current_rva >= relocs_start_rva)) {
60068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        // No more relocs in this section, don't bother encoding bytes.
60168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        break;
60268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      }
60368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
60468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
60568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (!program->EmitByteInstruction(*p))
60668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      return false;
60768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    p += 1;
60868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
60968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
61068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return true;
61168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
61268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
61368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#if COURGETTE_HISTOGRAM_TARGETS
61468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// Histogram is printed to std::cout.  It is purely for debugging the algorithm
61568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// and is only enabled manually in 'exploration' builds.  I don't want to add
61668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// command-line configuration for this feature because this code has to be
61768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// small, which means compiled-out.
61868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void DisassemblerWin32X64::HistogramTargets(const char* kind,
61968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                            const std::map<RVA, int>& map) {
62068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int total = 0;
62168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::map<int, std::vector<RVA> > h;
62268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  for (std::map<RVA, int>::const_iterator p = map.begin();
62368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)       p != map.end();
62468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)       ++p) {
62568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    h[p->second].push_back(p->first);
62668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    total += p->second;
62768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
62868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
62968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::cout << total << " " << kind << " to "
63068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)            << map.size() << " unique targets" << std::endl;
63168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
63268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::cout << "indegree: #targets-with-indegree (example)" << std::endl;
63368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  const int kFirstN = 15;
63468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  bool someSkipped = false;
63568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int index = 0;
63668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  for (std::map<int, std::vector<RVA> >::reverse_iterator p = h.rbegin();
63768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)       p != h.rend();
63868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)       ++p) {
63968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    ++index;
64068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (index <= kFirstN || p->first <= 3) {
64168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      if (someSkipped) {
64268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        std::cout << "..." << std::endl;
64368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      }
64468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      size_t count = p->second.size();
64568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      std::cout << std::dec << p->first << ": " << count;
64668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      if (count <= 2) {
64768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        for (size_t i = 0;  i < count;  ++i)
64868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          std::cout << "  " << DescribeRVA(p->second[i]);
64968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      }
65068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      std::cout << std::endl;
65168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      someSkipped = false;
65268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    } else {
65368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      someSkipped = true;
65468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
65568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
65668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
65768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#endif  // COURGETTE_HISTOGRAM_TARGETS
65868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
65968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
66068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// DescribeRVA is for debugging only.  I would put it under #ifdef DEBUG except
66168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// that during development I'm finding I need to call it when compiled in
66268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// Release mode.  Hence:
66368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// TODO(sra): make this compile only for debug mode.
66468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)std::string DisassemblerWin32X64::DescribeRVA(RVA rva) const {
66568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  const Section* section = RVAToSection(rva);
66668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::ostringstream s;
66768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  s << std::hex << rva;
66868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (section) {
66968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    s << " (";
67068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    s << SectionName(section) << "+"
67168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      << std::hex << (rva - section->virtual_address)
67268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      << ")";
67368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
67468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return s.str();
67568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
67668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
67768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)const Section* DisassemblerWin32X64::FindNextSection(uint32 fileOffset) const {
67868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  const Section* best = 0;
67968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  for (int i = 0; i < number_of_sections_; i++) {
68068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const Section* section = &sections_[i];
68168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (section->size_of_raw_data > 0) {  // i.e. has data in file.
68268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      if (fileOffset <= section->file_offset_of_raw_data) {
68368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        if (best == 0 ||
68468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)            section->file_offset_of_raw_data < best->file_offset_of_raw_data) {
68568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          best = section;
68668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        }
68768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      }
68868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
68968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
69068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return best;
69168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
69268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
69368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)RVA DisassemblerWin32X64::FileOffsetToRVA(uint32 file_offset) const {
69468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  for (int i = 0; i < number_of_sections_; i++) {
69568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const Section* section = &sections_[i];
69668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    uint32 offset = file_offset - section->file_offset_of_raw_data;
69768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (offset < section->size_of_raw_data) {
69868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      return section->virtual_address + offset;
69968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
70068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
70168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return 0;
70268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
70368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
70468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)bool DisassemblerWin32X64::ReadDataDirectory(
70568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    int index,
70668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    ImageDataDirectory* directory) {
70768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
70868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  if (index < number_of_data_directories_) {
70968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    size_t offset = index * 8 + offset_of_data_directories_;
71068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (offset >= size_of_optional_header_)
71168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      return Bad("number of data directories inconsistent");
71268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const uint8* data_directory = optional_header_ + offset;
71368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (data_directory < start() ||
71468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        data_directory + 8 >= end())
71568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      return Bad("data directory outside image");
71668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    RVA rva = ReadU32(data_directory, 0);
71768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    size_t size  = ReadU32(data_directory, 4);
71868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (size > size_of_image_)
71968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      return Bad("data directory size too big");
72068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
72168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    // TODO(sra): validate RVA.
72268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    directory->address_ = rva;
72368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    directory->size_ = static_cast<uint32>(size);
72468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return true;
72568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  } else {
72668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    directory->address_ = 0;
72768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    directory->size_ = 0;
72868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return true;
72968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
73068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
73168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
73268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}  // namespace courgette
733