[M108 Migration][HBBTV] Implement ewk_context_register_jsplugin_mime_types API
[platform/framework/web/chromium-efl.git] / courgette / disassembler_elf_32.h
1 // Copyright 2013 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.
4
5 #ifndef COURGETTE_DISASSEMBLER_ELF_32_H_
6 #define COURGETTE_DISASSEMBLER_ELF_32_H_
7
8 #include <stddef.h>
9 #include <stdint.h>
10
11 #include <memory>
12 #include <string>
13 #include <vector>
14
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_elf.h"
21
22 namespace courgette {
23
24 class AssemblyProgram;
25
26 // A Courgette disassembler for 32-bit ELF files. This is only a partial
27 // implementation that admits subclasses for the architecture-specific parts of
28 // 32-bit ELF file processing. Specifically:
29 // - RelToRVA() processes entries in ELF relocation table.
30 // - ParseRelocationSection() verifies the organization of the ELF relocation
31 //   table.
32 // - ParseRel32RelocsFromSection() finds branch targets by looking for relative
33 //   branch/call opcodes in the particular architecture's machine code.
34 class DisassemblerElf32 : public Disassembler {
35  public:
36   // Different instructions encode the target rva differently.  This
37   // class encapsulates this behavior.  public for use in unit tests.
38   class TypedRVA {
39    public:
40     explicit TypedRVA(RVA rva) : rva_(rva) { }
41
42     virtual ~TypedRVA() { }
43
44     RVA rva() const { return rva_; }
45     RVA relative_target() const { return relative_target_; }
46     FileOffset file_offset() const { return file_offset_; }
47
48     void set_relative_target(RVA relative_target) {
49       relative_target_ = relative_target;
50     }
51     void set_file_offset(FileOffset file_offset) { file_offset_ = file_offset; }
52
53     // Computes the relative jump's offset from the op in p.
54     virtual CheckBool ComputeRelativeTarget(const uint8_t* op_pointer) = 0;
55
56     // Emits the assembly instruction corresponding to |label|.
57     virtual CheckBool EmitInstruction(Label* label,
58                                       InstructionReceptor* receptor) = 0;
59
60     // Returns the size of the instruction containing the RVA.
61     virtual uint16_t op_size() const = 0;
62
63     // Comparator for sorting, which assumes uniqueness of RVAs.
64     static bool IsLessThanByRVA(const std::unique_ptr<TypedRVA>& a,
65                                 const std::unique_ptr<TypedRVA>& b) {
66       return a->rva() < b->rva();
67     }
68
69     // Comparator for sorting, which assumes uniqueness of file offsets.
70     static bool IsLessThanByFileOffset(const std::unique_ptr<TypedRVA>& a,
71                                        const std::unique_ptr<TypedRVA>& b) {
72       return a->file_offset() < b->file_offset();
73     }
74
75    private:
76     const RVA rva_;
77     RVA relative_target_ = kNoRVA;
78     FileOffset file_offset_ = kNoFileOffset;
79   };
80
81   // Visitor/adaptor to translate RVA to target RVA. This is the ELF
82   // counterpart to RvaVisitor_Rel32 that uses TypedRVA.
83   class Elf32RvaVisitor_Rel32 :
84   public VectorRvaVisitor<std::unique_ptr<TypedRVA>> {
85    public:
86     Elf32RvaVisitor_Rel32(
87         const std::vector<std::unique_ptr<TypedRVA>>& rva_locations);
88
89     Elf32RvaVisitor_Rel32(const Elf32RvaVisitor_Rel32&) = delete;
90     Elf32RvaVisitor_Rel32& operator=(const Elf32RvaVisitor_Rel32&) = delete;
91
92     ~Elf32RvaVisitor_Rel32() override { }
93
94     // VectorRvaVisitor<TypedRVA*> interfaces.
95     RVA Get() const override;
96   };
97
98  public:
99   DisassemblerElf32(const uint8_t* start, size_t length);
100
101   DisassemblerElf32(const DisassemblerElf32&) = delete;
102   DisassemblerElf32& operator=(const DisassemblerElf32&) = delete;
103
104   ~DisassemblerElf32() override { }
105
106   // Disassembler interfaces.
107   RVA FileOffsetToRVA(FileOffset file_offset) const override;
108   FileOffset RVAToFileOffset(RVA rva) const override;
109   RVA PointerToTargetRVA(const uint8_t* p) const override;
110   ExecutableType kind() const override = 0;
111   uint64_t image_base() const override { return 0; }
112   bool ParseHeader() override;
113
114   virtual e_machine_values ElfEM() const = 0;
115
116   [[nodiscard]] CheckBool IsValidTargetRVA(RVA rva) const;
117
118   // Converts an ELF relocation instruction into an RVA.
119   [[nodiscard]] virtual CheckBool RelToRVA(Elf32_Rel rel,
120                                            RVA* result) const = 0;
121
122   // Public for unittests only
123   std::vector<RVA>& Abs32Locations() { return abs32_locations_; }
124   std::vector<std::unique_ptr<TypedRVA>>& Rel32Locations() {
125     return rel32_locations_;
126   }
127
128  protected:
129   // Returns 'true' if an valid executable is detected using only quick checks.
130   // Derived classes should inject |elf_em| corresponding to their architecture,
131   // which will be checked against the detected one.
132   static bool QuickDetect(const uint8_t* start,
133                           size_t length,
134                           e_machine_values elf_em);
135
136   // Returns whether all non-SHT_NOBITS sections lie within image.
137   bool CheckSectionRanges();
138
139   // Returns whether all program segments lie within image.
140   bool CheckProgramSegmentRanges();
141
142   void UpdateLength();
143
144   // Misc Section Helpers
145
146   Elf32_Half SectionHeaderCount() const {
147     return section_header_table_size_;
148   }
149
150   const Elf32_Shdr* SectionHeader(Elf32_Half id) const {
151     assert(id >= 0 && id < SectionHeaderCount());
152     return &section_header_table_[id];
153   }
154
155   const uint8_t* SectionBody(Elf32_Half id) const {
156     const Elf32_Shdr* section_header = SectionHeader(id);
157     DCHECK(section_header->sh_type != SHT_NOBITS);
158     return FileOffsetToPointer(section_header->sh_offset);
159   }
160
161   // Gets the |name| of section |shdr|. Returns true on success.
162   CheckBool SectionName(const Elf32_Shdr& shdr, std::string* name) const;
163
164   // Misc Segment Helpers
165
166   Elf32_Half ProgramSegmentHeaderCount() const {
167     return program_header_table_size_;
168   }
169
170   const Elf32_Phdr* ProgramSegmentHeader(Elf32_Half id) const {
171     assert(id >= 0 && id < ProgramSegmentHeaderCount());
172     return program_header_table_ + id;
173   }
174
175   // Misc address space helpers
176
177   CheckBool RVAsToFileOffsets(const std::vector<RVA>& rvas,
178                               std::vector<FileOffset>* file_offsets) const;
179
180   CheckBool RVAsToFileOffsets(
181       std::vector<std::unique_ptr<TypedRVA>>* typed_rvas) const;
182
183   // Helpers for ParseFile().
184
185   [[nodiscard]] virtual CheckBool ParseRelocationSection(
186       const Elf32_Shdr* section_header,
187       InstructionReceptor* receptor) const = 0;
188
189   [[nodiscard]] virtual CheckBool ParseRel32RelocsFromSection(
190       const Elf32_Shdr* section) = 0;
191
192   [[nodiscard]] CheckBool ParseAbs32Relocs();
193
194   // Extracts all rel32 TypedRVAs. Does not sort the result.
195   [[nodiscard]] CheckBool ParseRel32RelocsFromSections();
196
197   // Disassembler interfaces.
198   bool ExtractAbs32Locations() override;
199   bool ExtractRel32Locations() override;
200   RvaVisitor* CreateAbs32TargetRvaVisitor() override;
201   RvaVisitor* CreateRel32TargetRvaVisitor() override;
202   void RemoveUnusedRel32Locations(AssemblyProgram* program) override;
203   InstructionGenerator GetInstructionGenerator(
204       AssemblyProgram* program) override;
205
206   [[nodiscard]] CheckBool ParseFile(AssemblyProgram* target,
207                                     InstructionReceptor* receptor) const;
208
209   [[nodiscard]] CheckBool ParseProgbitsSection(
210       const Elf32_Shdr* section_header,
211       std::vector<FileOffset>::iterator* current_abs_offset,
212       std::vector<FileOffset>::iterator end_abs_offset,
213       std::vector<std::unique_ptr<TypedRVA>>::iterator* current_rel,
214       std::vector<std::unique_ptr<TypedRVA>>::iterator end_rel,
215       AssemblyProgram* program,
216       InstructionReceptor* receptor) const;
217
218   [[nodiscard]] CheckBool ParseSimpleRegion(
219       FileOffset start_file_offset,
220       FileOffset end_file_offset,
221       InstructionReceptor* receptor) const;
222
223   [[nodiscard]] CheckBool CheckSection(RVA rva);
224
225   raw_ptr<const Elf32_Ehdr> header_;
226
227   Elf32_Half section_header_table_size_;
228
229   // Section header table, ordered by section id.
230   std::vector<Elf32_Shdr> section_header_table_;
231
232   // An ordering of |section_header_table_|, sorted by file offset.
233   std::vector<Elf32_Half> section_header_file_offset_order_;
234
235   raw_ptr<const Elf32_Phdr> program_header_table_;
236   Elf32_Half program_header_table_size_;
237
238   // Pointer to string table containing section names.
239   const char* default_string_section_;
240   size_t default_string_section_size_;
241
242   // Sorted abs32 RVAs.
243   std::vector<RVA> abs32_locations_;
244   // Sorted rel32 RVAs. This is mutable because ParseFile() temporarily sorts
245   // these by file offsets.
246   mutable std::vector<std::unique_ptr<TypedRVA>> rel32_locations_;
247 };
248
249 }  // namespace courgette
250
251 #endif  // COURGETTE_DISASSEMBLER_ELF_32_H_