| // All rights reserved. |
| // |
| // Redistribution and use in source and binary forms, with or without |
| // modification, are permitted provided that the following conditions are |
| // met: |
| // |
| // * Redistributions of source code must retain the above copyright |
| // notice, this list of conditions and the following disclaimer. |
| // * Redistributions in binary form must reproduce the above |
| // copyright notice, this list of conditions and the following disclaimer |
| // in the documentation and/or other materials provided with the |
| // distribution. |
| // * Neither the name of Google Inc. nor the names of its |
| // contributors may be used to endorse or promote products derived from |
| // this software without specific prior written permission. |
| // |
| // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| |
| // disassembler_x86.h: Basic x86 bytecode disassembler |
| // |
| // Provides a simple disassembler which wraps libdisasm. This allows simple |
| // tests to be run against bytecode to test for various properties. |
| // |
| // Author: Cris Neckar |
| |
| #ifndef GOOGLE_BREAKPAD_PROCESSOR_DISASSEMBLER_X86_H_ |
| #define GOOGLE_BREAKPAD_PROCESSOR_DISASSEMBLER_X86_H_ |
| |
| #include <stddef.h> |
| #include <sys/types.h> |
| |
| #include "google_breakpad/common/breakpad_types.h" |
| |
| namespace libdis { |
| #include "third_party/libdisasm/libdis.h" |
| } |
| |
| namespace google_breakpad { |
| |
| enum { |
| DISX86_NONE = 0x0, |
| DISX86_BAD_BRANCH_TARGET = 0x1, |
| DISX86_BAD_ARGUMENT_PASSED = 0x2, |
| DISX86_BAD_WRITE = 0x4, |
| DISX86_BAD_BLOCK_WRITE = 0x8, |
| DISX86_BAD_READ = 0x10, |
| DISX86_BAD_BLOCK_READ = 0x20, |
| DISX86_BAD_COMPARISON = 0x40 |
| }; |
| |
| class DisassemblerX86 { |
| public: |
| // TODO(cdn): Modify this class to take a MemoryRegion instead of just |
| // a raw buffer. This will make it easier to use this on arbitrary |
| // minidumps without first copying out the code segment. |
| DisassemblerX86(const uint8_t* bytecode, uint32_t, uint32_t); |
| ~DisassemblerX86(); |
| |
| // This walks to the next instruction in the memory region and |
| // sets flags based on the type of instruction and previous state |
| // including any registers marked as bad through setBadRead() |
| // or setBadWrite(). This method can be called in a loop to |
| // disassemble until the end of a region. |
| uint32_t NextInstruction(); |
| |
| // Indicates whether the current disassembled instruction was valid. |
| bool currentInstructionValid() { return instr_valid_; } |
| |
| // Returns the current instruction as defined in libdis.h, |
| // or NULL if the current instruction is not valid. |
| const libdis::x86_insn_t* currentInstruction() { |
| return instr_valid_ ? ¤t_instr_ : NULL; |
| } |
| |
| // Returns the type of the current instruction as defined in libdis.h. |
| libdis::x86_insn_group currentInstructionGroup() { |
| return current_instr_.group; |
| } |
| |
| // Indicates whether a return instruction has been encountered. |
| bool endOfBlock() { return end_of_block_; } |
| |
| // The flags set so far for the disassembly. |
| uint16_t flags() { return flags_; } |
| |
| // This sets an indicator that the register used to determine |
| // src or dest for the current instruction is tainted. These can |
| // be used after examining the current instruction to indicate, |
| // for example that a bad read or write occurred and the pointer |
| // stored in the register is currently invalid. |
| bool setBadRead(); |
| bool setBadWrite(); |
| |
| protected: |
| const uint8_t* bytecode_; |
| uint32_t size_; |
| uint32_t virtual_address_; |
| uint32_t current_byte_offset_; |
| uint32_t current_inst_offset_; |
| |
| bool instr_valid_; |
| libdis::x86_insn_t current_instr_; |
| |
| // TODO(cdn): Maybe also track an expression's index register. |
| // ex: mov eax, [ebx + ecx]; ebx is base, ecx is index. |
| bool register_valid_; |
| libdis::x86_reg_t bad_register_; |
| |
| bool pushed_bad_value_; |
| bool end_of_block_; |
| |
| uint16_t flags_; |
| }; |
| |
| } // namespace google_breakpad |
| |
| #endif // GOOGLE_BREAKPAD_PROCESSOR_DISASSEMBLER_X86_H_ |