disassembler_elf_32.h 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  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. #ifndef COURGETTE_DISASSEMBLER_ELF_32_H_
  5. #define COURGETTE_DISASSEMBLER_ELF_32_H_
  6. #include <stddef.h>
  7. #include <stdint.h>
  8. #include <memory>
  9. #include <string>
  10. #include <vector>
  11. #include "base/memory/raw_ptr.h"
  12. #include "courgette/disassembler.h"
  13. #include "courgette/image_utils.h"
  14. #include "courgette/instruction_utils.h"
  15. #include "courgette/memory_allocator.h"
  16. #include "courgette/types_elf.h"
  17. namespace courgette {
  18. class AssemblyProgram;
  19. // A Courgette disassembler for 32-bit ELF files. This is only a partial
  20. // implementation that admits subclasses for the architecture-specific parts of
  21. // 32-bit ELF file processing. Specifically:
  22. // - RelToRVA() processes entries in ELF relocation table.
  23. // - ParseRelocationSection() verifies the organization of the ELF relocation
  24. // table.
  25. // - ParseRel32RelocsFromSection() finds branch targets by looking for relative
  26. // branch/call opcodes in the particular 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:
  33. explicit TypedRVA(RVA rva) : rva_(rva) { }
  34. virtual ~TypedRVA() { }
  35. RVA rva() const { return rva_; }
  36. RVA relative_target() const { return relative_target_; }
  37. FileOffset file_offset() const { return file_offset_; }
  38. void set_relative_target(RVA relative_target) {
  39. relative_target_ = relative_target;
  40. }
  41. void set_file_offset(FileOffset file_offset) { file_offset_ = file_offset; }
  42. // Computes the relative jump's offset from the op in p.
  43. virtual CheckBool ComputeRelativeTarget(const uint8_t* op_pointer) = 0;
  44. // Emits the assembly instruction corresponding to |label|.
  45. virtual CheckBool EmitInstruction(Label* label,
  46. InstructionReceptor* receptor) = 0;
  47. // Returns the size of the instruction containing the RVA.
  48. virtual uint16_t op_size() const = 0;
  49. // Comparator for sorting, which assumes uniqueness of RVAs.
  50. static bool IsLessThanByRVA(const std::unique_ptr<TypedRVA>& a,
  51. const std::unique_ptr<TypedRVA>& b) {
  52. return a->rva() < b->rva();
  53. }
  54. // Comparator for sorting, which assumes uniqueness of file offsets.
  55. static bool IsLessThanByFileOffset(const std::unique_ptr<TypedRVA>& a,
  56. const std::unique_ptr<TypedRVA>& b) {
  57. return a->file_offset() < b->file_offset();
  58. }
  59. private:
  60. const RVA rva_;
  61. RVA relative_target_ = kNoRVA;
  62. FileOffset file_offset_ = kNoFileOffset;
  63. };
  64. // Visitor/adaptor to translate RVA to target RVA. This is the ELF
  65. // counterpart to RvaVisitor_Rel32 that uses TypedRVA.
  66. class Elf32RvaVisitor_Rel32 :
  67. public VectorRvaVisitor<std::unique_ptr<TypedRVA>> {
  68. public:
  69. Elf32RvaVisitor_Rel32(
  70. const std::vector<std::unique_ptr<TypedRVA>>& rva_locations);
  71. Elf32RvaVisitor_Rel32(const Elf32RvaVisitor_Rel32&) = delete;
  72. Elf32RvaVisitor_Rel32& operator=(const Elf32RvaVisitor_Rel32&) = delete;
  73. ~Elf32RvaVisitor_Rel32() override { }
  74. // VectorRvaVisitor<TypedRVA*> interfaces.
  75. RVA Get() const override;
  76. };
  77. public:
  78. DisassemblerElf32(const uint8_t* start, size_t length);
  79. DisassemblerElf32(const DisassemblerElf32&) = delete;
  80. DisassemblerElf32& operator=(const DisassemblerElf32&) = delete;
  81. ~DisassemblerElf32() override { }
  82. // Disassembler interfaces.
  83. RVA FileOffsetToRVA(FileOffset file_offset) const override;
  84. FileOffset RVAToFileOffset(RVA rva) const override;
  85. RVA PointerToTargetRVA(const uint8_t* p) const override;
  86. ExecutableType kind() const override = 0;
  87. uint64_t image_base() const override { return 0; }
  88. bool ParseHeader() override;
  89. virtual e_machine_values ElfEM() const = 0;
  90. [[nodiscard]] CheckBool IsValidTargetRVA(RVA rva) const;
  91. // Converts an ELF relocation instruction into an RVA.
  92. [[nodiscard]] virtual CheckBool RelToRVA(Elf32_Rel rel,
  93. RVA* result) const = 0;
  94. // Public for unittests only
  95. std::vector<RVA>& Abs32Locations() { return abs32_locations_; }
  96. std::vector<std::unique_ptr<TypedRVA>>& Rel32Locations() {
  97. return rel32_locations_;
  98. }
  99. protected:
  100. // Returns 'true' if an valid executable is detected using only quick checks.
  101. // Derived classes should inject |elf_em| corresponding to their architecture,
  102. // which will be checked against the detected one.
  103. static bool QuickDetect(const uint8_t* start,
  104. size_t length,
  105. e_machine_values elf_em);
  106. // Returns whether all non-SHT_NOBITS sections lie within image.
  107. bool CheckSectionRanges();
  108. // Returns whether all program segments lie within image.
  109. bool CheckProgramSegmentRanges();
  110. void UpdateLength();
  111. // Misc Section Helpers
  112. Elf32_Half SectionHeaderCount() const {
  113. return section_header_table_size_;
  114. }
  115. const Elf32_Shdr* SectionHeader(Elf32_Half id) const {
  116. assert(id >= 0 && id < SectionHeaderCount());
  117. return &section_header_table_[id];
  118. }
  119. const uint8_t* SectionBody(Elf32_Half id) const {
  120. const Elf32_Shdr* section_header = SectionHeader(id);
  121. DCHECK(section_header->sh_type != SHT_NOBITS);
  122. return FileOffsetToPointer(section_header->sh_offset);
  123. }
  124. // Gets the |name| of section |shdr|. Returns true on success.
  125. CheckBool SectionName(const Elf32_Shdr& shdr, std::string* name) const;
  126. // Misc Segment Helpers
  127. Elf32_Half ProgramSegmentHeaderCount() const {
  128. return program_header_table_size_;
  129. }
  130. const Elf32_Phdr* ProgramSegmentHeader(Elf32_Half id) const {
  131. assert(id >= 0 && id < ProgramSegmentHeaderCount());
  132. return program_header_table_ + id;
  133. }
  134. // Misc address space helpers
  135. CheckBool RVAsToFileOffsets(const std::vector<RVA>& rvas,
  136. std::vector<FileOffset>* file_offsets) const;
  137. CheckBool RVAsToFileOffsets(
  138. std::vector<std::unique_ptr<TypedRVA>>* typed_rvas) const;
  139. // Helpers for ParseFile().
  140. [[nodiscard]] virtual CheckBool ParseRelocationSection(
  141. const Elf32_Shdr* section_header,
  142. InstructionReceptor* receptor) const = 0;
  143. [[nodiscard]] virtual CheckBool ParseRel32RelocsFromSection(
  144. const Elf32_Shdr* section) = 0;
  145. [[nodiscard]] CheckBool ParseAbs32Relocs();
  146. // Extracts all rel32 TypedRVAs. Does not sort the result.
  147. [[nodiscard]] CheckBool ParseRel32RelocsFromSections();
  148. // Disassembler interfaces.
  149. bool ExtractAbs32Locations() override;
  150. bool ExtractRel32Locations() override;
  151. RvaVisitor* CreateAbs32TargetRvaVisitor() override;
  152. RvaVisitor* CreateRel32TargetRvaVisitor() override;
  153. void RemoveUnusedRel32Locations(AssemblyProgram* program) override;
  154. InstructionGenerator GetInstructionGenerator(
  155. AssemblyProgram* program) override;
  156. [[nodiscard]] CheckBool ParseFile(AssemblyProgram* target,
  157. InstructionReceptor* receptor) const;
  158. [[nodiscard]] CheckBool ParseProgbitsSection(
  159. const Elf32_Shdr* section_header,
  160. std::vector<FileOffset>::iterator* current_abs_offset,
  161. std::vector<FileOffset>::iterator end_abs_offset,
  162. std::vector<std::unique_ptr<TypedRVA>>::iterator* current_rel,
  163. std::vector<std::unique_ptr<TypedRVA>>::iterator end_rel,
  164. AssemblyProgram* program,
  165. InstructionReceptor* receptor) const;
  166. [[nodiscard]] CheckBool ParseSimpleRegion(
  167. FileOffset start_file_offset,
  168. FileOffset end_file_offset,
  169. InstructionReceptor* receptor) const;
  170. [[nodiscard]] CheckBool CheckSection(RVA rva);
  171. raw_ptr<const Elf32_Ehdr> header_;
  172. Elf32_Half section_header_table_size_;
  173. // Section header table, ordered by section id.
  174. std::vector<Elf32_Shdr> section_header_table_;
  175. // An ordering of |section_header_table_|, sorted by file offset.
  176. std::vector<Elf32_Half> section_header_file_offset_order_;
  177. raw_ptr<const Elf32_Phdr> program_header_table_;
  178. Elf32_Half program_header_table_size_;
  179. // Pointer to string table containing section names.
  180. const char* default_string_section_;
  181. size_t default_string_section_size_;
  182. // Sorted abs32 RVAs.
  183. std::vector<RVA> abs32_locations_;
  184. // Sorted rel32 RVAs. This is mutable because ParseFile() temporarily sorts
  185. // these by file offsets.
  186. mutable std::vector<std::unique_ptr<TypedRVA>> rel32_locations_;
  187. };
  188. } // namespace courgette
  189. #endif // COURGETTE_DISASSEMBLER_ELF_32_H_