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)#ifndef COURGETTE_DISASSEMBLER_WIN32_X64_H_
668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#define COURGETTE_DISASSEMBLER_WIN32_X64_H_
768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "base/basictypes.h"
968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "courgette/disassembler.h"
1068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "courgette/memory_allocator.h"
1168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "courgette/types_win_pe.h"
1268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
1368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#ifdef COURGETTE_HISTOGRAM_TARGETS
1468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include <map>
1568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#endif
1668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
1768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)namespace courgette {
1868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
1968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)class AssemblyProgram;
2068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
2168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)class DisassemblerWin32X64 : public Disassembler {
2268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) public:
2368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  explicit DisassemblerWin32X64(const void* start, size_t length);
2468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
2568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  virtual ExecutableType kind() { return EXE_WIN_32_X64; }
2668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
2768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Returns 'true' if the buffer appears to point to a Windows 32 bit
2868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // executable, 'false' otherwise.  If ParseHeader() succeeds, other member
2968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // functions may be called.
3068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  virtual bool ParseHeader();
3168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
3268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  virtual bool Disassemble(AssemblyProgram* target);
3368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
3468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  //
3568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Exposed for test purposes
3668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  //
3768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
3868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  bool has_text_section() const { return has_text_section_; }
3968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  uint32 size_of_code() const { return size_of_code_; }
4068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  bool is_32bit() const { return !is_PE32_plus_; }
4168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
4268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Returns 'true' if the base relocation table can be parsed.
4368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Output is a vector of the RVAs corresponding to locations within executable
4468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // that are listed in the base relocation table.
4568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  bool ParseRelocs(std::vector<RVA> *addresses);
4668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
4768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Returns Section containing the relative virtual address, or NULL if none.
4868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  const Section* RVAToSection(RVA rva) const;
4968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
5068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  static const int kNoOffset = -1;
5168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Returns kNoOffset if there is no file offset corresponding to 'rva'.
5268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int RVAToFileOffset(RVA rva) const;
5368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
5468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Returns same as FileOffsetToPointer(RVAToFileOffset(rva)) except that NULL
5568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // is returned if there is no file offset corresponding to 'rva'.
5668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  const uint8* RVAToPointer(RVA rva) const;
5768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
5868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  static std::string SectionName(const Section* section);
5968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
6068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) protected:
6168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  CheckBool ParseFile(AssemblyProgram* target) WARN_UNUSED_RESULT;
6268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  bool ParseAbs32Relocs();
6368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  void ParseRel32RelocsFromSections();
6468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  void ParseRel32RelocsFromSection(const Section* section);
6568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
6668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  CheckBool ParseNonSectionFileRegion(uint32 start_file_offset,
6768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      uint32 end_file_offset, AssemblyProgram* program) WARN_UNUSED_RESULT;
6868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  CheckBool ParseFileRegion(const Section* section,
6968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      uint32 start_file_offset, uint32 end_file_offset,
7068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      AssemblyProgram* program) WARN_UNUSED_RESULT;
7168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
7268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#if COURGETTE_HISTOGRAM_TARGETS
7368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  void HistogramTargets(const char* kind, const std::map<RVA, int>& map);
7468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#endif
7568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
7668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Most addresses are represented as 32-bit RVAs.  The one address we can't
7768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // do this with is the image base address.  'image_base' is valid only for
7868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // 32-bit executables. 'image_base_64' is valid for 32- and 64-bit executable.
7968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  uint64 image_base() const { return image_base_; }
8068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
8168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  const ImageDataDirectory& base_relocation_table() const {
8268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    return base_relocation_table_;
8368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
8468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
8568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  bool IsValidRVA(RVA rva) const { return rva < size_of_image_; }
8668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
8768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Returns description of the RVA, e.g. ".text+0x1243".  For debugging only.
8868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::string DescribeRVA(RVA rva) const;
8968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
9068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Finds the first section at file_offset or above.  Does not return sections
9168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // that have no raw bytes in the file.
9268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  const Section* FindNextSection(uint32 file_offset) const;
9368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
9468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // There are 2 'coordinate systems' for reasoning about executables.
9568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  //   FileOffset - the the offset within a single .EXE or .DLL *file*.
9668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  //   RVA - relative virtual address (offset within *loaded image*)
9768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // FileOffsetToRVA and RVAToFileOffset convert between these representations.
9868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
9968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  RVA FileOffsetToRVA(uint32 offset) const;
10068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
10168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
10268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) private:
10368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
10468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  bool ReadDataDirectory(int index, ImageDataDirectory* dir);
10568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
10668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  bool incomplete_disassembly_;  // 'true' if can leave out 'uninteresting' bits
10768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
10868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::vector<RVA> abs32_locations_;
10968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::vector<RVA> rel32_locations_;
11068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
11168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  //
11268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Fields that are always valid.
11368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  //
11468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
11568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  //
11668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Information that is valid after successful ParseHeader.
11768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  //
11868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  bool is_PE32_plus_;   // PE32_plus is for 64 bit executables.
11968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
12068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Location and size of IMAGE_OPTIONAL_HEADER in the buffer.
12168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  const uint8 *optional_header_;
12268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  uint16 size_of_optional_header_;
12368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  uint16 offset_of_data_directories_;
12468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
12568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  uint16 machine_type_;
12668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  uint16 number_of_sections_;
12768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  const Section *sections_;
12868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  bool has_text_section_;
12968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
13068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  uint32 size_of_code_;
13168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  uint32 size_of_initialized_data_;
13268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  uint32 size_of_uninitialized_data_;
13368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  RVA base_of_code_;
13468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  RVA base_of_data_;
13568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
13668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  uint64 image_base_;
13768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  uint32 size_of_image_;
13868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  int number_of_data_directories_;
13968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
14068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  ImageDataDirectory export_table_;
14168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  ImageDataDirectory import_table_;
14268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  ImageDataDirectory resource_table_;
14368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  ImageDataDirectory exception_table_;
14468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  ImageDataDirectory base_relocation_table_;
14568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  ImageDataDirectory bound_import_table_;
14668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  ImageDataDirectory import_address_table_;
14768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  ImageDataDirectory delay_import_descriptor_;
14868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  ImageDataDirectory clr_runtime_header_;
14968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
15068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#if COURGETTE_HISTOGRAM_TARGETS
15168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::map<RVA, int> abs32_target_rvas_;
15268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  std::map<RVA, int> rel32_target_rvas_;
15368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#endif
15468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
15568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
15668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(DisassemblerWin32X64);
15768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)};
15868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
15968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}  // namespace courgette
16068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#endif  // COURGETTE_DISASSEMBLER_WIN32_X64_H_
161