1 // Copyright 2017 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 COMPONENTS_ZUCCHINI_DISASSEMBLER_WIN32_H_ 6 #define COMPONENTS_ZUCCHINI_DISASSEMBLER_WIN32_H_ 7 8 #include <stddef.h> 9 #include <stdint.h> 10 11 #include <deque> 12 #include <memory> 13 #include <string> 14 #include <utility> 15 #include <vector> 16 17 #include "components/zucchini/address_translator.h" 18 #include "components/zucchini/buffer_view.h" 19 #include "components/zucchini/disassembler.h" 20 #include "components/zucchini/image_utils.h" 21 #include "components/zucchini/type_win_pe.h" 22 23 namespace zucchini { 24 25 class Rel32FinderX86; 26 class Rel32FinderX64; 27 28 struct Win32X86Traits { 29 static constexpr uint16_t kVersion = 1; 30 static constexpr Bitness kBitness = kBit32; 31 static constexpr ExecutableType kExeType = kExeTypeWin32X86; 32 enum : uint16_t { kMagic = 0x10B }; 33 enum : uint16_t { kRelocType = 3 }; 34 enum : uint32_t { kVAWidth = 4 }; 35 static const char kExeTypeString[]; 36 37 using ImageOptionalHeader = pe::ImageOptionalHeader; 38 using RelFinder = Rel32FinderX86; 39 using Address = uint32_t; 40 }; 41 42 struct Win32X64Traits { 43 static constexpr uint16_t kVersion = 1; 44 static constexpr Bitness kBitness = kBit64; 45 static constexpr ExecutableType kExeType = kExeTypeWin32X64; 46 enum : uint16_t { kMagic = 0x20B }; 47 enum : uint16_t { kRelocType = 10 }; 48 enum : uint32_t { kVAWidth = 8 }; 49 static const char kExeTypeString[]; 50 51 using ImageOptionalHeader = pe::ImageOptionalHeader64; 52 using RelFinder = Rel32FinderX64; 53 using Address = uint64_t; 54 }; 55 56 template <class TRAITS> 57 class DisassemblerWin32 : public Disassembler { 58 public: 59 using Traits = TRAITS; 60 static constexpr uint16_t kVersion = Traits::kVersion; 61 enum ReferenceType : uint8_t { kReloc, kAbs32, kRel32, kTypeCount }; 62 63 // Applies quick checks to determine whether |image| *may* point to the start 64 // of an executable. Returns true iff the check passes. 65 static bool QuickDetect(ConstBufferView image); 66 67 DisassemblerWin32(); 68 DisassemblerWin32(const DisassemblerWin32&) = delete; 69 const DisassemblerWin32& operator=(const DisassemblerWin32&) = delete; 70 ~DisassemblerWin32() override; 71 72 // Disassembler: 73 ExecutableType GetExeType() const override; 74 std::string GetExeTypeString() const override; 75 std::vector<ReferenceGroup> MakeReferenceGroups() const override; 76 77 // Functions that return reader / writer for references. 78 std::unique_ptr<ReferenceReader> MakeReadRelocs(offset_t lo, offset_t hi); 79 std::unique_ptr<ReferenceReader> MakeReadAbs32(offset_t lo, offset_t hi); 80 std::unique_ptr<ReferenceReader> MakeReadRel32(offset_t lo, offset_t hi); 81 std::unique_ptr<ReferenceWriter> MakeWriteRelocs(MutableBufferView image); 82 std::unique_ptr<ReferenceWriter> MakeWriteAbs32(MutableBufferView image); 83 std::unique_ptr<ReferenceWriter> MakeWriteRel32(MutableBufferView image); 84 85 private: 86 friend Disassembler; 87 88 // Disassembler: 89 bool Parse(ConstBufferView image) override; 90 91 // Parses the file header. Returns true iff successful. 92 bool ParseHeader(); 93 94 // Parsers to extract references. These are lazily called, and return whether 95 // parsing was successful (failures are non-fatal). 96 bool ParseAndStoreRelocBlocks(); 97 bool ParseAndStoreAbs32(); 98 bool ParseAndStoreRel32(); 99 100 // In-memory copy of sections. 101 std::vector<pe::ImageSectionHeader> sections_; 102 103 // Image base address to translate between RVA and VA. 104 typename Traits::Address image_base_ = 0; 105 106 // Pointer to data Directory entry of the relocation table. 107 const pe::ImageDataDirectory* base_relocation_table_ = nullptr; 108 109 // Translator between offsets and RVAs. 110 AddressTranslator translator_; 111 112 // Reference storage. 113 BufferRegion reloc_region_ = {kInvalidOffset, 0U}; 114 std::vector<offset_t> reloc_block_offsets_; 115 offset_t reloc_end_ = 0; 116 std::vector<offset_t> abs32_locations_; 117 // Using std::deque to reduce peak memory footprint. 118 std::deque<offset_t> rel32_locations_; 119 120 // Initialization states of reference storage, used for lazy initialization. 121 // TODO(huangs): Investigate whether lazy initialization is useful for memory 122 // reduction. This is a carryover from Courgette. To be sure we should run 123 // experiment after Zucchini is able to do ensemble patching. 124 bool has_parsed_relocs_ = false; 125 bool has_parsed_abs32_ = false; 126 bool has_parsed_rel32_ = false; 127 }; 128 129 using DisassemblerWin32X86 = DisassemblerWin32<Win32X86Traits>; 130 using DisassemblerWin32X64 = DisassemblerWin32<Win32X64Traits>; 131 132 } // namespace zucchini 133 134 #endif // COMPONENTS_ZUCCHINI_DISASSEMBLER_WIN32_H_ 135