summaryrefslogtreecommitdiffstats
path: root/libunwindstack/DwarfOp.cpp
diff options
context:
space:
mode:
authorChristopher Ferris <cferris@google.com>2018-02-12 20:18:03 -0800
committerChristopher Ferris <cferris@google.com>2018-02-13 16:45:38 -0800
commit559c7f209295a7070515bba9fa3985edf53d13a0 (patch)
tree3c4d389dd713cf1b388d58ecdf121e1c2c6989fd /libunwindstack/DwarfOp.cpp
parent71fa8125b90a99329561c2dd13c055adf52dd25a (diff)
downloadsystem_core-559c7f209295a7070515bba9fa3985edf53d13a0.tar.gz
system_core-559c7f209295a7070515bba9fa3985edf53d13a0.tar.bz2
system_core-559c7f209295a7070515bba9fa3985edf53d13a0.zip
Implement new DEX PC lookup scheme.
GDB wasn't handling the old one gracefully. - Create a RegsInfo structure that can be used to properly eval expression data. - Remove the versions on Dwarf ops. It doesn't work the in the real world and doesn't add useful information. - Fix dex pc frame number bug. Test: testrunner.py -j40 --host --cdex-fast -t 137 Test: libunwindstack_test Test: All unit tests pass. Change-Id: Iac4fea651b81cb6087fd237a9a5027a352a49245
Diffstat (limited to 'libunwindstack/DwarfOp.cpp')
-rw-r--r--libunwindstack/DwarfOp.cpp54
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;
}