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