• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
DetectDisassembler(const void * buffer,size_t length)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 
DetectExecutableType(const void * buffer,size_t length,ExecutableType * type,size_t * detected_length)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 
ParseDetectedExecutable(const void * buffer,size_t length,AssemblyProgram ** output)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 
DeleteAssemblyProgram(AssemblyProgram * program)98 void DeleteAssemblyProgram(AssemblyProgram* program) {
99   delete program;
100 }
101 
Disassembler(const void * start,size_t length)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 
~Disassembler()110 Disassembler::~Disassembler() {};
111 
OffsetToPointer(size_t offset) const112 const uint8* Disassembler::OffsetToPointer(size_t offset) const {
113   assert(start_ + offset <= end_);
114   return start_ + offset;
115 }
116 
Good()117 bool Disassembler::Good() {
118   failure_reason_ = NULL;
119   return true;
120 }
121 
Bad(const char * reason)122 bool Disassembler::Bad(const char* reason) {
123   failure_reason_ = reason;
124   return false;
125 }
126 
ReduceLength(size_t reduced_length)127 void Disassembler::ReduceLength(size_t reduced_length) {
128   if (reduced_length < length_)
129     length_ = reduced_length;
130 }
131 
132 }  // namespace courgette
133