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