dc44ec5edcf395897a55d0a3abeac01e757abe8c
[platform/framework/web/crosswalk.git] / src / 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 "base/basictypes.h"
9 #include "base/memory/scoped_vector.h"
10 #include "courgette/assembly_program.h"
11 #include "courgette/disassembler.h"
12 #include "courgette/memory_allocator.h"
13 #include "courgette/types_elf.h"
14
15 namespace courgette {
16
17 class AssemblyProgram;
18
19 // A courgette disassembler for 32-bit ELF files.  This class is only a
20 // partial implementation.  Subclasses implement the
21 // architecture-specific parts of processing 32-bit ELF files.  Specifically,
22 // RelToRVA processes entries in ELF relocation table,
23 // ParseRelocationSection verifies the organization of the ELF
24 // relocation table, and ParseRel32RelocsFromSection finds branch
25 // targets by looking for relative jump/call opcodes in the particular
26 // architecture's machine code.
27 class DisassemblerElf32 : public Disassembler {
28  public:
29   // Different instructions encode the target rva differently.  This
30   // class encapsulates this behavior.  public for use in unit tests.
31   class TypedRVA {
32    public:
33     explicit TypedRVA(RVA rva) : rva_(rva), offset_(-1) {
34     }
35
36     virtual ~TypedRVA() { };
37
38     RVA rva() {
39       return rva_;
40     }
41
42     RVA relative_target() {
43       return relative_target_;
44     }
45
46     void set_relative_target(RVA relative_target) {
47       relative_target_ = relative_target;
48     }
49
50     size_t get_offset() {
51       return offset_;
52     }
53
54     void set_offset(size_t offset) {
55       offset_ = offset;
56     }
57
58     // Computes the relative jump's offset from the op in p.
59     virtual CheckBool ComputeRelativeTarget(const uint8* op_pointer) = 0;
60
61     // Emits the courgette instruction corresponding to the RVA type.
62     virtual CheckBool EmitInstruction(AssemblyProgram* program,
63                                       RVA target_rva) = 0;
64
65     virtual uint16 op_size() const = 0;
66
67     static bool IsLessThan(TypedRVA *a, TypedRVA *b) {
68       return a->rva() < b->rva();
69     }
70
71   private:
72     const RVA rva_;
73     RVA relative_target_;
74     size_t offset_;
75   };
76
77  public:
78   explicit DisassemblerElf32(const void* start, size_t length);
79
80   virtual ~DisassemblerElf32() { };
81
82   virtual ExecutableType kind() = 0;
83
84   virtual e_machine_values ElfEM() = 0;
85
86   // Returns 'true' if the buffer appears to point to a valid ELF executable
87   // for 32 bit. If ParseHeader() succeeds, other member
88   // functions may be called.
89   virtual bool ParseHeader();
90
91   virtual bool Disassemble(AssemblyProgram* target);
92
93   // Public for unittests only
94   std::vector<RVA> &Abs32Locations() { return abs32_locations_; }
95   ScopedVector<TypedRVA> &Rel32Locations() { return rel32_locations_; }
96
97  protected:
98
99   uint32 DiscoverLength();
100
101   // Misc Section Helpers
102
103   Elf32_Half SectionHeaderCount() const {
104     return section_header_table_size_;
105   }
106
107   const Elf32_Shdr *SectionHeader(int id) const {
108     assert(id >= 0 && id < SectionHeaderCount());
109     return section_header_table_ + id;
110   }
111
112   const uint8 *SectionBody(int id) const {
113     return OffsetToPointer(SectionHeader(id)->sh_offset);
114   }
115
116   Elf32_Word SectionBodySize(int id) const {
117     return SectionHeader(id)->sh_size;
118   }
119
120   // Misc Segment Helpers
121
122   Elf32_Half ProgramSegmentHeaderCount() const {
123     return program_header_table_size_;
124   }
125
126   const Elf32_Phdr *ProgramSegmentHeader(int id) const {
127     assert(id >= 0 && id < ProgramSegmentHeaderCount());
128     return program_header_table_ + id;
129   }
130
131   // The virtual memory address at which this program segment will be loaded
132   Elf32_Addr ProgramSegmentMemoryBegin(int id) const {
133     return ProgramSegmentHeader(id)->p_vaddr;
134   }
135
136   // The number of virtual memory bytes for this program segment
137   Elf32_Word ProgramSegmentMemorySize(int id) const {
138     return ProgramSegmentHeader(id)->p_memsz;
139   }
140
141   // Pointer into the source file for this program segment
142   Elf32_Addr ProgramSegmentFileOffset(int id) const {
143     return ProgramSegmentHeader(id)->p_offset;
144   }
145
146   // Number of file bytes for this program segment. Is <= ProgramMemorySize.
147   Elf32_Word ProgramSegmentFileSize(int id) const {
148     return ProgramSegmentHeader(id)->p_filesz;
149   }
150
151   // Misc address space helpers
152
153   CheckBool IsValidRVA(RVA rva) const WARN_UNUSED_RESULT;
154
155   // Convert an ELF relocation struction into an RVA
156   virtual CheckBool RelToRVA(Elf32_Rel rel, RVA* result)
157     const WARN_UNUSED_RESULT = 0;
158
159   // Returns kNoOffset if there is no file offset corresponding to 'rva'.
160   CheckBool RVAToFileOffset(RVA rva, size_t* result) const WARN_UNUSED_RESULT;
161
162   RVA FileOffsetToRVA(size_t offset) const WARN_UNUSED_RESULT;
163
164   CheckBool RVAsToOffsets(std::vector<RVA>* rvas /*in*/,
165                           std::vector<size_t>* offsets /*out*/);
166
167   CheckBool RVAsToOffsets(ScopedVector<TypedRVA>* rvas /*in and out*/);
168
169   // Parsing Code used to really implement Disassemble
170
171   CheckBool ParseFile(AssemblyProgram* target) WARN_UNUSED_RESULT;
172   virtual CheckBool ParseRelocationSection(
173       const Elf32_Shdr *section_header,
174         AssemblyProgram* program) WARN_UNUSED_RESULT = 0;
175   CheckBool ParseProgbitsSection(
176       const Elf32_Shdr *section_header,
177       std::vector<size_t>::iterator* current_abs_offset,
178       std::vector<size_t>::iterator end_abs_offset,
179       ScopedVector<TypedRVA>::iterator* current_rel,
180       ScopedVector<TypedRVA>::iterator end_rel,
181       AssemblyProgram* program) WARN_UNUSED_RESULT;
182   CheckBool ParseSimpleRegion(size_t start_file_offset,
183                               size_t end_file_offset,
184                               AssemblyProgram* program) WARN_UNUSED_RESULT;
185
186   CheckBool ParseAbs32Relocs() WARN_UNUSED_RESULT;
187   CheckBool CheckSection(RVA rva) WARN_UNUSED_RESULT;
188   CheckBool ParseRel32RelocsFromSections() WARN_UNUSED_RESULT;
189   virtual CheckBool ParseRel32RelocsFromSection(
190       const Elf32_Shdr* section) WARN_UNUSED_RESULT = 0;
191
192   Elf32_Ehdr *header_;
193   Elf32_Shdr *section_header_table_;
194   Elf32_Half section_header_table_size_;
195
196   Elf32_Phdr *program_header_table_;
197   Elf32_Half program_header_table_size_;
198
199   // Section header for default
200   const char *default_string_section_;
201
202   std::vector<RVA> abs32_locations_;
203   ScopedVector<TypedRVA> rel32_locations_;
204
205   DISALLOW_COPY_AND_ASSIGN(DisassemblerElf32);
206 };
207
208 }  // namespace courgette
209
210 #endif  // COURGETTE_DISASSEMBLER_ELF_32_H_