xref: /aosp_15_r20/external/zucchini/disassembler_elf.h (revision a03ca8b91e029cd15055c20c78c2e087c84792e4)
1*a03ca8b9SKrzysztof Kosiński // Copyright 2018 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_ELF_H_
6*a03ca8b9SKrzysztof Kosiński #define COMPONENTS_ZUCCHINI_DISASSEMBLER_ELF_H_
7*a03ca8b9SKrzysztof Kosiński 
8*a03ca8b9SKrzysztof Kosiński #include <stdint.h>
9*a03ca8b9SKrzysztof Kosiński 
10*a03ca8b9SKrzysztof Kosiński #include <algorithm>
11*a03ca8b9SKrzysztof Kosiński #include <deque>
12*a03ca8b9SKrzysztof Kosiński #include <memory>
13*a03ca8b9SKrzysztof Kosiński #include <string>
14*a03ca8b9SKrzysztof Kosiński #include <vector>
15*a03ca8b9SKrzysztof Kosiński 
16*a03ca8b9SKrzysztof Kosiński #include "components/zucchini/address_translator.h"
17*a03ca8b9SKrzysztof Kosiński #include "components/zucchini/buffer_view.h"
18*a03ca8b9SKrzysztof Kosiński #include "components/zucchini/disassembler.h"
19*a03ca8b9SKrzysztof Kosiński #include "components/zucchini/image_utils.h"
20*a03ca8b9SKrzysztof Kosiński #include "components/zucchini/rel32_finder.h"
21*a03ca8b9SKrzysztof Kosiński #include "components/zucchini/rel32_utils.h"
22*a03ca8b9SKrzysztof Kosiński #include "components/zucchini/reloc_elf.h"
23*a03ca8b9SKrzysztof Kosiński #include "components/zucchini/type_elf.h"
24*a03ca8b9SKrzysztof Kosiński 
25*a03ca8b9SKrzysztof Kosiński namespace zucchini {
26*a03ca8b9SKrzysztof Kosiński 
27*a03ca8b9SKrzysztof Kosiński struct ArmReferencePool {
28*a03ca8b9SKrzysztof Kosiński   enum : uint8_t {
29*a03ca8b9SKrzysztof Kosiński     kPoolReloc,
30*a03ca8b9SKrzysztof Kosiński     kPoolAbs32,
31*a03ca8b9SKrzysztof Kosiński     kPoolRel32,
32*a03ca8b9SKrzysztof Kosiński   };
33*a03ca8b9SKrzysztof Kosiński };
34*a03ca8b9SKrzysztof Kosiński 
35*a03ca8b9SKrzysztof Kosiński struct AArch32ReferenceType {
36*a03ca8b9SKrzysztof Kosiński   enum : uint8_t {
37*a03ca8b9SKrzysztof Kosiński     kReloc,  // kPoolReloc
38*a03ca8b9SKrzysztof Kosiński 
39*a03ca8b9SKrzysztof Kosiński     kAbs32,  // kPoolAbs32
40*a03ca8b9SKrzysztof Kosiński 
41*a03ca8b9SKrzysztof Kosiński     kRel32_A24,  // kPoolRel32
42*a03ca8b9SKrzysztof Kosiński     kRel32_T8,
43*a03ca8b9SKrzysztof Kosiński     kRel32_T11,
44*a03ca8b9SKrzysztof Kosiński     kRel32_T20,
45*a03ca8b9SKrzysztof Kosiński     kRel32_T24,
46*a03ca8b9SKrzysztof Kosiński 
47*a03ca8b9SKrzysztof Kosiński     kTypeCount
48*a03ca8b9SKrzysztof Kosiński   };
49*a03ca8b9SKrzysztof Kosiński };
50*a03ca8b9SKrzysztof Kosiński 
51*a03ca8b9SKrzysztof Kosiński struct AArch64ReferenceType {
52*a03ca8b9SKrzysztof Kosiński   enum : uint8_t {
53*a03ca8b9SKrzysztof Kosiński     kReloc,  // kPoolReloc
54*a03ca8b9SKrzysztof Kosiński 
55*a03ca8b9SKrzysztof Kosiński     kAbs32,  // kPoolAbs32
56*a03ca8b9SKrzysztof Kosiński 
57*a03ca8b9SKrzysztof Kosiński     kRel32_Immd14,  // kPoolRel32
58*a03ca8b9SKrzysztof Kosiński     kRel32_Immd19,
59*a03ca8b9SKrzysztof Kosiński     kRel32_Immd26,
60*a03ca8b9SKrzysztof Kosiński 
61*a03ca8b9SKrzysztof Kosiński     kTypeCount
62*a03ca8b9SKrzysztof Kosiński   };
63*a03ca8b9SKrzysztof Kosiński };
64*a03ca8b9SKrzysztof Kosiński 
65*a03ca8b9SKrzysztof Kosiński struct Elf32Traits {
66*a03ca8b9SKrzysztof Kosiński   static constexpr uint16_t kVersion = 1;
67*a03ca8b9SKrzysztof Kosiński   static constexpr Bitness kBitness = kBit32;
68*a03ca8b9SKrzysztof Kosiński   static constexpr elf::FileClass kIdentificationClass = elf::ELFCLASS32;
69*a03ca8b9SKrzysztof Kosiński   using Elf_Shdr = elf::Elf32_Shdr;
70*a03ca8b9SKrzysztof Kosiński   using Elf_Phdr = elf::Elf32_Phdr;
71*a03ca8b9SKrzysztof Kosiński   using Elf_Ehdr = elf::Elf32_Ehdr;
72*a03ca8b9SKrzysztof Kosiński   using Elf_Rel = elf::Elf32_Rel;
73*a03ca8b9SKrzysztof Kosiński   using Elf_Rela = elf::Elf32_Rela;
74*a03ca8b9SKrzysztof Kosiński };
75*a03ca8b9SKrzysztof Kosiński 
76*a03ca8b9SKrzysztof Kosiński // Architecture-specific definitions.
77*a03ca8b9SKrzysztof Kosiński 
78*a03ca8b9SKrzysztof Kosiński struct Elf32IntelTraits : public Elf32Traits {
79*a03ca8b9SKrzysztof Kosiński   static constexpr ExecutableType kExeType = kExeTypeElfX86;
80*a03ca8b9SKrzysztof Kosiński   static const char kExeTypeString[];
81*a03ca8b9SKrzysztof Kosiński   static constexpr elf::MachineArchitecture kMachineValue = elf::EM_386;
82*a03ca8b9SKrzysztof Kosiński   static constexpr uint32_t kRelType = elf::R_386_RELATIVE;
83*a03ca8b9SKrzysztof Kosiński   enum : uint32_t { kVAWidth = 4 };
84*a03ca8b9SKrzysztof Kosiński   using Rel32FinderUse = Rel32FinderX86;
85*a03ca8b9SKrzysztof Kosiński };
86*a03ca8b9SKrzysztof Kosiński 
87*a03ca8b9SKrzysztof Kosiński struct ElfAArch32Traits : public Elf32Traits {
88*a03ca8b9SKrzysztof Kosiński   static constexpr ExecutableType kExeType = kExeTypeElfAArch32;
89*a03ca8b9SKrzysztof Kosiński   static const char kExeTypeString[];
90*a03ca8b9SKrzysztof Kosiński   static constexpr elf::MachineArchitecture kMachineValue = elf::EM_ARM;
91*a03ca8b9SKrzysztof Kosiński   static constexpr uint32_t kRelType = elf::R_ARM_RELATIVE;
92*a03ca8b9SKrzysztof Kosiński   enum : uint32_t { kVAWidth = 4 };
93*a03ca8b9SKrzysztof Kosiński   using ArmReferenceType = AArch32ReferenceType;
94*a03ca8b9SKrzysztof Kosiński   using Rel32FinderUse = Rel32FinderAArch32;
95*a03ca8b9SKrzysztof Kosiński };
96*a03ca8b9SKrzysztof Kosiński 
97*a03ca8b9SKrzysztof Kosiński struct Elf64Traits {
98*a03ca8b9SKrzysztof Kosiński   static constexpr uint16_t kVersion = 1;
99*a03ca8b9SKrzysztof Kosiński   static constexpr Bitness kBitness = kBit64;
100*a03ca8b9SKrzysztof Kosiński   static constexpr elf::FileClass kIdentificationClass = elf::ELFCLASS64;
101*a03ca8b9SKrzysztof Kosiński   using Elf_Shdr = elf::Elf64_Shdr;
102*a03ca8b9SKrzysztof Kosiński   using Elf_Phdr = elf::Elf64_Phdr;
103*a03ca8b9SKrzysztof Kosiński   using Elf_Ehdr = elf::Elf64_Ehdr;
104*a03ca8b9SKrzysztof Kosiński   using Elf_Rel = elf::Elf64_Rel;
105*a03ca8b9SKrzysztof Kosiński   using Elf_Rela = elf::Elf64_Rela;
106*a03ca8b9SKrzysztof Kosiński };
107*a03ca8b9SKrzysztof Kosiński 
108*a03ca8b9SKrzysztof Kosiński // Architecture-specific definitions.
109*a03ca8b9SKrzysztof Kosiński struct Elf64IntelTraits : public Elf64Traits {
110*a03ca8b9SKrzysztof Kosiński   static constexpr ExecutableType kExeType = kExeTypeElfX64;
111*a03ca8b9SKrzysztof Kosiński   static const char kExeTypeString[];
112*a03ca8b9SKrzysztof Kosiński   static constexpr elf::MachineArchitecture kMachineValue = elf::EM_X86_64;
113*a03ca8b9SKrzysztof Kosiński   static constexpr uint32_t kRelType = elf::R_X86_64_RELATIVE;
114*a03ca8b9SKrzysztof Kosiński   enum : uint32_t { kVAWidth = 8 };
115*a03ca8b9SKrzysztof Kosiński   using Rel32FinderUse = Rel32FinderX64;
116*a03ca8b9SKrzysztof Kosiński };
117*a03ca8b9SKrzysztof Kosiński 
118*a03ca8b9SKrzysztof Kosiński struct ElfAArch64Traits : public Elf64Traits {
119*a03ca8b9SKrzysztof Kosiński   static constexpr ExecutableType kExeType = kExeTypeElfAArch64;
120*a03ca8b9SKrzysztof Kosiński   static const char kExeTypeString[];
121*a03ca8b9SKrzysztof Kosiński   static constexpr elf::MachineArchitecture kMachineValue = elf::EM_AARCH64;
122*a03ca8b9SKrzysztof Kosiński   // TODO(huangs): See if R_AARCH64_GLOB_DAT and R_AARCH64_JUMP_SLOT should be
123*a03ca8b9SKrzysztof Kosiński   // used.
124*a03ca8b9SKrzysztof Kosiński   static constexpr uint32_t kRelType = elf::R_AARCH64_RELATIVE;
125*a03ca8b9SKrzysztof Kosiński   enum : uint32_t { kVAWidth = 8 };
126*a03ca8b9SKrzysztof Kosiński   using ArmReferenceType = AArch64ReferenceType;
127*a03ca8b9SKrzysztof Kosiński   using Rel32FinderUse = Rel32FinderAArch64;
128*a03ca8b9SKrzysztof Kosiński };
129*a03ca8b9SKrzysztof Kosiński 
130*a03ca8b9SKrzysztof Kosiński // Decides whether target |offset| is covered by a section in |sorted_headers|.
131*a03ca8b9SKrzysztof Kosiński template <class ELF_SHDR>
IsTargetOffsetInElfSectionList(const std::vector<const ELF_SHDR * > & sorted_headers,offset_t offset)132*a03ca8b9SKrzysztof Kosiński bool IsTargetOffsetInElfSectionList(
133*a03ca8b9SKrzysztof Kosiński     const std::vector<const ELF_SHDR*>& sorted_headers,
134*a03ca8b9SKrzysztof Kosiński     offset_t offset) {
135*a03ca8b9SKrzysztof Kosiński   // Use binary search to search in a list of intervals, in a fashion similar to
136*a03ca8b9SKrzysztof Kosiński   // AddressTranslator::OffsetToUnit().
137*a03ca8b9SKrzysztof Kosiński   auto comp = [](offset_t offset, const ELF_SHDR* header) -> bool {
138*a03ca8b9SKrzysztof Kosiński     return offset < header->sh_offset;
139*a03ca8b9SKrzysztof Kosiński   };
140*a03ca8b9SKrzysztof Kosiński   auto it = std::upper_bound(sorted_headers.begin(), sorted_headers.end(),
141*a03ca8b9SKrzysztof Kosiński                              offset, comp);
142*a03ca8b9SKrzysztof Kosiński   if (it == sorted_headers.begin())
143*a03ca8b9SKrzysztof Kosiński     return false;
144*a03ca8b9SKrzysztof Kosiński   --it;
145*a03ca8b9SKrzysztof Kosiński   // Just check offset without worrying about width, since this is a target.
146*a03ca8b9SKrzysztof Kosiński   // Not using RangeCovers() because |sh_offset| and |sh_size| can be 64-bit.
147*a03ca8b9SKrzysztof Kosiński   return offset >= (*it)->sh_offset &&
148*a03ca8b9SKrzysztof Kosiński          offset - (*it)->sh_offset < (*it)->sh_size;
149*a03ca8b9SKrzysztof Kosiński }
150*a03ca8b9SKrzysztof Kosiński 
151*a03ca8b9SKrzysztof Kosiński // Disassembler for ELF.
152*a03ca8b9SKrzysztof Kosiński template <class TRAITS>
153*a03ca8b9SKrzysztof Kosiński class DisassemblerElf : public Disassembler {
154*a03ca8b9SKrzysztof Kosiński  public:
155*a03ca8b9SKrzysztof Kosiński   using Traits = TRAITS;
156*a03ca8b9SKrzysztof Kosiński   static constexpr uint16_t kVersion = Traits::kVersion;
157*a03ca8b9SKrzysztof Kosiński   // Applies quick checks to determine whether |image| *may* point to the start
158*a03ca8b9SKrzysztof Kosiński   // of an executable. Returns true iff the check passes.
159*a03ca8b9SKrzysztof Kosiński   static bool QuickDetect(ConstBufferView image);
160*a03ca8b9SKrzysztof Kosiński 
161*a03ca8b9SKrzysztof Kosiński   DisassemblerElf(const DisassemblerElf&) = delete;
162*a03ca8b9SKrzysztof Kosiński   const DisassemblerElf& operator=(const DisassemblerElf&) = delete;
163*a03ca8b9SKrzysztof Kosiński   ~DisassemblerElf() override;
164*a03ca8b9SKrzysztof Kosiński 
165*a03ca8b9SKrzysztof Kosiński   // Disassembler:
166*a03ca8b9SKrzysztof Kosiński   ExecutableType GetExeType() const override;
167*a03ca8b9SKrzysztof Kosiński   std::string GetExeTypeString() const override;
168*a03ca8b9SKrzysztof Kosiński   std::vector<ReferenceGroup> MakeReferenceGroups() const override = 0;
169*a03ca8b9SKrzysztof Kosiński 
170*a03ca8b9SKrzysztof Kosiński   // Read/Write functions that are common among different architectures.
171*a03ca8b9SKrzysztof Kosiński   std::unique_ptr<ReferenceReader> MakeReadRelocs(offset_t lo, offset_t hi);
172*a03ca8b9SKrzysztof Kosiński   std::unique_ptr<ReferenceWriter> MakeWriteRelocs(MutableBufferView image);
173*a03ca8b9SKrzysztof Kosiński 
translator()174*a03ca8b9SKrzysztof Kosiński   const AddressTranslator& translator() const { return translator_; }
175*a03ca8b9SKrzysztof Kosiński 
176*a03ca8b9SKrzysztof Kosiński  protected:
177*a03ca8b9SKrzysztof Kosiński   friend Disassembler;
178*a03ca8b9SKrzysztof Kosiński 
179*a03ca8b9SKrzysztof Kosiński   DisassemblerElf();
180*a03ca8b9SKrzysztof Kosiński 
181*a03ca8b9SKrzysztof Kosiński   bool Parse(ConstBufferView image) override;
182*a03ca8b9SKrzysztof Kosiński 
183*a03ca8b9SKrzysztof Kosiński   // Returns the supported Elf_Ehdr::e_machine enum.
supported_architecture()184*a03ca8b9SKrzysztof Kosiński   static constexpr elf::MachineArchitecture supported_architecture() {
185*a03ca8b9SKrzysztof Kosiński     return Traits::kMachineValue;
186*a03ca8b9SKrzysztof Kosiński   }
187*a03ca8b9SKrzysztof Kosiński 
188*a03ca8b9SKrzysztof Kosiński   // Returns the type to look for in the reloc section.
supported_relocation_type()189*a03ca8b9SKrzysztof Kosiński   static constexpr uint32_t supported_relocation_type() {
190*a03ca8b9SKrzysztof Kosiński     return Traits::kRelType;
191*a03ca8b9SKrzysztof Kosiński   }
192*a03ca8b9SKrzysztof Kosiński 
193*a03ca8b9SKrzysztof Kosiński   // Performs architecture-specific parsing of an executable section, to extract
194*a03ca8b9SKrzysztof Kosiński   // rel32 references.
195*a03ca8b9SKrzysztof Kosiński   virtual void ParseExecSection(const typename Traits::Elf_Shdr& section) = 0;
196*a03ca8b9SKrzysztof Kosiński 
197*a03ca8b9SKrzysztof Kosiński   // Processes rel32 data after they are extracted from executable sections.
198*a03ca8b9SKrzysztof Kosiński   virtual void PostProcessRel32() = 0;
199*a03ca8b9SKrzysztof Kosiński 
200*a03ca8b9SKrzysztof Kosiński   // Parses ELF header and section headers, and performs basic validation.
201*a03ca8b9SKrzysztof Kosiński   // Returns whether parsing was successful.
202*a03ca8b9SKrzysztof Kosiński   bool ParseHeader();
203*a03ca8b9SKrzysztof Kosiński 
204*a03ca8b9SKrzysztof Kosiński   // Extracts and stores section headers that we need.
205*a03ca8b9SKrzysztof Kosiński   void ExtractInterestingSectionHeaders();
206*a03ca8b9SKrzysztof Kosiński 
207*a03ca8b9SKrzysztof Kosiński   // Parsing functions that extract references from various sections.
208*a03ca8b9SKrzysztof Kosiński   void GetAbs32FromRelocSections();
209*a03ca8b9SKrzysztof Kosiński   void GetRel32FromCodeSections();
210*a03ca8b9SKrzysztof Kosiński   void ParseSections();
211*a03ca8b9SKrzysztof Kosiński 
212*a03ca8b9SKrzysztof Kosiński   // Main ELF header.
213*a03ca8b9SKrzysztof Kosiński   const typename Traits::Elf_Ehdr* header_ = nullptr;
214*a03ca8b9SKrzysztof Kosiński 
215*a03ca8b9SKrzysztof Kosiński   // Section header table, ordered by section id.
216*a03ca8b9SKrzysztof Kosiński   elf::Elf32_Half sections_count_ = 0;
217*a03ca8b9SKrzysztof Kosiński   const typename Traits::Elf_Shdr* sections_ = nullptr;
218*a03ca8b9SKrzysztof Kosiński 
219*a03ca8b9SKrzysztof Kosiński   // Program header table.
220*a03ca8b9SKrzysztof Kosiński   elf::Elf32_Half segments_count_ = 0;
221*a03ca8b9SKrzysztof Kosiński   const typename Traits::Elf_Phdr* segments_ = nullptr;
222*a03ca8b9SKrzysztof Kosiński 
223*a03ca8b9SKrzysztof Kosiński   // Bit fields to store the role each section may play.
224*a03ca8b9SKrzysztof Kosiński   std::vector<int> section_judgements_;
225*a03ca8b9SKrzysztof Kosiński 
226*a03ca8b9SKrzysztof Kosiński   // Translator between offsets and RVAs.
227*a03ca8b9SKrzysztof Kosiński   AddressTranslator translator_;
228*a03ca8b9SKrzysztof Kosiński 
229*a03ca8b9SKrzysztof Kosiński   // Identity translator for abs32 translation.
230*a03ca8b9SKrzysztof Kosiński   AddressTranslator identity_translator_;
231*a03ca8b9SKrzysztof Kosiński 
232*a03ca8b9SKrzysztof Kosiński   // Extracted relocation section dimensions data, sorted by file offsets.
233*a03ca8b9SKrzysztof Kosiński   std::vector<SectionDimensionsElf> reloc_section_dims_;
234*a03ca8b9SKrzysztof Kosiński 
235*a03ca8b9SKrzysztof Kosiński   // Headers of executable sections, sorted by file offsets of the data each
236*a03ca8b9SKrzysztof Kosiński   // header points to.
237*a03ca8b9SKrzysztof Kosiński   std::vector<const typename Traits::Elf_Shdr*> exec_headers_;
238*a03ca8b9SKrzysztof Kosiński 
239*a03ca8b9SKrzysztof Kosiński   // Sorted file offsets of abs32 locations.
240*a03ca8b9SKrzysztof Kosiński   std::vector<offset_t> abs32_locations_;
241*a03ca8b9SKrzysztof Kosiński };
242*a03ca8b9SKrzysztof Kosiński 
243*a03ca8b9SKrzysztof Kosiński // Disassembler for ELF with Intel architectures.
244*a03ca8b9SKrzysztof Kosiński template <class TRAITS>
245*a03ca8b9SKrzysztof Kosiński class DisassemblerElfIntel : public DisassemblerElf<TRAITS> {
246*a03ca8b9SKrzysztof Kosiński  public:
247*a03ca8b9SKrzysztof Kosiński   using Traits = TRAITS;
248*a03ca8b9SKrzysztof Kosiński   enum ReferenceType : uint8_t { kReloc, kAbs32, kRel32, kTypeCount };
249*a03ca8b9SKrzysztof Kosiński 
250*a03ca8b9SKrzysztof Kosiński   DisassemblerElfIntel();
251*a03ca8b9SKrzysztof Kosiński   DisassemblerElfIntel(const DisassemblerElfIntel&) = delete;
252*a03ca8b9SKrzysztof Kosiński   const DisassemblerElfIntel& operator=(const DisassemblerElfIntel&) = delete;
253*a03ca8b9SKrzysztof Kosiński   ~DisassemblerElfIntel() override;
254*a03ca8b9SKrzysztof Kosiński 
255*a03ca8b9SKrzysztof Kosiński   // Disassembler:
256*a03ca8b9SKrzysztof Kosiński   std::vector<ReferenceGroup> MakeReferenceGroups() const override;
257*a03ca8b9SKrzysztof Kosiński 
258*a03ca8b9SKrzysztof Kosiński   // DisassemblerElf:
259*a03ca8b9SKrzysztof Kosiński   void ParseExecSection(const typename Traits::Elf_Shdr& section) override;
260*a03ca8b9SKrzysztof Kosiński   void PostProcessRel32() override;
261*a03ca8b9SKrzysztof Kosiński 
262*a03ca8b9SKrzysztof Kosiński   // Specialized Read/Write functions.
263*a03ca8b9SKrzysztof Kosiński   std::unique_ptr<ReferenceReader> MakeReadAbs32(offset_t lo, offset_t hi);
264*a03ca8b9SKrzysztof Kosiński   std::unique_ptr<ReferenceWriter> MakeWriteAbs32(MutableBufferView image);
265*a03ca8b9SKrzysztof Kosiński   std::unique_ptr<ReferenceReader> MakeReadRel32(offset_t lo, offset_t hi);
266*a03ca8b9SKrzysztof Kosiński   std::unique_ptr<ReferenceWriter> MakeWriteRel32(MutableBufferView image);
267*a03ca8b9SKrzysztof Kosiński 
268*a03ca8b9SKrzysztof Kosiński  private:
269*a03ca8b9SKrzysztof Kosiński   // Sorted file offsets of rel32 locations.
270*a03ca8b9SKrzysztof Kosiński   // Using std::deque to reduce peak memory footprint.
271*a03ca8b9SKrzysztof Kosiński   std::deque<offset_t> rel32_locations_;
272*a03ca8b9SKrzysztof Kosiński };
273*a03ca8b9SKrzysztof Kosiński 
274*a03ca8b9SKrzysztof Kosiński using DisassemblerElfX86 = DisassemblerElfIntel<Elf32IntelTraits>;
275*a03ca8b9SKrzysztof Kosiński using DisassemblerElfX64 = DisassemblerElfIntel<Elf64IntelTraits>;
276*a03ca8b9SKrzysztof Kosiński 
277*a03ca8b9SKrzysztof Kosiński // Disassembler for ELF with ARM architectures.
278*a03ca8b9SKrzysztof Kosiński template <class TRAITS>
279*a03ca8b9SKrzysztof Kosiński class DisassemblerElfArm : public DisassemblerElf<TRAITS> {
280*a03ca8b9SKrzysztof Kosiński  public:
281*a03ca8b9SKrzysztof Kosiński   using Traits = TRAITS;
282*a03ca8b9SKrzysztof Kosiński   DisassemblerElfArm();
283*a03ca8b9SKrzysztof Kosiński   DisassemblerElfArm(const DisassemblerElfArm&) = delete;
284*a03ca8b9SKrzysztof Kosiński   const DisassemblerElfArm& operator=(const DisassemblerElfArm&) = delete;
285*a03ca8b9SKrzysztof Kosiński   ~DisassemblerElfArm() override;
286*a03ca8b9SKrzysztof Kosiński 
287*a03ca8b9SKrzysztof Kosiński   // Determines whether target |offset| is in an executable section.
288*a03ca8b9SKrzysztof Kosiński   bool IsTargetOffsetInExecSection(offset_t offset) const;
289*a03ca8b9SKrzysztof Kosiński 
290*a03ca8b9SKrzysztof Kosiński   // Creates an architecture-specific Rel32Finder for ParseExecSection.
291*a03ca8b9SKrzysztof Kosiński   virtual std::unique_ptr<typename Traits::Rel32FinderUse> MakeRel32Finder(
292*a03ca8b9SKrzysztof Kosiński       const typename Traits::Elf_Shdr& section) = 0;
293*a03ca8b9SKrzysztof Kosiński 
294*a03ca8b9SKrzysztof Kosiński   // DisassemblerElf:
295*a03ca8b9SKrzysztof Kosiński   void ParseExecSection(const typename Traits::Elf_Shdr& section) override;
296*a03ca8b9SKrzysztof Kosiński   void PostProcessRel32() override;
297*a03ca8b9SKrzysztof Kosiński 
298*a03ca8b9SKrzysztof Kosiński   // Specialized Read/Write functions.
299*a03ca8b9SKrzysztof Kosiński   std::unique_ptr<ReferenceReader> MakeReadAbs32(offset_t lo, offset_t hi);
300*a03ca8b9SKrzysztof Kosiński   std::unique_ptr<ReferenceWriter> MakeWriteAbs32(MutableBufferView image);
301*a03ca8b9SKrzysztof Kosiński 
302*a03ca8b9SKrzysztof Kosiński   // Specialized Read/Write functions for different rel32 address types.
303*a03ca8b9SKrzysztof Kosiński   template <class ADDR_TRAITS>
304*a03ca8b9SKrzysztof Kosiński   std::unique_ptr<ReferenceReader> MakeReadRel32(offset_t lower,
305*a03ca8b9SKrzysztof Kosiński                                                  offset_t upper);
306*a03ca8b9SKrzysztof Kosiński   template <class ADDR_TRAITS>
307*a03ca8b9SKrzysztof Kosiński   std::unique_ptr<ReferenceWriter> MakeWriteRel32(MutableBufferView image);
308*a03ca8b9SKrzysztof Kosiński 
309*a03ca8b9SKrzysztof Kosiński  protected:
310*a03ca8b9SKrzysztof Kosiński   // Sorted file offsets of rel32 locations for each rel32 address type.
311*a03ca8b9SKrzysztof Kosiński   std::deque<offset_t>
312*a03ca8b9SKrzysztof Kosiński       rel32_locations_table_[Traits::ArmReferenceType::kTypeCount];
313*a03ca8b9SKrzysztof Kosiński };
314*a03ca8b9SKrzysztof Kosiński 
315*a03ca8b9SKrzysztof Kosiński // Disassembler for ELF with AArch32 (AKA ARM32).
316*a03ca8b9SKrzysztof Kosiński class DisassemblerElfAArch32 : public DisassemblerElfArm<ElfAArch32Traits> {
317*a03ca8b9SKrzysztof Kosiński  public:
318*a03ca8b9SKrzysztof Kosiński   DisassemblerElfAArch32();
319*a03ca8b9SKrzysztof Kosiński   DisassemblerElfAArch32(const DisassemblerElfAArch32&) = delete;
320*a03ca8b9SKrzysztof Kosiński   const DisassemblerElfAArch32& operator=(const DisassemblerElfAArch32&) =
321*a03ca8b9SKrzysztof Kosiński       delete;
322*a03ca8b9SKrzysztof Kosiński   ~DisassemblerElfAArch32() override;
323*a03ca8b9SKrzysztof Kosiński 
324*a03ca8b9SKrzysztof Kosiński   // Disassembler:
325*a03ca8b9SKrzysztof Kosiński   std::vector<ReferenceGroup> MakeReferenceGroups() const override;
326*a03ca8b9SKrzysztof Kosiński 
327*a03ca8b9SKrzysztof Kosiński   // DisassemblerElfArm:
328*a03ca8b9SKrzysztof Kosiński   std::unique_ptr<typename Traits::Rel32FinderUse> MakeRel32Finder(
329*a03ca8b9SKrzysztof Kosiński       const typename Traits::Elf_Shdr& section) override;
330*a03ca8b9SKrzysztof Kosiński 
331*a03ca8b9SKrzysztof Kosiński   // Under the naive assumption that an executable section is entirely ARM mode
332*a03ca8b9SKrzysztof Kosiński   // or THUMB2 mode, this function implements heuristics to distinguish between
333*a03ca8b9SKrzysztof Kosiński   // the two. Returns true if section is THUMB2 mode; otherwise return false.
334*a03ca8b9SKrzysztof Kosiński   bool IsExecSectionThumb2(const typename Traits::Elf_Shdr& section) const;
335*a03ca8b9SKrzysztof Kosiński };
336*a03ca8b9SKrzysztof Kosiński 
337*a03ca8b9SKrzysztof Kosiński // Disassembler for ELF with AArch64 (AKA ARM64).
338*a03ca8b9SKrzysztof Kosiński class DisassemblerElfAArch64 : public DisassemblerElfArm<ElfAArch64Traits> {
339*a03ca8b9SKrzysztof Kosiński  public:
340*a03ca8b9SKrzysztof Kosiński   DisassemblerElfAArch64();
341*a03ca8b9SKrzysztof Kosiński   DisassemblerElfAArch64(const DisassemblerElfAArch64&) = delete;
342*a03ca8b9SKrzysztof Kosiński   const DisassemblerElfAArch64& operator=(const DisassemblerElfAArch64&) =
343*a03ca8b9SKrzysztof Kosiński       delete;
344*a03ca8b9SKrzysztof Kosiński   ~DisassemblerElfAArch64() override;
345*a03ca8b9SKrzysztof Kosiński 
346*a03ca8b9SKrzysztof Kosiński   // Disassembler:
347*a03ca8b9SKrzysztof Kosiński   std::vector<ReferenceGroup> MakeReferenceGroups() const override;
348*a03ca8b9SKrzysztof Kosiński 
349*a03ca8b9SKrzysztof Kosiński   // DisassemblerElfArm:
350*a03ca8b9SKrzysztof Kosiński   std::unique_ptr<typename Traits::Rel32FinderUse> MakeRel32Finder(
351*a03ca8b9SKrzysztof Kosiński       const typename Traits::Elf_Shdr& section) override;
352*a03ca8b9SKrzysztof Kosiński };
353*a03ca8b9SKrzysztof Kosiński 
354*a03ca8b9SKrzysztof Kosiński }  // namespace zucchini
355*a03ca8b9SKrzysztof Kosiński 
356*a03ca8b9SKrzysztof Kosiński #endif  // COMPONENTS_ZUCCHINI_DISASSEMBLER_ELF_H_
357