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