Home | History | Annotate | Download | only in courgette
      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:
     33     explicit TypedRVA(RVA rva) : rva_(rva), offset_(static_cast<size_t>(-1)) {
     34     }
     35 
     36     virtual ~TypedRVA() { };
     37 
     38     RVA rva() {
     39       return rva_;
     40     }
     41 
     42     RVA relative_target() {
     43       return relative_target_;
     44     }
     45 
     46     void set_relative_target(RVA relative_target) {
     47       relative_target_ = relative_target;
     48     }
     49 
     50     size_t get_offset() {
     51       return offset_;
     52     }
     53 
     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 
     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 
     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
     94   std::vector<RVA> &Abs32Locations() { return abs32_locations_; }
     95   ScopedVector<TypedRVA> &Rel32Locations() { return rel32_locations_; }
     96 
     97  protected:
     98 
     99   uint32 DiscoverLength();
    100 
    101   // Misc Section Helpers
    102 
    103   Elf32_Half SectionHeaderCount() const {
    104     return section_header_table_size_;
    105   }
    106 
    107   const Elf32_Shdr *SectionHeader(int id) const {
    108     assert(id >= 0 && id < SectionHeaderCount());
    109     return section_header_table_ + id;
    110   }
    111 
    112   const uint8 *SectionBody(int id) const {
    113     return OffsetToPointer(SectionHeader(id)->sh_offset);
    114   }
    115 
    116   Elf32_Word SectionBodySize(int id) const {
    117     return SectionHeader(id)->sh_size;
    118   }
    119 
    120   // Misc Segment Helpers
    121 
    122   Elf32_Half ProgramSegmentHeaderCount() const {
    123     return program_header_table_size_;
    124   }
    125 
    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
    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
    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
    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.
    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