diff options
Diffstat (limited to 'libunwindstack/DwarfOp.cpp')
-rw-r--r-- | libunwindstack/DwarfOp.cpp | 54 |
1 files changed, 40 insertions, 14 deletions
diff --git a/libunwindstack/DwarfOp.cpp b/libunwindstack/DwarfOp.cpp index dcf04e6ff..5bc60b9d1 100644 --- a/libunwindstack/DwarfOp.cpp +++ b/libunwindstack/DwarfOp.cpp @@ -36,13 +36,45 @@ template <typename AddressType> constexpr typename DwarfOp<AddressType>::OpCallback DwarfOp<AddressType>::kCallbackTable[256]; template <typename AddressType> -bool DwarfOp<AddressType>::Eval(uint64_t start, uint64_t end, uint8_t dwarf_version) { - uint32_t iterations = 0; +bool DwarfOp<AddressType>::Eval(uint64_t start, uint64_t end) { is_register_ = false; stack_.clear(); memory_->set_cur_offset(start); + dex_pc_set_ = false; + + // Unroll the first Decode calls to be able to check for a special + // sequence of ops and values that indicate this is the dex pc. + // The pattern is: + // OP_const4u (0x0c) 'D' 'E' 'X' '1' + // OP_drop (0x13) + if (memory_->cur_offset() < end) { + if (!Decode()) { + return false; + } + } else { + return true; + } + bool check_for_drop; + if (cur_op_ == 0x0c && operands_.back() == 0x31584544) { + check_for_drop = true; + } else { + check_for_drop = false; + } + if (memory_->cur_offset() < end) { + if (!Decode()) { + return false; + } + } else { + return true; + } + + if (check_for_drop && cur_op_ == 0x13) { + dex_pc_set_ = true; + } + + uint32_t iterations = 2; while (memory_->cur_offset() < end) { - if (!Decode(dwarf_version)) { + if (!Decode()) { return false; } // To protect against a branch that creates an infinite loop, @@ -56,7 +88,7 @@ bool DwarfOp<AddressType>::Eval(uint64_t start, uint64_t end, uint8_t dwarf_vers } template <typename AddressType> -bool DwarfOp<AddressType>::Decode(uint8_t dwarf_version) { +bool DwarfOp<AddressType>::Decode() { last_error_.code = DWARF_ERROR_NONE; if (!memory_->ReadBytes(&cur_op_, 1)) { last_error_.code = DWARF_ERROR_MEMORY_INVALID; @@ -71,12 +103,6 @@ bool DwarfOp<AddressType>::Decode(uint8_t dwarf_version) { return false; } - // Check for an unsupported opcode. - if (dwarf_version < op->supported_version) { - last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; - return false; - } - // Make sure that the required number of stack elements is available. if (stack_.size() < op->num_required_stack_values) { last_error_.code = DWARF_ERROR_STACK_INDEX_NOT_VALID; @@ -434,22 +460,22 @@ bool DwarfOp<AddressType>::op_regx() { template <typename AddressType> bool DwarfOp<AddressType>::op_breg() { uint16_t reg = cur_op() - 0x70; - if (reg >= regs_->total_regs()) { + if (reg >= regs_info_->Total()) { last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; return false; } - stack_.push_front((*regs_)[reg] + OperandAt(0)); + stack_.push_front(regs_info_->Get(reg) + OperandAt(0)); return true; } template <typename AddressType> bool DwarfOp<AddressType>::op_bregx() { AddressType reg = OperandAt(0); - if (reg >= regs_->total_regs()) { + if (reg >= regs_info_->Total()) { last_error_.code = DWARF_ERROR_ILLEGAL_VALUE; return false; } - stack_.push_front((*regs_)[reg] + OperandAt(1)); + stack_.push_front(regs_info_->Get(reg) + OperandAt(1)); return true; } |