diff options
Diffstat (limited to 'toolkit/crashreporter/google-breakpad/src/processor/disassembler_x86.cc')
-rw-r--r-- | toolkit/crashreporter/google-breakpad/src/processor/disassembler_x86.cc | 240 |
1 files changed, 0 insertions, 240 deletions
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/disassembler_x86.cc b/toolkit/crashreporter/google-breakpad/src/processor/disassembler_x86.cc deleted file mode 100644 index 559022404..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/disassembler_x86.cc +++ /dev/null @@ -1,240 +0,0 @@ -// 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.cc: simple x86 disassembler. -// -// Provides single step disassembly of x86 bytecode and flags instructions -// that utilize known bad register values. -// -// Author: Cris Neckar - -#include "processor/disassembler_x86.h" - -#include <string.h> - -namespace google_breakpad { - -DisassemblerX86::DisassemblerX86(const uint8_t *bytecode, - uint32_t size, - uint32_t virtual_address) : - bytecode_(bytecode), - size_(size), - virtual_address_(virtual_address), - current_byte_offset_(0), - current_inst_offset_(0), - instr_valid_(false), - register_valid_(false), - pushed_bad_value_(false), - end_of_block_(false), - flags_(0) { - libdis::x86_init(libdis::opt_none, NULL, NULL); -} - -DisassemblerX86::~DisassemblerX86() { - if (instr_valid_) - libdis::x86_oplist_free(¤t_instr_); - - libdis::x86_cleanup(); -} - -uint32_t DisassemblerX86::NextInstruction() { - if (instr_valid_) - libdis::x86_oplist_free(¤t_instr_); - - if (current_byte_offset_ >= size_) { - instr_valid_ = false; - return 0; - } - uint32_t instr_size = 0; - instr_size = libdis::x86_disasm((unsigned char *)bytecode_, size_, - virtual_address_, current_byte_offset_, - ¤t_instr_); - if (instr_size == 0) { - instr_valid_ = false; - return 0; - } - - current_byte_offset_ += instr_size; - current_inst_offset_++; - instr_valid_ = libdis::x86_insn_is_valid(¤t_instr_); - if (!instr_valid_) - return 0; - - if (current_instr_.type == libdis::insn_return) - end_of_block_ = true; - libdis::x86_op_t *src = libdis::x86_get_src_operand(¤t_instr_); - libdis::x86_op_t *dest = libdis::x86_get_dest_operand(¤t_instr_); - - if (register_valid_) { - switch (current_instr_.group) { - // Flag branches based off of bad registers and calls that occur - // after pushing bad values. - case libdis::insn_controlflow: - switch (current_instr_.type) { - case libdis::insn_jmp: - case libdis::insn_jcc: - case libdis::insn_call: - case libdis::insn_callcc: - if (dest) { - switch (dest->type) { - case libdis::op_expression: - if (dest->data.expression.base.id == bad_register_.id) - flags_ |= DISX86_BAD_BRANCH_TARGET; - break; - case libdis::op_register: - if (dest->data.reg.id == bad_register_.id) - flags_ |= DISX86_BAD_BRANCH_TARGET; - break; - default: - if (pushed_bad_value_ && - (current_instr_.type == libdis::insn_call || - current_instr_.type == libdis::insn_callcc)) - flags_ |= DISX86_BAD_ARGUMENT_PASSED; - break; - } - } - break; - default: - break; - } - break; - - // Flag block data operations that use bad registers for src or dest. - case libdis::insn_string: - if (dest && dest->type == libdis::op_expression && - dest->data.expression.base.id == bad_register_.id) - flags_ |= DISX86_BAD_BLOCK_WRITE; - if (src && src->type == libdis::op_expression && - src->data.expression.base.id == bad_register_.id) - flags_ |= DISX86_BAD_BLOCK_READ; - break; - - // Flag comparisons based on bad data. - case libdis::insn_comparison: - if ((dest && dest->type == libdis::op_expression && - dest->data.expression.base.id == bad_register_.id) || - (src && src->type == libdis::op_expression && - src->data.expression.base.id == bad_register_.id) || - (dest && dest->type == libdis::op_register && - dest->data.reg.id == bad_register_.id) || - (src && src->type == libdis::op_register && - src->data.reg.id == bad_register_.id)) - flags_ |= DISX86_BAD_COMPARISON; - break; - - // Flag any other instruction which derefs a bad register for - // src or dest. - default: - if (dest && dest->type == libdis::op_expression && - dest->data.expression.base.id == bad_register_.id) - flags_ |= DISX86_BAD_WRITE; - if (src && src->type == libdis::op_expression && - src->data.expression.base.id == bad_register_.id) - flags_ |= DISX86_BAD_READ; - break; - } - } - - // When a register is marked as tainted check if it is pushed. - // TODO(cdn): may also want to check for MOVs into EBP offsets. - if (register_valid_ && dest && current_instr_.type == libdis::insn_push) { - switch (dest->type) { - case libdis::op_expression: - if (dest->data.expression.base.id == bad_register_.id || - dest->data.expression.index.id == bad_register_.id) - pushed_bad_value_ = true; - break; - case libdis::op_register: - if (dest->data.reg.id == bad_register_.id) - pushed_bad_value_ = true; - break; - default: - break; - } - } - - // Check if a tainted register value is clobbered. - // For conditional MOVs and XCHGs assume that - // there is a hit. - if (register_valid_) { - switch (current_instr_.type) { - case libdis::insn_xor: - if (src && src->type == libdis::op_register && - dest && dest->type == libdis::op_register && - src->data.reg.id == bad_register_.id && - src->data.reg.id == dest->data.reg.id) - register_valid_ = false; - break; - case libdis::insn_pop: - case libdis::insn_mov: - case libdis::insn_movcc: - if (dest && dest->type == libdis::op_register && - dest->data.reg.id == bad_register_.id) - register_valid_ = false; - break; - case libdis::insn_popregs: - register_valid_ = false; - break; - case libdis::insn_xchg: - case libdis::insn_xchgcc: - if (dest && dest->type == libdis::op_register && - src && src->type == libdis::op_register) { - if (dest->data.reg.id == bad_register_.id) - memcpy(&bad_register_, &src->data.reg, sizeof(libdis::x86_reg_t)); - else if (src->data.reg.id == bad_register_.id) - memcpy(&bad_register_, &dest->data.reg, sizeof(libdis::x86_reg_t)); - } - break; - default: - break; - } - } - - return instr_size; -} - -bool DisassemblerX86::setBadRead() { - if (!instr_valid_) - return false; - - libdis::x86_op_t *operand = libdis::x86_get_src_operand(¤t_instr_); - if (!operand || operand->type != libdis::op_expression) - return false; - - memcpy(&bad_register_, &operand->data.expression.base, - sizeof(libdis::x86_reg_t)); - register_valid_ = true; - return true; -} - -bool DisassemblerX86::setBadWrite() { - if (!instr_valid_) - return false; - - libdis::x86_op_t *operand = libdis::x86_get_dest_operand(¤t_instr_); - if (!operand || operand->type != libdis::op_expression) - return false; - - memcpy(&bad_register_, &operand->data.expression.base, - sizeof(libdis::x86_reg_t)); - register_valid_ = true; - return true; -} - -} // namespace google_breakpad |