1// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef COURGETTE_DISASSEMBLER_WIN32_X86_H_
6#define COURGETTE_DISASSEMBLER_WIN32_X86_H_
7
8#include "base/basictypes.h"
9#include "courgette/disassembler.h"
10#include "courgette/memory_allocator.h"
11#include "courgette/types_win_pe.h"
12
13#ifdef COURGETTE_HISTOGRAM_TARGETS
14#include <map>
15#endif
16
17namespace courgette {
18
19class AssemblyProgram;
20
21class DisassemblerWin32X86 : public Disassembler {
22 public:
23  explicit DisassemblerWin32X86(const void* start, size_t length);
24
25  virtual ExecutableType kind() { return EXE_WIN_32_X86; }
26
27  // Returns 'true' if the buffer appears to point to a Windows 32 bit
28  // executable, 'false' otherwise.  If ParseHeader() succeeds, other member
29  // functions may be called.
30  virtual bool ParseHeader();
31
32  virtual bool Disassemble(AssemblyProgram* target);
33
34  //
35  // Exposed for test purposes
36  //
37
38  bool has_text_section() const { return has_text_section_; }
39  uint32 size_of_code() const { return size_of_code_; }
40  bool is_32bit() const { return !is_PE32_plus_; }
41
42  // Returns 'true' if the base relocation table can be parsed.
43  // Output is a vector of the RVAs corresponding to locations within executable
44  // that are listed in the base relocation table.
45  bool ParseRelocs(std::vector<RVA> *addresses);
46
47  // Returns Section containing the relative virtual address, or NULL if none.
48  const Section* RVAToSection(RVA rva) const;
49
50  static const int kNoOffset = -1;
51  // Returns kNoOffset if there is no file offset corresponding to 'rva'.
52  int RVAToFileOffset(RVA rva) const;
53
54  // Returns same as FileOffsetToPointer(RVAToFileOffset(rva)) except that NULL
55  // is returned if there is no file offset corresponding to 'rva'.
56  const uint8* RVAToPointer(RVA rva) const;
57
58  static std::string SectionName(const Section* section);
59
60 protected:
61  CheckBool ParseFile(AssemblyProgram* target) WARN_UNUSED_RESULT;
62  bool ParseAbs32Relocs();
63  void ParseRel32RelocsFromSections();
64  void ParseRel32RelocsFromSection(const Section* section);
65
66  CheckBool ParseNonSectionFileRegion(uint32 start_file_offset,
67      uint32 end_file_offset, AssemblyProgram* program) WARN_UNUSED_RESULT;
68  CheckBool ParseFileRegion(const Section* section,
69      uint32 start_file_offset, uint32 end_file_offset,
70      AssemblyProgram* program) WARN_UNUSED_RESULT;
71
72#if COURGETTE_HISTOGRAM_TARGETS
73  void HistogramTargets(const char* kind, const std::map<RVA, int>& map);
74#endif
75
76  // Most addresses are represented as 32-bit RVAs.  The one address we can't
77  // do this with is the image base address.  'image_base' is valid only for
78  // 32-bit executables. 'image_base_64' is valid for 32- and 64-bit executable.
79  uint32 image_base() const { return static_cast<uint32>(image_base_); }
80
81  const ImageDataDirectory& base_relocation_table() const {
82    return base_relocation_table_;
83  }
84
85  bool IsValidRVA(RVA rva) const { return rva < size_of_image_; }
86
87  // Returns description of the RVA, e.g. ".text+0x1243".  For debugging only.
88  std::string DescribeRVA(RVA rva) const;
89
90  // Finds the first section at file_offset or above.  Does not return sections
91  // that have no raw bytes in the file.
92  const Section* FindNextSection(uint32 file_offset) const;
93
94  // There are 2 'coordinate systems' for reasoning about executables.
95  //   FileOffset - the the offset within a single .EXE or .DLL *file*.
96  //   RVA - relative virtual address (offset within *loaded image*)
97  // FileOffsetToRVA and RVAToFileOffset convert between these representations.
98
99  RVA FileOffsetToRVA(uint32 offset) const;
100
101
102 private:
103
104  bool ReadDataDirectory(int index, ImageDataDirectory* dir);
105
106  bool incomplete_disassembly_;  // 'true' if can leave out 'uninteresting' bits
107
108  std::vector<RVA> abs32_locations_;
109  std::vector<RVA> rel32_locations_;
110
111  //
112  // Fields that are always valid.
113  //
114
115  //
116  // Information that is valid after successful ParseHeader.
117  //
118  bool is_PE32_plus_;   // PE32_plus is for 64 bit executables.
119
120  // Location and size of IMAGE_OPTIONAL_HEADER in the buffer.
121  const uint8 *optional_header_;
122  uint16 size_of_optional_header_;
123  uint16 offset_of_data_directories_;
124
125  uint16 machine_type_;
126  uint16 number_of_sections_;
127  const Section *sections_;
128  bool has_text_section_;
129
130  uint32 size_of_code_;
131  uint32 size_of_initialized_data_;
132  uint32 size_of_uninitialized_data_;
133  RVA base_of_code_;
134  RVA base_of_data_;
135
136  uint64 image_base_;  // range limited to 32 bits for 32 bit executable
137  uint32 size_of_image_;
138  int number_of_data_directories_;
139
140  ImageDataDirectory export_table_;
141  ImageDataDirectory import_table_;
142  ImageDataDirectory resource_table_;
143  ImageDataDirectory exception_table_;
144  ImageDataDirectory base_relocation_table_;
145  ImageDataDirectory bound_import_table_;
146  ImageDataDirectory import_address_table_;
147  ImageDataDirectory delay_import_descriptor_;
148  ImageDataDirectory clr_runtime_header_;
149
150#if COURGETTE_HISTOGRAM_TARGETS
151  std::map<RVA, int> abs32_target_rvas_;
152  std::map<RVA, int> rel32_target_rvas_;
153#endif
154
155
156  DISALLOW_COPY_AND_ASSIGN(DisassemblerWin32X86);
157};
158
159}  // namespace courgette
160#endif  // COURGETTE_DISASSEMBLER_WIN32_X86_H_
161