• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
TypedRVA(RVA rva)33     explicit TypedRVA(RVA rva) : rva_(rva), offset_(static_cast<size_t>(-1)) {
34     }
35 
~TypedRVA()36     virtual ~TypedRVA() { };
37 
rva()38     RVA rva() {
39       return rva_;
40     }
41 
relative_target()42     RVA relative_target() {
43       return relative_target_;
44     }
45 
set_relative_target(RVA relative_target)46     void set_relative_target(RVA relative_target) {
47       relative_target_ = relative_target;
48     }
49 
get_offset()50     size_t get_offset() {
51       return offset_;
52     }
53 
set_offset(size_t offset)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 
IsLessThan(TypedRVA * a,TypedRVA * b)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 
~DisassemblerElf32()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
Abs32Locations()94   std::vector<RVA> &Abs32Locations() { return abs32_locations_; }
Rel32Locations()95   ScopedVector<TypedRVA> &Rel32Locations() { return rel32_locations_; }
96 
97  protected:
98 
99   uint32 DiscoverLength();
100 
101   // Misc Section Helpers
102 
SectionHeaderCount()103   Elf32_Half SectionHeaderCount() const {
104     return section_header_table_size_;
105   }
106 
SectionHeader(int id)107   const Elf32_Shdr *SectionHeader(int id) const {
108     assert(id >= 0 && id < SectionHeaderCount());
109     return section_header_table_ + id;
110   }
111 
SectionBody(int id)112   const uint8 *SectionBody(int id) const {
113     return OffsetToPointer(SectionHeader(id)->sh_offset);
114   }
115 
SectionBodySize(int id)116   Elf32_Word SectionBodySize(int id) const {
117     return SectionHeader(id)->sh_size;
118   }
119 
120   // Misc Segment Helpers
121 
ProgramSegmentHeaderCount()122   Elf32_Half ProgramSegmentHeaderCount() const {
123     return program_header_table_size_;
124   }
125 
ProgramSegmentHeader(int id)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
ProgramSegmentMemoryBegin(int id)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
ProgramSegmentMemorySize(int id)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
ProgramSegmentFileOffset(int id)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.
ProgramSegmentFileSize(int id)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_
211