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