blob: dfb2533304b88b9431c502422fe6bc30ec570278 [file] [log] [blame]
Samuel Huang06f1ae92018-03-13 18:19:34 +00001// 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
Etienne Pierre-doraye1c6a712021-04-16 18:20:33 +000011#include <deque>
Samuel Huang06f1ae92018-03-13 18:19:34 +000012#include <memory>
13#include <string>
14#include <utility>
15#include <vector>
16
Samuel Huang06f1ae92018-03-13 18:19:34 +000017#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
23namespace zucchini {
24
25class Rel32FinderX86;
26class Rel32FinderX64;
27
28struct Win32X86Traits {
Etienne Pierre-dorayb90a9472021-10-28 21:16:04 +000029 static constexpr uint16_t kVersion = 1;
Samuel Huang06f1ae92018-03-13 18:19:34 +000030 static constexpr Bitness kBitness = kBit32;
31 static constexpr ExecutableType kExeType = kExeTypeWin32X86;
32 enum : uint16_t { kMagic = 0x10B };
33 enum : uint16_t { kRelocType = 3 };
Samuel Huang607ce602018-06-13 17:47:39 +000034 enum : uint32_t { kVAWidth = 4 };
Samuel Huang06f1ae92018-03-13 18:19:34 +000035 static const char kExeTypeString[];
36
37 using ImageOptionalHeader = pe::ImageOptionalHeader;
38 using RelFinder = Rel32FinderX86;
39 using Address = uint32_t;
40};
41
42struct Win32X64Traits {
Etienne Pierre-dorayb90a9472021-10-28 21:16:04 +000043 static constexpr uint16_t kVersion = 1;
Samuel Huang06f1ae92018-03-13 18:19:34 +000044 static constexpr Bitness kBitness = kBit64;
45 static constexpr ExecutableType kExeType = kExeTypeWin32X64;
46 enum : uint16_t { kMagic = 0x20B };
47 enum : uint16_t { kRelocType = 10 };
Samuel Huang607ce602018-06-13 17:47:39 +000048 enum : uint32_t { kVAWidth = 8 };
Samuel Huang06f1ae92018-03-13 18:19:34 +000049 static const char kExeTypeString[];
50
51 using ImageOptionalHeader = pe::ImageOptionalHeader64;
52 using RelFinder = Rel32FinderX64;
53 using Address = uint64_t;
54};
55
Samuel Huang3e1f64d2021-08-04 00:58:50 +000056template <class TRAITS>
Samuel Huang06f1ae92018-03-13 18:19:34 +000057class DisassemblerWin32 : public Disassembler {
58 public:
Samuel Huang3e1f64d2021-08-04 00:58:50 +000059 using Traits = TRAITS;
Etienne Pierre-dorayb90a9472021-10-28 21:16:04 +000060 static constexpr uint16_t kVersion = Traits::kVersion;
Samuel Huang06f1ae92018-03-13 18:19:34 +000061 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();
Samuel Huangf137bf42021-08-13 15:42:26 +000068 DisassemblerWin32(const DisassemblerWin32&) = delete;
69 const DisassemblerWin32& operator=(const DisassemblerWin32&) = delete;
Samuel Huang06f1ae92018-03-13 18:19:34 +000070 ~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.
Samuel Huang431d1192018-12-31 19:59:22 +0000113 BufferRegion reloc_region_ = {kInvalidOffset, 0U};
Samuel Huang06f1ae92018-03-13 18:19:34 +0000114 std::vector<offset_t> reloc_block_offsets_;
115 offset_t reloc_end_ = 0;
116 std::vector<offset_t> abs32_locations_;
Etienne Pierre-doraye1c6a712021-04-16 18:20:33 +0000117 // Using std::deque to reduce peak memory footprint.
118 std::deque<offset_t> rel32_locations_;
Samuel Huang06f1ae92018-03-13 18:19:34 +0000119
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;
Samuel Huang06f1ae92018-03-13 18:19:34 +0000127};
128
129using DisassemblerWin32X86 = DisassemblerWin32<Win32X86Traits>;
130using DisassemblerWin32X64 = DisassemblerWin32<Win32X64Traits>;
131
132} // namespace zucchini
133
134#endif // COMPONENTS_ZUCCHINI_DISASSEMBLER_WIN32_H_