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_x64.h"
     19 #include "courgette/disassembler_win32_x86.h"
     20 #include "courgette/encoded_program.h"
     21 
     22 namespace courgette {
     23 
     24 ////////////////////////////////////////////////////////////////////////////////
     25 
     26 Disassembler* DetectDisassembler(const void* buffer, size_t length) {
     27   Disassembler* disassembler = NULL;
     28 
     29   disassembler = new DisassemblerWin32X86(buffer, length);
     30   if (disassembler->ParseHeader())
     31     return disassembler;
     32   else
     33     delete disassembler;
     34 
     35   disassembler = new DisassemblerWin32X64(buffer, length);
     36   if (disassembler->ParseHeader())
     37     return disassembler;
     38   else
     39     delete disassembler;
     40 
     41   disassembler = new DisassemblerElf32X86(buffer, length);
     42   if (disassembler->ParseHeader())
     43     return disassembler;
     44   else
     45     delete disassembler;
     46 
     47   disassembler = new DisassemblerElf32ARM(buffer, length);
     48   if (disassembler->ParseHeader())
     49     return disassembler;
     50   else
     51     delete disassembler;
     52 
     53   return NULL;
     54 }
     55 
     56 Status DetectExecutableType(const void* buffer, size_t length,
     57                             ExecutableType* type,
     58                             size_t* detected_length) {
     59 
     60   Disassembler* disassembler = DetectDisassembler(buffer, length);
     61 
     62   if (disassembler) {
     63     *type = disassembler->kind();
     64     *detected_length = disassembler->length();
     65     delete disassembler;
     66     return C_OK;
     67   }
     68 
     69   // We failed to detect anything
     70   *type = EXE_UNKNOWN;
     71   *detected_length = 0;
     72   return C_INPUT_NOT_RECOGNIZED;
     73 }
     74 
     75 Status ParseDetectedExecutable(const void* buffer, size_t length,
     76                                AssemblyProgram** output) {
     77   *output = NULL;
     78 
     79   Disassembler* disassembler = DetectDisassembler(buffer, length);
     80 
     81   if (!disassembler) {
     82     return C_INPUT_NOT_RECOGNIZED;
     83   }
     84 
     85   AssemblyProgram* program = new AssemblyProgram(disassembler->kind());
     86 
     87   if (!disassembler->Disassemble(program)) {
     88     delete program;
     89     delete disassembler;
     90     return C_DISASSEMBLY_FAILED;
     91   }
     92 
     93   delete disassembler;
     94   *output = program;
     95   return C_OK;
     96 }
     97 
     98 void DeleteAssemblyProgram(AssemblyProgram* program) {
     99   delete program;
    100 }
    101 
    102 Disassembler::Disassembler(const void* start, size_t length)
    103   : failure_reason_("uninitialized") {
    104 
    105   start_ = reinterpret_cast<const uint8*>(start);
    106   length_ = length;
    107   end_ = start_ + length_;
    108 };
    109 
    110 Disassembler::~Disassembler() {};
    111 
    112 const uint8* Disassembler::OffsetToPointer(size_t offset) const {
    113   assert(start_ + offset <= end_);
    114   return start_ + offset;
    115 }
    116 
    117 bool Disassembler::Good() {
    118   failure_reason_ = NULL;
    119   return true;
    120 }
    121 
    122 bool Disassembler::Bad(const char* reason) {
    123   failure_reason_ = reason;
    124   return false;
    125 }
    126 
    127 void Disassembler::ReduceLength(size_t reduced_length) {
    128   if (reduced_length < length_)
    129     length_ = reduced_length;
    130 }
    131 
    132 }  // namespace courgette
    133