Home | History | Annotate | Download | only in courgette
      1 // Copyright (c) 2011 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 #include "courgette/disassembler.h"
      6 
      7 #include <algorithm>
      8 #include <string>
      9 #include <vector>
     10 
     11 #include "base/basictypes.h"
     12 #include "base/logging.h"
     13 
     14 #include "courgette/assembly_program.h"
     15 #include "courgette/courgette.h"
     16 #include "courgette/disassembler_elf_32_arm.h"
     17 #include "courgette/disassembler_elf_32_x86.h"
     18 #include "courgette/disassembler_win32_x86.h"
     19 #include "courgette/encoded_program.h"
     20 
     21 // COURGETTE_HISTOGRAM_TARGETS prints out a histogram of how frequently
     22 // different target addresses are referenced.  Purely for debugging.
     23 #define COURGETTE_HISTOGRAM_TARGETS 0
     24 
     25 namespace courgette {
     26 
     27 ////////////////////////////////////////////////////////////////////////////////
     28 
     29 Disassembler* DetectDisassembler(const void* buffer, size_t length) {
     30   Disassembler* disassembler = NULL;
     31 
     32   disassembler = new DisassemblerWin32X86(buffer, length);
     33   if (disassembler->ParseHeader())
     34     return disassembler;
     35   else
     36     delete disassembler;
     37 
     38   disassembler = new DisassemblerElf32X86(buffer, length);
     39   if (disassembler->ParseHeader())
     40     return disassembler;
     41   else
     42     delete disassembler;
     43 
     44   disassembler = new DisassemblerElf32ARM(buffer, length);
     45   if (disassembler->ParseHeader())
     46     return disassembler;
     47   else
     48     delete disassembler;
     49 
     50   return NULL;
     51 }
     52 
     53 Status DetectExecutableType(const void* buffer, size_t length,
     54                             ExecutableType* type,
     55                             size_t* detected_length) {
     56 
     57   Disassembler* disassembler = DetectDisassembler(buffer, length);
     58 
     59   if (disassembler) {
     60     *type = disassembler->kind();
     61     *detected_length = disassembler->length();
     62     delete disassembler;
     63     return C_OK;
     64   }
     65 
     66   // We failed to detect anything
     67   *type = EXE_UNKNOWN;
     68   *detected_length = 0;
     69   return C_INPUT_NOT_RECOGNIZED;
     70 }
     71 
     72 Status ParseDetectedExecutable(const void* buffer, size_t length,
     73                                AssemblyProgram** output) {
     74   *output = NULL;
     75 
     76   Disassembler* disassembler = DetectDisassembler(buffer, length);
     77 
     78   if (!disassembler) {
     79     return C_INPUT_NOT_RECOGNIZED;
     80   }
     81 
     82   AssemblyProgram* program = new AssemblyProgram(disassembler->kind());
     83 
     84   if (!disassembler->Disassemble(program)) {
     85     delete program;
     86     delete disassembler;
     87     return C_DISASSEMBLY_FAILED;
     88   }
     89 
     90   delete disassembler;
     91   *output = program;
     92   return C_OK;
     93 }
     94 
     95 void DeleteAssemblyProgram(AssemblyProgram* program) {
     96   delete program;
     97 }
     98 
     99 Disassembler::Disassembler(const void* start, size_t length)
    100   : failure_reason_("uninitialized") {
    101 
    102   start_ = reinterpret_cast<const uint8*>(start);
    103   length_ = length;
    104   end_ = start_ + length_;
    105 };
    106 
    107 Disassembler::~Disassembler() {};
    108 
    109 const uint8* Disassembler::OffsetToPointer(size_t offset) const {
    110   assert(start_ + offset <= end_);
    111   return start_ + offset;
    112 }
    113 
    114 bool Disassembler::Good() {
    115   failure_reason_ = NULL;
    116   return true;
    117 }
    118 
    119 bool Disassembler::Bad(const char* reason) {
    120   failure_reason_ = reason;
    121   return false;
    122 }
    123 
    124 void Disassembler::ReduceLength(size_t reduced_length) {
    125   if (reduced_length < length_)
    126     length_ = reduced_length;
    127 }
    128 
    129 }  // namespace courgette
    130