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