1 | // All rights reserved. |
2 | // |
3 | // Redistribution and use in source and binary forms, with or without |
4 | // modification, are permitted provided that the following conditions are |
5 | // met: |
6 | // |
7 | // * Redistributions of source code must retain the above copyright |
8 | // notice, this list of conditions and the following disclaimer. |
9 | // * Redistributions in binary form must reproduce the above |
10 | // copyright notice, this list of conditions and the following disclaimer |
11 | // in the documentation and/or other materials provided with the |
12 | // distribution. |
13 | // * Neither the name of Google Inc. nor the names of its |
14 | // contributors may be used to endorse or promote products derived from |
15 | // this software without specific prior written permission. |
16 | // |
17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
18 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
19 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
20 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
21 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
22 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
23 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
24 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
25 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
26 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
27 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
28 | |
29 | // disassembler_x86.h: Basic x86 bytecode disassembler |
30 | // |
31 | // Provides a simple disassembler which wraps libdisasm. This allows simple |
32 | // tests to be run against bytecode to test for various properties. |
33 | // |
34 | // Author: Cris Neckar |
35 | |
36 | #ifndef GOOGLE_BREAKPAD_PROCESSOR_DISASSEMBLER_X86_H_ |
37 | #define GOOGLE_BREAKPAD_PROCESSOR_DISASSEMBLER_X86_H_ |
38 | |
39 | #include <stddef.h> |
40 | #include <sys/types.h> |
41 | |
42 | #include "google_breakpad/common/breakpad_types.h" |
43 | |
44 | namespace libdis { |
45 | #include "third_party/libdisasm/libdis.h" |
46 | } |
47 | |
48 | namespace google_breakpad { |
49 | |
50 | enum { |
51 | DISX86_NONE = 0x0, |
52 | DISX86_BAD_BRANCH_TARGET = 0x1, |
53 | DISX86_BAD_ARGUMENT_PASSED = 0x2, |
54 | DISX86_BAD_WRITE = 0x4, |
55 | DISX86_BAD_BLOCK_WRITE = 0x8, |
56 | DISX86_BAD_READ = 0x10, |
57 | DISX86_BAD_BLOCK_READ = 0x20, |
58 | DISX86_BAD_COMPARISON = 0x40 |
59 | }; |
60 | |
61 | class DisassemblerX86 { |
62 | public: |
63 | // TODO(cdn): Modify this class to take a MemoryRegion instead of just |
64 | // a raw buffer. This will make it easier to use this on arbitrary |
65 | // minidumps without first copying out the code segment. |
66 | DisassemblerX86(const uint8_t* bytecode, uint32_t, uint32_t); |
67 | ~DisassemblerX86(); |
68 | |
69 | // This walks to the next instruction in the memory region and |
70 | // sets flags based on the type of instruction and previous state |
71 | // including any registers marked as bad through setBadRead() |
72 | // or setBadWrite(). This method can be called in a loop to |
73 | // disassemble until the end of a region. |
74 | uint32_t NextInstruction(); |
75 | |
76 | // Indicates whether the current disassembled instruction was valid. |
77 | bool currentInstructionValid() { return instr_valid_; } |
78 | |
79 | // Returns the current instruction as defined in libdis.h, |
80 | // or NULL if the current instruction is not valid. |
81 | const libdis::x86_insn_t* currentInstruction() { |
82 | return instr_valid_ ? ¤t_instr_ : NULL; |
83 | } |
84 | |
85 | // Returns the type of the current instruction as defined in libdis.h. |
86 | libdis::x86_insn_group currentInstructionGroup() { |
87 | return current_instr_.group; |
88 | } |
89 | |
90 | // Indicates whether a return instruction has been encountered. |
91 | bool endOfBlock() { return end_of_block_; } |
92 | |
93 | // The flags set so far for the disassembly. |
94 | uint16_t flags() { return flags_; } |
95 | |
96 | // This sets an indicator that the register used to determine |
97 | // src or dest for the current instruction is tainted. These can |
98 | // be used after examining the current instruction to indicate, |
99 | // for example that a bad read or write occurred and the pointer |
100 | // stored in the register is currently invalid. |
101 | bool setBadRead(); |
102 | bool setBadWrite(); |
103 | |
104 | protected: |
105 | const uint8_t* bytecode_; |
106 | uint32_t size_; |
107 | uint32_t virtual_address_; |
108 | uint32_t current_byte_offset_; |
109 | uint32_t current_inst_offset_; |
110 | |
111 | bool instr_valid_; |
112 | libdis::x86_insn_t current_instr_; |
113 | |
114 | // TODO(cdn): Maybe also track an expression's index register. |
115 | // ex: mov eax, [ebx + ecx]; ebx is base, ecx is index. |
116 | bool register_valid_; |
117 | libdis::x86_reg_t bad_register_; |
118 | |
119 | bool pushed_bad_value_; |
120 | bool end_of_block_; |
121 | |
122 | uint16_t flags_; |
123 | }; |
124 | |
125 | } // namespace google_breakpad |
126 | |
127 | #endif // GOOGLE_BREAKPAD_PROCESSOR_DISASSEMBLER_X86_H_ |
128 | |