summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libunwindstack/ArmExidx.cpp8
-rw-r--r--libunwindstack/ArmExidx.h2
-rw-r--r--libunwindstack/Check.h6
-rw-r--r--libunwindstack/DwarfCfa.cpp29
-rw-r--r--libunwindstack/DwarfCfa.h9
-rw-r--r--libunwindstack/DwarfEhFrameWithHdr.cpp28
-rw-r--r--libunwindstack/DwarfOp.cpp38
-rw-r--r--libunwindstack/DwarfOp.h9
-rw-r--r--libunwindstack/DwarfSection.cpp167
-rw-r--r--libunwindstack/Elf.cpp20
-rw-r--r--libunwindstack/ElfInterface.cpp98
-rw-r--r--libunwindstack/ElfInterfaceArm.cpp29
-rw-r--r--libunwindstack/Unwinder.cpp8
-rw-r--r--libunwindstack/include/unwindstack/DwarfError.h44
-rw-r--r--libunwindstack/include/unwindstack/DwarfSection.h7
-rw-r--r--libunwindstack/include/unwindstack/Elf.h4
-rw-r--r--libunwindstack/include/unwindstack/ElfInterface.h7
-rw-r--r--libunwindstack/include/unwindstack/Error.h42
-rw-r--r--libunwindstack/include/unwindstack/Unwinder.h5
-rw-r--r--libunwindstack/tests/ArmExidxExtractTest.cpp5
-rw-r--r--libunwindstack/tests/DwarfCfaTest.cpp14
-rw-r--r--libunwindstack/tests/DwarfDebugFrameTest.cpp15
-rw-r--r--libunwindstack/tests/DwarfEhFrameTest.cpp15
-rw-r--r--libunwindstack/tests/DwarfEhFrameWithHdrTest.cpp23
-rw-r--r--libunwindstack/tests/DwarfOpLogTest.cpp2
-rw-r--r--libunwindstack/tests/DwarfOpTest.cpp118
-rw-r--r--libunwindstack/tests/DwarfSectionImplTest.cpp45
-rw-r--r--libunwindstack/tests/ElfFake.h4
-rw-r--r--libunwindstack/tests/ElfInterfaceArmTest.cpp12
-rw-r--r--libunwindstack/tests/ElfTest.cpp26
-rw-r--r--libunwindstack/tests/UnwinderTest.cpp13
31 files changed, 630 insertions, 222 deletions
diff --git a/libunwindstack/ArmExidx.cpp b/libunwindstack/ArmExidx.cpp
index 6b0646fbc..65638aea3 100644
--- a/libunwindstack/ArmExidx.cpp
+++ b/libunwindstack/ArmExidx.cpp
@@ -57,6 +57,7 @@ bool ArmExidx::ExtractEntryData(uint32_t entry_offset) {
57 uint32_t data; 57 uint32_t data;
58 if (!elf_memory_->Read32(entry_offset + 4, &data)) { 58 if (!elf_memory_->Read32(entry_offset + 4, &data)) {
59 status_ = ARM_STATUS_READ_FAILED; 59 status_ = ARM_STATUS_READ_FAILED;
60 status_address_ = entry_offset + 4;
60 return false; 61 return false;
61 } 62 }
62 if (data == 1) { 63 if (data == 1) {
@@ -97,6 +98,7 @@ bool ArmExidx::ExtractEntryData(uint32_t entry_offset) {
97 uint32_t addr = (entry_offset + 4) + signed_data; 98 uint32_t addr = (entry_offset + 4) + signed_data;
98 if (!elf_memory_->Read32(addr, &data)) { 99 if (!elf_memory_->Read32(addr, &data)) {
99 status_ = ARM_STATUS_READ_FAILED; 100 status_ = ARM_STATUS_READ_FAILED;
101 status_address_ = addr;
100 return false; 102 return false;
101 } 103 }
102 104
@@ -128,6 +130,7 @@ bool ArmExidx::ExtractEntryData(uint32_t entry_offset) {
128 addr += 4; 130 addr += 4;
129 if (!elf_memory_->Read32(addr, &data)) { 131 if (!elf_memory_->Read32(addr, &data)) {
130 status_ = ARM_STATUS_READ_FAILED; 132 status_ = ARM_STATUS_READ_FAILED;
133 status_address_ = addr;
131 return false; 134 return false;
132 } 135 }
133 num_table_words = (data >> 24) & 0xff; 136 num_table_words = (data >> 24) & 0xff;
@@ -145,6 +148,7 @@ bool ArmExidx::ExtractEntryData(uint32_t entry_offset) {
145 for (size_t i = 0; i < num_table_words; i++) { 148 for (size_t i = 0; i < num_table_words; i++) {
146 if (!elf_memory_->Read32(addr, &data)) { 149 if (!elf_memory_->Read32(addr, &data)) {
147 status_ = ARM_STATUS_READ_FAILED; 150 status_ = ARM_STATUS_READ_FAILED;
151 status_address_ = addr;
148 return false; 152 return false;
149 } 153 }
150 data_.push_back((data >> 24) & 0xff); 154 data_.push_back((data >> 24) & 0xff);
@@ -216,6 +220,7 @@ inline bool ArmExidx::DecodePrefix_10_00(uint8_t byte) {
216 if (registers & (1 << reg)) { 220 if (registers & (1 << reg)) {
217 if (!process_memory_->Read32(cfa_, &(*regs_)[reg])) { 221 if (!process_memory_->Read32(cfa_, &(*regs_)[reg])) {
218 status_ = ARM_STATUS_READ_FAILED; 222 status_ = ARM_STATUS_READ_FAILED;
223 status_address_ = cfa_;
219 return false; 224 return false;
220 } 225 }
221 cfa_ += 4; 226 cfa_ += 4;
@@ -284,6 +289,7 @@ inline bool ArmExidx::DecodePrefix_10_10(uint8_t byte) {
284 for (size_t i = 4; i <= 4 + (byte & 0x7); i++) { 289 for (size_t i = 4; i <= 4 + (byte & 0x7); i++) {
285 if (!process_memory_->Read32(cfa_, &(*regs_)[i])) { 290 if (!process_memory_->Read32(cfa_, &(*regs_)[i])) {
286 status_ = ARM_STATUS_READ_FAILED; 291 status_ = ARM_STATUS_READ_FAILED;
292 status_address_ = cfa_;
287 return false; 293 return false;
288 } 294 }
289 cfa_ += 4; 295 cfa_ += 4;
@@ -291,6 +297,7 @@ inline bool ArmExidx::DecodePrefix_10_10(uint8_t byte) {
291 if (byte & 0x8) { 297 if (byte & 0x8) {
292 if (!process_memory_->Read32(cfa_, &(*regs_)[ARM_REG_R14])) { 298 if (!process_memory_->Read32(cfa_, &(*regs_)[ARM_REG_R14])) {
293 status_ = ARM_STATUS_READ_FAILED; 299 status_ = ARM_STATUS_READ_FAILED;
300 status_address_ = cfa_;
294 return false; 301 return false;
295 } 302 }
296 cfa_ += 4; 303 cfa_ += 4;
@@ -357,6 +364,7 @@ inline bool ArmExidx::DecodePrefix_10_11_0001() {
357 if (byte & (1 << reg)) { 364 if (byte & (1 << reg)) {
358 if (!process_memory_->Read32(cfa_, &(*regs_)[reg])) { 365 if (!process_memory_->Read32(cfa_, &(*regs_)[reg])) {
359 status_ = ARM_STATUS_READ_FAILED; 366 status_ = ARM_STATUS_READ_FAILED;
367 status_address_ = cfa_;
360 return false; 368 return false;
361 } 369 }
362 cfa_ += 4; 370 cfa_ += 4;
diff --git a/libunwindstack/ArmExidx.h b/libunwindstack/ArmExidx.h
index f4361d43c..96756a017 100644
--- a/libunwindstack/ArmExidx.h
+++ b/libunwindstack/ArmExidx.h
@@ -61,6 +61,7 @@ class ArmExidx {
61 std::deque<uint8_t>* data() { return &data_; } 61 std::deque<uint8_t>* data() { return &data_; }
62 62
63 ArmStatus status() { return status_; } 63 ArmStatus status() { return status_; }
64 uint64_t status_address() { return status_address_; }
64 65
65 RegsArm* regs() { return regs_; } 66 RegsArm* regs() { return regs_; }
66 67
@@ -97,6 +98,7 @@ class ArmExidx {
97 uint32_t cfa_ = 0; 98 uint32_t cfa_ = 0;
98 std::deque<uint8_t> data_; 99 std::deque<uint8_t> data_;
99 ArmStatus status_ = ARM_STATUS_NONE; 100 ArmStatus status_ = ARM_STATUS_NONE;
101 uint64_t status_address_ = 0;
100 102
101 Memory* elf_memory_; 103 Memory* elf_memory_;
102 Memory* process_memory_; 104 Memory* process_memory_;
diff --git a/libunwindstack/Check.h b/libunwindstack/Check.h
index 2d216d78c..9643d7670 100644
--- a/libunwindstack/Check.h
+++ b/libunwindstack/Check.h
@@ -14,8 +14,8 @@
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 16
17#ifndef _LIBUNWINDSTACK_ERROR_H 17#ifndef _LIBUNWINDSTACK_CHECK_H
18#define _LIBUNWINDSTACK_ERROR_H 18#define _LIBUNWINDSTACK_CHECK_H
19 19
20#include <stdlib.h> 20#include <stdlib.h>
21 21
@@ -31,4 +31,4 @@ namespace unwindstack {
31 31
32} // namespace unwindstack 32} // namespace unwindstack
33 33
34#endif // _LIBUNWINDSTACK_ERROR_H 34#endif // _LIBUNWINDSTACK_CHECK_H
diff --git a/libunwindstack/DwarfCfa.cpp b/libunwindstack/DwarfCfa.cpp
index b1d55bae4..4fc95c766 100644
--- a/libunwindstack/DwarfCfa.cpp
+++ b/libunwindstack/DwarfCfa.cpp
@@ -23,12 +23,12 @@
23 23
24#include <android-base/stringprintf.h> 24#include <android-base/stringprintf.h>
25 25
26#include <unwindstack/DwarfError.h>
26#include <unwindstack/DwarfLocation.h> 27#include <unwindstack/DwarfLocation.h>
27#include <unwindstack/Log.h> 28#include <unwindstack/Log.h>
28 29
29#include "DwarfCfa.h" 30#include "DwarfCfa.h"
30#include "DwarfEncoding.h" 31#include "DwarfEncoding.h"
31#include "DwarfError.h"
32#include "DwarfOp.h" 32#include "DwarfOp.h"
33 33
34namespace unwindstack { 34namespace unwindstack {
@@ -44,7 +44,8 @@ bool DwarfCfa<AddressType>::GetLocationInfo(uint64_t pc, uint64_t start_offset,
44 (*loc_regs)[entry.first] = entry.second; 44 (*loc_regs)[entry.first] = entry.second;
45 } 45 }
46 } 46 }
47 last_error_ = DWARF_ERROR_NONE; 47 last_error_.code = DWARF_ERROR_NONE;
48 last_error_.address = 0;
48 49
49 memory_->set_cur_offset(start_offset); 50 memory_->set_cur_offset(start_offset);
50 uint64_t cfa_offset; 51 uint64_t cfa_offset;
@@ -54,7 +55,8 @@ bool DwarfCfa<AddressType>::GetLocationInfo(uint64_t pc, uint64_t start_offset,
54 // Read the cfa information. 55 // Read the cfa information.
55 uint8_t cfa_value; 56 uint8_t cfa_value;
56 if (!memory_->ReadBytes(&cfa_value, 1)) { 57 if (!memory_->ReadBytes(&cfa_value, 1)) {
57 last_error_ = DWARF_ERROR_MEMORY_INVALID; 58 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
59 last_error_.address = memory_->cur_offset();
58 return false; 60 return false;
59 } 61 }
60 uint8_t cfa_low = cfa_value & 0x3f; 62 uint8_t cfa_low = cfa_value & 0x3f;
@@ -66,7 +68,8 @@ bool DwarfCfa<AddressType>::GetLocationInfo(uint64_t pc, uint64_t start_offset,
66 case 2: { 68 case 2: {
67 uint64_t offset; 69 uint64_t offset;
68 if (!memory_->ReadULEB128(&offset)) { 70 if (!memory_->ReadULEB128(&offset)) {
69 last_error_ = DWARF_ERROR_MEMORY_INVALID; 71 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
72 last_error_.address = memory_->cur_offset();
70 return false; 73 return false;
71 } 74 }
72 SignedType signed_offset = 75 SignedType signed_offset =
@@ -78,7 +81,7 @@ bool DwarfCfa<AddressType>::GetLocationInfo(uint64_t pc, uint64_t start_offset,
78 case 3: { 81 case 3: {
79 if (cie_loc_regs_ == nullptr) { 82 if (cie_loc_regs_ == nullptr) {
80 log(0, "restore while processing cie"); 83 log(0, "restore while processing cie");
81 last_error_ = DWARF_ERROR_ILLEGAL_STATE; 84 last_error_.code = DWARF_ERROR_ILLEGAL_STATE;
82 return false; 85 return false;
83 } 86 }
84 87
@@ -93,7 +96,7 @@ bool DwarfCfa<AddressType>::GetLocationInfo(uint64_t pc, uint64_t start_offset,
93 case 0: { 96 case 0: {
94 const auto handle_func = DwarfCfa<AddressType>::kCallbackTable[cfa_low]; 97 const auto handle_func = DwarfCfa<AddressType>::kCallbackTable[cfa_low];
95 if (handle_func == nullptr) { 98 if (handle_func == nullptr) {
96 last_error_ = DWARF_ERROR_ILLEGAL_VALUE; 99 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
97 return false; 100 return false;
98 } 101 }
99 102
@@ -102,7 +105,8 @@ bool DwarfCfa<AddressType>::GetLocationInfo(uint64_t pc, uint64_t start_offset,
102 if (cfa->operands[i] == DW_EH_PE_block) { 105 if (cfa->operands[i] == DW_EH_PE_block) {
103 uint64_t block_length; 106 uint64_t block_length;
104 if (!memory_->ReadULEB128(&block_length)) { 107 if (!memory_->ReadULEB128(&block_length)) {
105 last_error_ = DWARF_ERROR_MEMORY_INVALID; 108 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
109 last_error_.address = memory_->cur_offset();
106 return false; 110 return false;
107 } 111 }
108 operands_.push_back(block_length); 112 operands_.push_back(block_length);
@@ -111,7 +115,8 @@ bool DwarfCfa<AddressType>::GetLocationInfo(uint64_t pc, uint64_t start_offset,
111 } 115 }
112 uint64_t value; 116 uint64_t value;
113 if (!memory_->ReadEncodedValue<AddressType>(cfa->operands[i], &value)) { 117 if (!memory_->ReadEncodedValue<AddressType>(cfa->operands[i], &value)) {
114 last_error_ = DWARF_ERROR_MEMORY_INVALID; 118 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
119 last_error_.address = memory_->cur_offset();
115 return false; 120 return false;
116 } 121 }
117 operands_.push_back(value); 122 operands_.push_back(value);
@@ -334,7 +339,7 @@ bool DwarfCfa<AddressType>::cfa_restore(dwarf_loc_regs_t* loc_regs) {
334 AddressType reg = operands_[0]; 339 AddressType reg = operands_[0];
335 if (cie_loc_regs_ == nullptr) { 340 if (cie_loc_regs_ == nullptr) {
336 log(0, "restore while processing cie"); 341 log(0, "restore while processing cie");
337 last_error_ = DWARF_ERROR_ILLEGAL_STATE; 342 last_error_.code = DWARF_ERROR_ILLEGAL_STATE;
338 return false; 343 return false;
339 } 344 }
340 auto reg_entry = cie_loc_regs_->find(reg); 345 auto reg_entry = cie_loc_regs_->find(reg);
@@ -396,7 +401,7 @@ bool DwarfCfa<AddressType>::cfa_def_cfa_register(dwarf_loc_regs_t* loc_regs) {
396 auto cfa_location = loc_regs->find(CFA_REG); 401 auto cfa_location = loc_regs->find(CFA_REG);
397 if (cfa_location == loc_regs->end() || cfa_location->second.type != DWARF_LOCATION_REGISTER) { 402 if (cfa_location == loc_regs->end() || cfa_location->second.type != DWARF_LOCATION_REGISTER) {
398 log(0, "Attempt to set new register, but cfa is not already set to a register."); 403 log(0, "Attempt to set new register, but cfa is not already set to a register.");
399 last_error_ = DWARF_ERROR_ILLEGAL_STATE; 404 last_error_.code = DWARF_ERROR_ILLEGAL_STATE;
400 return false; 405 return false;
401 } 406 }
402 407
@@ -410,7 +415,7 @@ bool DwarfCfa<AddressType>::cfa_def_cfa_offset(dwarf_loc_regs_t* loc_regs) {
410 auto cfa_location = loc_regs->find(CFA_REG); 415 auto cfa_location = loc_regs->find(CFA_REG);
411 if (cfa_location == loc_regs->end() || cfa_location->second.type != DWARF_LOCATION_REGISTER) { 416 if (cfa_location == loc_regs->end() || cfa_location->second.type != DWARF_LOCATION_REGISTER) {
412 log(0, "Attempt to set offset, but cfa is not set to a register."); 417 log(0, "Attempt to set offset, but cfa is not set to a register.");
413 last_error_ = DWARF_ERROR_ILLEGAL_STATE; 418 last_error_.code = DWARF_ERROR_ILLEGAL_STATE;
414 return false; 419 return false;
415 } 420 }
416 cfa_location->second.values[1] = operands_[0]; 421 cfa_location->second.values[1] = operands_[0];
@@ -454,7 +459,7 @@ bool DwarfCfa<AddressType>::cfa_def_cfa_offset_sf(dwarf_loc_regs_t* loc_regs) {
454 auto cfa_location = loc_regs->find(CFA_REG); 459 auto cfa_location = loc_regs->find(CFA_REG);
455 if (cfa_location == loc_regs->end() || cfa_location->second.type != DWARF_LOCATION_REGISTER) { 460 if (cfa_location == loc_regs->end() || cfa_location->second.type != DWARF_LOCATION_REGISTER) {
456 log(0, "Attempt to set offset, but cfa is not set to a register."); 461 log(0, "Attempt to set offset, but cfa is not set to a register.");
457 last_error_ = DWARF_ERROR_ILLEGAL_STATE; 462 last_error_.code = DWARF_ERROR_ILLEGAL_STATE;
458 return false; 463 return false;
459 } 464 }
460 SignedType offset = static_cast<SignedType>(operands_[0]) * fde_->cie->data_alignment_factor; 465 SignedType offset = static_cast<SignedType>(operands_[0]) * fde_->cie->data_alignment_factor;
diff --git a/libunwindstack/DwarfCfa.h b/libunwindstack/DwarfCfa.h
index 62b9b7ac0..16c66e296 100644
--- a/libunwindstack/DwarfCfa.h
+++ b/libunwindstack/DwarfCfa.h
@@ -24,12 +24,11 @@
24#include <type_traits> 24#include <type_traits>
25#include <vector> 25#include <vector>
26 26
27#include <unwindstack/DwarfError.h>
27#include <unwindstack/DwarfLocation.h> 28#include <unwindstack/DwarfLocation.h>
28#include <unwindstack/DwarfMemory.h> 29#include <unwindstack/DwarfMemory.h>
29#include <unwindstack/DwarfStructs.h> 30#include <unwindstack/DwarfStructs.h>
30 31
31#include "DwarfError.h"
32
33namespace unwindstack { 32namespace unwindstack {
34 33
35// DWARF Standard home: http://dwarfstd.org/ 34// DWARF Standard home: http://dwarfstd.org/
@@ -75,7 +74,9 @@ class DwarfCfa {
75 bool Log(uint32_t indent, uint64_t pc, uint64_t load_bias, uint64_t start_offset, 74 bool Log(uint32_t indent, uint64_t pc, uint64_t load_bias, uint64_t start_offset,
76 uint64_t end_offset); 75 uint64_t end_offset);
77 76
78 DwarfError last_error() { return last_error_; } 77 const DwarfErrorData& last_error() { return last_error_; }
78 DwarfErrorCode LastErrorCode() { return last_error_.code; }
79 uint64_t LastErrorAddress() { return last_error_.address; }
79 80
80 AddressType cur_pc() { return cur_pc_; } 81 AddressType cur_pc() { return cur_pc_; }
81 82
@@ -89,7 +90,7 @@ class DwarfCfa {
89 bool LogInstruction(uint32_t indent, uint64_t cfa_offset, uint8_t op, uint64_t* cur_pc); 90 bool LogInstruction(uint32_t indent, uint64_t cfa_offset, uint8_t op, uint64_t* cur_pc);
90 91
91 private: 92 private:
92 DwarfError last_error_; 93 DwarfErrorData last_error_;
93 DwarfMemory* memory_; 94 DwarfMemory* memory_;
94 const DwarfFde* fde_; 95 const DwarfFde* fde_;
95 96
diff --git a/libunwindstack/DwarfEhFrameWithHdr.cpp b/libunwindstack/DwarfEhFrameWithHdr.cpp
index e0f1eedf2..a131abea2 100644
--- a/libunwindstack/DwarfEhFrameWithHdr.cpp
+++ b/libunwindstack/DwarfEhFrameWithHdr.cpp
@@ -16,12 +16,12 @@
16 16
17#include <stdint.h> 17#include <stdint.h>
18 18
19#include <unwindstack/DwarfError.h>
19#include <unwindstack/DwarfStructs.h> 20#include <unwindstack/DwarfStructs.h>
20#include <unwindstack/Memory.h> 21#include <unwindstack/Memory.h>
21 22
22#include "Check.h" 23#include "Check.h"
23#include "DwarfEhFrameWithHdr.h" 24#include "DwarfEhFrameWithHdr.h"
24#include "DwarfError.h"
25 25
26namespace unwindstack { 26namespace unwindstack {
27 27
@@ -36,14 +36,15 @@ bool DwarfEhFrameWithHdr<AddressType>::Init(uint64_t offset, uint64_t size) {
36 36
37 // Read the first four bytes all at once. 37 // Read the first four bytes all at once.
38 if (!memory_.ReadBytes(data, 4)) { 38 if (!memory_.ReadBytes(data, 4)) {
39 last_error_ = DWARF_ERROR_MEMORY_INVALID; 39 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
40 last_error_.address = memory_.cur_offset();
40 return false; 41 return false;
41 } 42 }
42 43
43 version_ = data[0]; 44 version_ = data[0];
44 if (version_ != 1) { 45 if (version_ != 1) {
45 // Unknown version. 46 // Unknown version.
46 last_error_ = DWARF_ERROR_UNSUPPORTED_VERSION; 47 last_error_.code = DWARF_ERROR_UNSUPPORTED_VERSION;
47 return false; 48 return false;
48 } 49 }
49 50
@@ -54,18 +55,20 @@ bool DwarfEhFrameWithHdr<AddressType>::Init(uint64_t offset, uint64_t size) {
54 55
55 memory_.set_pc_offset(memory_.cur_offset()); 56 memory_.set_pc_offset(memory_.cur_offset());
56 if (!memory_.template ReadEncodedValue<AddressType>(ptr_encoding_, &ptr_offset_)) { 57 if (!memory_.template ReadEncodedValue<AddressType>(ptr_encoding_, &ptr_offset_)) {
57 last_error_ = DWARF_ERROR_MEMORY_INVALID; 58 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
59 last_error_.address = memory_.cur_offset();
58 return false; 60 return false;
59 } 61 }
60 62
61 memory_.set_pc_offset(memory_.cur_offset()); 63 memory_.set_pc_offset(memory_.cur_offset());
62 if (!memory_.template ReadEncodedValue<AddressType>(fde_count_encoding, &fde_count_)) { 64 if (!memory_.template ReadEncodedValue<AddressType>(fde_count_encoding, &fde_count_)) {
63 last_error_ = DWARF_ERROR_MEMORY_INVALID; 65 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
66 last_error_.address = memory_.cur_offset();
64 return false; 67 return false;
65 } 68 }
66 69
67 if (fde_count_ == 0) { 70 if (fde_count_ == 0) {
68 last_error_ = DWARF_ERROR_NO_FDES; 71 last_error_.code = DWARF_ERROR_NO_FDES;
69 return false; 72 return false;
70 } 73 }
71 74
@@ -101,7 +104,8 @@ DwarfEhFrameWithHdr<AddressType>::GetFdeInfoFromIndex(size_t index) {
101 uint64_t value; 104 uint64_t value;
102 if (!memory_.template ReadEncodedValue<AddressType>(table_encoding_, &value) || 105 if (!memory_.template ReadEncodedValue<AddressType>(table_encoding_, &value) ||
103 !memory_.template ReadEncodedValue<AddressType>(table_encoding_, &info->offset)) { 106 !memory_.template ReadEncodedValue<AddressType>(table_encoding_, &info->offset)) {
104 last_error_ = DWARF_ERROR_MEMORY_INVALID; 107 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
108 last_error_.address = memory_.cur_offset();
105 fde_info_.erase(index); 109 fde_info_.erase(index);
106 return nullptr; 110 return nullptr;
107 } 111 }
@@ -147,7 +151,9 @@ bool DwarfEhFrameWithHdr<AddressType>::GetFdeOffsetBinary(uint64_t pc, uint64_t*
147template <typename AddressType> 151template <typename AddressType>
148bool DwarfEhFrameWithHdr<AddressType>::GetFdeOffsetSequential(uint64_t pc, uint64_t* fde_offset) { 152bool DwarfEhFrameWithHdr<AddressType>::GetFdeOffsetSequential(uint64_t pc, uint64_t* fde_offset) {
149 CHECK(fde_count_ != 0); 153 CHECK(fde_count_ != 0);
150 last_error_ = DWARF_ERROR_NONE; 154 last_error_.code = DWARF_ERROR_NONE;
155 last_error_.address = 0;
156
151 // We can do a binary search if the pc is in the range of the elements 157 // We can do a binary search if the pc is in the range of the elements
152 // that have already been cached. 158 // that have already been cached.
153 if (!fde_info_.empty()) { 159 if (!fde_info_.empty()) {
@@ -176,14 +182,16 @@ bool DwarfEhFrameWithHdr<AddressType>::GetFdeOffsetSequential(uint64_t pc, uint6
176 memory_.set_pc_offset(memory_.cur_offset()); 182 memory_.set_pc_offset(memory_.cur_offset());
177 uint64_t value; 183 uint64_t value;
178 if (!memory_.template ReadEncodedValue<AddressType>(table_encoding_, &value)) { 184 if (!memory_.template ReadEncodedValue<AddressType>(table_encoding_, &value)) {
179 last_error_ = DWARF_ERROR_MEMORY_INVALID; 185 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
186 last_error_.address = memory_.cur_offset();
180 return false; 187 return false;
181 } 188 }
182 189
183 FdeInfo* info = &fde_info_[current]; 190 FdeInfo* info = &fde_info_[current];
184 if (!memory_.template ReadEncodedValue<AddressType>(table_encoding_, &info->offset)) { 191 if (!memory_.template ReadEncodedValue<AddressType>(table_encoding_, &info->offset)) {
185 fde_info_.erase(current); 192 fde_info_.erase(current);
186 last_error_ = DWARF_ERROR_MEMORY_INVALID; 193 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
194 last_error_.address = memory_.cur_offset();
187 return false; 195 return false;
188 } 196 }
189 info->pc = value + 4; 197 info->pc = value + 4;
diff --git a/libunwindstack/DwarfOp.cpp b/libunwindstack/DwarfOp.cpp
index 3b3d340f4..dcf04e6ff 100644
--- a/libunwindstack/DwarfOp.cpp
+++ b/libunwindstack/DwarfOp.cpp
@@ -22,12 +22,12 @@
22 22
23#include <android-base/stringprintf.h> 23#include <android-base/stringprintf.h>
24 24
25#include <unwindstack/DwarfError.h>
25#include <unwindstack/DwarfMemory.h> 26#include <unwindstack/DwarfMemory.h>
26#include <unwindstack/Log.h> 27#include <unwindstack/Log.h>
27#include <unwindstack/Memory.h> 28#include <unwindstack/Memory.h>
28#include <unwindstack/Regs.h> 29#include <unwindstack/Regs.h>
29 30
30#include "DwarfError.h"
31#include "DwarfOp.h" 31#include "DwarfOp.h"
32 32
33namespace unwindstack { 33namespace unwindstack {
@@ -48,7 +48,7 @@ bool DwarfOp<AddressType>::Eval(uint64_t start, uint64_t end, uint8_t dwarf_vers
48 // To protect against a branch that creates an infinite loop, 48 // To protect against a branch that creates an infinite loop,
49 // terminate if the number of iterations gets too high. 49 // terminate if the number of iterations gets too high.
50 if (iterations++ == 1000) { 50 if (iterations++ == 1000) {
51 last_error_ = DWARF_ERROR_TOO_MANY_ITERATIONS; 51 last_error_.code = DWARF_ERROR_TOO_MANY_ITERATIONS;
52 return false; 52 return false;
53 } 53 }
54 } 54 }
@@ -57,28 +57,29 @@ bool DwarfOp<AddressType>::Eval(uint64_t start, uint64_t end, uint8_t dwarf_vers
57 57
58template <typename AddressType> 58template <typename AddressType>
59bool DwarfOp<AddressType>::Decode(uint8_t dwarf_version) { 59bool DwarfOp<AddressType>::Decode(uint8_t dwarf_version) {
60 last_error_ = DWARF_ERROR_NONE; 60 last_error_.code = DWARF_ERROR_NONE;
61 if (!memory_->ReadBytes(&cur_op_, 1)) { 61 if (!memory_->ReadBytes(&cur_op_, 1)) {
62 last_error_ = DWARF_ERROR_MEMORY_INVALID; 62 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
63 last_error_.address = memory_->cur_offset();
63 return false; 64 return false;
64 } 65 }
65 66
66 const auto* op = &kCallbackTable[cur_op_]; 67 const auto* op = &kCallbackTable[cur_op_];
67 const auto handle_func = op->handle_func; 68 const auto handle_func = op->handle_func;
68 if (handle_func == nullptr) { 69 if (handle_func == nullptr) {
69 last_error_ = DWARF_ERROR_ILLEGAL_VALUE; 70 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
70 return false; 71 return false;
71 } 72 }
72 73
73 // Check for an unsupported opcode. 74 // Check for an unsupported opcode.
74 if (dwarf_version < op->supported_version) { 75 if (dwarf_version < op->supported_version) {
75 last_error_ = DWARF_ERROR_ILLEGAL_VALUE; 76 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
76 return false; 77 return false;
77 } 78 }
78 79
79 // Make sure that the required number of stack elements is available. 80 // Make sure that the required number of stack elements is available.
80 if (stack_.size() < op->num_required_stack_values) { 81 if (stack_.size() < op->num_required_stack_values) {
81 last_error_ = DWARF_ERROR_STACK_INDEX_NOT_VALID; 82 last_error_.code = DWARF_ERROR_STACK_INDEX_NOT_VALID;
82 return false; 83 return false;
83 } 84 }
84 85
@@ -86,7 +87,8 @@ bool DwarfOp<AddressType>::Decode(uint8_t dwarf_version) {
86 for (size_t i = 0; i < op->num_operands; i++) { 87 for (size_t i = 0; i < op->num_operands; i++) {
87 uint64_t value; 88 uint64_t value;
88 if (!memory_->ReadEncodedValue<AddressType>(op->operands[i], &value)) { 89 if (!memory_->ReadEncodedValue<AddressType>(op->operands[i], &value)) {
89 last_error_ = DWARF_ERROR_MEMORY_INVALID; 90 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
91 last_error_.address = memory_->cur_offset();
90 return false; 92 return false;
91 } 93 }
92 operands_.push_back(value); 94 operands_.push_back(value);
@@ -142,7 +144,8 @@ bool DwarfOp<AddressType>::op_deref() {
142 AddressType addr = StackPop(); 144 AddressType addr = StackPop();
143 AddressType value; 145 AddressType value;
144 if (!regular_memory()->ReadFully(addr, &value, sizeof(value))) { 146 if (!regular_memory()->ReadFully(addr, &value, sizeof(value))) {
145 last_error_ = DWARF_ERROR_MEMORY_INVALID; 147 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
148 last_error_.address = addr;
146 return false; 149 return false;
147 } 150 }
148 stack_.push_front(value); 151 stack_.push_front(value);
@@ -153,14 +156,15 @@ template <typename AddressType>
153bool DwarfOp<AddressType>::op_deref_size() { 156bool DwarfOp<AddressType>::op_deref_size() {
154 AddressType bytes_to_read = OperandAt(0); 157 AddressType bytes_to_read = OperandAt(0);
155 if (bytes_to_read > sizeof(AddressType) || bytes_to_read == 0) { 158 if (bytes_to_read > sizeof(AddressType) || bytes_to_read == 0) {
156 last_error_ = DWARF_ERROR_ILLEGAL_VALUE; 159 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
157 return false; 160 return false;
158 } 161 }
159 // Read the address and dereference it. 162 // Read the address and dereference it.
160 AddressType addr = StackPop(); 163 AddressType addr = StackPop();
161 AddressType value = 0; 164 AddressType value = 0;
162 if (!regular_memory()->ReadFully(addr, &value, bytes_to_read)) { 165 if (!regular_memory()->ReadFully(addr, &value, bytes_to_read)) {
163 last_error_ = DWARF_ERROR_MEMORY_INVALID; 166 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
167 last_error_.address = addr;
164 return false; 168 return false;
165 } 169 }
166 stack_.push_front(value); 170 stack_.push_front(value);
@@ -198,7 +202,7 @@ template <typename AddressType>
198bool DwarfOp<AddressType>::op_pick() { 202bool DwarfOp<AddressType>::op_pick() {
199 AddressType index = OperandAt(0); 203 AddressType index = OperandAt(0);
200 if (index > StackSize()) { 204 if (index > StackSize()) {
201 last_error_ = DWARF_ERROR_STACK_INDEX_NOT_VALID; 205 last_error_.code = DWARF_ERROR_STACK_INDEX_NOT_VALID;
202 return false; 206 return false;
203 } 207 }
204 stack_.push_front(StackAt(index)); 208 stack_.push_front(StackAt(index));
@@ -243,7 +247,7 @@ template <typename AddressType>
243bool DwarfOp<AddressType>::op_div() { 247bool DwarfOp<AddressType>::op_div() {
244 AddressType top = StackPop(); 248 AddressType top = StackPop();
245 if (top == 0) { 249 if (top == 0) {
246 last_error_ = DWARF_ERROR_ILLEGAL_VALUE; 250 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
247 return false; 251 return false;
248 } 252 }
249 SignedType signed_divisor = static_cast<SignedType>(top); 253 SignedType signed_divisor = static_cast<SignedType>(top);
@@ -263,7 +267,7 @@ template <typename AddressType>
263bool DwarfOp<AddressType>::op_mod() { 267bool DwarfOp<AddressType>::op_mod() {
264 AddressType top = StackPop(); 268 AddressType top = StackPop();
265 if (top == 0) { 269 if (top == 0) {
266 last_error_ = DWARF_ERROR_ILLEGAL_VALUE; 270 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
267 return false; 271 return false;
268 } 272 }
269 stack_[0] %= top; 273 stack_[0] %= top;
@@ -431,7 +435,7 @@ template <typename AddressType>
431bool DwarfOp<AddressType>::op_breg() { 435bool DwarfOp<AddressType>::op_breg() {
432 uint16_t reg = cur_op() - 0x70; 436 uint16_t reg = cur_op() - 0x70;
433 if (reg >= regs_->total_regs()) { 437 if (reg >= regs_->total_regs()) {
434 last_error_ = DWARF_ERROR_ILLEGAL_VALUE; 438 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
435 return false; 439 return false;
436 } 440 }
437 stack_.push_front((*regs_)[reg] + OperandAt(0)); 441 stack_.push_front((*regs_)[reg] + OperandAt(0));
@@ -442,7 +446,7 @@ template <typename AddressType>
442bool DwarfOp<AddressType>::op_bregx() { 446bool DwarfOp<AddressType>::op_bregx() {
443 AddressType reg = OperandAt(0); 447 AddressType reg = OperandAt(0);
444 if (reg >= regs_->total_regs()) { 448 if (reg >= regs_->total_regs()) {
445 last_error_ = DWARF_ERROR_ILLEGAL_VALUE; 449 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
446 return false; 450 return false;
447 } 451 }
448 stack_.push_front((*regs_)[reg] + OperandAt(1)); 452 stack_.push_front((*regs_)[reg] + OperandAt(1));
@@ -456,7 +460,7 @@ bool DwarfOp<AddressType>::op_nop() {
456 460
457template <typename AddressType> 461template <typename AddressType>
458bool DwarfOp<AddressType>::op_not_implemented() { 462bool DwarfOp<AddressType>::op_not_implemented() {
459 last_error_ = DWARF_ERROR_NOT_IMPLEMENTED; 463 last_error_.code = DWARF_ERROR_NOT_IMPLEMENTED;
460 return false; 464 return false;
461} 465}
462 466
diff --git a/libunwindstack/DwarfOp.h b/libunwindstack/DwarfOp.h
index c29bf35df..40b7b23b7 100644
--- a/libunwindstack/DwarfOp.h
+++ b/libunwindstack/DwarfOp.h
@@ -24,8 +24,9 @@
24#include <type_traits> 24#include <type_traits>
25#include <vector> 25#include <vector>
26 26
27#include <unwindstack/DwarfError.h>
28
27#include "DwarfEncoding.h" 29#include "DwarfEncoding.h"
28#include "DwarfError.h"
29 30
30namespace unwindstack { 31namespace unwindstack {
31 32
@@ -72,7 +73,9 @@ class DwarfOp {
72 73
73 void set_regs(RegsImpl<AddressType>* regs) { regs_ = regs; } 74 void set_regs(RegsImpl<AddressType>* regs) { regs_ = regs; }
74 75
75 DwarfError last_error() { return last_error_; } 76 const DwarfErrorData& last_error() { return last_error_; }
77 DwarfErrorCode LastErrorCode() { return last_error_.code; }
78 uint64_t LastErrorAddress() { return last_error_.address; }
76 79
77 bool is_register() { return is_register_; } 80 bool is_register() { return is_register_; }
78 81
@@ -96,7 +99,7 @@ class DwarfOp {
96 99
97 RegsImpl<AddressType>* regs_; 100 RegsImpl<AddressType>* regs_;
98 bool is_register_ = false; 101 bool is_register_ = false;
99 DwarfError last_error_ = DWARF_ERROR_NONE; 102 DwarfErrorData last_error_{DWARF_ERROR_NONE, 0};
100 uint8_t cur_op_; 103 uint8_t cur_op_;
101 std::vector<AddressType> operands_; 104 std::vector<AddressType> operands_;
102 std::deque<AddressType> stack_; 105 std::deque<AddressType> stack_;
diff --git a/libunwindstack/DwarfSection.cpp b/libunwindstack/DwarfSection.cpp
index 04a1faefa..4e94f887d 100644
--- a/libunwindstack/DwarfSection.cpp
+++ b/libunwindstack/DwarfSection.cpp
@@ -16,6 +16,7 @@
16 16
17#include <stdint.h> 17#include <stdint.h>
18 18
19#include <unwindstack/DwarfError.h>
19#include <unwindstack/DwarfLocation.h> 20#include <unwindstack/DwarfLocation.h>
20#include <unwindstack/DwarfMemory.h> 21#include <unwindstack/DwarfMemory.h>
21#include <unwindstack/DwarfSection.h> 22#include <unwindstack/DwarfSection.h>
@@ -26,7 +27,6 @@
26 27
27#include "DwarfCfa.h" 28#include "DwarfCfa.h"
28#include "DwarfEncoding.h" 29#include "DwarfEncoding.h"
29#include "DwarfError.h"
30#include "DwarfOp.h" 30#include "DwarfOp.h"
31 31
32#include "DwarfDebugFrame.h" 32#include "DwarfDebugFrame.h"
@@ -36,7 +36,7 @@ namespace unwindstack {
36 36
37constexpr uint64_t DEX_PC_REG = 0x20444558; 37constexpr uint64_t DEX_PC_REG = 0x20444558;
38 38
39DwarfSection::DwarfSection(Memory* memory) : memory_(memory), last_error_(DWARF_ERROR_NONE) {} 39DwarfSection::DwarfSection(Memory* memory) : memory_(memory) {}
40 40
41const DwarfFde* DwarfSection::GetFdeFromPc(uint64_t pc) { 41const DwarfFde* DwarfSection::GetFdeFromPc(uint64_t pc) {
42 uint64_t fde_offset; 42 uint64_t fde_offset;
@@ -52,15 +52,15 @@ const DwarfFde* DwarfSection::GetFdeFromPc(uint64_t pc) {
52 if (pc < fde->pc_end) { 52 if (pc < fde->pc_end) {
53 return fde; 53 return fde;
54 } 54 }
55 last_error_ = DWARF_ERROR_ILLEGAL_STATE; 55 last_error_.code = DWARF_ERROR_ILLEGAL_STATE;
56 return nullptr; 56 return nullptr;
57} 57}
58 58
59bool DwarfSection::Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished) { 59bool DwarfSection::Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished) {
60 last_error_ = DWARF_ERROR_NONE; 60 last_error_.code = DWARF_ERROR_NONE;
61 const DwarfFde* fde = GetFdeFromPc(pc); 61 const DwarfFde* fde = GetFdeFromPc(pc);
62 if (fde == nullptr || fde->cie == nullptr) { 62 if (fde == nullptr || fde->cie == nullptr) {
63 last_error_ = DWARF_ERROR_ILLEGAL_STATE; 63 last_error_.code = DWARF_ERROR_ILLEGAL_STATE;
64 return false; 64 return false;
65 } 65 }
66 66
@@ -87,12 +87,12 @@ bool DwarfSectionImpl<AddressType>::EvalExpression(const DwarfLocation& loc, uin
87 return false; 87 return false;
88 } 88 }
89 if (op.StackSize() == 0) { 89 if (op.StackSize() == 0) {
90 last_error_ = DWARF_ERROR_ILLEGAL_STATE; 90 last_error_.code = DWARF_ERROR_ILLEGAL_STATE;
91 return false; 91 return false;
92 } 92 }
93 // We don't support an expression that evaluates to a register number. 93 // We don't support an expression that evaluates to a register number.
94 if (op.is_register()) { 94 if (op.is_register()) {
95 last_error_ = DWARF_ERROR_NOT_IMPLEMENTED; 95 last_error_.code = DWARF_ERROR_NOT_IMPLEMENTED;
96 return false; 96 return false;
97 } 97 }
98 *value = op.StackAt(0); 98 *value = op.StackAt(0);
@@ -119,7 +119,8 @@ bool DwarfSectionImpl<AddressType>::EvalRegister(const DwarfLocation* loc, uint3
119 switch (loc->type) { 119 switch (loc->type) {
120 case DWARF_LOCATION_OFFSET: 120 case DWARF_LOCATION_OFFSET:
121 if (!regular_memory->ReadFully(eval_info->cfa + loc->values[0], reg_ptr, sizeof(AddressType))) { 121 if (!regular_memory->ReadFully(eval_info->cfa + loc->values[0], reg_ptr, sizeof(AddressType))) {
122 last_error_ = DWARF_ERROR_MEMORY_INVALID; 122 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
123 last_error_.address = eval_info->cfa + loc->values[0];
123 return false; 124 return false;
124 } 125 }
125 break; 126 break;
@@ -129,7 +130,7 @@ bool DwarfSectionImpl<AddressType>::EvalRegister(const DwarfLocation* loc, uint3
129 case DWARF_LOCATION_REGISTER: { 130 case DWARF_LOCATION_REGISTER: {
130 uint32_t cur_reg = loc->values[0]; 131 uint32_t cur_reg = loc->values[0];
131 if (cur_reg >= eval_info->cur_regs->total_regs()) { 132 if (cur_reg >= eval_info->cur_regs->total_regs()) {
132 last_error_ = DWARF_ERROR_ILLEGAL_VALUE; 133 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
133 return false; 134 return false;
134 } 135 }
135 AddressType* cur_reg_ptr = &(*eval_info->cur_regs)[cur_reg]; 136 AddressType* cur_reg_ptr = &(*eval_info->cur_regs)[cur_reg];
@@ -158,7 +159,8 @@ bool DwarfSectionImpl<AddressType>::EvalRegister(const DwarfLocation* loc, uint3
158 } 159 }
159 if (loc->type == DWARF_LOCATION_EXPRESSION) { 160 if (loc->type == DWARF_LOCATION_EXPRESSION) {
160 if (!regular_memory->ReadFully(value, reg_ptr, sizeof(AddressType))) { 161 if (!regular_memory->ReadFully(value, reg_ptr, sizeof(AddressType))) {
161 last_error_ = DWARF_ERROR_MEMORY_INVALID; 162 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
163 last_error_.address = value;
162 return false; 164 return false;
163 } 165 }
164 } else { 166 } else {
@@ -183,14 +185,14 @@ bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_me
183 bool* finished) { 185 bool* finished) {
184 RegsImpl<AddressType>* cur_regs = reinterpret_cast<RegsImpl<AddressType>*>(regs); 186 RegsImpl<AddressType>* cur_regs = reinterpret_cast<RegsImpl<AddressType>*>(regs);
185 if (cie->return_address_register >= cur_regs->total_regs()) { 187 if (cie->return_address_register >= cur_regs->total_regs()) {
186 last_error_ = DWARF_ERROR_ILLEGAL_VALUE; 188 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
187 return false; 189 return false;
188 } 190 }
189 191
190 // Get the cfa value; 192 // Get the cfa value;
191 auto cfa_entry = loc_regs.find(CFA_REG); 193 auto cfa_entry = loc_regs.find(CFA_REG);
192 if (cfa_entry == loc_regs.end()) { 194 if (cfa_entry == loc_regs.end()) {
193 last_error_ = DWARF_ERROR_CFA_NOT_DEFINED; 195 last_error_.code = DWARF_ERROR_CFA_NOT_DEFINED;
194 return false; 196 return false;
195 } 197 }
196 198
@@ -206,7 +208,7 @@ bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_me
206 switch (loc->type) { 208 switch (loc->type) {
207 case DWARF_LOCATION_REGISTER: 209 case DWARF_LOCATION_REGISTER:
208 if (loc->values[0] >= cur_regs->total_regs()) { 210 if (loc->values[0] >= cur_regs->total_regs()) {
209 last_error_ = DWARF_ERROR_ILLEGAL_VALUE; 211 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
210 return false; 212 return false;
211 } 213 }
212 // If the stack pointer register is the CFA, and the stack 214 // If the stack pointer register is the CFA, and the stack
@@ -227,7 +229,8 @@ bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_me
227 } 229 }
228 if (loc->type == DWARF_LOCATION_EXPRESSION) { 230 if (loc->type == DWARF_LOCATION_EXPRESSION) {
229 if (!regular_memory->ReadFully(value, &eval_info.cfa, sizeof(AddressType))) { 231 if (!regular_memory->ReadFully(value, &eval_info.cfa, sizeof(AddressType))) {
230 last_error_ = DWARF_ERROR_MEMORY_INVALID; 232 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
233 last_error_.address = value;
231 return false; 234 return false;
232 } 235 }
233 } else { 236 } else {
@@ -236,7 +239,7 @@ bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_me
236 break; 239 break;
237 } 240 }
238 default: 241 default:
239 last_error_ = DWARF_ERROR_ILLEGAL_VALUE; 242 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
240 return false; 243 return false;
241 } 244 }
242 245
@@ -305,7 +308,8 @@ template <typename AddressType>
305bool DwarfSectionImpl<AddressType>::FillInCie(DwarfCie* cie) { 308bool DwarfSectionImpl<AddressType>::FillInCie(DwarfCie* cie) {
306 uint32_t length32; 309 uint32_t length32;
307 if (!memory_.ReadBytes(&length32, sizeof(length32))) { 310 if (!memory_.ReadBytes(&length32, sizeof(length32))) {
308 last_error_ = DWARF_ERROR_MEMORY_INVALID; 311 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
312 last_error_.address = memory_.cur_offset();
309 return false; 313 return false;
310 } 314 }
311 // Set the default for the lsda encoding. 315 // Set the default for the lsda encoding.
@@ -315,7 +319,8 @@ bool DwarfSectionImpl<AddressType>::FillInCie(DwarfCie* cie) {
315 // 64 bit Cie 319 // 64 bit Cie
316 uint64_t length64; 320 uint64_t length64;
317 if (!memory_.ReadBytes(&length64, sizeof(length64))) { 321 if (!memory_.ReadBytes(&length64, sizeof(length64))) {
318 last_error_ = DWARF_ERROR_MEMORY_INVALID; 322 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
323 last_error_.address = memory_.cur_offset();
319 return false; 324 return false;
320 } 325 }
321 326
@@ -324,12 +329,13 @@ bool DwarfSectionImpl<AddressType>::FillInCie(DwarfCie* cie) {
324 329
325 uint64_t cie_id; 330 uint64_t cie_id;
326 if (!memory_.ReadBytes(&cie_id, sizeof(cie_id))) { 331 if (!memory_.ReadBytes(&cie_id, sizeof(cie_id))) {
327 last_error_ = DWARF_ERROR_MEMORY_INVALID; 332 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
333 last_error_.address = memory_.cur_offset();
328 return false; 334 return false;
329 } 335 }
330 if (cie_id != cie64_value_) { 336 if (cie_id != cie64_value_) {
331 // This is not a Cie, something has gone horribly wrong. 337 // This is not a Cie, something has gone horribly wrong.
332 last_error_ = DWARF_ERROR_ILLEGAL_VALUE; 338 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
333 return false; 339 return false;
334 } 340 }
335 } else { 341 } else {
@@ -339,24 +345,26 @@ bool DwarfSectionImpl<AddressType>::FillInCie(DwarfCie* cie) {
339 345
340 uint32_t cie_id; 346 uint32_t cie_id;
341 if (!memory_.ReadBytes(&cie_id, sizeof(cie_id))) { 347 if (!memory_.ReadBytes(&cie_id, sizeof(cie_id))) {
342 last_error_ = DWARF_ERROR_MEMORY_INVALID; 348 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
349 last_error_.address = memory_.cur_offset();
343 return false; 350 return false;
344 } 351 }
345 if (cie_id != cie32_value_) { 352 if (cie_id != cie32_value_) {
346 // This is not a Cie, something has gone horribly wrong. 353 // This is not a Cie, something has gone horribly wrong.
347 last_error_ = DWARF_ERROR_ILLEGAL_VALUE; 354 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
348 return false; 355 return false;
349 } 356 }
350 } 357 }
351 358
352 if (!memory_.ReadBytes(&cie->version, sizeof(cie->version))) { 359 if (!memory_.ReadBytes(&cie->version, sizeof(cie->version))) {
353 last_error_ = DWARF_ERROR_MEMORY_INVALID; 360 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
361 last_error_.address = memory_.cur_offset();
354 return false; 362 return false;
355 } 363 }
356 364
357 if (cie->version != 1 && cie->version != 3 && cie->version != 4) { 365 if (cie->version != 1 && cie->version != 3 && cie->version != 4) {
358 // Unrecognized version. 366 // Unrecognized version.
359 last_error_ = DWARF_ERROR_UNSUPPORTED_VERSION; 367 last_error_.code = DWARF_ERROR_UNSUPPORTED_VERSION;
360 return false; 368 return false;
361 } 369 }
362 370
@@ -364,7 +372,8 @@ bool DwarfSectionImpl<AddressType>::FillInCie(DwarfCie* cie) {
364 char aug_value; 372 char aug_value;
365 do { 373 do {
366 if (!memory_.ReadBytes(&aug_value, 1)) { 374 if (!memory_.ReadBytes(&aug_value, 1)) {
367 last_error_ = DWARF_ERROR_MEMORY_INVALID; 375 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
376 last_error_.address = memory_.cur_offset();
368 return false; 377 return false;
369 } 378 }
370 cie->augmentation_string.push_back(aug_value); 379 cie->augmentation_string.push_back(aug_value);
@@ -376,20 +385,23 @@ bool DwarfSectionImpl<AddressType>::FillInCie(DwarfCie* cie) {
376 385
377 // Segment Size 386 // Segment Size
378 if (!memory_.ReadBytes(&cie->segment_size, 1)) { 387 if (!memory_.ReadBytes(&cie->segment_size, 1)) {
379 last_error_ = DWARF_ERROR_MEMORY_INVALID; 388 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
389 last_error_.address = memory_.cur_offset();
380 return false; 390 return false;
381 } 391 }
382 } 392 }
383 393
384 // Code Alignment Factor 394 // Code Alignment Factor
385 if (!memory_.ReadULEB128(&cie->code_alignment_factor)) { 395 if (!memory_.ReadULEB128(&cie->code_alignment_factor)) {
386 last_error_ = DWARF_ERROR_MEMORY_INVALID; 396 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
397 last_error_.address = memory_.cur_offset();
387 return false; 398 return false;
388 } 399 }
389 400
390 // Data Alignment Factor 401 // Data Alignment Factor
391 if (!memory_.ReadSLEB128(&cie->data_alignment_factor)) { 402 if (!memory_.ReadSLEB128(&cie->data_alignment_factor)) {
392 last_error_ = DWARF_ERROR_MEMORY_INVALID; 403 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
404 last_error_.address = memory_.cur_offset();
393 return false; 405 return false;
394 } 406 }
395 407
@@ -397,12 +409,14 @@ bool DwarfSectionImpl<AddressType>::FillInCie(DwarfCie* cie) {
397 // Return Address is a single byte. 409 // Return Address is a single byte.
398 uint8_t return_address_register; 410 uint8_t return_address_register;
399 if (!memory_.ReadBytes(&return_address_register, 1)) { 411 if (!memory_.ReadBytes(&return_address_register, 1)) {
400 last_error_ = DWARF_ERROR_MEMORY_INVALID; 412 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
413 last_error_.address = memory_.cur_offset();
401 return false; 414 return false;
402 } 415 }
403 cie->return_address_register = return_address_register; 416 cie->return_address_register = return_address_register;
404 } else if (!memory_.ReadULEB128(&cie->return_address_register)) { 417 } else if (!memory_.ReadULEB128(&cie->return_address_register)) {
405 last_error_ = DWARF_ERROR_MEMORY_INVALID; 418 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
419 last_error_.address = memory_.cur_offset();
406 return false; 420 return false;
407 } 421 }
408 422
@@ -413,7 +427,8 @@ bool DwarfSectionImpl<AddressType>::FillInCie(DwarfCie* cie) {
413 427
414 uint64_t aug_length; 428 uint64_t aug_length;
415 if (!memory_.ReadULEB128(&aug_length)) { 429 if (!memory_.ReadULEB128(&aug_length)) {
416 last_error_ = DWARF_ERROR_MEMORY_INVALID; 430 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
431 last_error_.address = memory_.cur_offset();
417 return false; 432 return false;
418 } 433 }
419 cie->cfa_instructions_offset = memory_.cur_offset() + aug_length; 434 cie->cfa_instructions_offset = memory_.cur_offset() + aug_length;
@@ -422,24 +437,28 @@ bool DwarfSectionImpl<AddressType>::FillInCie(DwarfCie* cie) {
422 switch (cie->augmentation_string[i]) { 437 switch (cie->augmentation_string[i]) {
423 case 'L': 438 case 'L':
424 if (!memory_.ReadBytes(&cie->lsda_encoding, 1)) { 439 if (!memory_.ReadBytes(&cie->lsda_encoding, 1)) {
425 last_error_ = DWARF_ERROR_MEMORY_INVALID; 440 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
441 last_error_.address = memory_.cur_offset();
426 return false; 442 return false;
427 } 443 }
428 break; 444 break;
429 case 'P': { 445 case 'P': {
430 uint8_t encoding; 446 uint8_t encoding;
431 if (!memory_.ReadBytes(&encoding, 1)) { 447 if (!memory_.ReadBytes(&encoding, 1)) {
432 last_error_ = DWARF_ERROR_MEMORY_INVALID; 448 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
449 last_error_.address = memory_.cur_offset();
433 return false; 450 return false;
434 } 451 }
435 if (!memory_.ReadEncodedValue<AddressType>(encoding, &cie->personality_handler)) { 452 if (!memory_.ReadEncodedValue<AddressType>(encoding, &cie->personality_handler)) {
436 last_error_ = DWARF_ERROR_MEMORY_INVALID; 453 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
454 last_error_.address = memory_.cur_offset();
437 return false; 455 return false;
438 } 456 }
439 } break; 457 } break;
440 case 'R': 458 case 'R':
441 if (!memory_.ReadBytes(&cie->fde_address_encoding, 1)) { 459 if (!memory_.ReadBytes(&cie->fde_address_encoding, 1)) {
442 last_error_ = DWARF_ERROR_MEMORY_INVALID; 460 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
461 last_error_.address = memory_.cur_offset();
443 return false; 462 return false;
444 } 463 }
445 break; 464 break;
@@ -467,7 +486,8 @@ template <typename AddressType>
467bool DwarfSectionImpl<AddressType>::FillInFde(DwarfFde* fde) { 486bool DwarfSectionImpl<AddressType>::FillInFde(DwarfFde* fde) {
468 uint32_t length32; 487 uint32_t length32;
469 if (!memory_.ReadBytes(&length32, sizeof(length32))) { 488 if (!memory_.ReadBytes(&length32, sizeof(length32))) {
470 last_error_ = DWARF_ERROR_MEMORY_INVALID; 489 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
490 last_error_.address = memory_.cur_offset();
471 return false; 491 return false;
472 } 492 }
473 493
@@ -475,19 +495,21 @@ bool DwarfSectionImpl<AddressType>::FillInFde(DwarfFde* fde) {
475 // 64 bit Fde. 495 // 64 bit Fde.
476 uint64_t length64; 496 uint64_t length64;
477 if (!memory_.ReadBytes(&length64, sizeof(length64))) { 497 if (!memory_.ReadBytes(&length64, sizeof(length64))) {
478 last_error_ = DWARF_ERROR_MEMORY_INVALID; 498 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
499 last_error_.address = memory_.cur_offset();
479 return false; 500 return false;
480 } 501 }
481 fde->cfa_instructions_end = memory_.cur_offset() + length64; 502 fde->cfa_instructions_end = memory_.cur_offset() + length64;
482 503
483 uint64_t value64; 504 uint64_t value64;
484 if (!memory_.ReadBytes(&value64, sizeof(value64))) { 505 if (!memory_.ReadBytes(&value64, sizeof(value64))) {
485 last_error_ = DWARF_ERROR_MEMORY_INVALID; 506 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
507 last_error_.address = memory_.cur_offset();
486 return false; 508 return false;
487 } 509 }
488 if (value64 == cie64_value_) { 510 if (value64 == cie64_value_) {
489 // This is a Cie, this means something has gone wrong. 511 // This is a Cie, this means something has gone wrong.
490 last_error_ = DWARF_ERROR_ILLEGAL_VALUE; 512 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
491 return false; 513 return false;
492 } 514 }
493 515
@@ -500,12 +522,13 @@ bool DwarfSectionImpl<AddressType>::FillInFde(DwarfFde* fde) {
500 522
501 uint32_t value32; 523 uint32_t value32;
502 if (!memory_.ReadBytes(&value32, sizeof(value32))) { 524 if (!memory_.ReadBytes(&value32, sizeof(value32))) {
503 last_error_ = DWARF_ERROR_MEMORY_INVALID; 525 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
526 last_error_.address = memory_.cur_offset();
504 return false; 527 return false;
505 } 528 }
506 if (value32 == cie32_value_) { 529 if (value32 == cie32_value_) {
507 // This is a Cie, this means something has gone wrong. 530 // This is a Cie, this means something has gone wrong.
508 last_error_ = DWARF_ERROR_ILLEGAL_VALUE; 531 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
509 return false; 532 return false;
510 } 533 }
511 534
@@ -528,13 +551,15 @@ bool DwarfSectionImpl<AddressType>::FillInFde(DwarfFde* fde) {
528 memory_.set_cur_offset(cur_offset); 551 memory_.set_cur_offset(cur_offset);
529 552
530 if (!memory_.ReadEncodedValue<AddressType>(cie->fde_address_encoding & 0xf, &fde->pc_start)) { 553 if (!memory_.ReadEncodedValue<AddressType>(cie->fde_address_encoding & 0xf, &fde->pc_start)) {
531 last_error_ = DWARF_ERROR_MEMORY_INVALID; 554 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
555 last_error_.address = memory_.cur_offset();
532 return false; 556 return false;
533 } 557 }
534 fde->pc_start = AdjustPcFromFde(fde->pc_start); 558 fde->pc_start = AdjustPcFromFde(fde->pc_start);
535 559
536 if (!memory_.ReadEncodedValue<AddressType>(cie->fde_address_encoding & 0xf, &fde->pc_end)) { 560 if (!memory_.ReadEncodedValue<AddressType>(cie->fde_address_encoding & 0xf, &fde->pc_end)) {
537 last_error_ = DWARF_ERROR_MEMORY_INVALID; 561 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
562 last_error_.address = memory_.cur_offset();
538 return false; 563 return false;
539 } 564 }
540 fde->pc_end += fde->pc_start; 565 fde->pc_end += fde->pc_start;
@@ -542,13 +567,15 @@ bool DwarfSectionImpl<AddressType>::FillInFde(DwarfFde* fde) {
542 // Augmentation Size 567 // Augmentation Size
543 uint64_t aug_length; 568 uint64_t aug_length;
544 if (!memory_.ReadULEB128(&aug_length)) { 569 if (!memory_.ReadULEB128(&aug_length)) {
545 last_error_ = DWARF_ERROR_MEMORY_INVALID; 570 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
571 last_error_.address = memory_.cur_offset();
546 return false; 572 return false;
547 } 573 }
548 uint64_t cur_offset = memory_.cur_offset(); 574 uint64_t cur_offset = memory_.cur_offset();
549 575
550 if (!memory_.ReadEncodedValue<AddressType>(cie->lsda_encoding, &fde->lsda_address)) { 576 if (!memory_.ReadEncodedValue<AddressType>(cie->lsda_encoding, &fde->lsda_address)) {
551 last_error_ = DWARF_ERROR_MEMORY_INVALID; 577 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
578 last_error_.address = memory_.cur_offset();
552 return false; 579 return false;
553 } 580 }
554 581
@@ -619,7 +646,8 @@ template <typename AddressType>
619bool DwarfSectionImpl<AddressType>::GetCieInfo(uint8_t* segment_size, uint8_t* encoding) { 646bool DwarfSectionImpl<AddressType>::GetCieInfo(uint8_t* segment_size, uint8_t* encoding) {
620 uint8_t version; 647 uint8_t version;
621 if (!memory_.ReadBytes(&version, 1)) { 648 if (!memory_.ReadBytes(&version, 1)) {
622 last_error_ = DWARF_ERROR_MEMORY_INVALID; 649 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
650 last_error_.address = memory_.cur_offset();
623 return false; 651 return false;
624 } 652 }
625 // Read the augmentation string. 653 // Read the augmentation string.
@@ -628,7 +656,8 @@ bool DwarfSectionImpl<AddressType>::GetCieInfo(uint8_t* segment_size, uint8_t* e
628 bool get_encoding = false; 656 bool get_encoding = false;
629 do { 657 do {
630 if (!memory_.ReadBytes(&aug_value, 1)) { 658 if (!memory_.ReadBytes(&aug_value, 1)) {
631 last_error_ = DWARF_ERROR_MEMORY_INVALID; 659 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
660 last_error_.address = memory_.cur_offset();
632 return false; 661 return false;
633 } 662 }
634 if (aug_value == 'R') { 663 if (aug_value == 'R') {
@@ -643,7 +672,8 @@ bool DwarfSectionImpl<AddressType>::GetCieInfo(uint8_t* segment_size, uint8_t* e
643 672
644 // Read the segment size. 673 // Read the segment size.
645 if (!memory_.ReadBytes(segment_size, 1)) { 674 if (!memory_.ReadBytes(segment_size, 1)) {
646 last_error_ = DWARF_ERROR_MEMORY_INVALID; 675 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
676 last_error_.address = memory_.cur_offset();
647 return false; 677 return false;
648 } 678 }
649 } else { 679 } else {
@@ -659,7 +689,8 @@ bool DwarfSectionImpl<AddressType>::GetCieInfo(uint8_t* segment_size, uint8_t* e
659 uint8_t value; 689 uint8_t value;
660 do { 690 do {
661 if (!memory_.ReadBytes(&value, 1)) { 691 if (!memory_.ReadBytes(&value, 1)) {
662 last_error_ = DWARF_ERROR_MEMORY_INVALID; 692 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
693 last_error_.address = memory_.cur_offset();
663 return false; 694 return false;
664 } 695 }
665 } while (value & 0x80); 696 } while (value & 0x80);
@@ -667,7 +698,8 @@ bool DwarfSectionImpl<AddressType>::GetCieInfo(uint8_t* segment_size, uint8_t* e
667 // Skip data alignment factor 698 // Skip data alignment factor
668 do { 699 do {
669 if (!memory_.ReadBytes(&value, 1)) { 700 if (!memory_.ReadBytes(&value, 1)) {
670 last_error_ = DWARF_ERROR_MEMORY_INVALID; 701 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
702 last_error_.address = memory_.cur_offset();
671 return false; 703 return false;
672 } 704 }
673 } while (value & 0x80); 705 } while (value & 0x80);
@@ -679,7 +711,8 @@ bool DwarfSectionImpl<AddressType>::GetCieInfo(uint8_t* segment_size, uint8_t* e
679 // Skip return address register. 711 // Skip return address register.
680 do { 712 do {
681 if (!memory_.ReadBytes(&value, 1)) { 713 if (!memory_.ReadBytes(&value, 1)) {
682 last_error_ = DWARF_ERROR_MEMORY_INVALID; 714 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
715 last_error_.address = memory_.cur_offset();
683 return false; 716 return false;
684 } 717 }
685 } while (value & 0x80); 718 } while (value & 0x80);
@@ -688,7 +721,8 @@ bool DwarfSectionImpl<AddressType>::GetCieInfo(uint8_t* segment_size, uint8_t* e
688 // Skip the augmentation length. 721 // Skip the augmentation length.
689 do { 722 do {
690 if (!memory_.ReadBytes(&value, 1)) { 723 if (!memory_.ReadBytes(&value, 1)) {
691 last_error_ = DWARF_ERROR_MEMORY_INVALID; 724 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
725 last_error_.address = memory_.cur_offset();
692 return false; 726 return false;
693 } 727 }
694 } while (value & 0x80); 728 } while (value & 0x80);
@@ -696,7 +730,8 @@ bool DwarfSectionImpl<AddressType>::GetCieInfo(uint8_t* segment_size, uint8_t* e
696 for (size_t i = 1; i < aug_string.size(); i++) { 730 for (size_t i = 1; i < aug_string.size(); i++) {
697 if (aug_string[i] == 'R') { 731 if (aug_string[i] == 'R') {
698 if (!memory_.ReadBytes(encoding, 1)) { 732 if (!memory_.ReadBytes(encoding, 1)) {
699 last_error_ = DWARF_ERROR_MEMORY_INVALID; 733 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
734 last_error_.address = memory_.cur_offset();
700 return false; 735 return false;
701 } 736 }
702 // Got the encoding, that's all we are looking for. 737 // Got the encoding, that's all we are looking for.
@@ -706,12 +741,14 @@ bool DwarfSectionImpl<AddressType>::GetCieInfo(uint8_t* segment_size, uint8_t* e
706 } else if (aug_string[i] == 'P') { 741 } else if (aug_string[i] == 'P') {
707 uint8_t encoding; 742 uint8_t encoding;
708 if (!memory_.ReadBytes(&encoding, 1)) { 743 if (!memory_.ReadBytes(&encoding, 1)) {
709 last_error_ = DWARF_ERROR_MEMORY_INVALID; 744 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
745 last_error_.address = memory_.cur_offset();
710 return false; 746 return false;
711 } 747 }
712 uint64_t value; 748 uint64_t value;
713 if (!memory_.template ReadEncodedValue<AddressType>(encoding, &value)) { 749 if (!memory_.template ReadEncodedValue<AddressType>(encoding, &value)) {
714 last_error_ = DWARF_ERROR_MEMORY_INVALID; 750 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
751 last_error_.address = memory_.cur_offset();
715 return false; 752 return false;
716 } 753 }
717 } 754 }
@@ -730,14 +767,16 @@ bool DwarfSectionImpl<AddressType>::AddFdeInfo(uint64_t entry_offset, uint8_t se
730 767
731 uint64_t start; 768 uint64_t start;
732 if (!memory_.template ReadEncodedValue<AddressType>(encoding & 0xf, &start)) { 769 if (!memory_.template ReadEncodedValue<AddressType>(encoding & 0xf, &start)) {
733 last_error_ = DWARF_ERROR_MEMORY_INVALID; 770 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
771 last_error_.address = memory_.cur_offset();
734 return false; 772 return false;
735 } 773 }
736 start = AdjustPcFromFde(start); 774 start = AdjustPcFromFde(start);
737 775
738 uint64_t length; 776 uint64_t length;
739 if (!memory_.template ReadEncodedValue<AddressType>(encoding & 0xf, &length)) { 777 if (!memory_.template ReadEncodedValue<AddressType>(encoding & 0xf, &length)) {
740 last_error_ = DWARF_ERROR_MEMORY_INVALID; 778 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
779 last_error_.address = memory_.cur_offset();
741 return false; 780 return false;
742 } 781 }
743 if (length != 0) { 782 if (length != 0) {
@@ -764,7 +803,8 @@ bool DwarfSectionImpl<AddressType>::CreateSortedFdeList() {
764 // Figure out the entry length and type. 803 // Figure out the entry length and type.
765 uint32_t value32; 804 uint32_t value32;
766 if (!memory_.ReadBytes(&value32, sizeof(value32))) { 805 if (!memory_.ReadBytes(&value32, sizeof(value32))) {
767 last_error_ = DWARF_ERROR_MEMORY_INVALID; 806 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
807 last_error_.address = memory_.cur_offset();
768 return false; 808 return false;
769 } 809 }
770 810
@@ -772,14 +812,16 @@ bool DwarfSectionImpl<AddressType>::CreateSortedFdeList() {
772 if (value32 == static_cast<uint32_t>(-1)) { 812 if (value32 == static_cast<uint32_t>(-1)) {
773 uint64_t value64; 813 uint64_t value64;
774 if (!memory_.ReadBytes(&value64, sizeof(value64))) { 814 if (!memory_.ReadBytes(&value64, sizeof(value64))) {
775 last_error_ = DWARF_ERROR_MEMORY_INVALID; 815 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
816 last_error_.address = memory_.cur_offset();
776 return false; 817 return false;
777 } 818 }
778 next_entry_offset = memory_.cur_offset() + value64; 819 next_entry_offset = memory_.cur_offset() + value64;
779 820
780 // Read the Cie Id of a Cie or the pointer of the Fde. 821 // Read the Cie Id of a Cie or the pointer of the Fde.
781 if (!memory_.ReadBytes(&value64, sizeof(value64))) { 822 if (!memory_.ReadBytes(&value64, sizeof(value64))) {
782 last_error_ = DWARF_ERROR_MEMORY_INVALID; 823 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
824 last_error_.address = memory_.cur_offset();
783 return false; 825 return false;
784 } 826 }
785 827
@@ -794,7 +836,7 @@ bool DwarfSectionImpl<AddressType>::CreateSortedFdeList() {
794 uint64_t last_cie_offset = GetCieOffsetFromFde64(value64); 836 uint64_t last_cie_offset = GetCieOffsetFromFde64(value64);
795 if (last_cie_offset != cie_offset) { 837 if (last_cie_offset != cie_offset) {
796 // This means that this Fde is not following the Cie. 838 // This means that this Fde is not following the Cie.
797 last_error_ = DWARF_ERROR_ILLEGAL_VALUE; 839 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
798 return false; 840 return false;
799 } 841 }
800 842
@@ -808,7 +850,8 @@ bool DwarfSectionImpl<AddressType>::CreateSortedFdeList() {
808 850
809 // Read the Cie Id of a Cie or the pointer of the Fde. 851 // Read the Cie Id of a Cie or the pointer of the Fde.
810 if (!memory_.ReadBytes(&value32, sizeof(value32))) { 852 if (!memory_.ReadBytes(&value32, sizeof(value32))) {
811 last_error_ = DWARF_ERROR_MEMORY_INVALID; 853 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
854 last_error_.address = memory_.cur_offset();
812 return false; 855 return false;
813 } 856 }
814 857
@@ -823,7 +866,7 @@ bool DwarfSectionImpl<AddressType>::CreateSortedFdeList() {
823 uint64_t last_cie_offset = GetCieOffsetFromFde32(value32); 866 uint64_t last_cie_offset = GetCieOffsetFromFde32(value32);
824 if (last_cie_offset != cie_offset) { 867 if (last_cie_offset != cie_offset) {
825 // This means that this Fde is not following the Cie. 868 // This means that this Fde is not following the Cie.
826 last_error_ = DWARF_ERROR_ILLEGAL_VALUE; 869 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
827 return false; 870 return false;
828 } 871 }
829 872
diff --git a/libunwindstack/Elf.cpp b/libunwindstack/Elf.cpp
index 220e549aa..f120da2b2 100644
--- a/libunwindstack/Elf.cpp
+++ b/libunwindstack/Elf.cpp
@@ -134,6 +134,26 @@ bool Elf::GetGlobalVariable(const std::string& name, uint64_t* memory_address) {
134 return true; 134 return true;
135} 135}
136 136
137void Elf::GetLastError(ErrorData* data) {
138 if (valid_) {
139 *data = interface_->last_error();
140 }
141}
142
143ErrorCode Elf::GetLastErrorCode() {
144 if (valid_) {
145 return interface_->LastErrorCode();
146 }
147 return ERROR_NONE;
148}
149
150uint64_t Elf::GetLastErrorAddress() {
151 if (valid_) {
152 return interface_->LastErrorAddress();
153 }
154 return 0;
155}
156
137// The relative pc is always relative to the start of the map from which it comes. 157// The relative pc is always relative to the start of the map from which it comes.
138bool Elf::Step(uint64_t rel_pc, uint64_t adjusted_rel_pc, uint64_t elf_offset, Regs* regs, 158bool Elf::Step(uint64_t rel_pc, uint64_t adjusted_rel_pc, uint64_t elf_offset, Regs* regs,
139 Memory* process_memory, bool* finished) { 159 Memory* process_memory, bool* finished) {
diff --git a/libunwindstack/ElfInterface.cpp b/libunwindstack/ElfInterface.cpp
index 17cc16a9f..e41308171 100644
--- a/libunwindstack/ElfInterface.cpp
+++ b/libunwindstack/ElfInterface.cpp
@@ -24,6 +24,7 @@
24#include <Xz.h> 24#include <Xz.h>
25#include <XzCrc64.h> 25#include <XzCrc64.h>
26 26
27#include <unwindstack/DwarfError.h>
27#include <unwindstack/DwarfSection.h> 28#include <unwindstack/DwarfSection.h>
28#include <unwindstack/ElfInterface.h> 29#include <unwindstack/ElfInterface.h>
29#include <unwindstack/Log.h> 30#include <unwindstack/Log.h>
@@ -160,6 +161,8 @@ template <typename EhdrType, typename PhdrType, typename ShdrType>
160bool ElfInterface::ReadAllHeaders(uint64_t* load_bias) { 161bool ElfInterface::ReadAllHeaders(uint64_t* load_bias) {
161 EhdrType ehdr; 162 EhdrType ehdr;
162 if (!memory_->ReadFully(0, &ehdr, sizeof(ehdr))) { 163 if (!memory_->ReadFully(0, &ehdr, sizeof(ehdr))) {
164 last_error_.code = ERROR_MEMORY_INVALID;
165 last_error_.address = 0;
163 return false; 166 return false;
164 } 167 }
165 168
@@ -201,6 +204,9 @@ bool ElfInterface::ReadProgramHeaders(const EhdrType& ehdr, uint64_t* load_bias)
201 for (size_t i = 0; i < ehdr.e_phnum; i++, offset += ehdr.e_phentsize) { 204 for (size_t i = 0; i < ehdr.e_phnum; i++, offset += ehdr.e_phentsize) {
202 PhdrType phdr; 205 PhdrType phdr;
203 if (!memory_->ReadField(offset, &phdr, &phdr.p_type, sizeof(phdr.p_type))) { 206 if (!memory_->ReadField(offset, &phdr, &phdr.p_type, sizeof(phdr.p_type))) {
207 last_error_.code = ERROR_MEMORY_INVALID;
208 last_error_.address =
209 offset + reinterpret_cast<uintptr_t>(&phdr.p_type) - reinterpret_cast<uintptr_t>(&phdr);
204 return false; 210 return false;
205 } 211 }
206 212
@@ -213,6 +219,9 @@ bool ElfInterface::ReadProgramHeaders(const EhdrType& ehdr, uint64_t* load_bias)
213 { 219 {
214 // Get the flags first, if this isn't an executable header, ignore it. 220 // Get the flags first, if this isn't an executable header, ignore it.
215 if (!memory_->ReadField(offset, &phdr, &phdr.p_flags, sizeof(phdr.p_flags))) { 221 if (!memory_->ReadField(offset, &phdr, &phdr.p_flags, sizeof(phdr.p_flags))) {
222 last_error_.code = ERROR_MEMORY_INVALID;
223 last_error_.address = offset + reinterpret_cast<uintptr_t>(&phdr.p_flags) -
224 reinterpret_cast<uintptr_t>(&phdr);
216 return false; 225 return false;
217 } 226 }
218 if ((phdr.p_flags & PF_X) == 0) { 227 if ((phdr.p_flags & PF_X) == 0) {
@@ -220,12 +229,21 @@ bool ElfInterface::ReadProgramHeaders(const EhdrType& ehdr, uint64_t* load_bias)
220 } 229 }
221 230
222 if (!memory_->ReadField(offset, &phdr, &phdr.p_vaddr, sizeof(phdr.p_vaddr))) { 231 if (!memory_->ReadField(offset, &phdr, &phdr.p_vaddr, sizeof(phdr.p_vaddr))) {
232 last_error_.code = ERROR_MEMORY_INVALID;
233 last_error_.address = offset + reinterpret_cast<uintptr_t>(&phdr.p_vaddr) -
234 reinterpret_cast<uintptr_t>(&phdr);
223 return false; 235 return false;
224 } 236 }
225 if (!memory_->ReadField(offset, &phdr, &phdr.p_offset, sizeof(phdr.p_offset))) { 237 if (!memory_->ReadField(offset, &phdr, &phdr.p_offset, sizeof(phdr.p_offset))) {
238 last_error_.code = ERROR_MEMORY_INVALID;
239 last_error_.address = offset + reinterpret_cast<uintptr_t>(&phdr.p_offset) -
240 reinterpret_cast<uintptr_t>(&phdr);
226 return false; 241 return false;
227 } 242 }
228 if (!memory_->ReadField(offset, &phdr, &phdr.p_memsz, sizeof(phdr.p_memsz))) { 243 if (!memory_->ReadField(offset, &phdr, &phdr.p_memsz, sizeof(phdr.p_memsz))) {
244 last_error_.code = ERROR_MEMORY_INVALID;
245 last_error_.address = offset + reinterpret_cast<uintptr_t>(&phdr.p_memsz) -
246 reinterpret_cast<uintptr_t>(&phdr);
229 return false; 247 return false;
230 } 248 }
231 pt_loads_[phdr.p_offset] = LoadInfo{phdr.p_offset, phdr.p_vaddr, 249 pt_loads_[phdr.p_offset] = LoadInfo{phdr.p_offset, phdr.p_vaddr,
@@ -238,11 +256,17 @@ bool ElfInterface::ReadProgramHeaders(const EhdrType& ehdr, uint64_t* load_bias)
238 256
239 case PT_GNU_EH_FRAME: 257 case PT_GNU_EH_FRAME:
240 if (!memory_->ReadField(offset, &phdr, &phdr.p_offset, sizeof(phdr.p_offset))) { 258 if (!memory_->ReadField(offset, &phdr, &phdr.p_offset, sizeof(phdr.p_offset))) {
259 last_error_.code = ERROR_MEMORY_INVALID;
260 last_error_.address = offset + reinterpret_cast<uintptr_t>(&phdr.p_offset) -
261 reinterpret_cast<uintptr_t>(&phdr);
241 return false; 262 return false;
242 } 263 }
243 // This is really the pointer to the .eh_frame_hdr section. 264 // This is really the pointer to the .eh_frame_hdr section.
244 eh_frame_hdr_offset_ = phdr.p_offset; 265 eh_frame_hdr_offset_ = phdr.p_offset;
245 if (!memory_->ReadField(offset, &phdr, &phdr.p_memsz, sizeof(phdr.p_memsz))) { 266 if (!memory_->ReadField(offset, &phdr, &phdr.p_memsz, sizeof(phdr.p_memsz))) {
267 last_error_.code = ERROR_MEMORY_INVALID;
268 last_error_.address = offset + reinterpret_cast<uintptr_t>(&phdr.p_memsz) -
269 reinterpret_cast<uintptr_t>(&phdr);
246 return false; 270 return false;
247 } 271 }
248 eh_frame_hdr_size_ = phdr.p_memsz; 272 eh_frame_hdr_size_ = phdr.p_memsz;
@@ -250,14 +274,23 @@ bool ElfInterface::ReadProgramHeaders(const EhdrType& ehdr, uint64_t* load_bias)
250 274
251 case PT_DYNAMIC: 275 case PT_DYNAMIC:
252 if (!memory_->ReadField(offset, &phdr, &phdr.p_offset, sizeof(phdr.p_offset))) { 276 if (!memory_->ReadField(offset, &phdr, &phdr.p_offset, sizeof(phdr.p_offset))) {
277 last_error_.code = ERROR_MEMORY_INVALID;
278 last_error_.address = offset + reinterpret_cast<uintptr_t>(&phdr.p_offset) -
279 reinterpret_cast<uintptr_t>(&phdr);
253 return false; 280 return false;
254 } 281 }
255 dynamic_offset_ = phdr.p_offset; 282 dynamic_offset_ = phdr.p_offset;
256 if (!memory_->ReadField(offset, &phdr, &phdr.p_vaddr, sizeof(phdr.p_vaddr))) { 283 if (!memory_->ReadField(offset, &phdr, &phdr.p_vaddr, sizeof(phdr.p_vaddr))) {
284 last_error_.code = ERROR_MEMORY_INVALID;
285 last_error_.address = offset + reinterpret_cast<uintptr_t>(&phdr.p_vaddr) -
286 reinterpret_cast<uintptr_t>(&phdr);
257 return false; 287 return false;
258 } 288 }
259 dynamic_vaddr_ = phdr.p_vaddr; 289 dynamic_vaddr_ = phdr.p_vaddr;
260 if (!memory_->ReadField(offset, &phdr, &phdr.p_memsz, sizeof(phdr.p_memsz))) { 290 if (!memory_->ReadField(offset, &phdr, &phdr.p_memsz, sizeof(phdr.p_memsz))) {
291 last_error_.code = ERROR_MEMORY_INVALID;
292 last_error_.address = offset + reinterpret_cast<uintptr_t>(&phdr.p_memsz) -
293 reinterpret_cast<uintptr_t>(&phdr);
261 return false; 294 return false;
262 } 295 }
263 dynamic_size_ = phdr.p_memsz; 296 dynamic_size_ = phdr.p_memsz;
@@ -290,31 +323,47 @@ bool ElfInterface::ReadSectionHeaders(const EhdrType& ehdr) {
290 offset += ehdr.e_shentsize; 323 offset += ehdr.e_shentsize;
291 for (size_t i = 1; i < ehdr.e_shnum; i++, offset += ehdr.e_shentsize) { 324 for (size_t i = 1; i < ehdr.e_shnum; i++, offset += ehdr.e_shentsize) {
292 if (!memory_->ReadField(offset, &shdr, &shdr.sh_type, sizeof(shdr.sh_type))) { 325 if (!memory_->ReadField(offset, &shdr, &shdr.sh_type, sizeof(shdr.sh_type))) {
326 last_error_.code = ERROR_MEMORY_INVALID;
327 last_error_.address =
328 offset + reinterpret_cast<uintptr_t>(&shdr.sh_type) - reinterpret_cast<uintptr_t>(&shdr);
293 return false; 329 return false;
294 } 330 }
295 331
296 if (shdr.sh_type == SHT_SYMTAB || shdr.sh_type == SHT_DYNSYM) { 332 if (shdr.sh_type == SHT_SYMTAB || shdr.sh_type == SHT_DYNSYM) {
297 if (!memory_->ReadFully(offset, &shdr, sizeof(shdr))) { 333 if (!memory_->ReadFully(offset, &shdr, sizeof(shdr))) {
334 last_error_.code = ERROR_MEMORY_INVALID;
335 last_error_.address = offset;
298 return false; 336 return false;
299 } 337 }
300 // Need to go get the information about the section that contains 338 // Need to go get the information about the section that contains
301 // the string terminated names. 339 // the string terminated names.
302 ShdrType str_shdr; 340 ShdrType str_shdr;
303 if (shdr.sh_link >= ehdr.e_shnum) { 341 if (shdr.sh_link >= ehdr.e_shnum) {
342 last_error_.code = ERROR_UNWIND_INFO;
304 return false; 343 return false;
305 } 344 }
306 uint64_t str_offset = ehdr.e_shoff + shdr.sh_link * ehdr.e_shentsize; 345 uint64_t str_offset = ehdr.e_shoff + shdr.sh_link * ehdr.e_shentsize;
307 if (!memory_->ReadField(str_offset, &str_shdr, &str_shdr.sh_type, sizeof(str_shdr.sh_type))) { 346 if (!memory_->ReadField(str_offset, &str_shdr, &str_shdr.sh_type, sizeof(str_shdr.sh_type))) {
347 last_error_.code = ERROR_MEMORY_INVALID;
348 last_error_.address = str_offset + reinterpret_cast<uintptr_t>(&str_shdr.sh_type) -
349 reinterpret_cast<uintptr_t>(&str_shdr);
308 return false; 350 return false;
309 } 351 }
310 if (str_shdr.sh_type != SHT_STRTAB) { 352 if (str_shdr.sh_type != SHT_STRTAB) {
353 last_error_.code = ERROR_UNWIND_INFO;
311 return false; 354 return false;
312 } 355 }
313 if (!memory_->ReadField(str_offset, &str_shdr, &str_shdr.sh_offset, 356 if (!memory_->ReadField(str_offset, &str_shdr, &str_shdr.sh_offset,
314 sizeof(str_shdr.sh_offset))) { 357 sizeof(str_shdr.sh_offset))) {
358 last_error_.code = ERROR_MEMORY_INVALID;
359 last_error_.address = str_offset + reinterpret_cast<uintptr_t>(&str_shdr.sh_offset) -
360 reinterpret_cast<uintptr_t>(&str_shdr);
315 return false; 361 return false;
316 } 362 }
317 if (!memory_->ReadField(str_offset, &str_shdr, &str_shdr.sh_size, sizeof(str_shdr.sh_size))) { 363 if (!memory_->ReadField(str_offset, &str_shdr, &str_shdr.sh_size, sizeof(str_shdr.sh_size))) {
364 last_error_.code = ERROR_MEMORY_INVALID;
365 last_error_.address = str_offset + reinterpret_cast<uintptr_t>(&str_shdr.sh_size) -
366 reinterpret_cast<uintptr_t>(&str_shdr);
318 return false; 367 return false;
319 } 368 }
320 symbols_.push_back(new Symbols(shdr.sh_offset, shdr.sh_size, shdr.sh_entsize, 369 symbols_.push_back(new Symbols(shdr.sh_offset, shdr.sh_size, shdr.sh_entsize,
@@ -322,6 +371,9 @@ bool ElfInterface::ReadSectionHeaders(const EhdrType& ehdr) {
322 } else if (shdr.sh_type == SHT_PROGBITS && sec_size != 0) { 371 } else if (shdr.sh_type == SHT_PROGBITS && sec_size != 0) {
323 // Look for the .debug_frame and .gnu_debugdata. 372 // Look for the .debug_frame and .gnu_debugdata.
324 if (!memory_->ReadField(offset, &shdr, &shdr.sh_name, sizeof(shdr.sh_name))) { 373 if (!memory_->ReadField(offset, &shdr, &shdr.sh_name, sizeof(shdr.sh_name))) {
374 last_error_.code = ERROR_MEMORY_INVALID;
375 last_error_.address = offset + reinterpret_cast<uintptr_t>(&shdr.sh_name) -
376 reinterpret_cast<uintptr_t>(&shdr);
325 return false; 377 return false;
326 } 378 }
327 if (shdr.sh_name < sec_size) { 379 if (shdr.sh_name < sec_size) {
@@ -377,6 +429,8 @@ bool ElfInterface::GetSonameWithTemplate(std::string* soname) {
377 uint64_t max_offset = offset + dynamic_size_; 429 uint64_t max_offset = offset + dynamic_size_;
378 for (uint64_t offset = dynamic_offset_; offset < max_offset; offset += sizeof(DynType)) { 430 for (uint64_t offset = dynamic_offset_; offset < max_offset; offset += sizeof(DynType)) {
379 if (!memory_->ReadFully(offset, &dyn, sizeof(dyn))) { 431 if (!memory_->ReadFully(offset, &dyn, sizeof(dyn))) {
432 last_error_.code = ERROR_MEMORY_INVALID;
433 last_error_.address = offset;
380 return false; 434 return false;
381 } 435 }
382 436
@@ -434,8 +488,12 @@ bool ElfInterface::GetGlobalVariableWithTemplate(const std::string& name, uint64
434 488
435bool ElfInterface::Step(uint64_t pc, uint64_t load_bias, Regs* regs, Memory* process_memory, 489bool ElfInterface::Step(uint64_t pc, uint64_t load_bias, Regs* regs, Memory* process_memory,
436 bool* finished) { 490 bool* finished) {
491 last_error_.code = ERROR_NONE;
492 last_error_.address = 0;
493
437 // Adjust the load bias to get the real relative pc. 494 // Adjust the load bias to get the real relative pc.
438 if (pc < load_bias) { 495 if (pc < load_bias) {
496 last_error_.code = ERROR_UNWIND_INFO;
439 return false; 497 return false;
440 } 498 }
441 uint64_t adjusted_pc = pc - load_bias; 499 uint64_t adjusted_pc = pc - load_bias;
@@ -458,6 +516,46 @@ bool ElfInterface::Step(uint64_t pc, uint64_t load_bias, Regs* regs, Memory* pro
458 gnu_debugdata_interface_->Step(pc, 0, regs, process_memory, finished)) { 516 gnu_debugdata_interface_->Step(pc, 0, regs, process_memory, finished)) {
459 return true; 517 return true;
460 } 518 }
519
520 // Set the error code based on the first error encountered.
521 DwarfSection* section = nullptr;
522 if (debug_frame_ != nullptr) {
523 section = debug_frame_.get();
524 } else if (eh_frame_ != nullptr) {
525 section = eh_frame_.get();
526 } else if (gnu_debugdata_interface_ != nullptr) {
527 last_error_ = gnu_debugdata_interface_->last_error();
528 return false;
529 } else {
530 return false;
531 }
532
533 // Convert the DWARF ERROR to an external error.
534 DwarfErrorCode code = section->LastErrorCode();
535 switch (code) {
536 case DWARF_ERROR_NONE:
537 last_error_.code = ERROR_NONE;
538 break;
539
540 case DWARF_ERROR_MEMORY_INVALID:
541 last_error_.code = ERROR_MEMORY_INVALID;
542 last_error_.address = section->LastErrorAddress();
543 break;
544
545 case DWARF_ERROR_ILLEGAL_VALUE:
546 case DWARF_ERROR_ILLEGAL_STATE:
547 case DWARF_ERROR_STACK_INDEX_NOT_VALID:
548 case DWARF_ERROR_TOO_MANY_ITERATIONS:
549 case DWARF_ERROR_CFA_NOT_DEFINED:
550 case DWARF_ERROR_NO_FDES:
551 last_error_.code = ERROR_UNWIND_INFO;
552 break;
553
554 case DWARF_ERROR_NOT_IMPLEMENTED:
555 case DWARF_ERROR_UNSUPPORTED_VERSION:
556 last_error_.code = ERROR_UNSUPPORTED;
557 break;
558 }
461 return false; 559 return false;
462} 560}
463 561
diff --git a/libunwindstack/ElfInterfaceArm.cpp b/libunwindstack/ElfInterfaceArm.cpp
index 5d99bd791..616d1b1a1 100644
--- a/libunwindstack/ElfInterfaceArm.cpp
+++ b/libunwindstack/ElfInterfaceArm.cpp
@@ -28,6 +28,7 @@ namespace unwindstack {
28 28
29bool ElfInterfaceArm::FindEntry(uint32_t pc, uint64_t* entry_offset) { 29bool ElfInterfaceArm::FindEntry(uint32_t pc, uint64_t* entry_offset) {
30 if (start_offset_ == 0 || total_entries_ == 0) { 30 if (start_offset_ == 0 || total_entries_ == 0) {
31 last_error_.code = ERROR_UNWIND_INFO;
31 return false; 32 return false;
32 } 33 }
33 34
@@ -56,12 +57,15 @@ bool ElfInterfaceArm::FindEntry(uint32_t pc, uint64_t* entry_offset) {
56 *entry_offset = start_offset_ + (last - 1) * 8; 57 *entry_offset = start_offset_ + (last - 1) * 8;
57 return true; 58 return true;
58 } 59 }
60 last_error_.code = ERROR_UNWIND_INFO;
59 return false; 61 return false;
60} 62}
61 63
62bool ElfInterfaceArm::GetPrel31Addr(uint32_t offset, uint32_t* addr) { 64bool ElfInterfaceArm::GetPrel31Addr(uint32_t offset, uint32_t* addr) {
63 uint32_t data; 65 uint32_t data;
64 if (!memory_->Read32(offset, &data)) { 66 if (!memory_->Read32(offset, &data)) {
67 last_error_.code = ERROR_MEMORY_INVALID;
68 last_error_.address = offset;
65 return false; 69 return false;
66 } 70 }
67 71
@@ -106,6 +110,7 @@ bool ElfInterfaceArm::StepExidx(uint64_t pc, uint64_t load_bias, Regs* regs, Mem
106 bool* finished) { 110 bool* finished) {
107 // Adjust the load bias to get the real relative pc. 111 // Adjust the load bias to get the real relative pc.
108 if (pc < load_bias) { 112 if (pc < load_bias) {
113 last_error_.code = ERROR_UNWIND_INFO;
109 return false; 114 return false;
110 } 115 }
111 pc -= load_bias; 116 pc -= load_bias;
@@ -139,6 +144,30 @@ bool ElfInterfaceArm::StepExidx(uint64_t pc, uint64_t load_bias, Regs* regs, Mem
139 *finished = true; 144 *finished = true;
140 return true; 145 return true;
141 } 146 }
147
148 if (!return_value) {
149 switch (arm.status()) {
150 case ARM_STATUS_NONE:
151 case ARM_STATUS_NO_UNWIND:
152 case ARM_STATUS_FINISH:
153 last_error_.code = ERROR_NONE;
154 break;
155
156 case ARM_STATUS_RESERVED:
157 case ARM_STATUS_SPARE:
158 case ARM_STATUS_TRUNCATED:
159 case ARM_STATUS_MALFORMED:
160 case ARM_STATUS_INVALID_ALIGNMENT:
161 case ARM_STATUS_INVALID_PERSONALITY:
162 last_error_.code = ERROR_UNWIND_INFO;
163 break;
164
165 case ARM_STATUS_READ_FAILED:
166 last_error_.code = ERROR_MEMORY_INVALID;
167 last_error_.address = arm.status_address();
168 break;
169 }
170 }
142 return return_value; 171 return return_value;
143} 172}
144 173
diff --git a/libunwindstack/Unwinder.cpp b/libunwindstack/Unwinder.cpp
index d71177290..f70ed7b2a 100644
--- a/libunwindstack/Unwinder.cpp
+++ b/libunwindstack/Unwinder.cpp
@@ -78,6 +78,8 @@ static bool ShouldStop(const std::vector<std::string>* map_suffixes_to_ignore,
78void Unwinder::Unwind(const std::vector<std::string>* initial_map_names_to_skip, 78void Unwinder::Unwind(const std::vector<std::string>* initial_map_names_to_skip,
79 const std::vector<std::string>* map_suffixes_to_ignore) { 79 const std::vector<std::string>* map_suffixes_to_ignore) {
80 frames_.clear(); 80 frames_.clear();
81 last_error_.code = ERROR_NONE;
82 last_error_.address = 0;
81 83
82 bool return_address_attempt = false; 84 bool return_address_attempt = false;
83 bool adjust_pc = false; 85 bool adjust_pc = false;
@@ -95,6 +97,7 @@ void Unwinder::Unwind(const std::vector<std::string>* initial_map_names_to_skip,
95 rel_pc = regs_->pc(); 97 rel_pc = regs_->pc();
96 adjusted_rel_pc = rel_pc; 98 adjusted_rel_pc = rel_pc;
97 adjusted_pc = rel_pc; 99 adjusted_pc = rel_pc;
100 last_error_.code = ERROR_INVALID_MAP;
98 } else { 101 } else {
99 if (ShouldStop(map_suffixes_to_ignore, map_info->name)) { 102 if (ShouldStop(map_suffixes_to_ignore, map_info->name)) {
100 break; 103 break;
@@ -155,6 +158,7 @@ void Unwinder::Unwind(const std::vector<std::string>* initial_map_names_to_skip,
155 bool finished; 158 bool finished;
156 stepped = elf->Step(rel_pc, adjusted_pc, map_info->elf_offset, regs_, 159 stepped = elf->Step(rel_pc, adjusted_pc, map_info->elf_offset, regs_,
157 process_memory_.get(), &finished); 160 process_memory_.get(), &finished);
161 elf->GetLastError(&last_error_);
158 if (stepped && finished) { 162 if (stepped && finished) {
159 break; 163 break;
160 } 164 }
@@ -180,10 +184,14 @@ void Unwinder::Unwind(const std::vector<std::string>* initial_map_names_to_skip,
180 } 184 }
181 } else { 185 } else {
182 return_address_attempt = false; 186 return_address_attempt = false;
187 if (max_frames_ == frames_.size()) {
188 last_error_.code = ERROR_MAX_FRAMES_EXCEEDED;
189 }
183 } 190 }
184 191
185 // If the pc and sp didn't change, then consider everything stopped. 192 // If the pc and sp didn't change, then consider everything stopped.
186 if (cur_pc == regs_->pc() && cur_sp == regs_->sp()) { 193 if (cur_pc == regs_->pc() && cur_sp == regs_->sp()) {
194 last_error_.code = ERROR_REPEATED_FRAME;
187 break; 195 break;
188 } 196 }
189 } 197 }
diff --git a/libunwindstack/include/unwindstack/DwarfError.h b/libunwindstack/include/unwindstack/DwarfError.h
new file mode 100644
index 000000000..763e2cbfe
--- /dev/null
+++ b/libunwindstack/include/unwindstack/DwarfError.h
@@ -0,0 +1,44 @@
1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef _LIBUNWINDSTACK_DWARF_ERROR_H
18#define _LIBUNWINDSTACK_DWARF_ERROR_H
19
20#include <stdint.h>
21
22namespace unwindstack {
23
24enum DwarfErrorCode : uint8_t {
25 DWARF_ERROR_NONE,
26 DWARF_ERROR_MEMORY_INVALID,
27 DWARF_ERROR_ILLEGAL_VALUE,
28 DWARF_ERROR_ILLEGAL_STATE,
29 DWARF_ERROR_STACK_INDEX_NOT_VALID,
30 DWARF_ERROR_NOT_IMPLEMENTED,
31 DWARF_ERROR_TOO_MANY_ITERATIONS,
32 DWARF_ERROR_CFA_NOT_DEFINED,
33 DWARF_ERROR_UNSUPPORTED_VERSION,
34 DWARF_ERROR_NO_FDES,
35};
36
37struct DwarfErrorData {
38 DwarfErrorCode code;
39 uint64_t address;
40};
41
42} // namespace unwindstack
43
44#endif // _LIBUNWINDSTACK_DWARF_ERROR_H
diff --git a/libunwindstack/include/unwindstack/DwarfSection.h b/libunwindstack/include/unwindstack/DwarfSection.h
index e0004aa46..03f40d699 100644
--- a/libunwindstack/include/unwindstack/DwarfSection.h
+++ b/libunwindstack/include/unwindstack/DwarfSection.h
@@ -22,6 +22,7 @@
22#include <iterator> 22#include <iterator>
23#include <unordered_map> 23#include <unordered_map>
24 24
25#include <unwindstack/DwarfError.h>
25#include <unwindstack/DwarfLocation.h> 26#include <unwindstack/DwarfLocation.h>
26#include <unwindstack/DwarfMemory.h> 27#include <unwindstack/DwarfMemory.h>
27#include <unwindstack/DwarfStructs.h> 28#include <unwindstack/DwarfStructs.h>
@@ -29,7 +30,6 @@
29namespace unwindstack { 30namespace unwindstack {
30 31
31// Forward declarations. 32// Forward declarations.
32enum DwarfError : uint8_t;
33class Memory; 33class Memory;
34class Regs; 34class Regs;
35 35
@@ -72,7 +72,8 @@ class DwarfSection {
72 iterator begin() { return iterator(this, 0); } 72 iterator begin() { return iterator(this, 0); }
73 iterator end() { return iterator(this, fde_count_); } 73 iterator end() { return iterator(this, fde_count_); }
74 74
75 DwarfError last_error() { return last_error_; } 75 DwarfErrorCode LastErrorCode() { return last_error_.code; }
76 uint64_t LastErrorAddress() { return last_error_.address; }
76 77
77 virtual bool Init(uint64_t offset, uint64_t size) = 0; 78 virtual bool Init(uint64_t offset, uint64_t size) = 0;
78 79
@@ -100,7 +101,7 @@ class DwarfSection {
100 101
101 protected: 102 protected:
102 DwarfMemory memory_; 103 DwarfMemory memory_;
103 DwarfError last_error_; 104 DwarfErrorData last_error_{DWARF_ERROR_NONE, 0};
104 105
105 uint32_t cie32_value_ = 0; 106 uint32_t cie32_value_ = 0;
106 uint64_t cie64_value_ = 0; 107 uint64_t cie64_value_ = 0;
diff --git a/libunwindstack/include/unwindstack/Elf.h b/libunwindstack/include/unwindstack/Elf.h
index 5f343916a..e562d6de9 100644
--- a/libunwindstack/include/unwindstack/Elf.h
+++ b/libunwindstack/include/unwindstack/Elf.h
@@ -72,6 +72,10 @@ class Elf {
72 72
73 bool IsValidPc(uint64_t pc); 73 bool IsValidPc(uint64_t pc);
74 74
75 void GetLastError(ErrorData* data);
76 ErrorCode GetLastErrorCode();
77 uint64_t GetLastErrorAddress();
78
75 bool valid() { return valid_; } 79 bool valid() { return valid_; }
76 80
77 uint32_t machine_type() { return machine_type_; } 81 uint32_t machine_type() { return machine_type_; }
diff --git a/libunwindstack/include/unwindstack/ElfInterface.h b/libunwindstack/include/unwindstack/ElfInterface.h
index faa61ee97..ea9ec9dac 100644
--- a/libunwindstack/include/unwindstack/ElfInterface.h
+++ b/libunwindstack/include/unwindstack/ElfInterface.h
@@ -26,6 +26,7 @@
26#include <vector> 26#include <vector>
27 27
28#include <unwindstack/DwarfSection.h> 28#include <unwindstack/DwarfSection.h>
29#include <unwindstack/Error.h>
29 30
30namespace unwindstack { 31namespace unwindstack {
31 32
@@ -90,6 +91,10 @@ class ElfInterface {
90 DwarfSection* eh_frame() { return eh_frame_.get(); } 91 DwarfSection* eh_frame() { return eh_frame_.get(); }
91 DwarfSection* debug_frame() { return debug_frame_.get(); } 92 DwarfSection* debug_frame() { return debug_frame_.get(); }
92 93
94 const ErrorData& last_error() { return last_error_; }
95 ErrorCode LastErrorCode() { return last_error_.code; }
96 uint64_t LastErrorAddress() { return last_error_.address; }
97
93 template <typename EhdrType, typename PhdrType> 98 template <typename EhdrType, typename PhdrType>
94 static uint64_t GetLoadBias(Memory* memory); 99 static uint64_t GetLoadBias(Memory* memory);
95 100
@@ -144,6 +149,8 @@ class ElfInterface {
144 uint8_t soname_type_ = SONAME_UNKNOWN; 149 uint8_t soname_type_ = SONAME_UNKNOWN;
145 std::string soname_; 150 std::string soname_;
146 151
152 ErrorData last_error_{ERROR_NONE, 0};
153
147 std::unique_ptr<DwarfSection> eh_frame_; 154 std::unique_ptr<DwarfSection> eh_frame_;
148 std::unique_ptr<DwarfSection> debug_frame_; 155 std::unique_ptr<DwarfSection> debug_frame_;
149 // The Elf object owns the gnu_debugdata interface object. 156 // The Elf object owns the gnu_debugdata interface object.
diff --git a/libunwindstack/include/unwindstack/Error.h b/libunwindstack/include/unwindstack/Error.h
new file mode 100644
index 000000000..6ed0e0fb0
--- /dev/null
+++ b/libunwindstack/include/unwindstack/Error.h
@@ -0,0 +1,42 @@
1/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef _LIBUNWINDSTACK_ERROR_H
18#define _LIBUNWINDSTACK_ERROR_H
19
20#include <stdint.h>
21
22namespace unwindstack {
23
24enum ErrorCode : uint8_t {
25 ERROR_NONE, // No error.
26 ERROR_MEMORY_INVALID, // Memory read failed.
27 ERROR_UNWIND_INFO, // Unable to use unwind information to unwind.
28 ERROR_UNSUPPORTED, // Encountered unsupported feature.
29 ERROR_INVALID_MAP, // Unwind in an invalid map.
30 ERROR_MAX_FRAMES_EXCEEDED, // The number of frames exceed the total allowed.
31 ERROR_REPEATED_FRAME, // The last frame has the same pc/sp as the next.
32};
33
34struct ErrorData {
35 ErrorCode code;
36 uint64_t address; // Only valid when code is ERROR_MEMORY_INVALID.
37 // Indicates the failing address.
38};
39
40} // namespace unwindstack
41
42#endif // _LIBUNWINDSTACK_ERROR_H
diff --git a/libunwindstack/include/unwindstack/Unwinder.h b/libunwindstack/include/unwindstack/Unwinder.h
index 32858ae52..a7b57e6a7 100644
--- a/libunwindstack/include/unwindstack/Unwinder.h
+++ b/libunwindstack/include/unwindstack/Unwinder.h
@@ -24,6 +24,7 @@
24#include <string> 24#include <string>
25#include <vector> 25#include <vector>
26 26
27#include <unwindstack/Error.h>
27#include <unwindstack/Maps.h> 28#include <unwindstack/Maps.h>
28#include <unwindstack/Memory.h> 29#include <unwindstack/Memory.h>
29#include <unwindstack/Regs.h> 30#include <unwindstack/Regs.h>
@@ -74,6 +75,9 @@ class Unwinder {
74 75
75 void SetJitDebug(JitDebug* jit_debug, ArchEnum arch); 76 void SetJitDebug(JitDebug* jit_debug, ArchEnum arch);
76 77
78 ErrorCode LastErrorCode() { return last_error_.code; }
79 uint64_t LastErrorAddress() { return last_error_.address; }
80
77 private: 81 private:
78 void FillInFrame(MapInfo* map_info, Elf* elf, uint64_t adjusted_rel_pc, uint64_t adjusted_pc); 82 void FillInFrame(MapInfo* map_info, Elf* elf, uint64_t adjusted_rel_pc, uint64_t adjusted_pc);
79 83
@@ -83,6 +87,7 @@ class Unwinder {
83 std::vector<FrameData> frames_; 87 std::vector<FrameData> frames_;
84 std::shared_ptr<Memory> process_memory_; 88 std::shared_ptr<Memory> process_memory_;
85 JitDebug* jit_debug_ = nullptr; 89 JitDebug* jit_debug_ = nullptr;
90 ErrorData last_error_;
86}; 91};
87 92
88} // namespace unwindstack 93} // namespace unwindstack
diff --git a/libunwindstack/tests/ArmExidxExtractTest.cpp b/libunwindstack/tests/ArmExidxExtractTest.cpp
index caad13165..8d0f0e599 100644
--- a/libunwindstack/tests/ArmExidxExtractTest.cpp
+++ b/libunwindstack/tests/ArmExidxExtractTest.cpp
@@ -257,22 +257,27 @@ TEST_F(ArmExidxExtractTest, second_read_not_compact) {
257TEST_F(ArmExidxExtractTest, read_failures) { 257TEST_F(ArmExidxExtractTest, read_failures) {
258 ASSERT_FALSE(exidx_->ExtractEntryData(0x5000)); 258 ASSERT_FALSE(exidx_->ExtractEntryData(0x5000));
259 ASSERT_EQ(ARM_STATUS_READ_FAILED, exidx_->status()); 259 ASSERT_EQ(ARM_STATUS_READ_FAILED, exidx_->status());
260 EXPECT_EQ(0x5004U, exidx_->status_address());
260 261
261 elf_memory_.SetData32(0x5000, 0x100); 262 elf_memory_.SetData32(0x5000, 0x100);
262 ASSERT_FALSE(exidx_->ExtractEntryData(0x5000)); 263 ASSERT_FALSE(exidx_->ExtractEntryData(0x5000));
263 ASSERT_EQ(ARM_STATUS_READ_FAILED, exidx_->status()); 264 ASSERT_EQ(ARM_STATUS_READ_FAILED, exidx_->status());
265 EXPECT_EQ(0x5004U, exidx_->status_address());
264 266
265 elf_memory_.SetData32(0x5004, 0x100); 267 elf_memory_.SetData32(0x5004, 0x100);
266 ASSERT_FALSE(exidx_->ExtractEntryData(0x5000)); 268 ASSERT_FALSE(exidx_->ExtractEntryData(0x5000));
267 ASSERT_EQ(ARM_STATUS_READ_FAILED, exidx_->status()); 269 ASSERT_EQ(ARM_STATUS_READ_FAILED, exidx_->status());
270 EXPECT_EQ(0x5104U, exidx_->status_address());
268 271
269 elf_memory_.SetData32(0x5104, 0x1); 272 elf_memory_.SetData32(0x5104, 0x1);
270 ASSERT_FALSE(exidx_->ExtractEntryData(0x5000)); 273 ASSERT_FALSE(exidx_->ExtractEntryData(0x5000));
271 ASSERT_EQ(ARM_STATUS_READ_FAILED, exidx_->status()); 274 ASSERT_EQ(ARM_STATUS_READ_FAILED, exidx_->status());
275 EXPECT_EQ(0x5108U, exidx_->status_address());
272 276
273 elf_memory_.SetData32(0x5108, 0x01010203); 277 elf_memory_.SetData32(0x5108, 0x01010203);
274 ASSERT_FALSE(exidx_->ExtractEntryData(0x5000)); 278 ASSERT_FALSE(exidx_->ExtractEntryData(0x5000));
275 ASSERT_EQ(ARM_STATUS_READ_FAILED, exidx_->status()); 279 ASSERT_EQ(ARM_STATUS_READ_FAILED, exidx_->status());
280 EXPECT_EQ(0x510cU, exidx_->status_address());
276} 281}
277 282
278TEST_F(ArmExidxExtractTest, malformed) { 283TEST_F(ArmExidxExtractTest, malformed) {
diff --git a/libunwindstack/tests/DwarfCfaTest.cpp b/libunwindstack/tests/DwarfCfaTest.cpp
index 73a67ac6a..68dc30cd9 100644
--- a/libunwindstack/tests/DwarfCfaTest.cpp
+++ b/libunwindstack/tests/DwarfCfaTest.cpp
@@ -21,13 +21,13 @@
21 21
22#include <gtest/gtest.h> 22#include <gtest/gtest.h>
23 23
24#include <unwindstack/DwarfError.h>
24#include <unwindstack/DwarfLocation.h> 25#include <unwindstack/DwarfLocation.h>
25#include <unwindstack/DwarfMemory.h> 26#include <unwindstack/DwarfMemory.h>
26#include <unwindstack/DwarfStructs.h> 27#include <unwindstack/DwarfStructs.h>
27#include <unwindstack/Log.h> 28#include <unwindstack/Log.h>
28 29
29#include "DwarfCfa.h" 30#include "DwarfCfa.h"
30#include "DwarfError.h"
31 31
32#include "LogFake.h" 32#include "LogFake.h"
33#include "MemoryFake.h" 33#include "MemoryFake.h"
@@ -78,7 +78,7 @@ TYPED_TEST_P(DwarfCfaTest, cfa_illegal) {
78 dwarf_loc_regs_t loc_regs; 78 dwarf_loc_regs_t loc_regs;
79 79
80 ASSERT_FALSE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x2000, 0x2001, &loc_regs)); 80 ASSERT_FALSE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x2000, 0x2001, &loc_regs));
81 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->cfa_->last_error()); 81 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->cfa_->LastErrorCode());
82 ASSERT_EQ(0x2001U, this->dmem_->cur_offset()); 82 ASSERT_EQ(0x2001U, this->dmem_->cur_offset());
83 83
84 ASSERT_EQ("", GetFakeLogPrint()); 84 ASSERT_EQ("", GetFakeLogPrint());
@@ -198,7 +198,7 @@ TYPED_TEST_P(DwarfCfaTest, cfa_restore) {
198 dwarf_loc_regs_t loc_regs; 198 dwarf_loc_regs_t loc_regs;
199 199
200 ASSERT_FALSE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x2000, 0x2001, &loc_regs)); 200 ASSERT_FALSE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x2000, 0x2001, &loc_regs));
201 ASSERT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->cfa_->last_error()); 201 ASSERT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->cfa_->LastErrorCode());
202 ASSERT_EQ(0x2001U, this->dmem_->cur_offset()); 202 ASSERT_EQ(0x2001U, this->dmem_->cur_offset());
203 ASSERT_EQ(0U, loc_regs.size()); 203 ASSERT_EQ(0U, loc_regs.size());
204 204
@@ -227,7 +227,7 @@ TYPED_TEST_P(DwarfCfaTest, cfa_restore_extended) {
227 dwarf_loc_regs_t loc_regs; 227 dwarf_loc_regs_t loc_regs;
228 228
229 ASSERT_FALSE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x4000, 0x4002, &loc_regs)); 229 ASSERT_FALSE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x4000, 0x4002, &loc_regs));
230 ASSERT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->cfa_->last_error()); 230 ASSERT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->cfa_->LastErrorCode());
231 ASSERT_EQ(0x4002U, this->dmem_->cur_offset()); 231 ASSERT_EQ(0x4002U, this->dmem_->cur_offset());
232 ASSERT_EQ(0U, loc_regs.size()); 232 ASSERT_EQ(0U, loc_regs.size());
233 233
@@ -594,7 +594,7 @@ TYPED_TEST_P(DwarfCfaTest, cfa_def_cfa_register) {
594 // This fails because the cfa is not defined as a register. 594 // This fails because the cfa is not defined as a register.
595 ASSERT_FALSE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x102, &loc_regs)); 595 ASSERT_FALSE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x102, &loc_regs));
596 ASSERT_EQ(0U, loc_regs.size()); 596 ASSERT_EQ(0U, loc_regs.size());
597 ASSERT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->cfa_->last_error()); 597 ASSERT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->cfa_->LastErrorCode());
598 598
599 ASSERT_EQ("4 unwind Attempt to set new register, but cfa is not already set to a register.\n", 599 ASSERT_EQ("4 unwind Attempt to set new register, but cfa is not already set to a register.\n",
600 GetFakeLogPrint()); 600 GetFakeLogPrint());
@@ -637,7 +637,7 @@ TYPED_TEST_P(DwarfCfaTest, cfa_def_cfa_offset) {
637 // This fails because the cfa is not defined as a register. 637 // This fails because the cfa is not defined as a register.
638 ASSERT_FALSE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x102, &loc_regs)); 638 ASSERT_FALSE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x102, &loc_regs));
639 ASSERT_EQ(0U, loc_regs.size()); 639 ASSERT_EQ(0U, loc_regs.size());
640 ASSERT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->cfa_->last_error()); 640 ASSERT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->cfa_->LastErrorCode());
641 641
642 ASSERT_EQ("4 unwind Attempt to set offset, but cfa is not set to a register.\n", 642 ASSERT_EQ("4 unwind Attempt to set offset, but cfa is not set to a register.\n",
643 GetFakeLogPrint()); 643 GetFakeLogPrint());
@@ -679,7 +679,7 @@ TYPED_TEST_P(DwarfCfaTest, cfa_def_cfa_offset_sf) {
679 679
680 // This fails because the cfa is not defined as a register. 680 // This fails because the cfa is not defined as a register.
681 ASSERT_FALSE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x102, &loc_regs)); 681 ASSERT_FALSE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x102, &loc_regs));
682 ASSERT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->cfa_->last_error()); 682 ASSERT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->cfa_->LastErrorCode());
683 683
684 ASSERT_EQ("4 unwind Attempt to set offset, but cfa is not set to a register.\n", 684 ASSERT_EQ("4 unwind Attempt to set offset, but cfa is not set to a register.\n",
685 GetFakeLogPrint()); 685 GetFakeLogPrint());
diff --git a/libunwindstack/tests/DwarfDebugFrameTest.cpp b/libunwindstack/tests/DwarfDebugFrameTest.cpp
index 243198e4f..c28a41edb 100644
--- a/libunwindstack/tests/DwarfDebugFrameTest.cpp
+++ b/libunwindstack/tests/DwarfDebugFrameTest.cpp
@@ -19,9 +19,10 @@
19#include <gmock/gmock.h> 19#include <gmock/gmock.h>
20#include <gtest/gtest.h> 20#include <gtest/gtest.h>
21 21
22#include <unwindstack/DwarfError.h>
23
22#include "DwarfDebugFrame.h" 24#include "DwarfDebugFrame.h"
23#include "DwarfEncoding.h" 25#include "DwarfEncoding.h"
24#include "DwarfError.h"
25 26
26#include "LogFake.h" 27#include "LogFake.h"
27#include "MemoryFake.h" 28#include "MemoryFake.h"
@@ -142,7 +143,7 @@ TYPED_TEST_P(DwarfDebugFrameTest, Init32_fde_not_following_cie) {
142 this->memory_.SetData32(0x510c, 0x200); 143 this->memory_.SetData32(0x510c, 0x200);
143 144
144 ASSERT_FALSE(this->debug_frame_->Init(0x5000, 0x600)); 145 ASSERT_FALSE(this->debug_frame_->Init(0x5000, 0x600));
145 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->debug_frame_->last_error()); 146 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->debug_frame_->LastErrorCode());
146} 147}
147 148
148TYPED_TEST_P(DwarfDebugFrameTest, Init32_do_not_fail_on_bad_next_entry) { 149TYPED_TEST_P(DwarfDebugFrameTest, Init32_do_not_fail_on_bad_next_entry) {
@@ -267,7 +268,7 @@ TYPED_TEST_P(DwarfDebugFrameTest, Init64_fde_not_following_cie) {
267 this->memory_.SetData64(0x511c, 0x200); 268 this->memory_.SetData64(0x511c, 0x200);
268 269
269 ASSERT_FALSE(this->debug_frame_->Init(0x5000, 0x600)); 270 ASSERT_FALSE(this->debug_frame_->Init(0x5000, 0x600));
270 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->debug_frame_->last_error()); 271 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->debug_frame_->LastErrorCode());
271} 272}
272 273
273TYPED_TEST_P(DwarfDebugFrameTest, Init64_do_not_fail_on_bad_next_entry) { 274TYPED_TEST_P(DwarfDebugFrameTest, Init64_do_not_fail_on_bad_next_entry) {
@@ -404,11 +405,11 @@ TYPED_TEST_P(DwarfDebugFrameTest, GetFdeOffsetFromPc) {
404 this->debug_frame_->TestSetFdeCount(0); 405 this->debug_frame_->TestSetFdeCount(0);
405 uint64_t fde_offset; 406 uint64_t fde_offset;
406 ASSERT_FALSE(this->debug_frame_->GetFdeOffsetFromPc(0x1000, &fde_offset)); 407 ASSERT_FALSE(this->debug_frame_->GetFdeOffsetFromPc(0x1000, &fde_offset));
407 ASSERT_EQ(DWARF_ERROR_NONE, this->debug_frame_->last_error()); 408 ASSERT_EQ(DWARF_ERROR_NONE, this->debug_frame_->LastErrorCode());
408 409
409 this->debug_frame_->TestSetFdeCount(9); 410 this->debug_frame_->TestSetFdeCount(9);
410 ASSERT_FALSE(this->debug_frame_->GetFdeOffsetFromPc(0x100, &fde_offset)); 411 ASSERT_FALSE(this->debug_frame_->GetFdeOffsetFromPc(0x100, &fde_offset));
411 ASSERT_EQ(DWARF_ERROR_NONE, this->debug_frame_->last_error()); 412 ASSERT_EQ(DWARF_ERROR_NONE, this->debug_frame_->LastErrorCode());
412 // Odd number of elements. 413 // Odd number of elements.
413 for (size_t i = 0; i < 9; i++) { 414 for (size_t i = 0; i < 9; i++) {
414 TypeParam pc = 0x1000 * (i + 1); 415 TypeParam pc = 0x1000 * (i + 1);
@@ -422,7 +423,7 @@ TYPED_TEST_P(DwarfDebugFrameTest, GetFdeOffsetFromPc) {
422 EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i; 423 EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i;
423 ASSERT_FALSE(this->debug_frame_->GetFdeOffsetFromPc(pc + 0xfff, &fde_offset)) 424 ASSERT_FALSE(this->debug_frame_->GetFdeOffsetFromPc(pc + 0xfff, &fde_offset))
424 << "Failed at index " << i; 425 << "Failed at index " << i;
425 ASSERT_EQ(DWARF_ERROR_NONE, this->debug_frame_->last_error()); 426 ASSERT_EQ(DWARF_ERROR_NONE, this->debug_frame_->LastErrorCode());
426 } 427 }
427 428
428 // Even number of elements. 429 // Even number of elements.
@@ -444,7 +445,7 @@ TYPED_TEST_P(DwarfDebugFrameTest, GetFdeOffsetFromPc) {
444 EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i; 445 EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i;
445 ASSERT_FALSE(this->debug_frame_->GetFdeOffsetFromPc(pc + 0xfff, &fde_offset)) 446 ASSERT_FALSE(this->debug_frame_->GetFdeOffsetFromPc(pc + 0xfff, &fde_offset))
446 << "Failed at index " << i; 447 << "Failed at index " << i;
447 ASSERT_EQ(DWARF_ERROR_NONE, this->debug_frame_->last_error()); 448 ASSERT_EQ(DWARF_ERROR_NONE, this->debug_frame_->LastErrorCode());
448 } 449 }
449} 450}
450 451
diff --git a/libunwindstack/tests/DwarfEhFrameTest.cpp b/libunwindstack/tests/DwarfEhFrameTest.cpp
index 3a629f886..a73db6580 100644
--- a/libunwindstack/tests/DwarfEhFrameTest.cpp
+++ b/libunwindstack/tests/DwarfEhFrameTest.cpp
@@ -19,9 +19,10 @@
19#include <gmock/gmock.h> 19#include <gmock/gmock.h>
20#include <gtest/gtest.h> 20#include <gtest/gtest.h>
21 21
22#include <unwindstack/DwarfError.h>
23
22#include "DwarfEhFrame.h" 24#include "DwarfEhFrame.h"
23#include "DwarfEncoding.h" 25#include "DwarfEncoding.h"
24#include "DwarfError.h"
25 26
26#include "LogFake.h" 27#include "LogFake.h"
27#include "MemoryFake.h" 28#include "MemoryFake.h"
@@ -142,7 +143,7 @@ TYPED_TEST_P(DwarfEhFrameTest, Init32_fde_not_following_cie) {
142 this->memory_.SetData32(0x510c, 0x200); 143 this->memory_.SetData32(0x510c, 0x200);
143 144
144 ASSERT_FALSE(this->eh_frame_->Init(0x5000, 0x600)); 145 ASSERT_FALSE(this->eh_frame_->Init(0x5000, 0x600));
145 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->eh_frame_->last_error()); 146 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->eh_frame_->LastErrorCode());
146} 147}
147 148
148TYPED_TEST_P(DwarfEhFrameTest, Init64) { 149TYPED_TEST_P(DwarfEhFrameTest, Init64) {
@@ -228,7 +229,7 @@ TYPED_TEST_P(DwarfEhFrameTest, Init64_fde_not_following_cie) {
228 this->memory_.SetData64(0x511c, 0x200); 229 this->memory_.SetData64(0x511c, 0x200);
229 230
230 ASSERT_FALSE(this->eh_frame_->Init(0x5000, 0x600)); 231 ASSERT_FALSE(this->eh_frame_->Init(0x5000, 0x600));
231 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->eh_frame_->last_error()); 232 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->eh_frame_->LastErrorCode());
232} 233}
233 234
234TYPED_TEST_P(DwarfEhFrameTest, Init_version1) { 235TYPED_TEST_P(DwarfEhFrameTest, Init_version1) {
@@ -320,11 +321,11 @@ TYPED_TEST_P(DwarfEhFrameTest, GetFdeOffsetFromPc) {
320 this->eh_frame_->TestSetFdeCount(0); 321 this->eh_frame_->TestSetFdeCount(0);
321 uint64_t fde_offset; 322 uint64_t fde_offset;
322 ASSERT_FALSE(this->eh_frame_->GetFdeOffsetFromPc(0x1000, &fde_offset)); 323 ASSERT_FALSE(this->eh_frame_->GetFdeOffsetFromPc(0x1000, &fde_offset));
323 ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->last_error()); 324 ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->LastErrorCode());
324 325
325 this->eh_frame_->TestSetFdeCount(9); 326 this->eh_frame_->TestSetFdeCount(9);
326 ASSERT_FALSE(this->eh_frame_->GetFdeOffsetFromPc(0x100, &fde_offset)); 327 ASSERT_FALSE(this->eh_frame_->GetFdeOffsetFromPc(0x100, &fde_offset));
327 ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->last_error()); 328 ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->LastErrorCode());
328 // Odd number of elements. 329 // Odd number of elements.
329 for (size_t i = 0; i < 9; i++) { 330 for (size_t i = 0; i < 9; i++) {
330 TypeParam pc = 0x1000 * (i + 1); 331 TypeParam pc = 0x1000 * (i + 1);
@@ -337,7 +338,7 @@ TYPED_TEST_P(DwarfEhFrameTest, GetFdeOffsetFromPc) {
337 EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i; 338 EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i;
338 ASSERT_FALSE(this->eh_frame_->GetFdeOffsetFromPc(pc + 0xfff, &fde_offset)) 339 ASSERT_FALSE(this->eh_frame_->GetFdeOffsetFromPc(pc + 0xfff, &fde_offset))
339 << "Failed at index " << i; 340 << "Failed at index " << i;
340 ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->last_error()); 341 ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->LastErrorCode());
341 } 342 }
342 343
343 // Even number of elements. 344 // Even number of elements.
@@ -358,7 +359,7 @@ TYPED_TEST_P(DwarfEhFrameTest, GetFdeOffsetFromPc) {
358 EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i; 359 EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i;
359 ASSERT_FALSE(this->eh_frame_->GetFdeOffsetFromPc(pc + 0xfff, &fde_offset)) 360 ASSERT_FALSE(this->eh_frame_->GetFdeOffsetFromPc(pc + 0xfff, &fde_offset))
360 << "Failed at index " << i; 361 << "Failed at index " << i;
361 ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->last_error()); 362 ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->LastErrorCode());
362 } 363 }
363} 364}
364 365
diff --git a/libunwindstack/tests/DwarfEhFrameWithHdrTest.cpp b/libunwindstack/tests/DwarfEhFrameWithHdrTest.cpp
index ef2fb32ab..a2ae5ebf7 100644
--- a/libunwindstack/tests/DwarfEhFrameWithHdrTest.cpp
+++ b/libunwindstack/tests/DwarfEhFrameWithHdrTest.cpp
@@ -19,9 +19,10 @@
19#include <gmock/gmock.h> 19#include <gmock/gmock.h>
20#include <gtest/gtest.h> 20#include <gtest/gtest.h>
21 21
22#include <unwindstack/DwarfError.h>
23
22#include "DwarfEhFrameWithHdr.h" 24#include "DwarfEhFrameWithHdr.h"
23#include "DwarfEncoding.h" 25#include "DwarfEncoding.h"
24#include "DwarfError.h"
25 26
26#include "LogFake.h" 27#include "LogFake.h"
27#include "MemoryFake.h" 28#include "MemoryFake.h"
@@ -97,25 +98,29 @@ TYPED_TEST_P(DwarfEhFrameWithHdrTest, Init) {
97 // Verify a zero fde count fails to init. 98 // Verify a zero fde count fails to init.
98 this->memory_.SetData32(0x1006, 0); 99 this->memory_.SetData32(0x1006, 0);
99 ASSERT_FALSE(this->eh_frame_->Init(0x1000, 0x100)); 100 ASSERT_FALSE(this->eh_frame_->Init(0x1000, 0x100));
100 ASSERT_EQ(DWARF_ERROR_NO_FDES, this->eh_frame_->last_error()); 101 ASSERT_EQ(DWARF_ERROR_NO_FDES, this->eh_frame_->LastErrorCode());
101 102
102 // Verify an unexpected version will cause a fail. 103 // Verify an unexpected version will cause a fail.
103 this->memory_.SetData32(0x1006, 126); 104 this->memory_.SetData32(0x1006, 126);
104 this->memory_.SetData8(0x1000, 0); 105 this->memory_.SetData8(0x1000, 0);
105 ASSERT_FALSE(this->eh_frame_->Init(0x1000, 0x100)); 106 ASSERT_FALSE(this->eh_frame_->Init(0x1000, 0x100));
106 ASSERT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->eh_frame_->last_error()); 107 ASSERT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->eh_frame_->LastErrorCode());
107 this->memory_.SetData8(0x1000, 2); 108 this->memory_.SetData8(0x1000, 2);
108 ASSERT_FALSE(this->eh_frame_->Init(0x1000, 0x100)); 109 ASSERT_FALSE(this->eh_frame_->Init(0x1000, 0x100));
109 ASSERT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->eh_frame_->last_error()); 110 ASSERT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->eh_frame_->LastErrorCode());
110} 111}
111 112
112TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeInfoFromIndex_expect_cache_fail) { 113TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeInfoFromIndex_expect_cache_fail) {
113 this->eh_frame_->TestSetTableEntrySize(0x10); 114 this->eh_frame_->TestSetTableEntrySize(0x10);
114 this->eh_frame_->TestSetTableEncoding(DW_EH_PE_udata4); 115 this->eh_frame_->TestSetTableEncoding(DW_EH_PE_udata4);
116 this->eh_frame_->TestSetEntriesOffset(0x1000);
117
115 ASSERT_TRUE(this->eh_frame_->GetFdeInfoFromIndex(0) == nullptr); 118 ASSERT_TRUE(this->eh_frame_->GetFdeInfoFromIndex(0) == nullptr);
116 ASSERT_EQ(DWARF_ERROR_MEMORY_INVALID, this->eh_frame_->last_error()); 119 ASSERT_EQ(DWARF_ERROR_MEMORY_INVALID, this->eh_frame_->LastErrorCode());
120 EXPECT_EQ(0x1000U, this->eh_frame_->LastErrorAddress());
117 ASSERT_TRUE(this->eh_frame_->GetFdeInfoFromIndex(0) == nullptr); 121 ASSERT_TRUE(this->eh_frame_->GetFdeInfoFromIndex(0) == nullptr);
118 ASSERT_EQ(DWARF_ERROR_MEMORY_INVALID, this->eh_frame_->last_error()); 122 ASSERT_EQ(DWARF_ERROR_MEMORY_INVALID, this->eh_frame_->LastErrorCode());
123 EXPECT_EQ(0x1000U, this->eh_frame_->LastErrorAddress());
119} 124}
120 125
121TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeInfoFromIndex_read_pcrel) { 126TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeInfoFromIndex_read_pcrel) {
@@ -184,7 +189,7 @@ TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetBinary_verify) {
184 uint64_t fde_offset; 189 uint64_t fde_offset;
185 EXPECT_FALSE(this->eh_frame_->GetFdeOffsetBinary(0x100, &fde_offset, 10)); 190 EXPECT_FALSE(this->eh_frame_->GetFdeOffsetBinary(0x100, &fde_offset, 10));
186 // Not an error, just not found. 191 // Not an error, just not found.
187 ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->last_error()); 192 ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->LastErrorCode());
188 // Even number of elements. 193 // Even number of elements.
189 for (size_t i = 0; i < 10; i++) { 194 for (size_t i = 0; i < 10; i++) {
190 TypeParam pc = 0x1000 * (i + 1); 195 TypeParam pc = 0x1000 * (i + 1);
@@ -280,7 +285,7 @@ TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetSequential_end_check) {
280 285
281 uint64_t fde_offset; 286 uint64_t fde_offset;
282 ASSERT_FALSE(this->eh_frame_->GetFdeOffsetSequential(0x540, &fde_offset)); 287 ASSERT_FALSE(this->eh_frame_->GetFdeOffsetSequential(0x540, &fde_offset));
283 ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->last_error()); 288 ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->LastErrorCode());
284} 289}
285 290
286TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetFromPc_fail_fde_count) { 291TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetFromPc_fail_fde_count) {
@@ -288,7 +293,7 @@ TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetFromPc_fail_fde_count) {
288 293
289 uint64_t fde_offset; 294 uint64_t fde_offset;
290 ASSERT_FALSE(this->eh_frame_->GetFdeOffsetFromPc(0x100, &fde_offset)); 295 ASSERT_FALSE(this->eh_frame_->GetFdeOffsetFromPc(0x100, &fde_offset));
291 ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->last_error()); 296 ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->LastErrorCode());
292} 297}
293 298
294TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetFromPc_binary_search) { 299TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeOffsetFromPc_binary_search) {
diff --git a/libunwindstack/tests/DwarfOpLogTest.cpp b/libunwindstack/tests/DwarfOpLogTest.cpp
index 234d1c97d..3f09dd87e 100644
--- a/libunwindstack/tests/DwarfOpLogTest.cpp
+++ b/libunwindstack/tests/DwarfOpLogTest.cpp
@@ -21,11 +21,11 @@
21 21
22#include <gtest/gtest.h> 22#include <gtest/gtest.h>
23 23
24#include <unwindstack/DwarfError.h>
24#include <unwindstack/DwarfMemory.h> 25#include <unwindstack/DwarfMemory.h>
25#include <unwindstack/Log.h> 26#include <unwindstack/Log.h>
26#include <unwindstack/Regs.h> 27#include <unwindstack/Regs.h>
27 28
28#include "DwarfError.h"
29#include "DwarfOp.h" 29#include "DwarfOp.h"
30 30
31#include "MemoryFake.h" 31#include "MemoryFake.h"
diff --git a/libunwindstack/tests/DwarfOpTest.cpp b/libunwindstack/tests/DwarfOpTest.cpp
index 2d5007b8f..036226d03 100644
--- a/libunwindstack/tests/DwarfOpTest.cpp
+++ b/libunwindstack/tests/DwarfOpTest.cpp
@@ -21,10 +21,10 @@
21 21
22#include <gtest/gtest.h> 22#include <gtest/gtest.h>
23 23
24#include <unwindstack/DwarfError.h>
24#include <unwindstack/DwarfMemory.h> 25#include <unwindstack/DwarfMemory.h>
25#include <unwindstack/Log.h> 26#include <unwindstack/Log.h>
26 27
27#include "DwarfError.h"
28#include "DwarfOp.h" 28#include "DwarfOp.h"
29 29
30#include "MemoryFake.h" 30#include "MemoryFake.h"
@@ -53,13 +53,14 @@ TYPED_TEST_CASE_P(DwarfOpTest);
53TYPED_TEST_P(DwarfOpTest, decode) { 53TYPED_TEST_P(DwarfOpTest, decode) {
54 // Memory error. 54 // Memory error.
55 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 55 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
56 ASSERT_EQ(DWARF_ERROR_MEMORY_INVALID, this->op_->last_error()); 56 ASSERT_EQ(DWARF_ERROR_MEMORY_INVALID, this->op_->LastErrorCode());
57 EXPECT_EQ(0U, this->op_->LastErrorAddress());
57 58
58 // No error. 59 // No error.
59 this->op_memory_.SetMemory(0, std::vector<uint8_t>{0x96}); 60 this->op_memory_.SetMemory(0, std::vector<uint8_t>{0x96});
60 this->mem_->set_cur_offset(0); 61 this->mem_->set_cur_offset(0);
61 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 62 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
62 ASSERT_EQ(DWARF_ERROR_NONE, this->op_->last_error()); 63 ASSERT_EQ(DWARF_ERROR_NONE, this->op_->LastErrorCode());
63 ASSERT_EQ(0x96U, this->op_->cur_op()); 64 ASSERT_EQ(0x96U, this->op_->cur_op());
64 ASSERT_EQ(1U, this->mem_->cur_offset()); 65 ASSERT_EQ(1U, this->mem_->cur_offset());
65} 66}
@@ -67,7 +68,8 @@ TYPED_TEST_P(DwarfOpTest, decode) {
67TYPED_TEST_P(DwarfOpTest, eval) { 68TYPED_TEST_P(DwarfOpTest, eval) {
68 // Memory error. 69 // Memory error.
69 ASSERT_FALSE(this->op_->Eval(0, 2, DWARF_VERSION_MAX)); 70 ASSERT_FALSE(this->op_->Eval(0, 2, DWARF_VERSION_MAX));
70 ASSERT_EQ(DWARF_ERROR_MEMORY_INVALID, this->op_->last_error()); 71 ASSERT_EQ(DWARF_ERROR_MEMORY_INVALID, this->op_->LastErrorCode());
72 EXPECT_EQ(0U, this->op_->LastErrorAddress());
71 73
72 // Register set. 74 // Register set.
73 // Do this first, to verify that subsequent calls reset the value. 75 // Do this first, to verify that subsequent calls reset the value.
@@ -84,7 +86,7 @@ TYPED_TEST_P(DwarfOpTest, eval) {
84 this->op_memory_.SetMemory(0, opcode_buffer); 86 this->op_memory_.SetMemory(0, opcode_buffer);
85 87
86 ASSERT_TRUE(this->op_->Eval(0, 8, DWARF_VERSION_MAX)); 88 ASSERT_TRUE(this->op_->Eval(0, 8, DWARF_VERSION_MAX));
87 ASSERT_EQ(DWARF_ERROR_NONE, this->op_->last_error()); 89 ASSERT_EQ(DWARF_ERROR_NONE, this->op_->LastErrorCode());
88 ASSERT_FALSE(this->op_->is_register()); 90 ASSERT_FALSE(this->op_->is_register());
89 ASSERT_EQ(8U, this->mem_->cur_offset()); 91 ASSERT_EQ(8U, this->mem_->cur_offset());
90 ASSERT_EQ(4U, this->op_->StackSize()); 92 ASSERT_EQ(4U, this->op_->StackSize());
@@ -96,7 +98,7 @@ TYPED_TEST_P(DwarfOpTest, eval) {
96 // Infinite loop. 98 // Infinite loop.
97 this->op_memory_.SetMemory(0, std::vector<uint8_t>{0x2f, 0xfd, 0xff}); 99 this->op_memory_.SetMemory(0, std::vector<uint8_t>{0x2f, 0xfd, 0xff});
98 ASSERT_FALSE(this->op_->Eval(0, 4, DWARF_VERSION_MAX)); 100 ASSERT_FALSE(this->op_->Eval(0, 4, DWARF_VERSION_MAX));
99 ASSERT_EQ(DWARF_ERROR_TOO_MANY_ITERATIONS, this->op_->last_error()); 101 ASSERT_EQ(DWARF_ERROR_TOO_MANY_ITERATIONS, this->op_->LastErrorCode());
100 ASSERT_FALSE(this->op_->is_register()); 102 ASSERT_FALSE(this->op_->is_register());
101 ASSERT_EQ(0U, this->op_->StackSize()); 103 ASSERT_EQ(0U, this->op_->StackSize());
102} 104}
@@ -111,7 +113,7 @@ TYPED_TEST_P(DwarfOpTest, illegal_opcode) {
111 113
112 for (size_t i = 0; i < opcode_buffer.size(); i++) { 114 for (size_t i = 0; i < opcode_buffer.size(); i++) {
113 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 115 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
114 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->op_->last_error()); 116 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->op_->LastErrorCode());
115 ASSERT_EQ(opcode_buffer[i], this->op_->cur_op()); 117 ASSERT_EQ(opcode_buffer[i], this->op_->cur_op());
116 } 118 }
117} 119}
@@ -122,7 +124,7 @@ TYPED_TEST_P(DwarfOpTest, illegal_in_version3) {
122 124
123 for (size_t i = 0; i < opcode_buffer.size(); i++) { 125 for (size_t i = 0; i < opcode_buffer.size(); i++) {
124 ASSERT_FALSE(this->op_->Decode(2)); 126 ASSERT_FALSE(this->op_->Decode(2));
125 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->op_->last_error()); 127 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->op_->LastErrorCode());
126 ASSERT_EQ(opcode_buffer[i], this->op_->cur_op()); 128 ASSERT_EQ(opcode_buffer[i], this->op_->cur_op());
127 } 129 }
128} 130}
@@ -133,7 +135,7 @@ TYPED_TEST_P(DwarfOpTest, illegal_in_version4) {
133 135
134 for (size_t i = 0; i < opcode_buffer.size(); i++) { 136 for (size_t i = 0; i < opcode_buffer.size(); i++) {
135 ASSERT_FALSE(this->op_->Decode(3)); 137 ASSERT_FALSE(this->op_->Decode(3));
136 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->op_->last_error()); 138 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->op_->LastErrorCode());
137 ASSERT_EQ(opcode_buffer[i], this->op_->cur_op()); 139 ASSERT_EQ(opcode_buffer[i], this->op_->cur_op());
138 } 140 }
139} 141}
@@ -178,7 +180,7 @@ TYPED_TEST_P(DwarfOpTest, not_implemented) {
178 180
179 while (this->mem_->cur_offset() < opcode_buffer.size()) { 181 while (this->mem_->cur_offset() < opcode_buffer.size()) {
180 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 182 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
181 ASSERT_EQ(DWARF_ERROR_NOT_IMPLEMENTED, this->op_->last_error()); 183 ASSERT_EQ(DWARF_ERROR_NOT_IMPLEMENTED, this->op_->LastErrorCode());
182 } 184 }
183} 185}
184 186
@@ -216,7 +218,7 @@ TYPED_TEST_P(DwarfOpTest, op_deref) {
216 this->regular_memory_.SetMemory(0x2010, &value, sizeof(value)); 218 this->regular_memory_.SetMemory(0x2010, &value, sizeof(value));
217 219
218 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 220 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
219 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->last_error()); 221 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
220 222
221 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 223 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
222 ASSERT_EQ(1U, this->op_->StackSize()); 224 ASSERT_EQ(1U, this->op_->StackSize());
@@ -226,7 +228,8 @@ TYPED_TEST_P(DwarfOpTest, op_deref) {
226 ASSERT_EQ(value, this->op_->StackAt(0)); 228 ASSERT_EQ(value, this->op_->StackAt(0));
227 229
228 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 230 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
229 ASSERT_EQ(DWARF_ERROR_MEMORY_INVALID, this->op_->last_error()); 231 ASSERT_EQ(DWARF_ERROR_MEMORY_INVALID, this->op_->LastErrorCode());
232 ASSERT_EQ(0x12345678U, this->op_->LastErrorAddress());
230} 233}
231 234
232TYPED_TEST_P(DwarfOpTest, op_deref_size) { 235TYPED_TEST_P(DwarfOpTest, op_deref_size) {
@@ -235,7 +238,7 @@ TYPED_TEST_P(DwarfOpTest, op_deref_size) {
235 this->regular_memory_.SetMemory(0x2010, &value, sizeof(value)); 238 this->regular_memory_.SetMemory(0x2010, &value, sizeof(value));
236 239
237 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 240 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
238 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->last_error()); 241 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
239 242
240 // Read all byte sizes up to the sizeof the type. 243 // Read all byte sizes up to the sizeof the type.
241 for (size_t i = 1; i < sizeof(TypeParam); i++) { 244 for (size_t i = 1; i < sizeof(TypeParam); i++) {
@@ -252,17 +255,18 @@ TYPED_TEST_P(DwarfOpTest, op_deref_size) {
252 // Zero byte read. 255 // Zero byte read.
253 this->op_memory_.SetMemory(0, std::vector<uint8_t>{0x0a, 0x10, 0x20, 0x94, 0x00}); 256 this->op_memory_.SetMemory(0, std::vector<uint8_t>{0x0a, 0x10, 0x20, 0x94, 0x00});
254 ASSERT_FALSE(this->op_->Eval(0, 5, DWARF_VERSION_MAX)); 257 ASSERT_FALSE(this->op_->Eval(0, 5, DWARF_VERSION_MAX));
255 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->op_->last_error()); 258 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->op_->LastErrorCode());
256 259
257 // Read too many bytes. 260 // Read too many bytes.
258 this->op_memory_.SetMemory(0, std::vector<uint8_t>{0x0a, 0x10, 0x20, 0x94, sizeof(TypeParam) + 1}); 261 this->op_memory_.SetMemory(0, std::vector<uint8_t>{0x0a, 0x10, 0x20, 0x94, sizeof(TypeParam) + 1});
259 ASSERT_FALSE(this->op_->Eval(0, 5, DWARF_VERSION_MAX)); 262 ASSERT_FALSE(this->op_->Eval(0, 5, DWARF_VERSION_MAX));
260 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->op_->last_error()); 263 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->op_->LastErrorCode());
261 264
262 // Force bad memory read. 265 // Force bad memory read.
263 this->op_memory_.SetMemory(0, std::vector<uint8_t>{0x0a, 0x10, 0x40, 0x94, 0x01}); 266 this->op_memory_.SetMemory(0, std::vector<uint8_t>{0x0a, 0x10, 0x40, 0x94, 0x01});
264 ASSERT_FALSE(this->op_->Eval(0, 5, DWARF_VERSION_MAX)); 267 ASSERT_FALSE(this->op_->Eval(0, 5, DWARF_VERSION_MAX));
265 ASSERT_EQ(DWARF_ERROR_MEMORY_INVALID, this->op_->last_error()); 268 ASSERT_EQ(DWARF_ERROR_MEMORY_INVALID, this->op_->LastErrorCode());
269 EXPECT_EQ(0x4010U, this->op_->LastErrorAddress());
266} 270}
267 271
268TYPED_TEST_P(DwarfOpTest, const_unsigned) { 272TYPED_TEST_P(DwarfOpTest, const_unsigned) {
@@ -529,7 +533,7 @@ TYPED_TEST_P(DwarfOpTest, op_dup) {
529 533
530 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 534 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
531 ASSERT_EQ(0x12, this->op_->cur_op()); 535 ASSERT_EQ(0x12, this->op_->cur_op());
532 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->last_error()); 536 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
533 537
534 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 538 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
535 ASSERT_EQ(1U, this->op_->StackSize()); 539 ASSERT_EQ(1U, this->op_->StackSize());
@@ -577,7 +581,7 @@ TYPED_TEST_P(DwarfOpTest, op_drop) {
577 581
578 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 582 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
579 ASSERT_EQ(0x13, this->op_->cur_op()); 583 ASSERT_EQ(0x13, this->op_->cur_op());
580 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->last_error()); 584 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
581} 585}
582 586
583TYPED_TEST_P(DwarfOpTest, op_over) { 587TYPED_TEST_P(DwarfOpTest, op_over) {
@@ -612,7 +616,7 @@ TYPED_TEST_P(DwarfOpTest, op_over) {
612 616
613 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 617 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
614 ASSERT_EQ(0x14, this->op_->cur_op()); 618 ASSERT_EQ(0x14, this->op_->cur_op());
615 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->last_error()); 619 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
616} 620}
617 621
618TYPED_TEST_P(DwarfOpTest, op_pick) { 622TYPED_TEST_P(DwarfOpTest, op_pick) {
@@ -654,7 +658,7 @@ TYPED_TEST_P(DwarfOpTest, op_pick) {
654 658
655 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 659 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
656 ASSERT_EQ(0x15, this->op_->cur_op()); 660 ASSERT_EQ(0x15, this->op_->cur_op());
657 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->last_error()); 661 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
658} 662}
659 663
660TYPED_TEST_P(DwarfOpTest, op_swap) { 664TYPED_TEST_P(DwarfOpTest, op_swap) {
@@ -686,7 +690,7 @@ TYPED_TEST_P(DwarfOpTest, op_swap) {
686 690
687 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 691 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
688 ASSERT_EQ(0x16, this->op_->cur_op()); 692 ASSERT_EQ(0x16, this->op_->cur_op());
689 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->last_error()); 693 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
690} 694}
691 695
692TYPED_TEST_P(DwarfOpTest, op_rot) { 696TYPED_TEST_P(DwarfOpTest, op_rot) {
@@ -703,19 +707,19 @@ TYPED_TEST_P(DwarfOpTest, op_rot) {
703 this->op_memory_.SetMemory(0, opcode_buffer); 707 this->op_memory_.SetMemory(0, opcode_buffer);
704 708
705 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 709 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
706 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->last_error()); 710 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
707 711
708 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 712 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
709 ASSERT_EQ(1U, this->op_->StackSize()); 713 ASSERT_EQ(1U, this->op_->StackSize());
710 714
711 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 715 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
712 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->last_error()); 716 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
713 717
714 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 718 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
715 ASSERT_EQ(2U, this->op_->StackSize()); 719 ASSERT_EQ(2U, this->op_->StackSize());
716 720
717 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 721 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
718 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->last_error()); 722 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
719 723
720 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 724 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
721 ASSERT_EQ(3U, this->op_->StackSize()); 725 ASSERT_EQ(3U, this->op_->StackSize());
@@ -753,7 +757,7 @@ TYPED_TEST_P(DwarfOpTest, op_abs) {
753 this->op_memory_.SetMemory(0, opcode_buffer); 757 this->op_memory_.SetMemory(0, opcode_buffer);
754 758
755 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 759 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
756 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->last_error()); 760 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
757 761
758 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 762 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
759 ASSERT_EQ(1U, this->op_->StackSize()); 763 ASSERT_EQ(1U, this->op_->StackSize());
@@ -805,13 +809,13 @@ TYPED_TEST_P(DwarfOpTest, op_and) {
805 this->op_memory_.SetMemory(0, opcode_buffer); 809 this->op_memory_.SetMemory(0, opcode_buffer);
806 810
807 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 811 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
808 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->last_error()); 812 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
809 813
810 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 814 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
811 ASSERT_EQ(1U, this->op_->StackSize()); 815 ASSERT_EQ(1U, this->op_->StackSize());
812 816
813 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 817 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
814 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->last_error()); 818 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
815 819
816 // Two positive values. 820 // Two positive values.
817 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 821 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
@@ -854,7 +858,7 @@ TYPED_TEST_P(DwarfOpTest, op_and) {
854 ASSERT_EQ(5U, this->op_->StackSize()); 858 ASSERT_EQ(5U, this->op_->StackSize());
855 859
856 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 860 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
857 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->op_->last_error()); 861 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->op_->LastErrorCode());
858} 862}
859 863
860TYPED_TEST_P(DwarfOpTest, op_div) { 864TYPED_TEST_P(DwarfOpTest, op_div) {
@@ -871,13 +875,13 @@ TYPED_TEST_P(DwarfOpTest, op_div) {
871 this->op_memory_.SetMemory(0, opcode_buffer); 875 this->op_memory_.SetMemory(0, opcode_buffer);
872 876
873 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 877 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
874 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->last_error()); 878 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
875 879
876 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 880 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
877 ASSERT_EQ(1U, this->op_->StackSize()); 881 ASSERT_EQ(1U, this->op_->StackSize());
878 882
879 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 883 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
880 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->last_error()); 884 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
881 885
882 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 886 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
883 ASSERT_EQ(2U, this->op_->StackSize()); 887 ASSERT_EQ(2U, this->op_->StackSize());
@@ -902,13 +906,13 @@ TYPED_TEST_P(DwarfOpTest, op_minus) {
902 this->op_memory_.SetMemory(0, opcode_buffer); 906 this->op_memory_.SetMemory(0, opcode_buffer);
903 907
904 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 908 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
905 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->last_error()); 909 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
906 910
907 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 911 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
908 ASSERT_EQ(1U, this->op_->StackSize()); 912 ASSERT_EQ(1U, this->op_->StackSize());
909 913
910 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 914 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
911 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->last_error()); 915 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
912 916
913 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 917 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
914 ASSERT_EQ(2U, this->op_->StackSize()); 918 ASSERT_EQ(2U, this->op_->StackSize());
@@ -935,13 +939,13 @@ TYPED_TEST_P(DwarfOpTest, op_mod) {
935 this->op_memory_.SetMemory(0, opcode_buffer); 939 this->op_memory_.SetMemory(0, opcode_buffer);
936 940
937 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 941 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
938 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->last_error()); 942 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
939 943
940 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 944 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
941 ASSERT_EQ(1U, this->op_->StackSize()); 945 ASSERT_EQ(1U, this->op_->StackSize());
942 946
943 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 947 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
944 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->last_error()); 948 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
945 949
946 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 950 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
947 ASSERT_EQ(2U, this->op_->StackSize()); 951 ASSERT_EQ(2U, this->op_->StackSize());
@@ -957,7 +961,7 @@ TYPED_TEST_P(DwarfOpTest, op_mod) {
957 ASSERT_EQ(3U, this->op_->StackSize()); 961 ASSERT_EQ(3U, this->op_->StackSize());
958 962
959 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 963 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
960 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->op_->last_error()); 964 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->op_->LastErrorCode());
961} 965}
962 966
963TYPED_TEST_P(DwarfOpTest, op_mul) { 967TYPED_TEST_P(DwarfOpTest, op_mul) {
@@ -974,13 +978,13 @@ TYPED_TEST_P(DwarfOpTest, op_mul) {
974 this->op_memory_.SetMemory(0, opcode_buffer); 978 this->op_memory_.SetMemory(0, opcode_buffer);
975 979
976 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 980 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
977 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->last_error()); 981 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
978 982
979 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 983 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
980 ASSERT_EQ(1U, this->op_->StackSize()); 984 ASSERT_EQ(1U, this->op_->StackSize());
981 985
982 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 986 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
983 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->last_error()); 987 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
984 988
985 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 989 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
986 ASSERT_EQ(2U, this->op_->StackSize()); 990 ASSERT_EQ(2U, this->op_->StackSize());
@@ -1003,7 +1007,7 @@ TYPED_TEST_P(DwarfOpTest, op_neg) {
1003 this->op_memory_.SetMemory(0, opcode_buffer); 1007 this->op_memory_.SetMemory(0, opcode_buffer);
1004 1008
1005 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 1009 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
1006 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->last_error()); 1010 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
1007 1011
1008 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 1012 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
1009 ASSERT_EQ(1U, this->op_->StackSize()); 1013 ASSERT_EQ(1U, this->op_->StackSize());
@@ -1034,7 +1038,7 @@ TYPED_TEST_P(DwarfOpTest, op_not) {
1034 this->op_memory_.SetMemory(0, opcode_buffer); 1038 this->op_memory_.SetMemory(0, opcode_buffer);
1035 1039
1036 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 1040 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
1037 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->last_error()); 1041 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
1038 1042
1039 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 1043 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
1040 ASSERT_EQ(1U, this->op_->StackSize()); 1044 ASSERT_EQ(1U, this->op_->StackSize());
@@ -1067,13 +1071,13 @@ TYPED_TEST_P(DwarfOpTest, op_or) {
1067 this->op_memory_.SetMemory(0, opcode_buffer); 1071 this->op_memory_.SetMemory(0, opcode_buffer);
1068 1072
1069 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 1073 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
1070 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->last_error()); 1074 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
1071 1075
1072 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 1076 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
1073 ASSERT_EQ(1U, this->op_->StackSize()); 1077 ASSERT_EQ(1U, this->op_->StackSize());
1074 1078
1075 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 1079 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
1076 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->last_error()); 1080 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
1077 1081
1078 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 1082 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
1079 ASSERT_EQ(2U, this->op_->StackSize()); 1083 ASSERT_EQ(2U, this->op_->StackSize());
@@ -1098,13 +1102,13 @@ TYPED_TEST_P(DwarfOpTest, op_plus) {
1098 this->op_memory_.SetMemory(0, opcode_buffer); 1102 this->op_memory_.SetMemory(0, opcode_buffer);
1099 1103
1100 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 1104 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
1101 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->last_error()); 1105 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
1102 1106
1103 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 1107 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
1104 ASSERT_EQ(1U, this->op_->StackSize()); 1108 ASSERT_EQ(1U, this->op_->StackSize());
1105 1109
1106 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 1110 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
1107 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->last_error()); 1111 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
1108 1112
1109 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 1113 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
1110 ASSERT_EQ(2U, this->op_->StackSize()); 1114 ASSERT_EQ(2U, this->op_->StackSize());
@@ -1125,7 +1129,7 @@ TYPED_TEST_P(DwarfOpTest, op_plus_uconst) {
1125 this->op_memory_.SetMemory(0, opcode_buffer); 1129 this->op_memory_.SetMemory(0, opcode_buffer);
1126 1130
1127 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 1131 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
1128 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->last_error()); 1132 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
1129 1133
1130 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 1134 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
1131 ASSERT_EQ(1U, this->op_->StackSize()); 1135 ASSERT_EQ(1U, this->op_->StackSize());
@@ -1150,13 +1154,13 @@ TYPED_TEST_P(DwarfOpTest, op_shl) {
1150 this->op_memory_.SetMemory(0, opcode_buffer); 1154 this->op_memory_.SetMemory(0, opcode_buffer);
1151 1155
1152 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 1156 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
1153 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->last_error()); 1157 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
1154 1158
1155 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 1159 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
1156 ASSERT_EQ(1U, this->op_->StackSize()); 1160 ASSERT_EQ(1U, this->op_->StackSize());
1157 1161
1158 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 1162 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
1159 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->last_error()); 1163 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
1160 1164
1161 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 1165 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
1162 ASSERT_EQ(2U, this->op_->StackSize()); 1166 ASSERT_EQ(2U, this->op_->StackSize());
@@ -1181,13 +1185,13 @@ TYPED_TEST_P(DwarfOpTest, op_shr) {
1181 this->op_memory_.SetMemory(0, opcode_buffer); 1185 this->op_memory_.SetMemory(0, opcode_buffer);
1182 1186
1183 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 1187 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
1184 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->last_error()); 1188 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
1185 1189
1186 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 1190 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
1187 ASSERT_EQ(1U, this->op_->StackSize()); 1191 ASSERT_EQ(1U, this->op_->StackSize());
1188 1192
1189 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 1193 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
1190 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->last_error()); 1194 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
1191 1195
1192 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 1196 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
1193 ASSERT_EQ(2U, this->op_->StackSize()); 1197 ASSERT_EQ(2U, this->op_->StackSize());
@@ -1216,13 +1220,13 @@ TYPED_TEST_P(DwarfOpTest, op_shra) {
1216 this->op_memory_.SetMemory(0, opcode_buffer); 1220 this->op_memory_.SetMemory(0, opcode_buffer);
1217 1221
1218 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 1222 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
1219 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->last_error()); 1223 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
1220 1224
1221 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 1225 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
1222 ASSERT_EQ(1U, this->op_->StackSize()); 1226 ASSERT_EQ(1U, this->op_->StackSize());
1223 1227
1224 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 1228 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
1225 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->last_error()); 1229 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
1226 1230
1227 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 1231 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
1228 ASSERT_EQ(2U, this->op_->StackSize()); 1232 ASSERT_EQ(2U, this->op_->StackSize());
@@ -1247,13 +1251,13 @@ TYPED_TEST_P(DwarfOpTest, op_xor) {
1247 this->op_memory_.SetMemory(0, opcode_buffer); 1251 this->op_memory_.SetMemory(0, opcode_buffer);
1248 1252
1249 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 1253 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
1250 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->last_error()); 1254 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
1251 1255
1252 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 1256 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
1253 ASSERT_EQ(1U, this->op_->StackSize()); 1257 ASSERT_EQ(1U, this->op_->StackSize());
1254 1258
1255 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 1259 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
1256 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->last_error()); 1260 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
1257 1261
1258 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 1262 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
1259 ASSERT_EQ(2U, this->op_->StackSize()); 1263 ASSERT_EQ(2U, this->op_->StackSize());
@@ -1280,7 +1284,7 @@ TYPED_TEST_P(DwarfOpTest, op_bra) {
1280 this->op_memory_.SetMemory(0, opcode_buffer); 1284 this->op_memory_.SetMemory(0, opcode_buffer);
1281 1285
1282 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX)); 1286 ASSERT_FALSE(this->op_->Decode(DWARF_VERSION_MAX));
1283 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->last_error()); 1287 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
1284 1288
1285 // Push on a non-zero value with a positive branch. 1289 // Push on a non-zero value with a positive branch.
1286 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX)); 1290 ASSERT_TRUE(this->op_->Decode(DWARF_VERSION_MAX));
@@ -1342,12 +1346,12 @@ TYPED_TEST_P(DwarfOpTest, compare_opcode_stack_error) {
1342 1346
1343 ASSERT_FALSE(this->op_->Eval(0, 1, DWARF_VERSION_MAX)); 1347 ASSERT_FALSE(this->op_->Eval(0, 1, DWARF_VERSION_MAX));
1344 ASSERT_EQ(opcode, this->op_->cur_op()); 1348 ASSERT_EQ(opcode, this->op_->cur_op());
1345 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->last_error()); 1349 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
1346 1350
1347 ASSERT_FALSE(this->op_->Eval(1, 4, DWARF_VERSION_MAX)); 1351 ASSERT_FALSE(this->op_->Eval(1, 4, DWARF_VERSION_MAX));
1348 ASSERT_EQ(opcode, this->op_->cur_op()); 1352 ASSERT_EQ(opcode, this->op_->cur_op());
1349 ASSERT_EQ(1U, this->op_->StackSize()); 1353 ASSERT_EQ(1U, this->op_->StackSize());
1350 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->last_error()); 1354 ASSERT_EQ(DWARF_ERROR_STACK_INDEX_NOT_VALID, this->op_->LastErrorCode());
1351 } 1355 }
1352} 1356}
1353 1357
@@ -1532,7 +1536,7 @@ TYPED_TEST_P(DwarfOpTest, op_breg_invalid_register) {
1532 1536
1533 // Should fail since this references a non-existent register. 1537 // Should fail since this references a non-existent register.
1534 ASSERT_FALSE(this->op_->Eval(2, 4, DWARF_VERSION_MAX)); 1538 ASSERT_FALSE(this->op_->Eval(2, 4, DWARF_VERSION_MAX));
1535 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->op_->last_error()); 1539 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->op_->LastErrorCode());
1536} 1540}
1537 1541
1538TYPED_TEST_P(DwarfOpTest, op_bregx) { 1542TYPED_TEST_P(DwarfOpTest, op_bregx) {
@@ -1560,7 +1564,7 @@ TYPED_TEST_P(DwarfOpTest, op_bregx) {
1560 ASSERT_EQ(0x90U, this->op_->StackAt(0)); 1564 ASSERT_EQ(0x90U, this->op_->StackAt(0));
1561 1565
1562 ASSERT_FALSE(this->op_->Eval(7, 12, DWARF_VERSION_MAX)); 1566 ASSERT_FALSE(this->op_->Eval(7, 12, DWARF_VERSION_MAX));
1563 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->op_->last_error()); 1567 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->op_->LastErrorCode());
1564} 1568}
1565 1569
1566TYPED_TEST_P(DwarfOpTest, op_nop) { 1570TYPED_TEST_P(DwarfOpTest, op_nop) {
diff --git a/libunwindstack/tests/DwarfSectionImplTest.cpp b/libunwindstack/tests/DwarfSectionImplTest.cpp
index dfd2ce059..7e10935eb 100644
--- a/libunwindstack/tests/DwarfSectionImplTest.cpp
+++ b/libunwindstack/tests/DwarfSectionImplTest.cpp
@@ -19,10 +19,10 @@
19#include <gmock/gmock.h> 19#include <gmock/gmock.h>
20#include <gtest/gtest.h> 20#include <gtest/gtest.h>
21 21
22#include <unwindstack/DwarfError.h>
22#include <unwindstack/DwarfSection.h> 23#include <unwindstack/DwarfSection.h>
23 24
24#include "DwarfEncoding.h" 25#include "DwarfEncoding.h"
25#include "DwarfError.h"
26 26
27#include "LogFake.h" 27#include "LogFake.h"
28#include "MemoryFake.h" 28#include "MemoryFake.h"
@@ -67,7 +67,7 @@ class MockDwarfSectionImpl : public DwarfSectionImpl<TypeParam> {
67 } 67 }
68 void TestClearCachedCieLocRegs() { this->cie_loc_regs_.clear(); } 68 void TestClearCachedCieLocRegs() { this->cie_loc_regs_.clear(); }
69 69
70 void TestClearError() { this->last_error_ = DWARF_ERROR_NONE; } 70 void TestClearError() { this->last_error_.code = DWARF_ERROR_NONE; }
71}; 71};
72 72
73template <typename TypeParam> 73template <typename TypeParam>
@@ -102,7 +102,8 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_eval_fail) {
102 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x2, 0x5000}}; 102 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x2, 0x5000}};
103 bool finished; 103 bool finished;
104 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished)); 104 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
105 EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->last_error()); 105 EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode());
106 EXPECT_EQ(0x5000U, this->section_->LastErrorAddress());
106} 107}
107 108
108TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_no_stack) { 109TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_no_stack) {
@@ -118,7 +119,7 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_no_stack) {
118 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x2, 0x5000}}; 119 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x2, 0x5000}};
119 bool finished; 120 bool finished;
120 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished)); 121 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
121 EXPECT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->section_->last_error()); 122 EXPECT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->section_->LastErrorCode());
122} 123}
123 124
124TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr) { 125TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr) {
@@ -172,7 +173,7 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_is_register) {
172 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x2, 0x5000}}; 173 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x2, 0x5000}};
173 bool finished; 174 bool finished;
174 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished)); 175 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
175 EXPECT_EQ(DWARF_ERROR_NOT_IMPLEMENTED, this->section_->last_error()); 176 EXPECT_EQ(DWARF_ERROR_NOT_IMPLEMENTED, this->section_->LastErrorCode());
176} 177}
177 178
178TYPED_TEST_P(DwarfSectionImplTest, Eval_bad_regs) { 179TYPED_TEST_P(DwarfSectionImplTest, Eval_bad_regs) {
@@ -182,7 +183,7 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_bad_regs) {
182 183
183 bool finished; 184 bool finished;
184 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished)); 185 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
185 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->last_error()); 186 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
186} 187}
187 188
188TYPED_TEST_P(DwarfSectionImplTest, Eval_no_cfa) { 189TYPED_TEST_P(DwarfSectionImplTest, Eval_no_cfa) {
@@ -192,7 +193,7 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_no_cfa) {
192 193
193 bool finished; 194 bool finished;
194 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished)); 195 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
195 EXPECT_EQ(DWARF_ERROR_CFA_NOT_DEFINED, this->section_->last_error()); 196 EXPECT_EQ(DWARF_ERROR_CFA_NOT_DEFINED, this->section_->LastErrorCode());
196} 197}
197 198
198TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_bad) { 199TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_bad) {
@@ -203,25 +204,25 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_bad) {
203 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {20, 0}}; 204 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {20, 0}};
204 bool finished; 205 bool finished;
205 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished)); 206 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
206 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->last_error()); 207 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
207 208
208 this->section_->TestClearError(); 209 this->section_->TestClearError();
209 loc_regs.erase(CFA_REG); 210 loc_regs.erase(CFA_REG);
210 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_INVALID, {0, 0}}; 211 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_INVALID, {0, 0}};
211 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished)); 212 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
212 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->last_error()); 213 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
213 214
214 this->section_->TestClearError(); 215 this->section_->TestClearError();
215 loc_regs.erase(CFA_REG); 216 loc_regs.erase(CFA_REG);
216 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_OFFSET, {0, 0}}; 217 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_OFFSET, {0, 0}};
217 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished)); 218 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
218 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->last_error()); 219 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
219 220
220 this->section_->TestClearError(); 221 this->section_->TestClearError();
221 loc_regs.erase(CFA_REG); 222 loc_regs.erase(CFA_REG);
222 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_VAL_OFFSET, {0, 0}}; 223 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_VAL_OFFSET, {0, 0}};
223 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished)); 224 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
224 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->last_error()); 225 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
225} 226}
226 227
227TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_register_prev) { 228TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_register_prev) {
@@ -341,7 +342,7 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_invalid_register) {
341 loc_regs[1] = DwarfLocation{DWARF_LOCATION_REGISTER, {10, 0}}; 342 loc_regs[1] = DwarfLocation{DWARF_LOCATION_REGISTER, {10, 0}};
342 bool finished; 343 bool finished;
343 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished)); 344 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, &regs, &finished));
344 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->last_error()); 345 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
345} 346}
346 347
347TYPED_TEST_P(DwarfSectionImplTest, Eval_different_reg_locations) { 348TYPED_TEST_P(DwarfSectionImplTest, Eval_different_reg_locations) {
@@ -489,10 +490,12 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_reg_val_expr) {
489 490
490TYPED_TEST_P(DwarfSectionImplTest, GetCie_fail_should_not_cache) { 491TYPED_TEST_P(DwarfSectionImplTest, GetCie_fail_should_not_cache) {
491 ASSERT_TRUE(this->section_->GetCie(0x4000) == nullptr); 492 ASSERT_TRUE(this->section_->GetCie(0x4000) == nullptr);
492 EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->last_error()); 493 EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode());
494 EXPECT_EQ(0x4000U, this->section_->LastErrorAddress());
493 this->section_->TestClearError(); 495 this->section_->TestClearError();
494 ASSERT_TRUE(this->section_->GetCie(0x4000) == nullptr); 496 ASSERT_TRUE(this->section_->GetCie(0x4000) == nullptr);
495 EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->last_error()); 497 EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode());
498 EXPECT_EQ(0x4000U, this->section_->LastErrorAddress());
496} 499}
497 500
498TYPED_TEST_P(DwarfSectionImplTest, GetCie_32_version_check) { 501TYPED_TEST_P(DwarfSectionImplTest, GetCie_32_version_check) {
@@ -518,24 +521,24 @@ TYPED_TEST_P(DwarfSectionImplTest, GetCie_32_version_check) {
518 EXPECT_EQ(4U, cie->code_alignment_factor); 521 EXPECT_EQ(4U, cie->code_alignment_factor);
519 EXPECT_EQ(8, cie->data_alignment_factor); 522 EXPECT_EQ(8, cie->data_alignment_factor);
520 EXPECT_EQ(0x20U, cie->return_address_register); 523 EXPECT_EQ(0x20U, cie->return_address_register);
521 EXPECT_EQ(DWARF_ERROR_NONE, this->section_->last_error()); 524 EXPECT_EQ(DWARF_ERROR_NONE, this->section_->LastErrorCode());
522 525
523 this->section_->TestClearCachedCieEntry(); 526 this->section_->TestClearCachedCieEntry();
524 // Set version to 0, 2, 5 and verify we fail. 527 // Set version to 0, 2, 5 and verify we fail.
525 this->memory_.SetData8(0x5008, 0x0); 528 this->memory_.SetData8(0x5008, 0x0);
526 this->section_->TestClearError(); 529 this->section_->TestClearError();
527 ASSERT_TRUE(this->section_->GetCie(0x5000) == nullptr); 530 ASSERT_TRUE(this->section_->GetCie(0x5000) == nullptr);
528 EXPECT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->section_->last_error()); 531 EXPECT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->section_->LastErrorCode());
529 532
530 this->memory_.SetData8(0x5008, 0x2); 533 this->memory_.SetData8(0x5008, 0x2);
531 this->section_->TestClearError(); 534 this->section_->TestClearError();
532 ASSERT_TRUE(this->section_->GetCie(0x5000) == nullptr); 535 ASSERT_TRUE(this->section_->GetCie(0x5000) == nullptr);
533 EXPECT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->section_->last_error()); 536 EXPECT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->section_->LastErrorCode());
534 537
535 this->memory_.SetData8(0x5008, 0x5); 538 this->memory_.SetData8(0x5008, 0x5);
536 this->section_->TestClearError(); 539 this->section_->TestClearError();
537 ASSERT_TRUE(this->section_->GetCie(0x5000) == nullptr); 540 ASSERT_TRUE(this->section_->GetCie(0x5000) == nullptr);
538 EXPECT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->section_->last_error()); 541 EXPECT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->section_->LastErrorCode());
539} 542}
540 543
541TYPED_TEST_P(DwarfSectionImplTest, GetCie_negative_data_alignment_factor) { 544TYPED_TEST_P(DwarfSectionImplTest, GetCie_negative_data_alignment_factor) {
@@ -681,10 +684,12 @@ TYPED_TEST_P(DwarfSectionImplTest, GetCie_version_4) {
681 684
682TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_fail_should_not_cache) { 685TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_fail_should_not_cache) {
683 ASSERT_TRUE(this->section_->GetFdeFromOffset(0x4000) == nullptr); 686 ASSERT_TRUE(this->section_->GetFdeFromOffset(0x4000) == nullptr);
684 EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->last_error()); 687 EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode());
688 EXPECT_EQ(0x4000U, this->section_->LastErrorAddress());
685 this->section_->TestClearError(); 689 this->section_->TestClearError();
686 ASSERT_TRUE(this->section_->GetFdeFromOffset(0x4000) == nullptr); 690 ASSERT_TRUE(this->section_->GetFdeFromOffset(0x4000) == nullptr);
687 EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->last_error()); 691 EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode());
692 EXPECT_EQ(0x4000U, this->section_->LastErrorAddress());
688} 693}
689 694
690TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_32_no_augment) { 695TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_32_no_augment) {
diff --git a/libunwindstack/tests/ElfFake.h b/libunwindstack/tests/ElfFake.h
index 099026ce0..e23298670 100644
--- a/libunwindstack/tests/ElfFake.h
+++ b/libunwindstack/tests/ElfFake.h
@@ -87,6 +87,10 @@ class ElfInterfaceFake : public ElfInterface {
87 steps_.clear(); 87 steps_.clear();
88 } 88 }
89 89
90 void FakeSetErrorCode(ErrorCode code) { last_error_.code = code; }
91
92 void FakeSetErrorAddress(uint64_t address) { last_error_.address = address; }
93
90 private: 94 private:
91 std::unordered_map<std::string, uint64_t> globals_; 95 std::unordered_map<std::string, uint64_t> globals_;
92 96
diff --git a/libunwindstack/tests/ElfInterfaceArmTest.cpp b/libunwindstack/tests/ElfInterfaceArmTest.cpp
index e6763ab01..31d6a6314 100644
--- a/libunwindstack/tests/ElfInterfaceArmTest.cpp
+++ b/libunwindstack/tests/ElfInterfaceArmTest.cpp
@@ -303,6 +303,7 @@ TEST_F(ElfInterfaceArmTest, StepExidx) {
303 // FindEntry fails. 303 // FindEntry fails.
304 bool finished; 304 bool finished;
305 ASSERT_FALSE(interface.StepExidx(0x7000, 0, nullptr, nullptr, &finished)); 305 ASSERT_FALSE(interface.StepExidx(0x7000, 0, nullptr, nullptr, &finished));
306 EXPECT_EQ(ERROR_UNWIND_INFO, interface.LastErrorCode());
306 307
307 // ExtractEntry should fail. 308 // ExtractEntry should fail.
308 interface.FakeSetStartOffset(0x1000); 309 interface.FakeSetStartOffset(0x1000);
@@ -316,14 +317,18 @@ TEST_F(ElfInterfaceArmTest, StepExidx) {
316 regs.set_sp(regs[ARM_REG_SP]); 317 regs.set_sp(regs[ARM_REG_SP]);
317 regs.set_pc(0x1234); 318 regs.set_pc(0x1234);
318 ASSERT_FALSE(interface.StepExidx(0x7000, 0, &regs, &process_memory_, &finished)); 319 ASSERT_FALSE(interface.StepExidx(0x7000, 0, &regs, &process_memory_, &finished));
320 EXPECT_EQ(ERROR_MEMORY_INVALID, interface.LastErrorCode());
321 EXPECT_EQ(0x1004U, interface.LastErrorAddress());
319 322
320 // Eval should fail. 323 // Eval should fail.
321 memory_.SetData32(0x1004, 0x81000000); 324 memory_.SetData32(0x1004, 0x81000000);
322 ASSERT_FALSE(interface.StepExidx(0x7000, 0, &regs, &process_memory_, &finished)); 325 ASSERT_FALSE(interface.StepExidx(0x7000, 0, &regs, &process_memory_, &finished));
326 EXPECT_EQ(ERROR_UNWIND_INFO, interface.LastErrorCode());
323 327
324 // Everything should pass. 328 // Everything should pass.
325 memory_.SetData32(0x1004, 0x80b0b0b0); 329 memory_.SetData32(0x1004, 0x80b0b0b0);
326 ASSERT_TRUE(interface.StepExidx(0x7000, 0, &regs, &process_memory_, &finished)); 330 ASSERT_TRUE(interface.StepExidx(0x7000, 0, &regs, &process_memory_, &finished));
331 EXPECT_EQ(ERROR_UNWIND_INFO, interface.LastErrorCode());
327 ASSERT_FALSE(finished); 332 ASSERT_FALSE(finished);
328 ASSERT_EQ(0x1000U, regs.sp()); 333 ASSERT_EQ(0x1000U, regs.sp());
329 ASSERT_EQ(0x1000U, regs[ARM_REG_SP]); 334 ASSERT_EQ(0x1000U, regs[ARM_REG_SP]);
@@ -332,9 +337,11 @@ TEST_F(ElfInterfaceArmTest, StepExidx) {
332 337
333 // Load bias is non-zero. 338 // Load bias is non-zero.
334 ASSERT_TRUE(interface.StepExidx(0x8000, 0x1000, &regs, &process_memory_, &finished)); 339 ASSERT_TRUE(interface.StepExidx(0x8000, 0x1000, &regs, &process_memory_, &finished));
340 EXPECT_EQ(ERROR_UNWIND_INFO, interface.LastErrorCode());
335 341
336 // Pc too small. 342 // Pc too small.
337 ASSERT_FALSE(interface.StepExidx(0x8000, 0x9000, &regs, &process_memory_, &finished)); 343 ASSERT_FALSE(interface.StepExidx(0x8000, 0x9000, &regs, &process_memory_, &finished));
344 EXPECT_EQ(ERROR_UNWIND_INFO, interface.LastErrorCode());
338} 345}
339 346
340TEST_F(ElfInterfaceArmTest, StepExidx_pc_set) { 347TEST_F(ElfInterfaceArmTest, StepExidx_pc_set) {
@@ -356,6 +363,7 @@ TEST_F(ElfInterfaceArmTest, StepExidx_pc_set) {
356 // Everything should pass. 363 // Everything should pass.
357 bool finished; 364 bool finished;
358 ASSERT_TRUE(interface.StepExidx(0x7000, 0, &regs, &process_memory_, &finished)); 365 ASSERT_TRUE(interface.StepExidx(0x7000, 0, &regs, &process_memory_, &finished));
366 EXPECT_EQ(ERROR_NONE, interface.LastErrorCode());
359 ASSERT_FALSE(finished); 367 ASSERT_FALSE(finished);
360 ASSERT_EQ(0x10004U, regs.sp()); 368 ASSERT_EQ(0x10004U, regs.sp());
361 ASSERT_EQ(0x10004U, regs[ARM_REG_SP]); 369 ASSERT_EQ(0x10004U, regs[ARM_REG_SP]);
@@ -379,6 +387,7 @@ TEST_F(ElfInterfaceArmTest, StepExidx_cant_unwind) {
379 387
380 bool finished; 388 bool finished;
381 ASSERT_TRUE(interface.StepExidx(0x7000, 0, &regs, &process_memory_, &finished)); 389 ASSERT_TRUE(interface.StepExidx(0x7000, 0, &regs, &process_memory_, &finished));
390 EXPECT_EQ(ERROR_NONE, interface.LastErrorCode());
382 ASSERT_TRUE(finished); 391 ASSERT_TRUE(finished);
383 ASSERT_EQ(0x10000U, regs.sp()); 392 ASSERT_EQ(0x10000U, regs.sp());
384 ASSERT_EQ(0x10000U, regs[ARM_REG_SP]); 393 ASSERT_EQ(0x10000U, regs[ARM_REG_SP]);
@@ -401,6 +410,7 @@ TEST_F(ElfInterfaceArmTest, StepExidx_refuse_unwind) {
401 410
402 bool finished; 411 bool finished;
403 ASSERT_TRUE(interface.StepExidx(0x7000, 0, &regs, &process_memory_, &finished)); 412 ASSERT_TRUE(interface.StepExidx(0x7000, 0, &regs, &process_memory_, &finished));
413 EXPECT_EQ(ERROR_NONE, interface.LastErrorCode());
404 ASSERT_TRUE(finished); 414 ASSERT_TRUE(finished);
405 ASSERT_EQ(0x10000U, regs.sp()); 415 ASSERT_EQ(0x10000U, regs.sp());
406 ASSERT_EQ(0x10000U, regs[ARM_REG_SP]); 416 ASSERT_EQ(0x10000U, regs[ARM_REG_SP]);
@@ -427,6 +437,7 @@ TEST_F(ElfInterfaceArmTest, StepExidx_pc_zero) {
427 437
428 bool finished; 438 bool finished;
429 ASSERT_TRUE(interface.StepExidx(0x7000, 0, &regs, &process_memory_, &finished)); 439 ASSERT_TRUE(interface.StepExidx(0x7000, 0, &regs, &process_memory_, &finished));
440 EXPECT_EQ(ERROR_NONE, interface.LastErrorCode());
430 ASSERT_TRUE(finished); 441 ASSERT_TRUE(finished);
431 ASSERT_EQ(0U, regs.pc()); 442 ASSERT_EQ(0U, regs.pc());
432 443
@@ -439,6 +450,7 @@ TEST_F(ElfInterfaceArmTest, StepExidx_pc_zero) {
439 regs.set_pc(0x1234); 450 regs.set_pc(0x1234);
440 451
441 ASSERT_TRUE(interface.StepExidx(0x7000, 0, &regs, &process_memory_, &finished)); 452 ASSERT_TRUE(interface.StepExidx(0x7000, 0, &regs, &process_memory_, &finished));
453 EXPECT_EQ(ERROR_NONE, interface.LastErrorCode());
442 ASSERT_TRUE(finished); 454 ASSERT_TRUE(finished);
443 ASSERT_EQ(0U, regs.pc()); 455 ASSERT_EQ(0U, regs.pc());
444} 456}
diff --git a/libunwindstack/tests/ElfTest.cpp b/libunwindstack/tests/ElfTest.cpp
index 7e6a62a32..eb850336b 100644
--- a/libunwindstack/tests/ElfTest.cpp
+++ b/libunwindstack/tests/ElfTest.cpp
@@ -581,4 +581,30 @@ TEST_F(ElfTest, is_valid_pc_from_gnu_debugdata) {
581 EXPECT_TRUE(elf.IsValidPc(0x1500)); 581 EXPECT_TRUE(elf.IsValidPc(0x1500));
582} 582}
583 583
584TEST_F(ElfTest, error_code_not_valid) {
585 ElfFake elf(memory_);
586 elf.FakeSetValid(false);
587
588 ErrorData error{ERROR_MEMORY_INVALID, 0x100};
589 elf.GetLastError(&error);
590 EXPECT_EQ(ERROR_MEMORY_INVALID, error.code);
591 EXPECT_EQ(0x100U, error.address);
592}
593
594TEST_F(ElfTest, error_code_valid) {
595 ElfFake elf(memory_);
596 elf.FakeSetValid(true);
597 ElfInterfaceFake* interface = new ElfInterfaceFake(memory_);
598 elf.FakeSetInterface(interface);
599 interface->FakeSetErrorCode(ERROR_MEMORY_INVALID);
600 interface->FakeSetErrorAddress(0x1000);
601
602 ErrorData error{ERROR_NONE, 0};
603 elf.GetLastError(&error);
604 EXPECT_EQ(ERROR_MEMORY_INVALID, error.code);
605 EXPECT_EQ(0x1000U, error.address);
606 EXPECT_EQ(ERROR_MEMORY_INVALID, elf.GetLastErrorCode());
607 EXPECT_EQ(0x1000U, elf.GetLastErrorAddress());
608}
609
584} // namespace unwindstack 610} // namespace unwindstack
diff --git a/libunwindstack/tests/UnwinderTest.cpp b/libunwindstack/tests/UnwinderTest.cpp
index cd468074e..bf2c1d892 100644
--- a/libunwindstack/tests/UnwinderTest.cpp
+++ b/libunwindstack/tests/UnwinderTest.cpp
@@ -129,6 +129,7 @@ TEST_F(UnwinderTest, multiple_frames) {
129 129
130 Unwinder unwinder(64, &maps_, &regs_, process_memory_); 130 Unwinder unwinder(64, &maps_, &regs_, process_memory_);
131 unwinder.Unwind(); 131 unwinder.Unwind();
132 EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
132 133
133 ASSERT_EQ(3U, unwinder.NumFrames()); 134 ASSERT_EQ(3U, unwinder.NumFrames());
134 135
@@ -184,6 +185,7 @@ TEST_F(UnwinderTest, non_zero_map_offset) {
184 185
185 Unwinder unwinder(64, &maps_, &regs_, process_memory_); 186 Unwinder unwinder(64, &maps_, &regs_, process_memory_);
186 unwinder.Unwind(); 187 unwinder.Unwind();
188 EXPECT_EQ(ERROR_NONE, unwinder.LastErrorCode());
187 189
188 ASSERT_EQ(1U, unwinder.NumFrames());