Enable dev build with the latest repo
[platform/framework/web/chromium-efl.git] / courgette / disassembler_elf_32.h
1 // Copyright 2013 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 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/macros.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     ~Elf32RvaVisitor_Rel32() override { }
89
90     // VectorRvaVisitor<TypedRVA*> interfaces.
91     RVA Get() const override;
92
93    private:
94     DISALLOW_COPY_AND_ASSIGN(Elf32RvaVisitor_Rel32);
95   };
96
97  public:
98   DisassemblerElf32(const uint8_t* start, size_t length);
99
100   ~DisassemblerElf32() override { }
101
102   // Disassembler interfaces.
103   RVA FileOffsetToRVA(FileOffset file_offset) const override;
104   FileOffset RVAToFileOffset(RVA rva) const override;
105   RVA PointerToTargetRVA(const uint8_t* p) const override;
106   ExecutableType kind() const override = 0;
107   uint64_t image_base() const override { return 0; }
108   bool ParseHeader() override;
109
110   virtual e_machine_values ElfEM() const = 0;
111
112   CheckBool IsValidTargetRVA(RVA rva) const WARN_UNUSED_RESULT;
113
114   // Converts an ELF relocation instruction into an RVA.
115   virtual CheckBool RelToRVA(Elf32_Rel rel, RVA* result)
116     const WARN_UNUSED_RESULT = 0;
117
118   // Public for unittests only
119   std::vector<RVA>& Abs32Locations() { return abs32_locations_; }
120   std::vector<std::unique_ptr<TypedRVA>>& Rel32Locations() {
121     return rel32_locations_;
122   }
123
124  protected:
125   // Returns 'true' if an valid executable is detected using only quick checks.
126   // Derived classes should inject |elf_em| corresponding to their architecture,
127   // which will be checked against the detected one.
128   static bool QuickDetect(const uint8_t* start,
129                           size_t length,
130                           e_machine_values elf_em);
131
132   // Returns whether all non-SHT_NOBITS sections lie within image.
133   bool CheckSectionRanges();
134
135   // Returns whether all program segments lie within image.
136   bool CheckProgramSegmentRanges();
137
138   void UpdateLength();
139
140   // Misc Section Helpers
141
142   Elf32_Half SectionHeaderCount() const {
143     return section_header_table_size_;
144   }
145
146   const Elf32_Shdr* SectionHeader(Elf32_Half id) const {
147     assert(id >= 0 && id < SectionHeaderCount());
148     return &section_header_table_[id];
149   }
150
151   const uint8_t* SectionBody(Elf32_Half id) const {
152     const Elf32_Shdr* section_header = SectionHeader(id);
153     DCHECK(section_header->sh_type != SHT_NOBITS);
154     return FileOffsetToPointer(section_header->sh_offset);
155   }
156
157   // Gets the |name| of section |shdr|. Returns true on success.
158   CheckBool SectionName(const Elf32_Shdr& shdr, std::string* name) const;
159
160   // Misc Segment Helpers
161
162   Elf32_Half ProgramSegmentHeaderCount() const {
163     return program_header_table_size_;
164   }
165
166   const Elf32_Phdr* ProgramSegmentHeader(Elf32_Half id) const {
167     assert(id >= 0 && id < ProgramSegmentHeaderCount());
168     return program_header_table_ + id;
169   }
170
171   // Misc address space helpers
172
173   CheckBool RVAsToFileOffsets(const std::vector<RVA>& rvas,
174                               std::vector<FileOffset>* file_offsets) const;
175
176   CheckBool RVAsToFileOffsets(
177       std::vector<std::unique_ptr<TypedRVA>>* typed_rvas) const;
178
179   // Helpers for ParseFile().
180
181   virtual CheckBool ParseRelocationSection(const Elf32_Shdr* section_header,
182                                            InstructionReceptor* receptor) const
183       WARN_UNUSED_RESULT = 0;
184
185   virtual CheckBool ParseRel32RelocsFromSection(const Elf32_Shdr* section)
186       WARN_UNUSED_RESULT = 0;
187
188   CheckBool ParseAbs32Relocs() WARN_UNUSED_RESULT;
189
190   // Extracts all rel32 TypedRVAs. Does not sort the result.
191   CheckBool ParseRel32RelocsFromSections() WARN_UNUSED_RESULT;
192
193   // Disassembler interfaces.
194   bool ExtractAbs32Locations() override;
195   bool ExtractRel32Locations() override;
196   RvaVisitor* CreateAbs32TargetRvaVisitor() override;
197   RvaVisitor* CreateRel32TargetRvaVisitor() override;
198   void RemoveUnusedRel32Locations(AssemblyProgram* program) override;
199   InstructionGenerator GetInstructionGenerator(
200       AssemblyProgram* program) override;
201
202   CheckBool ParseFile(AssemblyProgram* target,
203                       InstructionReceptor* receptor) const WARN_UNUSED_RESULT;
204
205   CheckBool ParseProgbitsSection(
206       const Elf32_Shdr* section_header,
207       std::vector<FileOffset>::iterator* current_abs_offset,
208       std::vector<FileOffset>::iterator end_abs_offset,
209       std::vector<std::unique_ptr<TypedRVA>>::iterator* current_rel,
210       std::vector<std::unique_ptr<TypedRVA>>::iterator end_rel,
211       AssemblyProgram* program,
212       InstructionReceptor* receptor) const WARN_UNUSED_RESULT;
213
214   CheckBool ParseSimpleRegion(FileOffset start_file_offset,
215                               FileOffset end_file_offset,
216                               InstructionReceptor* receptor) const
217       WARN_UNUSED_RESULT;
218
219   CheckBool CheckSection(RVA rva) WARN_UNUSED_RESULT;
220
221   const Elf32_Ehdr* header_;
222
223   Elf32_Half section_header_table_size_;
224
225   // Section header table, ordered by section id.
226   std::vector<Elf32_Shdr> section_header_table_;
227
228   // An ordering of |section_header_table_|, sorted by file offset.
229   std::vector<Elf32_Half> section_header_file_offset_order_;
230
231   const Elf32_Phdr* program_header_table_;
232   Elf32_Half program_header_table_size_;
233
234   // Pointer to string table containing section names.
235   const char* default_string_section_;
236   size_t default_string_section_size_;
237
238   // Sorted abs32 RVAs.
239   std::vector<RVA> abs32_locations_;
240   // Sorted rel32 RVAs. This is mutable because ParseFile() temporarily sorts
241   // these by file offsets.
242   mutable std::vector<std::unique_ptr<TypedRVA>> rel32_locations_;
243
244  private:
245   DISALLOW_COPY_AND_ASSIGN(DisassemblerElf32);
246 };
247
248 }  // namespace courgette
249
250 #endif  // COURGETTE_DISASSEMBLER_ELF_32_H_