blob: 6bcf1b888b80cd80f3529a3f3900d3f405bee630 [file] [log] [blame]
[email protected]39ed9732013-06-20 10:17:531// 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
aviab98dcc92015-12-21 19:35:338#include <stddef.h>
9#include <stdint.h>
10
etiennep7d4e8ee2016-05-11 20:13:3611#include <memory>
huangsc8037632016-05-19 18:16:4012#include <string>
huangsdda11d062016-03-14 16:35:3913#include <vector>
14
aviab98dcc92015-12-21 19:35:3315#include "base/macros.h"
[email protected]39ed9732013-06-20 10:17:5316#include "courgette/disassembler.h"
huangsdda11d062016-03-14 16:35:3917#include "courgette/image_utils.h"
[email protected]39ed9732013-06-20 10:17:5318#include "courgette/memory_allocator.h"
19#include "courgette/types_elf.h"
20
21namespace courgette {
22
23class AssemblyProgram;
24
huangsdda11d062016-03-14 16:35:3925// A Courgette disassembler for 32-bit ELF files. This is only a partial
26// implementation that admits subclasses for the architecture-specific parts of
27// 32-bit ELF file processing. Specifically:
28// - RelToRVA() processes entries in ELF relocation table.
29// - ParseRelocationSection() verifies the organization of the ELF relocation
30// table.
31// - ParseRel32RelocsFromSection() finds branch targets by looking for relative
32// branch/call opcodes in the particular architecture's machine code.
[email protected]39ed9732013-06-20 10:17:5333class DisassemblerElf32 : public Disassembler {
34 public:
[email protected]144c8e92013-07-23 21:18:1935 // Different instructions encode the target rva differently. This
36 // class encapsulates this behavior. public for use in unit tests.
37 class TypedRVA {
38 public:
huangsdda11d062016-03-14 16:35:3939 explicit TypedRVA(RVA rva) : rva_(rva) { }
[email protected]144c8e92013-07-23 21:18:1940
huangsdda11d062016-03-14 16:35:3941 virtual ~TypedRVA() { }
[email protected]144c8e92013-07-23 21:18:1942
huangsdda11d062016-03-14 16:35:3943 RVA rva() const { return rva_; }
44 RVA relative_target() const { return relative_target_; }
45 FileOffset file_offset() const { return file_offset_; }
[email protected]144c8e92013-07-23 21:18:1946
47 void set_relative_target(RVA relative_target) {
48 relative_target_ = relative_target;
49 }
etiennep7d4e8ee2016-05-11 20:13:3650 void set_file_offset(FileOffset file_offset) { file_offset_ = file_offset; }
[email protected]144c8e92013-07-23 21:18:1951
[email protected]2b637b62013-08-01 00:11:2452 // Computes the relative jump's offset from the op in p.
aviab98dcc92015-12-21 19:35:3353 virtual CheckBool ComputeRelativeTarget(const uint8_t* op_pointer) = 0;
[email protected]144c8e92013-07-23 21:18:1954
huangsc8037632016-05-19 18:16:4055 // Emits the assembly instruction corresponding to |label|.
[email protected]2b637b62013-08-01 00:11:2456 virtual CheckBool EmitInstruction(AssemblyProgram* program,
huangsc8037632016-05-19 18:16:4057 Label* label) = 0;
[email protected]2b637b62013-08-01 00:11:2458
huangsdda11d062016-03-14 16:35:3959 // Returns the size of the instruction containing the RVA.
aviab98dcc92015-12-21 19:35:3360 virtual uint16_t op_size() const = 0;
[email protected]2b637b62013-08-01 00:11:2461
huangsdda11d062016-03-14 16:35:3962 // Comparator for sorting, which assumes uniqueness of RVAs.
etiennep7d4e8ee2016-05-11 20:13:3663 static bool IsLessThanByRVA(const std::unique_ptr<TypedRVA>& a,
64 const std::unique_ptr<TypedRVA>& b) {
[email protected]144c8e92013-07-23 21:18:1965 return a->rva() < b->rva();
66 }
67
huangs3da0dd932016-04-28 22:14:4568 // Comparator for sorting, which assumes uniqueness of file offsets.
etiennep7d4e8ee2016-05-11 20:13:3669 static bool IsLessThanByFileOffset(const std::unique_ptr<TypedRVA>& a,
70 const std::unique_ptr<TypedRVA>& b) {
huangs3da0dd932016-04-28 22:14:4571 return a->file_offset() < b->file_offset();
72 }
73
[email protected]144c8e92013-07-23 21:18:1974 private:
75 const RVA rva_;
huangsdda11d062016-03-14 16:35:3976 RVA relative_target_ = kNoRVA;
77 FileOffset file_offset_ = kNoFileOffset;
[email protected]144c8e92013-07-23 21:18:1978 };
79
huangsc8037632016-05-19 18:16:4080 // Visitor/adaptor to translate RVA to target RVA. This is the ELF
81 // counterpart to RvaVisitor_Rel32 that uses TypedRVA.
82 class Elf32RvaVisitor_Rel32 :
83 public VectorRvaVisitor<std::unique_ptr<TypedRVA>> {
84 public:
85 Elf32RvaVisitor_Rel32(
86 const std::vector<std::unique_ptr<TypedRVA>>& rva_locations);
87 ~Elf32RvaVisitor_Rel32() override { }
88
89 // VectorRvaVisitor<TypedRVA*> interfaces.
90 RVA Get() const override;
91
92 private:
93 DISALLOW_COPY_AND_ASSIGN(Elf32RvaVisitor_Rel32);
94 };
95
[email protected]144c8e92013-07-23 21:18:1996 public:
huangsdda11d062016-03-14 16:35:3997 DisassemblerElf32(const void* start, size_t length);
[email protected]39ed9732013-06-20 10:17:5398
huangsdda11d062016-03-14 16:35:3999 ~DisassemblerElf32() override { }
[email protected]144c8e92013-07-23 21:18:19100
huangsdda11d062016-03-14 16:35:39101 // Disassembler interfaces.
102 RVA FileOffsetToRVA(FileOffset file_offset) const override;
103 FileOffset RVAToFileOffset(RVA rva) const override;
huangsf940a8c92016-03-23 20:40:35104 RVA PointerToTargetRVA(const uint8_t* p) const override;
huangsdda11d062016-03-14 16:35:39105 virtual ExecutableType kind() const override = 0;
106 bool ParseHeader() override;
107 bool Disassemble(AssemblyProgram* target) override;
[email protected]39ed9732013-06-20 10:17:53108
huangsdda11d062016-03-14 16:35:39109 virtual e_machine_values ElfEM() const = 0;
[email protected]39ed9732013-06-20 10:17:53110
huangsc8037632016-05-19 18:16:40111 CheckBool IsValidTargetRVA(RVA rva) const WARN_UNUSED_RESULT;
112
113 // Converts an ELF relocation instruction into an RVA.
114 virtual CheckBool RelToRVA(Elf32_Rel rel, RVA* result)
115 const WARN_UNUSED_RESULT = 0;
116
[email protected]39ed9732013-06-20 10:17:53117 // Public for unittests only
etiennep7d4e8ee2016-05-11 20:13:36118 std::vector<RVA>& Abs32Locations() { return abs32_locations_; }
119 std::vector<std::unique_ptr<TypedRVA>>& Rel32Locations() {
120 return rel32_locations_;
121 }
[email protected]39ed9732013-06-20 10:17:53122
123 protected:
halyavinc9de6f72015-03-24 15:40:12124 bool UpdateLength();
[email protected]39ed9732013-06-20 10:17:53125
126 // Misc Section Helpers
127
[email protected]e3e696d32013-06-21 20:41:36128 Elf32_Half SectionHeaderCount() const {
[email protected]39ed9732013-06-20 10:17:53129 return section_header_table_size_;
130 }
131
huangsdda11d062016-03-14 16:35:39132 const Elf32_Shdr* SectionHeader(Elf32_Half id) const {
[email protected]39ed9732013-06-20 10:17:53133 assert(id >= 0 && id < SectionHeaderCount());
huangs8cffb282016-04-09 19:43:50134 return &section_header_table_[id];
[email protected]39ed9732013-06-20 10:17:53135 }
136
huangsdda11d062016-03-14 16:35:39137 const uint8_t* SectionBody(Elf32_Half id) const {
huangs16f01e02016-04-21 19:38:38138 // TODO(huangs): Assert that section does not have SHT_NOBITS.
huangsdda11d062016-03-14 16:35:39139 return FileOffsetToPointer(SectionHeader(id)->sh_offset);
[email protected]39ed9732013-06-20 10:17:53140 }
141
huangs16f01e02016-04-21 19:38:38142 // Gets the |name| of section |shdr|. Returns true on success.
143 CheckBool SectionName(const Elf32_Shdr& shdr, std::string* name) const;
144
[email protected]39ed9732013-06-20 10:17:53145 // Misc Segment Helpers
146
[email protected]e3e696d32013-06-21 20:41:36147 Elf32_Half ProgramSegmentHeaderCount() const {
[email protected]39ed9732013-06-20 10:17:53148 return program_header_table_size_;
149 }
150
huangsdda11d062016-03-14 16:35:39151 const Elf32_Phdr* ProgramSegmentHeader(Elf32_Half id) const {
[email protected]39ed9732013-06-20 10:17:53152 assert(id >= 0 && id < ProgramSegmentHeaderCount());
153 return program_header_table_ + id;
154 }
155
[email protected]39ed9732013-06-20 10:17:53156 // Misc address space helpers
157
huangsdda11d062016-03-14 16:35:39158 CheckBool RVAsToFileOffsets(const std::vector<RVA>& rvas,
159 std::vector<FileOffset>* file_offsets);
[email protected]39ed9732013-06-20 10:17:53160
etiennep7d4e8ee2016-05-11 20:13:36161 CheckBool RVAsToFileOffsets(
162 std::vector<std::unique_ptr<TypedRVA>>* typed_rvas);
[email protected]39ed9732013-06-20 10:17:53163
huangsdda11d062016-03-14 16:35:39164 // Parsing code for Disassemble().
[email protected]39ed9732013-06-20 10:17:53165
huangsdda11d062016-03-14 16:35:39166 virtual CheckBool ParseRelocationSection(const Elf32_Shdr* section_header,
167 AssemblyProgram* program)
168 WARN_UNUSED_RESULT = 0;
[email protected]144c8e92013-07-23 21:18:19169
huangsdda11d062016-03-14 16:35:39170 virtual CheckBool ParseRel32RelocsFromSection(const Elf32_Shdr* section)
171 WARN_UNUSED_RESULT = 0;
[email protected]39ed9732013-06-20 10:17:53172
huangsc8037632016-05-19 18:16:40173 // Disassembler interfaces.
174 RvaVisitor* CreateAbs32TargetRvaVisitor() override;
175 RvaVisitor* CreateRel32TargetRvaVisitor() override;
176 void RemoveUnusedRel32Locations(AssemblyProgram* program) override;
177
[email protected]39ed9732013-06-20 10:17:53178 CheckBool ParseFile(AssemblyProgram* target) WARN_UNUSED_RESULT;
huangsdda11d062016-03-14 16:35:39179
[email protected]39ed9732013-06-20 10:17:53180 CheckBool ParseProgbitsSection(
huangsdda11d062016-03-14 16:35:39181 const Elf32_Shdr* section_header,
182 std::vector<FileOffset>::iterator* current_abs_offset,
183 std::vector<FileOffset>::iterator end_abs_offset,
etiennep7d4e8ee2016-05-11 20:13:36184 std::vector<std::unique_ptr<TypedRVA>>::iterator* current_rel,
185 std::vector<std::unique_ptr<TypedRVA>>::iterator end_rel,
[email protected]39ed9732013-06-20 10:17:53186 AssemblyProgram* program) WARN_UNUSED_RESULT;
huangsdda11d062016-03-14 16:35:39187
188 CheckBool ParseSimpleRegion(FileOffset start_file_offset,
189 FileOffset end_file_offset,
[email protected]39ed9732013-06-20 10:17:53190 AssemblyProgram* program) WARN_UNUSED_RESULT;
191
192 CheckBool ParseAbs32Relocs() WARN_UNUSED_RESULT;
huangs58b822d42016-03-12 20:56:11193
huangsdda11d062016-03-14 16:35:39194 CheckBool CheckSection(RVA rva) WARN_UNUSED_RESULT;
195
huangs3da0dd932016-04-28 22:14:45196 // Extracts all rel32 TypedRVAs. Does not sort the result.
huangsdda11d062016-03-14 16:35:39197 CheckBool ParseRel32RelocsFromSections() WARN_UNUSED_RESULT;
198
199 const Elf32_Ehdr* header_;
huangs691893002016-04-19 20:04:33200
[email protected]39ed9732013-06-20 10:17:53201 Elf32_Half section_header_table_size_;
202
huangs691893002016-04-19 20:04:33203 // Section header table, ordered by section id.
204 std::vector<Elf32_Shdr> section_header_table_;
205
206 // An ordering of |section_header_table_|, sorted by file offset.
207 std::vector<Elf32_Half> section_header_file_offset_order_;
208
huangsdda11d062016-03-14 16:35:39209 const Elf32_Phdr* program_header_table_;
[email protected]39ed9732013-06-20 10:17:53210 Elf32_Half program_header_table_size_;
211
huangs16f01e02016-04-21 19:38:38212 // Pointer to string table containing section names.
huangsdda11d062016-03-14 16:35:39213 const char* default_string_section_;
huangs16f01e02016-04-21 19:38:38214 size_t default_string_section_size_;
[email protected]39ed9732013-06-20 10:17:53215
216 std::vector<RVA> abs32_locations_;
etiennep7d4e8ee2016-05-11 20:13:36217 std::vector<std::unique_ptr<TypedRVA>> rel32_locations_;
[email protected]39ed9732013-06-20 10:17:53218
219 DISALLOW_COPY_AND_ASSIGN(DisassemblerElf32);
220};
221
222} // namespace courgette
223
224#endif // COURGETTE_DISASSEMBLER_ELF_32_H_