1 // Copyright 2016 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.
5 #ifndef COURGETTE_DISASSEMBLER_WIN32_H_
6 #define COURGETTE_DISASSEMBLER_WIN32_H_
15 #include "base/macros.h"
16 #include "courgette/disassembler.h"
17 #include "courgette/image_utils.h"
18 #include "courgette/instruction_utils.h"
19 #include "courgette/memory_allocator.h"
20 #include "courgette/types_win_pe.h"
24 class AssemblyProgram;
26 class DisassemblerWin32 : public Disassembler {
28 virtual ~DisassemblerWin32() = default;
30 // Disassembler interfaces.
31 RVA FileOffsetToRVA(FileOffset file_offset) const override;
32 FileOffset RVAToFileOffset(RVA rva) const override;
33 ExecutableType kind() const override = 0;
34 uint64_t image_base() const override { return image_base_; }
35 RVA PointerToTargetRVA(const uint8_t* p) const override = 0;
36 bool ParseHeader() override;
38 // Exposed for test purposes
39 bool has_text_section() const { return has_text_section_; }
40 uint32_t size_of_code() const { return size_of_code_; }
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);
47 // Returns Section containing the relative virtual address, or null if none.
48 const Section* RVAToSection(RVA rva) const;
50 static std::string SectionName(const Section* section);
53 // Returns true if a valid executable is detected using only quick checks.
54 // Derived classes should inject |magic| corresponding to their architecture,
55 // which will be checked against the detected one.
56 static bool QuickDetect(const uint8_t* start, size_t length, uint16_t magic);
58 // Returns true if the given RVA range lies within [0, |size_of_image_|).
59 bool IsRvaRangeInBounds(size_t start, size_t length);
61 // Returns whether all sections lie within image.
62 bool CheckSectionRanges();
64 // Disassembler interfaces.
65 bool ExtractAbs32Locations() override;
66 bool ExtractRel32Locations() override;
67 RvaVisitor* CreateAbs32TargetRvaVisitor() override;
68 RvaVisitor* CreateRel32TargetRvaVisitor() override;
69 void RemoveUnusedRel32Locations(AssemblyProgram* program) override;
70 InstructionGenerator GetInstructionGenerator(
71 AssemblyProgram* program) override;
73 DisassemblerWin32(const uint8_t* start, size_t length);
75 CheckBool ParseFile(AssemblyProgram* target,
76 InstructionReceptor* receptor) const WARN_UNUSED_RESULT;
77 virtual void ParseRel32RelocsFromSection(const Section* section) = 0;
79 CheckBool ParseNonSectionFileRegion(FileOffset start_file_offset,
80 FileOffset end_file_offset,
81 InstructionReceptor* receptor) const
83 CheckBool ParseFileRegion(const Section* section,
84 FileOffset start_file_offset,
85 FileOffset end_file_offset,
86 AssemblyProgram* program,
87 InstructionReceptor* receptor) const
90 // Returns address width in byte count.
91 virtual int AbsVAWidth() const = 0;
92 // Emits Abs 32/64 |label| to the |receptor|.
93 virtual CheckBool EmitAbs(Label* label,
94 InstructionReceptor* receptor) const = 0;
95 // Returns true if type is recognized.
96 virtual bool SupportsRelTableType(int type) const = 0;
97 virtual uint16_t RelativeOffsetOfDataDirectories() const = 0;
99 #if COURGETTE_HISTOGRAM_TARGETS
100 void HistogramTargets(const char* kind, const std::map<RVA, int>& map) const;
103 const ImageDataDirectory& base_relocation_table() const {
104 return base_relocation_table_;
107 // Returns description of the RVA, e.g. ".text+0x1243". For debugging only.
108 std::string DescribeRVA(RVA rva) const;
110 // Finds the first section at file_offset or above. Does not return sections
111 // that have no raw bytes in the file.
112 const Section* FindNextSection(FileOffset file_offset) const;
114 bool ReadDataDirectory(int index, ImageDataDirectory* dir);
116 bool incomplete_disassembly_ =
117 false; // true if can omit "uninteresting" bits.
119 std::vector<RVA> abs32_locations_;
120 std::vector<RVA> rel32_locations_;
122 // Location and size of IMAGE_OPTIONAL_HEADER in the buffer.
123 const uint8_t* optional_header_ = nullptr;
124 uint16_t size_of_optional_header_ = 0;
126 uint16_t machine_type_ = 0;
127 uint16_t number_of_sections_ = 0;
128 const Section* sections_ = nullptr;
129 bool has_text_section_ = false;
131 uint32_t size_of_code_ = 0;
132 uint32_t size_of_initialized_data_ = 0;
133 uint32_t size_of_uninitialized_data_ = 0;
134 RVA base_of_code_ = 0;
135 RVA base_of_data_ = 0;
137 uint64_t image_base_ = 0; // Range limited to 32 bits for 32 bit executable.
138 // Specifies size of loaded PE in memory, and provides bound on RVA.
139 uint32_t size_of_image_ = 0;
140 int number_of_data_directories_ = 0;
142 ImageDataDirectory export_table_;
143 ImageDataDirectory import_table_;
144 ImageDataDirectory resource_table_;
145 ImageDataDirectory exception_table_;
146 ImageDataDirectory base_relocation_table_;
147 ImageDataDirectory bound_import_table_;
148 ImageDataDirectory import_address_table_;
149 ImageDataDirectory delay_import_descriptor_;
150 ImageDataDirectory clr_runtime_header_;
152 #if COURGETTE_HISTOGRAM_TARGETS
153 std::map<RVA, int> abs32_target_rvas_;
154 std::map<RVA, int> rel32_target_rvas_;
158 DISALLOW_COPY_AND_ASSIGN(DisassemblerWin32);
161 } // namespace courgette
163 #endif // COURGETTE_DISASSEMBLER_WIN32_H_