[go: nahoru, domu]

blob: a75773d78b0579f7dc64b58f1ed05c34fab17126 [file] [log] [blame]
paulgazz@chromium.org39ed9732013-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"
paulgazz@chromium.org39ed9732013-06-20 10:17:5316#include "courgette/disassembler.h"
huangsdda11d062016-03-14 16:35:3917#include "courgette/image_utils.h"
huangs257f9fb2017-03-23 23:17:5018#include "courgette/instruction_utils.h"
paulgazz@chromium.org39ed9732013-06-20 10:17:5319#include "courgette/memory_allocator.h"
20#include "courgette/types_elf.h"
21
22namespace courgette {
23
24class AssemblyProgram;
25
huangsdda11d062016-03-14 16:35:3926// A Courgette disassembler for 32-bit ELF files. This is only a partial
27// implementation that admits subclasses for the architecture-specific parts of
28// 32-bit ELF file processing. Specifically:
29// - RelToRVA() processes entries in ELF relocation table.
30// - ParseRelocationSection() verifies the organization of the ELF relocation
31// table.
32// - ParseRel32RelocsFromSection() finds branch targets by looking for relative
33// branch/call opcodes in the particular architecture's machine code.
paulgazz@chromium.org39ed9732013-06-20 10:17:5334class DisassemblerElf32 : public Disassembler {
35 public:
paulgazz@chromium.org144c8e92013-07-23 21:18:1936 // Different instructions encode the target rva differently. This
37 // class encapsulates this behavior. public for use in unit tests.
38 class TypedRVA {
39 public:
huangsdda11d062016-03-14 16:35:3940 explicit TypedRVA(RVA rva) : rva_(rva) { }
paulgazz@chromium.org144c8e92013-07-23 21:18:1941
huangsdda11d062016-03-14 16:35:3942 virtual ~TypedRVA() { }
paulgazz@chromium.org144c8e92013-07-23 21:18:1943
huangsdda11d062016-03-14 16:35:3944 RVA rva() const { return rva_; }
45 RVA relative_target() const { return relative_target_; }
46 FileOffset file_offset() const { return file_offset_; }
paulgazz@chromium.org144c8e92013-07-23 21:18:1947
48 void set_relative_target(RVA relative_target) {
49 relative_target_ = relative_target;
50 }
etiennep7d4e8ee2016-05-11 20:13:3651 void set_file_offset(FileOffset file_offset) { file_offset_ = file_offset; }
paulgazz@chromium.org144c8e92013-07-23 21:18:1952
paulgazz@chromium.org2b637b62013-08-01 00:11:2453 // Computes the relative jump's offset from the op in p.
aviab98dcc92015-12-21 19:35:3354 virtual CheckBool ComputeRelativeTarget(const uint8_t* op_pointer) = 0;
paulgazz@chromium.org144c8e92013-07-23 21:18:1955
huangsc8037632016-05-19 18:16:4056 // Emits the assembly instruction corresponding to |label|.
huangs7b221a52016-11-09 22:28:2357 virtual CheckBool EmitInstruction(Label* label,
58 InstructionReceptor* receptor) = 0;
paulgazz@chromium.org2b637b62013-08-01 00:11:2459
huangsdda11d062016-03-14 16:35:3960 // Returns the size of the instruction containing the RVA.
aviab98dcc92015-12-21 19:35:3361 virtual uint16_t op_size() const = 0;
paulgazz@chromium.org2b637b62013-08-01 00:11:2462
huangsdda11d062016-03-14 16:35:3963 // Comparator for sorting, which assumes uniqueness of RVAs.
etiennep7d4e8ee2016-05-11 20:13:3664 static bool IsLessThanByRVA(const std::unique_ptr<TypedRVA>& a,
65 const std::unique_ptr<TypedRVA>& b) {
paulgazz@chromium.org144c8e92013-07-23 21:18:1966 return a->rva() < b->rva();
huangs3da0dd932016-04-28 22:14:4567 }
68
69 // Comparator for sorting, which assumes uniqueness of file offsets.
etiennep7d4e8ee2016-05-11 20:13:3670 static bool IsLessThanByFileOffset(const std::unique_ptr<TypedRVA>& a,
71 const std::unique_ptr<TypedRVA>& b) {
huangs3da0dd932016-04-28 22:14:4572 return a->file_offset() < b->file_offset();
paulgazz@chromium.org144c8e92013-07-23 21:18:1973 }
74
huangs7b221a52016-11-09 22:28:2375 private:
paulgazz@chromium.org144c8e92013-07-23 21:18:1976 const RVA rva_;
huangsdda11d062016-03-14 16:35:3977 RVA relative_target_ = kNoRVA;
78 FileOffset file_offset_ = kNoFileOffset;
paulgazz@chromium.org144c8e92013-07-23 21:18:1979 };
80
huangsc8037632016-05-19 18:16:4081 // Visitor/adaptor to translate RVA to target RVA. This is the ELF
82 // counterpart to RvaVisitor_Rel32 that uses TypedRVA.
83 class Elf32RvaVisitor_Rel32 :
84 public VectorRvaVisitor<std::unique_ptr<TypedRVA>> {
85 public:
86 Elf32RvaVisitor_Rel32(
87 const std::vector<std::unique_ptr<TypedRVA>>& rva_locations);
88 ~Elf32RvaVisitor_Rel32() override { }
89
90 // VectorRvaVisitor<TypedRVA*> interfaces.
91 RVA Get() const override;
92
93 private:
94 DISALLOW_COPY_AND_ASSIGN(Elf32RvaVisitor_Rel32);
95 };
96
paulgazz@chromium.org144c8e92013-07-23 21:18:1997 public:
etiennep5059bca2016-07-08 17:55:2098 DisassemblerElf32(const uint8_t* start, size_t length);
paulgazz@chromium.org144c8e92013-07-23 21:18:1999
huangsdda11d062016-03-14 16:35:39100 ~DisassemblerElf32() override { }
paulgazz@chromium.org39ed9732013-06-20 10:17:53101
huangsdda11d062016-03-14 16:35:39102 // Disassembler interfaces.
103 RVA FileOffsetToRVA(FileOffset file_offset) const override;
104 FileOffset RVAToFileOffset(RVA rva) const override;
huangsf940a8c92016-03-23 20:40:35105 RVA PointerToTargetRVA(const uint8_t* p) const override;
huangs7b221a52016-11-09 22:28:23106 ExecutableType kind() const override = 0;
huangs85636222017-01-13 18:09:13107 uint64_t image_base() const override { return 0; }
huangsdda11d062016-03-14 16:35:39108 bool ParseHeader() override;
paulgazz@chromium.org39ed9732013-06-20 10:17:53109
huangsdda11d062016-03-14 16:35:39110 virtual e_machine_values ElfEM() const = 0;
huangsc8037632016-05-19 18:16:40111
112 CheckBool IsValidTargetRVA(RVA rva) const WARN_UNUSED_RESULT;
113
114 // Converts an ELF relocation instruction into an RVA.
115 virtual CheckBool RelToRVA(Elf32_Rel rel, RVA* result)
116 const WARN_UNUSED_RESULT = 0;
paulgazz@chromium.org39ed9732013-06-20 10:17:53117
118 // Public for unittests only
etiennep7d4e8ee2016-05-11 20:13:36119 std::vector<RVA>& Abs32Locations() { return abs32_locations_; }
120 std::vector<std::unique_ptr<TypedRVA>>& Rel32Locations() {
121 return rel32_locations_;
122 }
paulgazz@chromium.org39ed9732013-06-20 10:17:53123
124 protected:
etiennep5059bca2016-07-08 17:55:20125 // Returns 'true' if an valid executable is detected using only quick checks.
126 // Derived classes should inject |elf_em| corresponding to their architecture,
127 // which will be checked against the detected one.
128 static bool QuickDetect(const uint8_t* start,
129 size_t length,
130 e_machine_values elf_em);
131
halyavinc9de6f72015-03-24 15:40:12132 bool UpdateLength();
paulgazz@chromium.org39ed9732013-06-20 10:17:53133
134 // Misc Section Helpers
135
sorin@chromium.orge3e696d32013-06-21 20:41:36136 Elf32_Half SectionHeaderCount() const {
paulgazz@chromium.org39ed9732013-06-20 10:17:53137 return section_header_table_size_;
138 }
139
huangsdda11d062016-03-14 16:35:39140 const Elf32_Shdr* SectionHeader(Elf32_Half id) const {
paulgazz@chromium.org39ed9732013-06-20 10:17:53141 assert(id >= 0 && id < SectionHeaderCount());
huangs8cffb282016-04-09 19:43:50142 return &section_header_table_[id];
paulgazz@chromium.org39ed9732013-06-20 10:17:53143 }
144
huangsdda11d062016-03-14 16:35:39145 const uint8_t* SectionBody(Elf32_Half id) const {
huangs16f01e02016-04-21 19:38:38146 // TODO(huangs): Assert that section does not have SHT_NOBITS.
huangsdda11d062016-03-14 16:35:39147 return FileOffsetToPointer(SectionHeader(id)->sh_offset);
paulgazz@chromium.org39ed9732013-06-20 10:17:53148 }
huangs16f01e02016-04-21 19:38:38149
150 // Gets the |name| of section |shdr|. Returns true on success.
151 CheckBool SectionName(const Elf32_Shdr& shdr, std::string* name) const;
paulgazz@chromium.org39ed9732013-06-20 10:17:53152
paulgazz@chromium.org39ed9732013-06-20 10:17:53153 // Misc Segment Helpers
154
sorin@chromium.orge3e696d32013-06-21 20:41:36155 Elf32_Half ProgramSegmentHeaderCount() const {
paulgazz@chromium.org39ed9732013-06-20 10:17:53156 return program_header_table_size_;
157 }
158
huangsdda11d062016-03-14 16:35:39159 const Elf32_Phdr* ProgramSegmentHeader(Elf32_Half id) const {
paulgazz@chromium.org39ed9732013-06-20 10:17:53160 assert(id >= 0 && id < ProgramSegmentHeaderCount());
161 return program_header_table_ + id;
paulgazz@chromium.org39ed9732013-06-20 10:17:53162 }
163
164 // Misc address space helpers
165
huangsdda11d062016-03-14 16:35:39166 CheckBool RVAsToFileOffsets(const std::vector<RVA>& rvas,
huangs7b221a52016-11-09 22:28:23167 std::vector<FileOffset>* file_offsets) const;
paulgazz@chromium.org39ed9732013-06-20 10:17:53168
etiennep7d4e8ee2016-05-11 20:13:36169 CheckBool RVAsToFileOffsets(
huangs7b221a52016-11-09 22:28:23170 std::vector<std::unique_ptr<TypedRVA>>* typed_rvas) const;
paulgazz@chromium.org39ed9732013-06-20 10:17:53171
huangs257f9fb2017-03-23 23:17:50172 // Helpers for ParseFile().
paulgazz@chromium.org39ed9732013-06-20 10:17:53173
huangsdda11d062016-03-14 16:35:39174 virtual CheckBool ParseRelocationSection(const Elf32_Shdr* section_header,
huangs7b221a52016-11-09 22:28:23175 InstructionReceptor* receptor) const
huangsdda11d062016-03-14 16:35:39176 WARN_UNUSED_RESULT = 0;
paulgazz@chromium.org144c8e92013-07-23 21:18:19177
huangsdda11d062016-03-14 16:35:39178 virtual CheckBool ParseRel32RelocsFromSection(const Elf32_Shdr* section)
179 WARN_UNUSED_RESULT = 0;
paulgazz@chromium.org39ed9732013-06-20 10:17:53180
huangsdc779d92017-03-01 22:22:38181 CheckBool ParseAbs32Relocs() WARN_UNUSED_RESULT;
182
183 // Extracts all rel32 TypedRVAs. Does not sort the result.
184 CheckBool ParseRel32RelocsFromSections() WARN_UNUSED_RESULT;
185
huangsc8037632016-05-19 18:16:40186 // Disassembler interfaces.
huangs257f9fb2017-03-23 23:17:50187 bool ExtractAbs32Locations() override;
188 bool ExtractRel32Locations() override;
huangsc8037632016-05-19 18:16:40189 RvaVisitor* CreateAbs32TargetRvaVisitor() override;
190 RvaVisitor* CreateRel32TargetRvaVisitor() override;
191 void RemoveUnusedRel32Locations(AssemblyProgram* program) override;
huangs257f9fb2017-03-23 23:17:50192 InstructionGenerator GetInstructionGenerator(
193 AssemblyProgram* program) override;
huangsc8037632016-05-19 18:16:40194
huangs7b221a52016-11-09 22:28:23195 CheckBool ParseFile(AssemblyProgram* target,
196 InstructionReceptor* receptor) const WARN_UNUSED_RESULT;
huangsdda11d062016-03-14 16:35:39197
paulgazz@chromium.org39ed9732013-06-20 10:17:53198 CheckBool ParseProgbitsSection(
huangsdda11d062016-03-14 16:35:39199 const Elf32_Shdr* section_header,
200 std::vector<FileOffset>::iterator* current_abs_offset,
201 std::vector<FileOffset>::iterator end_abs_offset,
etiennep7d4e8ee2016-05-11 20:13:36202 std::vector<std::unique_ptr<TypedRVA>>::iterator* current_rel,
203 std::vector<std::unique_ptr<TypedRVA>>::iterator end_rel,
huangs7b221a52016-11-09 22:28:23204 AssemblyProgram* program,
205 InstructionReceptor* receptor) const WARN_UNUSED_RESULT;
huangsdda11d062016-03-14 16:35:39206
207 CheckBool ParseSimpleRegion(FileOffset start_file_offset,
208 FileOffset end_file_offset,
huangs7b221a52016-11-09 22:28:23209 InstructionReceptor* receptor) const
210 WARN_UNUSED_RESULT;
paulgazz@chromium.org39ed9732013-06-20 10:17:53211
huangsdda11d062016-03-14 16:35:39212 CheckBool CheckSection(RVA rva) WARN_UNUSED_RESULT;
huangsdda11d062016-03-14 16:35:39213
214 const Elf32_Ehdr* header_;
huangs691893002016-04-19 20:04:33215
paulgazz@chromium.org39ed9732013-06-20 10:17:53216 Elf32_Half section_header_table_size_;
huangs691893002016-04-19 20:04:33217
218 // Section header table, ordered by section id.
219 std::vector<Elf32_Shdr> section_header_table_;
220
221 // An ordering of |section_header_table_|, sorted by file offset.
222 std::vector<Elf32_Half> section_header_file_offset_order_;
paulgazz@chromium.org39ed9732013-06-20 10:17:53223
huangsdda11d062016-03-14 16:35:39224 const Elf32_Phdr* program_header_table_;
paulgazz@chromium.org39ed9732013-06-20 10:17:53225 Elf32_Half program_header_table_size_;
226
huangs16f01e02016-04-21 19:38:38227 // Pointer to string table containing section names.
huangsdda11d062016-03-14 16:35:39228 const char* default_string_section_;
huangs16f01e02016-04-21 19:38:38229 size_t default_string_section_size_;
paulgazz@chromium.org39ed9732013-06-20 10:17:53230
huangs257f9fb2017-03-23 23:17:50231 // Sorted abs32 RVAs.
232 std::vector<RVA> abs32_locations_;
233 // Sorted rel32 RVAs. This is mutable because ParseFile() temporarily sorts
234 // these by file offsets.
huangs7b221a52016-11-09 22:28:23235 mutable std::vector<std::unique_ptr<TypedRVA>> rel32_locations_;
paulgazz@chromium.org39ed9732013-06-20 10:17:53236
huangs7b221a52016-11-09 22:28:23237 private:
paulgazz@chromium.org39ed9732013-06-20 10:17:53238 DISALLOW_COPY_AND_ASSIGN(DisassemblerElf32);
239};
240
241} // namespace courgette
242
243#endif // COURGETTE_DISASSEMBLER_ELF_32_H_