1 // Copyright 2016 The Chromium Authors
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/memory/raw_ptr.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 DisassemblerWin32(const DisassemblerWin32&) = delete;
29 DisassemblerWin32& operator=(const DisassemblerWin32&) = delete;
31 virtual ~DisassemblerWin32() = default;
33 // Disassembler interfaces.
34 RVA FileOffsetToRVA(FileOffset file_offset) const override;
35 FileOffset RVAToFileOffset(RVA rva) const override;
36 ExecutableType kind() const override = 0;
37 uint64_t image_base() const override { return image_base_; }
38 RVA PointerToTargetRVA(const uint8_t* p) const override = 0;
39 bool ParseHeader() override;
41 // Exposed for test purposes
42 bool has_text_section() const { return has_text_section_; }
43 uint32_t size_of_code() const { return size_of_code_; }
45 // Returns 'true' if the base relocation table can be parsed.
46 // Output is a vector of the RVAs corresponding to locations within executable
47 // that are listed in the base relocation table.
48 bool ParseRelocs(std::vector<RVA>* addresses);
50 // Returns Section containing the relative virtual address, or null if none.
51 const Section* RVAToSection(RVA rva) const;
53 static std::string SectionName(const Section* section);
56 // Returns true if a valid executable is detected using only quick checks.
57 // Derived classes should inject |magic| corresponding to their architecture,
58 // which will be checked against the detected one.
59 static bool QuickDetect(const uint8_t* start, size_t length, uint16_t magic);
61 // Returns true if the given RVA range lies within [0, |size_of_image_|).
62 bool IsRvaRangeInBounds(size_t start, size_t length);
64 // Returns whether all sections lie within image.
65 bool CheckSectionRanges();
67 // Disassembler interfaces.
68 bool ExtractAbs32Locations() override;
69 bool ExtractRel32Locations() override;
70 RvaVisitor* CreateAbs32TargetRvaVisitor() override;
71 RvaVisitor* CreateRel32TargetRvaVisitor() override;
72 void RemoveUnusedRel32Locations(AssemblyProgram* program) override;
73 InstructionGenerator GetInstructionGenerator(
74 AssemblyProgram* program) override;
76 DisassemblerWin32(const uint8_t* start, size_t length);
78 [[nodiscard]] CheckBool ParseFile(AssemblyProgram* target,
79 InstructionReceptor* receptor) const;
80 virtual void ParseRel32RelocsFromSection(const Section* section) = 0;
82 [[nodiscard]] CheckBool ParseNonSectionFileRegion(
83 FileOffset start_file_offset,
84 FileOffset end_file_offset,
85 InstructionReceptor* receptor) const;
86 [[nodiscard]] CheckBool ParseFileRegion(const Section* section,
87 FileOffset start_file_offset,
88 FileOffset end_file_offset,
89 AssemblyProgram* program,
90 InstructionReceptor* receptor) const;
92 // Returns address width in byte count.
93 virtual int AbsVAWidth() const = 0;
94 // Emits Abs 32/64 |label| to the |receptor|.
95 virtual CheckBool EmitAbs(Label* label,
96 InstructionReceptor* receptor) const = 0;
97 // Returns true if type is recognized.
98 virtual bool SupportsRelTableType(int type) const = 0;
99 virtual uint16_t RelativeOffsetOfDataDirectories() const = 0;
101 #if COURGETTE_HISTOGRAM_TARGETS
102 void HistogramTargets(const char* kind, const std::map<RVA, int>& map) const;
105 const ImageDataDirectory& base_relocation_table() const {
106 return base_relocation_table_;
109 // Returns description of the RVA, e.g. ".text+0x1243". For debugging only.
110 std::string DescribeRVA(RVA rva) const;
112 // Finds the first section at file_offset or above. Does not return sections
113 // that have no raw bytes in the file.
114 const Section* FindNextSection(FileOffset file_offset) const;
116 bool ReadDataDirectory(int index, ImageDataDirectory* dir);
118 bool incomplete_disassembly_ =
119 false; // true if can omit "uninteresting" bits.
121 std::vector<RVA> abs32_locations_;
122 std::vector<RVA> rel32_locations_;
124 // Location and size of IMAGE_OPTIONAL_HEADER in the buffer.
125 const uint8_t* optional_header_ = nullptr;
126 uint16_t size_of_optional_header_ = 0;
128 uint16_t machine_type_ = 0;
129 uint16_t number_of_sections_ = 0;
130 raw_ptr<const Section> sections_ = nullptr;
131 bool has_text_section_ = false;
133 uint32_t size_of_code_ = 0;
134 uint32_t size_of_initialized_data_ = 0;
135 uint32_t size_of_uninitialized_data_ = 0;
136 RVA base_of_code_ = 0;
137 RVA base_of_data_ = 0;
139 uint64_t image_base_ = 0; // Range limited to 32 bits for 32 bit executable.
140 // Specifies size of loaded PE in memory, and provides bound on RVA.
141 uint32_t size_of_image_ = 0;
142 int number_of_data_directories_ = 0;
144 ImageDataDirectory export_table_;
145 ImageDataDirectory import_table_;
146 ImageDataDirectory resource_table_;
147 ImageDataDirectory exception_table_;
148 ImageDataDirectory base_relocation_table_;
149 ImageDataDirectory bound_import_table_;
150 ImageDataDirectory import_address_table_;
151 ImageDataDirectory delay_import_descriptor_;
152 ImageDataDirectory clr_runtime_header_;
154 #if COURGETTE_HISTOGRAM_TARGETS
155 std::map<RVA, int> abs32_target_rvas_;
156 std::map<RVA, int> rel32_target_rvas_;
160 } // namespace courgette
162 #endif // COURGETTE_DISASSEMBLER_WIN32_H_