summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristopher Ferris2018-06-21 12:44:02 -0500
committerChristopher Ferris2018-06-27 16:52:21 -0500
commit92acaac8c713c3e1828948064ebca055dc00a723 (patch)
treed50cf188a4df626b8e9718469575e7ff17671dd7 /libunwindstack
parentfc1cf90741e59d5615a7dcea1813f38bfa3a2eec (diff)
downloadplatform-system-core-92acaac8c713c3e1828948064ebca055dc00a723.tar.gz
platform-system-core-92acaac8c713c3e1828948064ebca055dc00a723.tar.xz
platform-system-core-92acaac8c713c3e1828948064ebca055dc00a723.zip
Refactor the DwarfSection classes.
Modify the code for the no header sections because it turns out that it is not okay to assume that the fdes are non-overlapping. It's necessary to read the fdes in order and match as you go. Modify the code so that it only reads until it finds the given pc rather than reading all of the cie/fde entries at once. Rewrote the tests to verify the new behavior. Bug: 68998033 Bug: 110235461 Test: Ran libbacktrace/libunwindstack unit tests. Test: Unwind the mediaserver process on a walleye and verify it Test: unwinds properly. Change-Id: I7bb59d1db72c13fa34caa9735ec34c1a60e20ed2
Diffstat (limited to 'libunwindstack')
-rw-r--r--libunwindstack/DwarfDebugFrame.h4
-rw-r--r--libunwindstack/DwarfEhFrame.h4
-rw-r--r--libunwindstack/DwarfEhFrameWithHdr.cpp34
-rw-r--r--libunwindstack/DwarfEhFrameWithHdr.h28
-rw-r--r--libunwindstack/DwarfSection.cpp787
-rw-r--r--libunwindstack/include/unwindstack/DwarfSection.h97
-rw-r--r--libunwindstack/tests/DwarfDebugFrameTest.cpp1064
-rw-r--r--libunwindstack/tests/DwarfEhFrameTest.cpp472
-rw-r--r--libunwindstack/tests/DwarfEhFrameWithHdrTest.cpp99
-rw-r--r--libunwindstack/tests/DwarfSectionImplTest.cpp412
-rw-r--r--libunwindstack/tests/DwarfSectionTest.cpp135
-rw-r--r--libunwindstack/tests/ElfInterfaceTest.cpp65
12 files changed, 1312 insertions, 1889 deletions
diff --git a/libunwindstack/DwarfDebugFrame.h b/libunwindstack/DwarfDebugFrame.h
index 635cefdf2..388ab0a4f 100644
--- a/libunwindstack/DwarfDebugFrame.h
+++ b/libunwindstack/DwarfDebugFrame.h
@@ -26,9 +26,9 @@
26namespace unwindstack { 26namespace unwindstack {
27 27
28template <typename AddressType> 28template <typename AddressType>
29class DwarfDebugFrame : public DwarfSectionImpl<AddressType> { 29class DwarfDebugFrame : public DwarfSectionImplNoHdr<AddressType> {
30 public: 30 public:
31 DwarfDebugFrame(Memory* memory) : DwarfSectionImpl<AddressType>(memory) { 31 DwarfDebugFrame(Memory* memory) : DwarfSectionImplNoHdr<AddressType>(memory) {
32 this->cie32_value_ = static_cast<uint32_t>(-1); 32 this->cie32_value_ = static_cast<uint32_t>(-1);
33 this->cie64_value_ = static_cast<uint64_t>(-1); 33 this->cie64_value_ = static_cast<uint64_t>(-1);
34 } 34 }
diff --git a/libunwindstack/DwarfEhFrame.h b/libunwindstack/DwarfEhFrame.h
index 7a41e4550..df441fb52 100644
--- a/libunwindstack/DwarfEhFrame.h
+++ b/libunwindstack/DwarfEhFrame.h
@@ -25,9 +25,9 @@
25namespace unwindstack { 25namespace unwindstack {
26 26
27template <typename AddressType> 27template <typename AddressType>
28class DwarfEhFrame : public DwarfSectionImpl<AddressType> { 28class DwarfEhFrame : public DwarfSectionImplNoHdr<AddressType> {
29 public: 29 public:
30 DwarfEhFrame(Memory* memory) : DwarfSectionImpl<AddressType>(memory) {} 30 DwarfEhFrame(Memory* memory) : DwarfSectionImplNoHdr<AddressType>(memory) {}
31 virtual ~DwarfEhFrame() = default; 31 virtual ~DwarfEhFrame() = default;
32 32
33 uint64_t GetCieOffsetFromFde32(uint32_t pointer) override { 33 uint64_t GetCieOffsetFromFde32(uint32_t pointer) override {
diff --git a/libunwindstack/DwarfEhFrameWithHdr.cpp b/libunwindstack/DwarfEhFrameWithHdr.cpp
index fd6a457ef..668527a4d 100644
--- a/libunwindstack/DwarfEhFrameWithHdr.cpp
+++ b/libunwindstack/DwarfEhFrameWithHdr.cpp
@@ -39,6 +39,7 @@ bool DwarfEhFrameWithHdr<AddressType>::Init(uint64_t offset, uint64_t size, uint
39 memory_.clear_text_offset(); 39 memory_.clear_text_offset();
40 memory_.set_data_offset(offset); 40 memory_.set_data_offset(offset);
41 memory_.set_cur_offset(offset); 41 memory_.set_cur_offset(offset);
42 pc_offset_ = offset;
42 43
43 // Read the first four bytes all at once. 44 // Read the first four bytes all at once.
44 uint8_t data[4]; 45 uint8_t data[4];
@@ -88,12 +89,22 @@ bool DwarfEhFrameWithHdr<AddressType>::Init(uint64_t offset, uint64_t size, uint
88} 89}
89 90
90template <typename AddressType> 91template <typename AddressType>
91const DwarfFde* DwarfEhFrameWithHdr<AddressType>::GetFdeFromIndex(size_t index) { 92const DwarfFde* DwarfEhFrameWithHdr<AddressType>::GetFdeFromPc(uint64_t pc) {
92 const FdeInfo* info = GetFdeInfoFromIndex(index); 93 uint64_t fde_offset;
93 if (info == nullptr) { 94 if (!GetFdeOffsetFromPc(pc, &fde_offset)) {
94 return nullptr; 95 return nullptr;
95 } 96 }
96 return this->GetFdeFromOffset(info->offset); 97 const DwarfFde* fde = this->GetFdeFromOffset(fde_offset);
98 if (fde == nullptr) {
99 return nullptr;
100 }
101
102 // Guaranteed pc >= pc_start, need to check pc in the fde range.
103 if (pc < fde->pc_end) {
104 return fde;
105 }
106 last_error_.code = DWARF_ERROR_ILLEGAL_STATE;
107 return nullptr;
97} 108}
98 109
99template <typename AddressType> 110template <typename AddressType>
@@ -241,6 +252,21 @@ bool DwarfEhFrameWithHdr<AddressType>::GetFdeOffsetFromPc(uint64_t pc, uint64_t*
241 } 252 }
242} 253}
243 254
255template <typename AddressType>
256void DwarfEhFrameWithHdr<AddressType>::GetFdes(std::vector<const DwarfFde*>* fdes) {
257 for (size_t i = 0; i < fde_count_; i++) {
258 const FdeInfo* info = GetFdeInfoFromIndex(i);
259 if (info == nullptr) {
260 break;
261 }
262 const DwarfFde* fde = this->GetFdeFromOffset(info->offset);
263 if (fde == nullptr) {
264 break;
265 }
266 fdes->push_back(fde);
267 }
268}
269
244// Explicitly instantiate DwarfEhFrameWithHdr 270// Explicitly instantiate DwarfEhFrameWithHdr
245template class DwarfEhFrameWithHdr<uint32_t>; 271template class DwarfEhFrameWithHdr<uint32_t>;
246template class DwarfEhFrameWithHdr<uint64_t>; 272template class DwarfEhFrameWithHdr<uint64_t>;
diff --git a/libunwindstack/DwarfEhFrameWithHdr.h b/libunwindstack/DwarfEhFrameWithHdr.h
index d16dd1006..e3e9ca885 100644
--- a/libunwindstack/DwarfEhFrameWithHdr.h
+++ b/libunwindstack/DwarfEhFrameWithHdr.h
@@ -21,7 +21,7 @@
21 21
22#include <unordered_map> 22#include <unordered_map>
23 23
24#include "DwarfEhFrame.h" 24#include <unwindstack/DwarfSection.h>
25 25
26namespace unwindstack { 26namespace unwindstack {
27 27
@@ -29,12 +29,12 @@ namespace unwindstack {
29class Memory; 29class Memory;
30 30
31template <typename AddressType> 31template <typename AddressType>
32class DwarfEhFrameWithHdr : public DwarfEhFrame<AddressType> { 32class DwarfEhFrameWithHdr : public DwarfSectionImpl<AddressType> {
33 public: 33 public:
34 // Add these so that the protected members of DwarfSectionImpl 34 // Add these so that the protected members of DwarfSectionImpl
35 // can be accessed without needing a this->. 35 // can be accessed without needing a this->.
36 using DwarfSectionImpl<AddressType>::memory_; 36 using DwarfSectionImpl<AddressType>::memory_;
37 using DwarfSectionImpl<AddressType>::fde_count_; 37 using DwarfSectionImpl<AddressType>::pc_offset_;
38 using DwarfSectionImpl<AddressType>::entries_offset_; 38 using DwarfSectionImpl<AddressType>::entries_offset_;
39 using DwarfSectionImpl<AddressType>::entries_end_; 39 using DwarfSectionImpl<AddressType>::entries_end_;
40 using DwarfSectionImpl<AddressType>::last_error_; 40 using DwarfSectionImpl<AddressType>::last_error_;
@@ -45,14 +45,27 @@ class DwarfEhFrameWithHdr : public DwarfEhFrame<AddressType> {
45 uint64_t offset; 45 uint64_t offset;
46 }; 46 };
47 47
48 DwarfEhFrameWithHdr(Memory* memory) : DwarfEhFrame<AddressType>(memory) {} 48 DwarfEhFrameWithHdr(Memory* memory) : DwarfSectionImpl<AddressType>(memory) {}
49 virtual ~DwarfEhFrameWithHdr() = default; 49 virtual ~DwarfEhFrameWithHdr() = default;
50 50
51 uint64_t GetCieOffsetFromFde32(uint32_t pointer) override {
52 return this->memory_.cur_offset() - pointer - 4;
53 }
54
55 uint64_t GetCieOffsetFromFde64(uint64_t pointer) override {
56 return this->memory_.cur_offset() - pointer - 8;
57 }
58
59 uint64_t AdjustPcFromFde(uint64_t pc) override {
60 // The eh_frame uses relative pcs.
61 return pc + this->memory_.cur_offset() - 4;
62 }
63
51 bool Init(uint64_t offset, uint64_t size, uint64_t load_bias) override; 64 bool Init(uint64_t offset, uint64_t size, uint64_t load_bias) override;
52 65
53 bool GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) override; 66 const DwarfFde* GetFdeFromPc(uint64_t pc) override;
54 67
55 const DwarfFde* GetFdeFromIndex(size_t index) override; 68 bool GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset);
56 69
57 const FdeInfo* GetFdeInfoFromIndex(size_t index); 70 const FdeInfo* GetFdeInfoFromIndex(size_t index);
58 71
@@ -60,6 +73,8 @@ class DwarfEhFrameWithHdr : public DwarfEhFrame<AddressType> {
60 73
61 bool GetFdeOffsetBinary(uint64_t pc, uint64_t* fde_offset, uint64_t total_entries); 74 bool GetFdeOffsetBinary(uint64_t pc, uint64_t* fde_offset, uint64_t total_entries);
62 75
76 void GetFdes(std::vector<const DwarfFde*>* fdes) override;
77
63 protected: 78 protected:
64 uint8_t version_; 79 uint8_t version_;
65 uint8_t ptr_encoding_; 80 uint8_t ptr_encoding_;
@@ -71,6 +86,7 @@ class DwarfEhFrameWithHdr : public DwarfEhFrame<AddressType> {
71 uint64_t entries_data_offset_; 86 uint64_t entries_data_offset_;
72 uint64_t cur_entries_offset_ = 0; 87 uint64_t cur_entries_offset_ = 0;
73 88
89 uint64_t fde_count_;
74 std::unordered_map<uint64_t, FdeInfo> fde_info_; 90 std::unordered_map<uint64_t, FdeInfo> fde_info_;
75}; 91};
76 92
diff --git a/libunwindstack/DwarfSection.cpp b/libunwindstack/DwarfSection.cpp
index eb8394989..6061f6137 100644
--- a/libunwindstack/DwarfSection.cpp
+++ b/libunwindstack/DwarfSection.cpp
@@ -36,24 +36,6 @@ namespace unwindstack {
36 36
37DwarfSection::DwarfSection(Memory* memory) : memory_(memory) {} 37DwarfSection::DwarfSection(Memory* memory) : memory_(memory) {}
38 38
39const DwarfFde* DwarfSection::GetFdeFromPc(uint64_t pc) {
40 uint64_t fde_offset;
41 if (!GetFdeOffsetFromPc(pc, &fde_offset)) {
42 return nullptr;
43 }
44 const DwarfFde* fde = GetFdeFromOffset(fde_offset);
45 if (fde == nullptr) {
46 return nullptr;
47 }
48
49 // Guaranteed pc >= pc_start, need to check pc in the fde range.
50 if (pc < fde->pc_end) {
51 return fde;
52 }
53 last_error_.code = DWARF_ERROR_ILLEGAL_STATE;
54 return nullptr;
55}
56
57bool DwarfSection::Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished) { 39bool DwarfSection::Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished) {
58 // Lookup the pc in the cache. 40 // Lookup the pc in the cache.
59 auto it = loc_regs_.upper_bound(pc); 41 auto it = loc_regs_.upper_bound(pc);
@@ -81,193 +63,14 @@ bool DwarfSection::Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* f
81} 63}
82 64
83template <typename AddressType> 65template <typename AddressType>
84bool DwarfSectionImpl<AddressType>::EvalExpression(const DwarfLocation& loc, Memory* regular_memory, 66const DwarfCie* DwarfSectionImpl<AddressType>::GetCieFromOffset(uint64_t offset) {
85 AddressType* value,
86 RegsInfo<AddressType>* regs_info,
87 bool* is_dex_pc) {
88 DwarfOp<AddressType> op(&memory_, regular_memory);
89 op.set_regs_info(regs_info);
90
91 // Need to evaluate the op data.
92 uint64_t end = loc.values[1];
93 uint64_t start = end - loc.values[0];
94 if (!op.Eval(start, end)) {
95 last_error_ = op.last_error();
96 return false;
97 }
98 if (op.StackSize() == 0) {
99 last_error_.code = DWARF_ERROR_ILLEGAL_STATE;
100 return false;
101 }
102 // We don't support an expression that evaluates to a register number.
103 if (op.is_register()) {
104 last_error_.code = DWARF_ERROR_NOT_IMPLEMENTED;
105 return false;
106 }
107 *value = op.StackAt(0);
108 if (is_dex_pc != nullptr && op.dex_pc_set()) {
109 *is_dex_pc = true;
110 }
111 return true;
112}
113
114template <typename AddressType>
115struct EvalInfo {
116 const dwarf_loc_regs_t* loc_regs;
117 const DwarfCie* cie;
118 Memory* regular_memory;
119 AddressType cfa;
120 bool return_address_undefined = false;
121 RegsInfo<AddressType> regs_info;
122};
123
124template <typename AddressType>
125bool DwarfSectionImpl<AddressType>::EvalRegister(const DwarfLocation* loc, uint32_t reg,
126 AddressType* reg_ptr, void* info) {
127 EvalInfo<AddressType>* eval_info = reinterpret_cast<EvalInfo<AddressType>*>(info);
128 Memory* regular_memory = eval_info->regular_memory;
129 switch (loc->type) {
130 case DWARF_LOCATION_OFFSET:
131 if (!regular_memory->ReadFully(eval_info->cfa + loc->values[0], reg_ptr, sizeof(AddressType))) {
132 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
133 last_error_.address = eval_info->cfa + loc->values[0];
134 return false;
135 }
136 break;
137 case DWARF_LOCATION_VAL_OFFSET:
138 *reg_ptr = eval_info->cfa + loc->values[0];
139 break;
140 case DWARF_LOCATION_REGISTER: {
141 uint32_t cur_reg = loc->values[0];
142 if (cur_reg >= eval_info->regs_info.Total()) {
143 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
144 return false;
145 }
146 *reg_ptr = eval_info->regs_info.Get(cur_reg) + loc->values[1];
147 break;
148 }
149 case DWARF_LOCATION_EXPRESSION:
150 case DWARF_LOCATION_VAL_EXPRESSION: {
151 AddressType value;
152 bool is_dex_pc = false;
153 if (!EvalExpression(*loc, regular_memory, &value, &eval_info->regs_info, &is_dex_pc)) {
154 return false;
155 }
156 if (loc->type == DWARF_LOCATION_EXPRESSION) {
157 if (!regular_memory->ReadFully(value, reg_ptr, sizeof(AddressType))) {
158 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
159 last_error_.address = value;
160 return false;
161 }
162 } else {
163 *reg_ptr = value;
164 if (is_dex_pc) {
165 eval_info->regs_info.regs->set_dex_pc(value);
166 }
167 }
168 break;
169 }
170 case DWARF_LOCATION_UNDEFINED:
171 if (reg == eval_info->cie->return_address_register) {
172 eval_info->return_address_undefined = true;
173 }
174 default:
175 break;
176 }
177
178 return true;
179}
180
181template <typename AddressType>
182bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_memory,
183 const dwarf_loc_regs_t& loc_regs, Regs* regs,
184 bool* finished) {
185 RegsImpl<AddressType>* cur_regs = reinterpret_cast<RegsImpl<AddressType>*>(regs);
186 if (cie->return_address_register >= cur_regs->total_regs()) {
187 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
188 return false;
189 }
190
191 // Get the cfa value;
192 auto cfa_entry = loc_regs.find(CFA_REG);
193 if (cfa_entry == loc_regs.end()) {
194 last_error_.code = DWARF_ERROR_CFA_NOT_DEFINED;
195 return false;
196 }
197
198 // Always set the dex pc to zero when evaluating.
199 cur_regs->set_dex_pc(0);
200
201 EvalInfo<AddressType> eval_info{.loc_regs = &loc_regs,
202 .cie = cie,
203 .regular_memory = regular_memory,
204 .regs_info = RegsInfo<AddressType>(cur_regs)};
205 const DwarfLocation* loc = &cfa_entry->second;
206 // Only a few location types are valid for the cfa.
207 switch (loc->type) {
208 case DWARF_LOCATION_REGISTER:
209 if (loc->values[0] >= cur_regs->total_regs()) {
210 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
211 return false;
212 }
213 eval_info.cfa = (*cur_regs)[loc->values[0]];
214 eval_info.cfa += loc->values[1];
215 break;
216 case DWARF_LOCATION_VAL_EXPRESSION: {
217 AddressType value;
218 if (!EvalExpression(*loc, regular_memory, &value, &eval_info.regs_info, nullptr)) {
219 return false;
220 }
221 // There is only one type of valid expression for CFA evaluation.
222 eval_info.cfa = value;
223 break;
224 }
225 default:
226 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
227 return false;
228 }
229
230 for (const auto& entry : loc_regs) {
231 uint32_t reg = entry.first;
232 // Already handled the CFA register.
233 if (reg == CFA_REG) continue;
234
235 AddressType* reg_ptr;
236 if (reg >= cur_regs->total_regs()) {
237 // Skip this unknown register.
238 continue;
239 }
240
241 reg_ptr = eval_info.regs_info.Save(reg);
242 if (!EvalRegister(&entry.second, reg, reg_ptr, &eval_info)) {
243 return false;
244 }
245 }
246
247 // Find the return address location.
248 if (eval_info.return_address_undefined) {
249 cur_regs->set_pc(0);
250 } else {
251 cur_regs->set_pc((*cur_regs)[cie->return_address_register]);
252 }
253
254 // If the pc was set to zero, consider this the final frame.
255 *finished = (cur_regs->pc() == 0) ? true : false;
256
257 cur_regs->set_sp(eval_info.cfa);
258
259 return true;
260}
261
262template <typename AddressType>
263const DwarfCie* DwarfSectionImpl<AddressType>::GetCie(uint64_t offset) {
264 auto cie_entry = cie_entries_.find(offset); 67 auto cie_entry = cie_entries_.find(offset);
265 if (cie_entry != cie_entries_.end()) { 68 if (cie_entry != cie_entries_.end()) {
266 return &cie_entry->second; 69 return &cie_entry->second;
267 } 70 }
268 DwarfCie* cie = &cie_entries_[offset]; 71 DwarfCie* cie = &cie_entries_[offset];
269 memory_.set_cur_offset(offset); 72 memory_.set_cur_offset(offset);
270 if (!FillInCie(cie)) { 73 if (!FillInCieHeader(cie) || !FillInCie(cie)) {
271 // Erase the cached entry. 74 // Erase the cached entry.
272 cie_entries_.erase(offset); 75 cie_entries_.erase(offset);
273 return nullptr; 76 return nullptr;
@@ -276,16 +79,14 @@ const DwarfCie* DwarfSectionImpl<AddressType>::GetCie(uint64_t offset) {
276} 79}
277 80
278template <typename AddressType> 81template <typename AddressType>
279bool DwarfSectionImpl<AddressType>::FillInCie(DwarfCie* cie) { 82bool DwarfSectionImpl<AddressType>::FillInCieHeader(DwarfCie* cie) {
83 cie->lsda_encoding = DW_EH_PE_omit;
280 uint32_t length32; 84 uint32_t length32;
281 if (!memory_.ReadBytes(&length32, sizeof(length32))) { 85 if (!memory_.ReadBytes(&length32, sizeof(length32))) {
282 last_error_.code = DWARF_ERROR_MEMORY_INVALID; 86 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
283 last_error_.address = memory_.cur_offset(); 87 last_error_.address = memory_.cur_offset();
284 return false; 88 return false;
285 } 89 }
286 // Set the default for the lsda encoding.
287 cie->lsda_encoding = DW_EH_PE_omit;
288
289 if (length32 == static_cast<uint32_t>(-1)) { 90 if (length32 == static_cast<uint32_t>(-1)) {
290 // 64 bit Cie 91 // 64 bit Cie
291 uint64_t length64; 92 uint64_t length64;
@@ -326,7 +127,11 @@ bool DwarfSectionImpl<AddressType>::FillInCie(DwarfCie* cie) {
326 return false; 127 return false;
327 } 128 }
328 } 129 }
130 return true;
131}
329 132
133template <typename AddressType>
134bool DwarfSectionImpl<AddressType>::FillInCie(DwarfCie* cie) {
330 if (!memory_.ReadBytes(&cie->version, sizeof(cie->version))) { 135 if (!memory_.ReadBytes(&cie->version, sizeof(cie->version))) {
331 last_error_.code = DWARF_ERROR_MEMORY_INVALID; 136 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
332 last_error_.address = memory_.cur_offset(); 137 last_error_.address = memory_.cur_offset();
@@ -447,7 +252,7 @@ const DwarfFde* DwarfSectionImpl<AddressType>::GetFdeFromOffset(uint64_t offset)
447 } 252 }
448 DwarfFde* fde = &fde_entries_[offset]; 253 DwarfFde* fde = &fde_entries_[offset];
449 memory_.set_cur_offset(offset); 254 memory_.set_cur_offset(offset);
450 if (!FillInFde(fde)) { 255 if (!FillInFdeHeader(fde) || !FillInFde(fde)) {
451 fde_entries_.erase(offset); 256 fde_entries_.erase(offset);
452 return nullptr; 257 return nullptr;
453 } 258 }
@@ -455,7 +260,7 @@ const DwarfFde* DwarfSectionImpl<AddressType>::GetFdeFromOffset(uint64_t offset)
455} 260}
456 261
457template <typename AddressType> 262template <typename AddressType>
458bool DwarfSectionImpl<AddressType>::FillInFde(DwarfFde* fde) { 263bool DwarfSectionImpl<AddressType>::FillInFdeHeader(DwarfFde* fde) {
459 uint32_t length32; 264 uint32_t length32;
460 if (!memory_.ReadBytes(&length32, sizeof(length32))) { 265 if (!memory_.ReadBytes(&length32, sizeof(length32))) {
461 last_error_.code = DWARF_ERROR_MEMORY_INVALID; 266 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
@@ -508,9 +313,14 @@ bool DwarfSectionImpl<AddressType>::FillInFde(DwarfFde* fde) {
508 // of the Fde information. 313 // of the Fde information.
509 fde->cie_offset = GetCieOffsetFromFde32(value32); 314 fde->cie_offset = GetCieOffsetFromFde32(value32);
510 } 315 }
316 return true;
317}
318
319template <typename AddressType>
320bool DwarfSectionImpl<AddressType>::FillInFde(DwarfFde* fde) {
511 uint64_t cur_offset = memory_.cur_offset(); 321 uint64_t cur_offset = memory_.cur_offset();
512 322
513 const DwarfCie* cie = GetCie(fde->cie_offset); 323 const DwarfCie* cie = GetCieFromOffset(fde->cie_offset);
514 if (cie == nullptr) { 324 if (cie == nullptr) {
515 return false; 325 return false;
516 } 326 }
@@ -561,6 +371,185 @@ bool DwarfSectionImpl<AddressType>::FillInFde(DwarfFde* fde) {
561} 371}
562 372
563template <typename AddressType> 373template <typename AddressType>
374bool DwarfSectionImpl<AddressType>::EvalExpression(const DwarfLocation& loc, Memory* regular_memory,
375 AddressType* value,
376 RegsInfo<AddressType>* regs_info,
377 bool* is_dex_pc) {
378 DwarfOp<AddressType> op(&memory_, regular_memory);
379 op.set_regs_info(regs_info);
380
381 // Need to evaluate the op data.
382 uint64_t end = loc.values[1];
383 uint64_t start = end - loc.values[0];
384 if (!op.Eval(start, end)) {
385 last_error_ = op.last_error();
386 return false;
387 }
388 if (op.StackSize() == 0) {
389 last_error_.code = DWARF_ERROR_ILLEGAL_STATE;
390 return false;
391 }
392 // We don't support an expression that evaluates to a register number.
393 if (op.is_register()) {
394 last_error_.code = DWARF_ERROR_NOT_IMPLEMENTED;
395 return false;
396 }
397 *value = op.StackAt(0);
398 if (is_dex_pc != nullptr && op.dex_pc_set()) {
399 *is_dex_pc = true;
400 }
401 return true;
402}
403
404template <typename AddressType>
405struct EvalInfo {
406 const dwarf_loc_regs_t* loc_regs;
407 const DwarfCie* cie;
408 Memory* regular_memory;
409 AddressType cfa;
410 bool return_address_undefined = false;
411 RegsInfo<AddressType> regs_info;
412};
413
414template <typename AddressType>
415bool DwarfSectionImpl<AddressType>::EvalRegister(const DwarfLocation* loc, uint32_t reg,
416 AddressType* reg_ptr, void* info) {
417 EvalInfo<AddressType>* eval_info = reinterpret_cast<EvalInfo<AddressType>*>(info);
418 Memory* regular_memory = eval_info->regular_memory;
419 switch (loc->type) {
420 case DWARF_LOCATION_OFFSET:
421 if (!regular_memory->ReadFully(eval_info->cfa + loc->values[0], reg_ptr, sizeof(AddressType))) {
422 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
423 last_error_.address = eval_info->cfa + loc->values[0];
424 return false;
425 }
426 break;
427 case DWARF_LOCATION_VAL_OFFSET:
428 *reg_ptr = eval_info->cfa + loc->values[0];
429 break;
430 case DWARF_LOCATION_REGISTER: {
431 uint32_t cur_reg = loc->values[0];
432 if (cur_reg >= eval_info->regs_info.Total()) {
433 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
434 return false;
435 }
436 *reg_ptr = eval_info->regs_info.Get(cur_reg) + loc->values[1];
437 break;
438 }
439 case DWARF_LOCATION_EXPRESSION:
440 case DWARF_LOCATION_VAL_EXPRESSION: {
441 AddressType value;
442 bool is_dex_pc = false;
443 if (!EvalExpression(*loc, regular_memory, &value, &eval_info->regs_info, &is_dex_pc)) {
444 return false;
445 }
446 if (loc->type == DWARF_LOCATION_EXPRESSION) {
447 if (!regular_memory->ReadFully(value, reg_ptr, sizeof(AddressType))) {
448 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
449 last_error_.address = value;
450 return false;
451 }
452 } else {
453 *reg_ptr = value;
454 if (is_dex_pc) {
455 eval_info->regs_info.regs->set_dex_pc(value);
456 }
457 }
458 break;
459 }
460 case DWARF_LOCATION_UNDEFINED:
461 if (reg == eval_info->cie->return_address_register) {
462 eval_info->return_address_undefined = true;
463 }
464 default:
465 break;
466 }
467
468 return true;
469}
470
471template <typename AddressType>
472bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_memory,
473 const dwarf_loc_regs_t& loc_regs, Regs* regs,
474 bool* finished) {
475 RegsImpl<AddressType>* cur_regs = reinterpret_cast<RegsImpl<AddressType>*>(regs);
476 if (cie->return_address_register >= cur_regs->total_regs()) {
477 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
478 return false;
479 }
480
481 // Get the cfa value;
482 auto cfa_entry = loc_regs.find(CFA_REG);
483 if (cfa_entry == loc_regs.end()) {
484 last_error_.code = DWARF_ERROR_CFA_NOT_DEFINED;
485 return false;
486 }
487
488 // Always set the dex pc to zero when evaluating.
489 cur_regs->set_dex_pc(0);
490
491 EvalInfo<AddressType> eval_info{.loc_regs = &loc_regs,
492 .cie = cie,
493 .regular_memory = regular_memory,
494 .regs_info = RegsInfo<AddressType>(cur_regs)};
495 const DwarfLocation* loc = &cfa_entry->second;
496 // Only a few location types are valid for the cfa.
497 switch (loc->type) {
498 case DWARF_LOCATION_REGISTER:
499 if (loc->values[0] >= cur_regs->total_regs()) {
500 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
501 return false;
502 }
503 eval_info.cfa = (*cur_regs)[loc->values[0]];
504 eval_info.cfa += loc->values[1];
505 break;
506 case DWARF_LOCATION_VAL_EXPRESSION: {
507 AddressType value;
508 if (!EvalExpression(*loc, regular_memory, &value, &eval_info.regs_info, nullptr)) {
509 return false;
510 }
511 // There is only one type of valid expression for CFA evaluation.
512 eval_info.cfa = value;
513 break;
514 }
515 default:
516 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
517 return false;
518 }
519
520 for (const auto& entry : loc_regs) {
521 uint32_t reg = entry.first;
522 // Already handled the CFA register.
523 if (reg == CFA_REG) continue;
524
525 AddressType* reg_ptr;
526 if (reg >= cur_regs->total_regs()) {
527 // Skip this unknown register.
528 continue;
529 }
530
531 reg_ptr = eval_info.regs_info.Save(reg);
532 if (!EvalRegister(&entry.second, reg, reg_ptr, &eval_info)) {
533 return false;
534 }
535 }
536
537 // Find the return address location.
538 if (eval_info.return_address_undefined) {
539 cur_regs->set_pc(0);
540 } else {
541 cur_regs->set_pc((*cur_regs)[cie->return_address_register]);
542 }
543
544 // If the pc was set to zero, consider this the final frame.
545 *finished = (cur_regs->pc() == 0) ? true : false;
546
547 cur_regs->set_sp(eval_info.cfa);
548
549 return true;
550}
551
552template <typename AddressType>
564bool DwarfSectionImpl<AddressType>::GetCfaLocationInfo(uint64_t pc, const DwarfFde* fde, 553bool DwarfSectionImpl<AddressType>::GetCfaLocationInfo(uint64_t pc, const DwarfFde* fde,
565 dwarf_loc_regs_t* loc_regs) { 554 dwarf_loc_regs_t* loc_regs) {
566 DwarfCfa<AddressType> cfa(&memory_, fde); 555 DwarfCfa<AddressType> cfa(&memory_, fde);
@@ -601,9 +590,10 @@ bool DwarfSectionImpl<AddressType>::Log(uint8_t indent, uint64_t pc, const Dwarf
601} 590}
602 591
603template <typename AddressType> 592template <typename AddressType>
604bool DwarfSectionImpl<AddressType>::Init(uint64_t offset, uint64_t size, uint64_t load_bias) { 593bool DwarfSectionImplNoHdr<AddressType>::Init(uint64_t offset, uint64_t size, uint64_t load_bias) {
605 load_bias_ = load_bias; 594 load_bias_ = load_bias;
606 entries_offset_ = offset; 595 entries_offset_ = offset;
596 next_entries_offset_ = offset;
607 entries_end_ = offset + size; 597 entries_end_ = offset + size;
608 598
609 memory_.clear_func_offset(); 599 memory_.clear_func_offset();
@@ -612,298 +602,213 @@ bool DwarfSectionImpl<AddressType>::Init(uint64_t offset, uint64_t size, uint64_
612 memory_.set_data_offset(offset); 602 memory_.set_data_offset(offset);
613 pc_offset_ = offset; 603 pc_offset_ = offset;
614 604
615 return CreateSortedFdeList(); 605 return true;
616} 606}
617 607
608// Create a cached version of the fde information such that it is a std::map
609// that is indexed by end pc and contains a pair that represents the start pc
610// followed by the fde object. The fde pointers are owned by fde_entries_
611// and not by the map object.
612// It is possible for an fde to be represented by multiple entries in
613// the map. This can happen if the the start pc and end pc overlap already
614// existing entries. For example, if there is already an entry of 0x400, 0x200,
615// and an fde has a start pc of 0x100 and end pc of 0x500, two new entries
616// will be added: 0x200, 0x100 and 0x500, 0x400.
618template <typename AddressType> 617template <typename AddressType>
619bool DwarfSectionImpl<AddressType>::GetCieInfo(uint8_t* segment_size, uint8_t* encoding) { 618void DwarfSectionImplNoHdr<AddressType>::InsertFde(const DwarfFde* fde) {
620 uint8_t version; 619 uint64_t start = fde->pc_start;
621 if (!memory_.ReadBytes(&version, 1)) { 620 uint64_t end = fde->pc_end;
622 last_error_.code = DWARF_ERROR_MEMORY_INVALID; 621 auto it = fdes_.upper_bound(start);
623 last_error_.address = memory_.cur_offset(); 622 bool add_element = false;
624 return false; 623 while (it != fdes_.end() && start < end) {
625 } 624 if (add_element) {
626 // Read the augmentation string. 625 add_element = false;
627 std::vector<char> aug_string; 626 if (end < it->second.first) {
628 char aug_value; 627 if (it->first == end) {
629 bool get_encoding = false; 628 return;
630 do { 629 }
631 if (!memory_.ReadBytes(&aug_value, 1)) { 630 fdes_[end] = std::make_pair(start, fde);
632 last_error_.code = DWARF_ERROR_MEMORY_INVALID; 631 return;
633 last_error_.address = memory_.cur_offset(); 632 }
634 return false; 633 if (start != it->second.first) {
635 } 634 fdes_[it->second.first] = std::make_pair(start, fde);
636 if (aug_value == 'R') { 635 }
637 get_encoding = true;
638 } 636 }
639 aug_string.push_back(aug_value); 637 if (start < it->first) {
640 } while (aug_value != '\0'); 638 if (end < it->second.first) {
641 639 if (it->first != end) {
642 if (version == 4) { 640 fdes_[end] = std::make_pair(start, fde);
643 // Skip the Address Size field. 641 }
644 memory_.set_cur_offset(memory_.cur_offset() + 1); 642 return;
645 643 }
646 // Read the segment size. 644 add_element = true;
647 if (!memory_.ReadBytes(segment_size, 1)) {
648 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
649 last_error_.address = memory_.cur_offset();
650 return false;
651 } 645 }
652 } else { 646 start = it->first;
653 *segment_size = 0; 647 ++it;
654 } 648 }
649 if (start < end) {
650 fdes_[end] = std::make_pair(start, fde);
651 }
652}
655 653
656 if (aug_string[0] != 'z' || !get_encoding) { 654template <typename AddressType>
657 // No encoding 655bool DwarfSectionImplNoHdr<AddressType>::GetNextCieOrFde(DwarfFde** fde_entry) {
658 return true; 656 uint64_t start_offset = next_entries_offset_;
657
658 memory_.set_cur_offset(next_entries_offset_);
659 uint32_t value32;
660 if (!memory_.ReadBytes(&value32, sizeof(value32))) {
661 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
662 last_error_.address = memory_.cur_offset();
663 return false;
659 } 664 }
660 665
661 // Skip code alignment factor 666 uint64_t cie_offset;
662 uint8_t value; 667 uint8_t cie_fde_encoding;
663 do { 668 bool entry_is_cie = false;
664 if (!memory_.ReadBytes(&value, 1)) { 669 if (value32 == static_cast<uint32_t>(-1)) {
670 // 64 bit entry.
671 uint64_t value64;
672 if (!memory_.ReadBytes(&value64, sizeof(value64))) {
665 last_error_.code = DWARF_ERROR_MEMORY_INVALID; 673 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
666 last_error_.address = memory_.cur_offset(); 674 last_error_.address = memory_.cur_offset();
667 return false; 675 return false;
668 } 676 }
669 } while (value & 0x80);
670 677
671 // Skip data alignment factor 678 next_entries_offset_ = memory_.cur_offset() + value64;
672 do { 679 // Read the Cie Id of a Cie or the pointer of the Fde.
673 if (!memory_.ReadBytes(&value, 1)) { 680 if (!memory_.ReadBytes(&value64, sizeof(value64))) {
674 last_error_.code = DWARF_ERROR_MEMORY_INVALID; 681 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
675 last_error_.address = memory_.cur_offset(); 682 last_error_.address = memory_.cur_offset();
676 return false; 683 return false;
677 } 684 }
678 } while (value & 0x80);
679 685
680 if (version == 1) { 686 if (value64 == cie64_value_) {
681 // Skip return address register. 687 entry_is_cie = true;
682 memory_.set_cur_offset(memory_.cur_offset() + 1); 688 cie_fde_encoding = DW_EH_PE_sdata8;
689 } else {
690 cie_offset = this->GetCieOffsetFromFde64(value64);
691 }
683 } else { 692 } else {
684 // Skip return address register. 693 next_entries_offset_ = memory_.cur_offset() + value32;
685 do {
686 if (!memory_.ReadBytes(&value, 1)) {
687 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
688 last_error_.address = memory_.cur_offset();
689 return false;
690 }
691 } while (value & 0x80);
692 }
693 694
694 // Skip the augmentation length. 695 // 32 bit Cie
695 do { 696 if (!memory_.ReadBytes(&value32, sizeof(value32))) {
696 if (!memory_.ReadBytes(&value, 1)) {
697 last_error_.code = DWARF_ERROR_MEMORY_INVALID; 697 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
698 last_error_.address = memory_.cur_offset(); 698 last_error_.address = memory_.cur_offset();
699 return false; 699 return false;
700 } 700 }
701 } while (value & 0x80);
702 701
703 for (size_t i = 1; i < aug_string.size(); i++) { 702 if (value32 == cie32_value_) {
704 if (aug_string[i] == 'R') { 703 entry_is_cie = true;
705 if (!memory_.ReadBytes(encoding, 1)) { 704 cie_fde_encoding = DW_EH_PE_sdata4;
706 last_error_.code = DWARF_ERROR_MEMORY_INVALID; 705 } else {
707 last_error_.address = memory_.cur_offset(); 706 cie_offset = this->GetCieOffsetFromFde32(value32);
708 return false;
709 }
710 // Got the encoding, that's all we are looking for.
711 return true;
712 } else if (aug_string[i] == 'L') {
713 memory_.set_cur_offset(memory_.cur_offset() + 1);
714 } else if (aug_string[i] == 'P') {
715 uint8_t encoding;
716 if (!memory_.ReadBytes(&encoding, 1)) {
717 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
718 last_error_.address = memory_.cur_offset();
719 return false;
720 }
721 uint64_t value;
722 memory_.set_pc_offset(pc_offset_);
723 if (!memory_.template ReadEncodedValue<AddressType>(encoding, &value)) {
724 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
725 last_error_.address = memory_.cur_offset();
726 return false;
727 }
728 } 707 }
729 } 708 }
730 709
731 // It should be impossible to get here. 710 if (entry_is_cie) {
732 abort(); 711 DwarfCie* cie = &cie_entries_[start_offset];
733} 712 cie->lsda_encoding = DW_EH_PE_omit;
734 713 cie->cfa_instructions_end = next_entries_offset_;
735template <typename AddressType> 714 cie->fde_address_encoding = cie_fde_encoding;
736bool DwarfSectionImpl<AddressType>::AddFdeInfo(uint64_t entry_offset, uint8_t segment_size,
737 uint8_t encoding) {
738 if (segment_size != 0) {
739 memory_.set_cur_offset(memory_.cur_offset() + 1);
740 }
741 715
742 uint64_t start; 716 if (!this->FillInCie(cie)) {
743 memory_.set_pc_offset(load_bias_); 717 cie_entries_.erase(start_offset);
744 bool valid = memory_.template ReadEncodedValue<AddressType>(encoding, &start); 718 return false;
745 start = AdjustPcFromFde(start); 719 }
720 *fde_entry = nullptr;
721 } else {
722 DwarfFde* fde = &fde_entries_[start_offset];
723 fde->cfa_instructions_end = next_entries_offset_;
724 fde->cie_offset = cie_offset;
746 725
747 uint64_t length; 726 if (!this->FillInFde(fde)) {
748 memory_.set_pc_offset(0); 727 fde_entries_.erase(start_offset);
749 if (!valid || !memory_.template ReadEncodedValue<AddressType>(encoding, &length)) { 728 return false;
750 last_error_.code = DWARF_ERROR_MEMORY_INVALID; 729 }
751 last_error_.address = memory_.cur_offset(); 730 *fde_entry = fde;
752 return false;
753 }
754 if (length != 0) {
755 fdes_.emplace_back(entry_offset, start, length);
756 } 731 }
757
758 return true; 732 return true;
759} 733}
760 734
761template <typename AddressType> 735template <typename AddressType>
762bool DwarfSectionImpl<AddressType>::CreateSortedFdeList() { 736void DwarfSectionImplNoHdr<AddressType>::GetFdes(std::vector<const DwarfFde*>* fdes) {
763 memory_.set_cur_offset(entries_offset_); 737 // Loop through the already cached entries.
764 738 uint64_t entry_offset = entries_offset_;
765 // Loop through all of the entries and read just enough to create 739 while (entry_offset < next_entries_offset_) {
766 // a sorted list of pcs. 740 auto cie_it = cie_entries_.find(entry_offset);
767 // This code assumes that first comes the cie, then the fdes that 741 if (cie_it != cie_entries_.end()) {
768 // it applies to. 742 entry_offset = cie_it->second.cfa_instructions_end;
769 uint64_t cie_offset = 0;
770 uint8_t address_encoding;
771 uint8_t segment_size;
772 while (memory_.cur_offset() < entries_end_) {
773 uint64_t cur_entry_offset = memory_.cur_offset();
774
775 // Figure out the entry length and type.
776 uint32_t value32;
777 if (!memory_.ReadBytes(&value32, sizeof(value32))) {
778 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
779 last_error_.address = memory_.cur_offset();
780 return false;
781 }
782
783 uint64_t next_entry_offset;
784 if (value32 == static_cast<uint32_t>(-1)) {
785 uint64_t value64;
786 if (!memory_.ReadBytes(&value64, sizeof(value64))) {
787 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
788 last_error_.address = memory_.cur_offset();
789 return false;
790 }
791 next_entry_offset = memory_.cur_offset() + value64;
792
793 // Read the Cie Id of a Cie or the pointer of the Fde.
794 if (!memory_.ReadBytes(&value64, sizeof(value64))) {
795 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
796 last_error_.address = memory_.cur_offset();
797 return false;
798 }
799
800 if (value64 == cie64_value_) {
801 // Cie 64 bit
802 address_encoding = DW_EH_PE_sdata8;
803 if (!GetCieInfo(&segment_size, &address_encoding)) {
804 return false;
805 }
806 cie_offset = cur_entry_offset;
807 } else {
808 uint64_t last_cie_offset = GetCieOffsetFromFde64(value64);
809 if (last_cie_offset != cie_offset) {
810 // This means that this Fde is not following the Cie.
811 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
812 return false;
813 }
814
815 // Fde 64 bit
816 if (!AddFdeInfo(cur_entry_offset, segment_size, address_encoding)) {
817 return false;
818 }
819 }
820 } else { 743 } else {
821 next_entry_offset = memory_.cur_offset() + value32; 744 auto fde_it = fde_entries_.find(entry_offset);
822 745 if (fde_it == fde_entries_.end()) {
823 // Read the Cie Id of a Cie or the pointer of the Fde. 746 // No fde or cie at this entry, should not be possible.
824 if (!memory_.ReadBytes(&value32, sizeof(value32))) { 747 return;
825 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
826 last_error_.address = memory_.cur_offset();
827 return false;
828 } 748 }
749 entry_offset = fde_it->second.cfa_instructions_end;
750 fdes->push_back(&fde_it->second);
751 }
752 }
829 753
830 if (value32 == cie32_value_) { 754 while (next_entries_offset_ < entries_end_) {
831 // Cie 32 bit 755 DwarfFde* fde;
832 address_encoding = DW_EH_PE_sdata4; 756 if (!GetNextCieOrFde(&fde)) {
833 if (!GetCieInfo(&segment_size, &address_encoding)) { 757 break;
834 return false; 758 }
835 } 759 if (fde != nullptr) {
836 cie_offset = cur_entry_offset; 760 InsertFde(fde);
837 } else { 761 fdes->push_back(fde);
838 uint64_t last_cie_offset = GetCieOffsetFromFde32(value32);
839 if (last_cie_offset != cie_offset) {
840 // This means that this Fde is not following the Cie.
841 last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
842 return false;
843 }
844
845 // Fde 32 bit
846 if (!AddFdeInfo(cur_entry_offset, segment_size, address_encoding)) {
847 return false;
848 }
849 }
850 } 762 }
851 763
852 if (next_entry_offset < memory_.cur_offset()) { 764 if (next_entries_offset_ < memory_.cur_offset()) {
853 // Simply consider the processing done in this case. 765 // Simply consider the processing done in this case.
854 break; 766 break;
855 } 767 }
856 memory_.set_cur_offset(next_entry_offset);
857 } 768 }
858
859 // Sort the entries.
860 std::sort(fdes_.begin(), fdes_.end(), [](const FdeInfo& a, const FdeInfo& b) {
861 if (a.start == b.start) return a.end < b.end;
862 return a.start < b.start;
863 });
864
865 fde_count_ = fdes_.size();
866
867 return true;
868} 769}
869 770
870template <typename AddressType> 771template <typename AddressType>
871bool DwarfSectionImpl<AddressType>::GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) { 772const DwarfFde* DwarfSectionImplNoHdr<AddressType>::GetFdeFromPc(uint64_t pc) {
872 if (fde_count_ == 0) { 773 // Search in the list of fdes we already have.
873 return false; 774 auto it = fdes_.upper_bound(pc);
874 } 775 if (it != fdes_.end()) {
875 776 if (pc >= it->second.first) {
876 size_t first = 0; 777 return it->second.second;
877 size_t last = fde_count_; 778 }
878 while (first < last) { 779 }
879 size_t current = (first + last) / 2; 780
880 const FdeInfo* info = &fdes_[current]; 781 // The section might have overlapping pcs in fdes, so it is necessary
881 if (pc >= info->start && pc < info->end) { 782 // to do a linear search of the fdes by pc. As fdes are read, a cached
882 *fde_offset = info->offset; 783 // search map is created.
883 return true; 784 while (next_entries_offset_ < entries_end_) {
785 DwarfFde* fde;
786 if (!GetNextCieOrFde(&fde)) {
787 return nullptr;
788 }
789 if (fde != nullptr) {
790 InsertFde(fde);
791 if (pc >= fde->pc_start && pc < fde->pc_end) {
792 return fde;
793 }
884 } 794 }
885 795
886 if (pc < info->start) { 796 if (next_entries_offset_ < memory_.cur_offset()) {
887 last = current; 797 // Simply consider the processing done in this case.
888 } else { 798 break;
889 first = current + 1;
890 } 799 }
891 } 800 }
892 return false; 801 return nullptr;
893}
894
895template <typename AddressType>
896const DwarfFde* DwarfSectionImpl<AddressType>::GetFdeFromIndex(size_t index) {
897 if (index >= fdes_.size()) {
898 return nullptr;
899 }
900 return this->GetFdeFromOffset(fdes_[index].offset);
901} 802}
902 803
903// Explicitly instantiate DwarfSectionImpl 804// Explicitly instantiate DwarfSectionImpl
904template class DwarfSectionImpl<uint32_t>; 805template class DwarfSectionImpl<uint32_t>;
905template class DwarfSectionImpl<uint64_t>; 806template class DwarfSectionImpl<uint64_t>;
906 807
808// Explicitly instantiate DwarfSectionImplNoHdr
809template class DwarfSectionImplNoHdr<uint32_t>;
810template class DwarfSectionImplNoHdr<uint64_t>;
811
907// Explicitly instantiate DwarfDebugFrame 812// Explicitly instantiate DwarfDebugFrame
908template class DwarfDebugFrame<uint32_t>; 813template class DwarfDebugFrame<uint32_t>;
909template class DwarfDebugFrame<uint64_t>; 814template class DwarfDebugFrame<uint64_t>;
diff --git a/libunwindstack/include/unwindstack/DwarfSection.h b/libunwindstack/include/unwindstack/DwarfSection.h
index 847f382ed..e9942decd 100644
--- a/libunwindstack/include/unwindstack/DwarfSection.h
+++ b/libunwindstack/include/unwindstack/DwarfSection.h
@@ -43,7 +43,12 @@ class DwarfSection {
43 43
44 class iterator : public std::iterator<std::bidirectional_iterator_tag, DwarfFde*> { 44 class iterator : public std::iterator<std::bidirectional_iterator_tag, DwarfFde*> {
45 public: 45 public:
46 iterator(DwarfSection* section, size_t index) : section_(section), index_(index) {} 46 iterator(DwarfSection* section, size_t index) : index_(index) {
47 section->GetFdes(&fdes_);
48 if (index_ == static_cast<size_t>(-1)) {
49 index_ = fdes_.size();
50 }
51 }
47 52
48 iterator& operator++() { 53 iterator& operator++() {
49 index_++; 54 index_++;
@@ -65,15 +70,18 @@ class DwarfSection {
65 bool operator==(const iterator& rhs) { return this->index_ == rhs.index_; } 70 bool operator==(const iterator& rhs) { return this->index_ == rhs.index_; }
66 bool operator!=(const iterator& rhs) { return this->index_ != rhs.index_; } 71 bool operator!=(const iterator& rhs) { return this->index_ != rhs.index_; }
67 72
68 const DwarfFde* operator*() { return section_->GetFdeFromIndex(index_); } 73 const DwarfFde* operator*() {
74 if (index_ > fdes_.size()) return nullptr;
75 return fdes_[index_];
76 }
69 77
70 private: 78 private:
71 DwarfSection* section_ = nullptr; 79 std::vector<const DwarfFde*> fdes_;
72 size_t index_ = 0; 80 size_t index_ = 0;
73 }; 81 };
74 82
75 iterator begin() { return iterator(this, 0); } 83 iterator begin() { return iterator(this, 0); }
76 iterator end() { return iterator(this, fde_count_); } 84 iterator end() { return iterator(this, static_cast<size_t>(-1)); }
77 85
78 DwarfErrorCode LastErrorCode() { return last_error_.code; } 86 DwarfErrorCode LastErrorCode() { return last_error_.code; }
79 uint64_t LastErrorAddress() { return last_error_.address; } 87 uint64_t LastErrorAddress() { return last_error_.address; }
@@ -82,15 +90,11 @@ class DwarfSection {
82 90
83 virtual bool Eval(const DwarfCie*, Memory*, const dwarf_loc_regs_t&, Regs*, bool*) = 0; 91 virtual bool Eval(const DwarfCie*, Memory*, const dwarf_loc_regs_t&, Regs*, bool*) = 0;
84 92
85 virtual bool GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) = 0;
86
87 virtual bool Log(uint8_t indent, uint64_t pc, const DwarfFde* fde) = 0; 93 virtual bool Log(uint8_t indent, uint64_t pc, const DwarfFde* fde) = 0;
88 94
89 virtual const DwarfFde* GetFdeFromIndex(size_t index) = 0; 95 virtual void GetFdes(std::vector<const DwarfFde*>* fdes) = 0;
90
91 const DwarfFde* GetFdeFromPc(uint64_t pc);
92 96
93 virtual const DwarfFde* GetFdeFromOffset(uint64_t fde_offset) = 0; 97 virtual const DwarfFde* GetFdeFromPc(uint64_t pc) = 0;
94 98
95 virtual bool GetCfaLocationInfo(uint64_t pc, const DwarfFde* fde, dwarf_loc_regs_t* loc_regs) = 0; 99 virtual bool GetCfaLocationInfo(uint64_t pc, const DwarfFde* fde, dwarf_loc_regs_t* loc_regs) = 0;
96 100
@@ -109,7 +113,6 @@ class DwarfSection {
109 uint32_t cie32_value_ = 0; 113 uint32_t cie32_value_ = 0;
110 uint64_t cie64_value_ = 0; 114 uint64_t cie64_value_ = 0;
111 115
112 uint64_t fde_count_ = 0;
113 std::unordered_map<uint64_t, DwarfFde> fde_entries_; 116 std::unordered_map<uint64_t, DwarfFde> fde_entries_;
114 std::unordered_map<uint64_t, DwarfCie> cie_entries_; 117 std::unordered_map<uint64_t, DwarfCie> cie_entries_;
115 std::unordered_map<uint64_t, dwarf_loc_regs_t> cie_loc_regs_; 118 std::unordered_map<uint64_t, dwarf_loc_regs_t> cie_loc_regs_;
@@ -119,55 +122,73 @@ class DwarfSection {
119template <typename AddressType> 122template <typename AddressType>
120class DwarfSectionImpl : public DwarfSection { 123class DwarfSectionImpl : public DwarfSection {
121 public: 124 public:
122 struct FdeInfo {
123 FdeInfo(uint64_t offset, uint64_t start, uint64_t length)
124 : offset(offset), start(start), end(start + length) {}
125
126 uint64_t offset;
127 AddressType start;
128 AddressType end;
129 };
130
131 DwarfSectionImpl(Memory* memory) : DwarfSection(memory) {} 125 DwarfSectionImpl(Memory* memory) : DwarfSection(memory) {}
132 virtual ~DwarfSectionImpl() = default; 126 virtual ~DwarfSectionImpl() = default;
133 127
134 bool Init(uint64_t offset, uint64_t size, uint64_t load_bias) override; 128 const DwarfCie* GetCieFromOffset(uint64_t offset);
135
136 bool GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) override;
137 129
138 const DwarfFde* GetFdeFromIndex(size_t index) override; 130 const DwarfFde* GetFdeFromOffset(uint64_t offset);
139 131
140 bool EvalRegister(const DwarfLocation* loc, uint32_t reg, AddressType* reg_ptr, void* info); 132 bool EvalRegister(const DwarfLocation* loc, uint32_t reg, AddressType* reg_ptr, void* info);
141 133
142 bool Eval(const DwarfCie* cie, Memory* regular_memory, const dwarf_loc_regs_t& loc_regs, 134 bool Eval(const DwarfCie* cie, Memory* regular_memory, const dwarf_loc_regs_t& loc_regs,
143 Regs* regs, bool* finished) override; 135 Regs* regs, bool* finished) override;
144 136
145 const DwarfCie* GetCie(uint64_t offset);
146 bool FillInCie(DwarfCie* cie);
147
148 const DwarfFde* GetFdeFromOffset(uint64_t offset) override;
149 bool FillInFde(DwarfFde* fde);
150
151 bool GetCfaLocationInfo(uint64_t pc, const DwarfFde* fde, dwarf_loc_regs_t* loc_regs) override; 137 bool GetCfaLocationInfo(uint64_t pc, const DwarfFde* fde, dwarf_loc_regs_t* loc_regs) override;
152 138
153 bool Log(uint8_t indent, uint64_t pc, const DwarfFde* fde) override; 139 bool Log(uint8_t indent, uint64_t pc, const DwarfFde* fde) override;
154 140
155 protected: 141 protected:
156 bool EvalExpression(const DwarfLocation& loc, Memory* regular_memory, AddressType* value, 142 bool FillInCieHeader(DwarfCie* cie);
157 RegsInfo<AddressType>* regs_info, bool* is_dex_pc); 143
144 bool FillInCie(DwarfCie* cie);
158 145
159 bool GetCieInfo(uint8_t* segment_size, uint8_t* encoding); 146 bool FillInFdeHeader(DwarfFde* fde);
160 147
161 bool AddFdeInfo(uint64_t entry_offset, uint8_t segment_size, uint8_t encoding); 148 bool FillInFde(DwarfFde* fde);
162 149
163 bool CreateSortedFdeList(); 150 bool EvalExpression(const DwarfLocation& loc, Memory* regular_memory, AddressType* value,
151 RegsInfo<AddressType>* regs_info, bool* is_dex_pc);
164 152
165 uint64_t load_bias_ = 0; 153 uint64_t load_bias_ = 0;
154 uint64_t entries_offset_ = 0;
155 uint64_t entries_end_ = 0;
166 uint64_t pc_offset_ = 0; 156 uint64_t pc_offset_ = 0;
157};
158
159template <typename AddressType>
160class DwarfSectionImplNoHdr : public DwarfSectionImpl<AddressType> {
161 public:
162 // Add these so that the protected members of DwarfSectionImpl
163 // can be accessed without needing a this->.
164 using DwarfSectionImpl<AddressType>::memory_;
165 using DwarfSectionImpl<AddressType>::pc_offset_;
166 using DwarfSectionImpl<AddressType>::entries_offset_;
167 using DwarfSectionImpl<AddressType>::entries_end_;
168 using DwarfSectionImpl<AddressType>::last_error_;
169 using DwarfSectionImpl<AddressType>::load_bias_;
170 using DwarfSectionImpl<AddressType>::cie_entries_;
171 using DwarfSectionImpl<AddressType>::fde_entries_;
172 using DwarfSectionImpl<AddressType>::cie32_value_;
173 using DwarfSectionImpl<AddressType>::cie64_value_;
174
175 DwarfSectionImplNoHdr(Memory* memory) : DwarfSectionImpl<AddressType>(memory) {}
176 virtual ~DwarfSectionImplNoHdr() = default;
177
178 bool Init(uint64_t offset, uint64_t size, uint64_t load_bias) override;
179
180 const DwarfFde* GetFdeFromPc(uint64_t pc) override;
181
182 void GetFdes(std::vector<const DwarfFde*>* fdes) override;
183
184 protected:
185 bool GetNextCieOrFde(DwarfFde** fde_entry);
186
187 void InsertFde(const DwarfFde* fde);
188
189 uint64_t next_entries_offset_ = 0;
167 190
168 std::vector<FdeInfo> fdes_; 191 std::map<uint64_t, std::pair<uint64_t, const DwarfFde*>> fdes_;
169 uint64_t entries_offset_;
170 uint64_t entries_end_;
171}; 192};
172 193
173} // namespace unwindstack 194} // namespace unwindstack
diff --git a/libunwindstack/tests/DwarfDebugFrameTest.cpp b/libunwindstack/tests/DwarfDebugFrameTest.cpp
index 3a5204463..d62093404 100644
--- a/libunwindstack/tests/DwarfDebugFrameTest.cpp
+++ b/libunwindstack/tests/DwarfDebugFrameTest.cpp
@@ -16,7 +16,8 @@
16 16
17#include <stdint.h> 17#include <stdint.h>
18 18
19#include <gmock/gmock.h> 19#include <vector>
20
20#include <gtest/gtest.h> 21#include <gtest/gtest.h>
21 22
22#include <unwindstack/DwarfError.h> 23#include <unwindstack/DwarfError.h>
@@ -30,480 +31,377 @@
30namespace unwindstack { 31namespace unwindstack {
31 32
32template <typename TypeParam> 33template <typename TypeParam>
33class MockDwarfDebugFrame : public DwarfDebugFrame<TypeParam> {
34 public:
35 MockDwarfDebugFrame(Memory* memory) : DwarfDebugFrame<TypeParam>(memory) {}
36 ~MockDwarfDebugFrame() = default;
37
38 void TestSetFdeCount(uint64_t count) { this->fde_count_ = count; }
39 void TestSetOffset(uint64_t offset) { this->entries_offset_ = offset; }
40 void TestSetEndOffset(uint64_t offset) { this->entries_end_ = offset; }
41 void TestPushFdeInfo(const typename DwarfDebugFrame<TypeParam>::FdeInfo& info) {
42 this->fdes_.push_back(info);
43 }
44
45 uint64_t TestGetFdeCount() { return this->fde_count_; }
46 uint8_t TestGetOffset() { return this->offset_; }
47 uint8_t TestGetEndOffset() { return this->end_offset_; }
48 void TestGetFdeInfo(size_t index, typename DwarfDebugFrame<TypeParam>::FdeInfo* info) {
49 *info = this->fdes_[index];
50 }
51};
52
53template <typename TypeParam>
54class DwarfDebugFrameTest : public ::testing::Test { 34class DwarfDebugFrameTest : public ::testing::Test {
55 protected: 35 protected:
56 void SetUp() override { 36 void SetUp() override {
57 memory_.Clear(); 37 memory_.Clear();
58 debug_frame_ = new MockDwarfDebugFrame<TypeParam>(&memory_); 38 debug_frame_ = new DwarfDebugFrame<TypeParam>(&memory_);
59 ResetLogs(); 39 ResetLogs();
60 } 40 }
61 41
62 void TearDown() override { delete debug_frame_; } 42 void TearDown() override { delete debug_frame_; }
63 43
64 MemoryFake memory_; 44 MemoryFake memory_;
65 MockDwarfDebugFrame<TypeParam>* debug_frame_ = nullptr; 45 DwarfDebugFrame<TypeParam>* debug_frame_ = nullptr;
66}; 46};
67TYPED_TEST_CASE_P(DwarfDebugFrameTest); 47TYPED_TEST_CASE_P(DwarfDebugFrameTest);
68 48
69// NOTE: All test class variables need to be referenced as this->. 49// NOTE: All test class variables need to be referenced as this->.
70 50
71TYPED_TEST_P(DwarfDebugFrameTest, Init32) { 51static void SetCie32(MemoryFake* memory, uint64_t offset, uint32_t length,
72 // CIE 32 information. 52 std::vector<uint8_t> data) {
73 this->memory_.SetData32(0x5000, 0xfc); 53 memory->SetData32(offset, length);
74 this->memory_.SetData32(0x5004, 0xffffffff); 54 offset += 4;
75 this->memory_.SetData8(0x5008, 1); 55 // Indicates this is a cie.
76 this->memory_.SetData8(0x5009, '\0'); 56 memory->SetData32(offset, 0xffffffff);
57 offset += 4;
58 memory->SetMemory(offset, data);
59}
77 60
78 // FDE 32 information. 61static void SetCie64(MemoryFake* memory, uint64_t offset, uint64_t length,
79 this->memory_.SetData32(0x5100, 0xfc); 62 std::vector<uint8_t> data) {
80 this->memory_.SetData32(0x5104, 0); 63 memory->SetData32(offset, 0xffffffff);
81 this->memory_.SetData32(0x5108, 0x1500); 64 offset += 4;
82 this->memory_.SetData32(0x510c, 0x200); 65 memory->SetData64(offset, length);
66 offset += 8;
67 // Indicates this is a cie.
68 memory->SetData64(offset, 0xffffffffffffffffUL);
69 offset += 8;
70 memory->SetMemory(offset, data);
71}
83 72
84 this->memory_.SetData32(0x5200, 0xfc); 73static void SetFde32(MemoryFake* memory, uint64_t offset, uint32_t length, uint64_t cie_offset,
85 this->memory_.SetData32(0x5204, 0); 74 uint32_t pc_start, uint32_t pc_length, uint64_t segment_length = 0,
86 this->memory_.SetData32(0x5208, 0x2500); 75 std::vector<uint8_t>* data = nullptr) {
87 this->memory_.SetData32(0x520c, 0x300); 76 memory->SetData32(offset, length);
77 offset += 4;
78 memory->SetData32(offset, cie_offset);
79 offset += 4 + segment_length;
80 memory->SetData32(offset, pc_start);
81 offset += 4;
82 memory->SetData32(offset, pc_length);
83 if (data != nullptr) {
84 offset += 4;
85 memory->SetMemory(offset, *data);
86 }
87}
88 88
89 // CIE 32 information. 89static void SetFde64(MemoryFake* memory, uint64_t offset, uint64_t length, uint64_t cie_offset,
90 this->memory_.SetData32(0x5300, 0xfc); 90 uint64_t pc_start, uint64_t pc_length, uint64_t segment_length = 0,
91 this->memory_.SetData32(0x5304, 0xffffffff); 91 std::vector<uint8_t>* data = nullptr) {
92 this->memory_.SetData8(0x5308, 1); 92 memory->SetData32(offset, 0xffffffff);
93 this->memory_.SetData8(0x5309, '\0'); 93 offset += 4;
94 memory->SetData64(offset, length);
95 offset += 8;
96 memory->SetData64(offset, cie_offset);
97 offset += 8 + segment_length;
98 memory->SetData64(offset, pc_start);
99 offset += 8;
100 memory->SetData64(offset, pc_length);
101 if (data != nullptr) {
102 offset += 8;
103 memory->SetMemory(offset, *data);
104 }
105}
94 106
95 // FDE 32 information. 107static void SetFourFdes32(MemoryFake* memory) {
96 this->memory_.SetData32(0x5400, 0xfc); 108 SetCie32(memory, 0x5000, 0xfc, std::vector<uint8_t>{1, '\0', 0, 0, 1});
97 this->memory_.SetData32(0x5404, 0x300);
98 this->memory_.SetData32(0x5408, 0x3500);
99 this->memory_.SetData32(0x540c, 0x400);
100 109
101 this->memory_.SetData32(0x5500, 0xfc); 110 // FDE 32 information.
102 this->memory_.SetData32(0x5504, 0x300); 111 SetFde32(memory, 0x5100, 0xfc, 0, 0x1500, 0x200);
103 this->memory_.SetData32(0x5508, 0x4500); 112 SetFde32(memory, 0x5200, 0xfc, 0, 0x2500, 0x300);
104 this->memory_.SetData32(0x550c, 0x500);
105 113
106 ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x600, 0)); 114 // CIE 32 information.
107 ASSERT_EQ(4U, this->debug_frame_->TestGetFdeCount()); 115 SetCie32(memory, 0x5300, 0xfc, std::vector<uint8_t>{1, '\0', 0, 0, 1});
108 116
109 typename DwarfDebugFrame<TypeParam>::FdeInfo info(0, 0, 0); 117 // FDE 32 information.
118 SetFde32(memory, 0x5400, 0xfc, 0x300, 0x3500, 0x400);
119 SetFde32(memory, 0x5500, 0xfc, 0x300, 0x4500, 0x500);
120}
110 121
111 this->debug_frame_->TestGetFdeInfo(0, &info); 122TYPED_TEST_P(DwarfDebugFrameTest, GetFdes32) {
112 EXPECT_EQ(0x5100U, info.offset); 123 SetFourFdes32(&this->memory_);
113 EXPECT_EQ(0x1500U, info.start); 124 ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x600, 0));
114 EXPECT_EQ(0x1700U, info.end);
115 125
116 this->debug_frame_->TestGetFdeInfo(1, &info); 126 std::vector<const DwarfFde*> fdes;
117 EXPECT_EQ(0x5200U, info.offset); 127 this->debug_frame_->GetFdes(&fdes);
118 EXPECT_EQ(0x2500U, info.start); 128
119 EXPECT_EQ(0x2800U, info.end); 129 ASSERT_EQ(4U, fdes.size());
130
131 EXPECT_EQ(0x5000U, fdes[0]->cie_offset);
132 EXPECT_EQ(0x5110U, fdes[0]->cfa_instructions_offset);
133 EXPECT_EQ(0x5200U, fdes[0]->cfa_instructions_end);
134 EXPECT_EQ(0x1500U, fdes[0]->pc_start);
135 EXPECT_EQ(0x1700U, fdes[0]->pc_end);
136 EXPECT_EQ(0U, fdes[0]->lsda_address);
137 EXPECT_TRUE(fdes[0]->cie != nullptr);
138
139 EXPECT_EQ(0x5000U, fdes[1]->cie_offset);
140 EXPECT_EQ(0x5210U, fdes[1]->cfa_instructions_offset);
141 EXPECT_EQ(0x5300U, fdes[1]->cfa_instructions_end);
142 EXPECT_EQ(0x2500U, fdes[1]->pc_start);
143 EXPECT_EQ(0x2800U, fdes[1]->pc_end);
144 EXPECT_EQ(0U, fdes[1]->lsda_address);
145 EXPECT_TRUE(fdes[1]->cie != nullptr);
146
147 EXPECT_EQ(0x5300U, fdes[2]->cie_offset);
148 EXPECT_EQ(0x5410U, fdes[2]->cfa_instructions_offset);
149 EXPECT_EQ(0x5500U, fdes[2]->cfa_instructions_end);
150 EXPECT_EQ(0x3500U, fdes[2]->pc_start);
151 EXPECT_EQ(0x3900U, fdes[2]->pc_end);
152 EXPECT_EQ(0U, fdes[2]->lsda_address);
153 EXPECT_TRUE(fdes[2]->cie != nullptr);
154
155 EXPECT_EQ(0x5300U, fdes[3]->cie_offset);
156 EXPECT_EQ(0x5510U, fdes[3]->cfa_instructions_offset);
157 EXPECT_EQ(0x5600U, fdes[3]->cfa_instructions_end);
158 EXPECT_EQ(0x4500U, fdes[3]->pc_start);
159 EXPECT_EQ(0x4a00U, fdes[3]->pc_end);
160 EXPECT_EQ(0U, fdes[3]->lsda_address);
161 EXPECT_TRUE(fdes[3]->cie != nullptr);
162}
120 163
121 this->debug_frame_->TestGetFdeInfo(2, &info); 164TYPED_TEST_P(DwarfDebugFrameTest, GetFdes32_after_GetFdeFromPc) {
122 EXPECT_EQ(0x5400U, info.offset); 165 SetFourFdes32(&this->memory_);
123 EXPECT_EQ(0x3500U, info.start); 166 ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x600, 0));
124 EXPECT_EQ(0x3900U, info.end);
125 167
126 this->debug_frame_->TestGetFdeInfo(3, &info); 168 const DwarfFde* fde = this->debug_frame_->GetFdeFromPc(0x3600);
127 EXPECT_EQ(0x5500U, info.offset); 169 ASSERT_TRUE(fde != nullptr);
128 EXPECT_EQ(0x4500U, info.start); 170 EXPECT_EQ(0x3500U, fde->pc_start);
129 EXPECT_EQ(0x4a00U, info.end); 171 EXPECT_EQ(0x3900U, fde->pc_end);
172
173 std::vector<const DwarfFde*> fdes;
174 this->debug_frame_->GetFdes(&fdes);
175 ASSERT_EQ(4U, fdes.size());
176
177 // Verify that they got added in the correct order.
178 EXPECT_EQ(0x1500U, fdes[0]->pc_start);
179 EXPECT_EQ(0x1700U, fdes[0]->pc_end);
180 EXPECT_EQ(0x2500U, fdes[1]->pc_start);
181 EXPECT_EQ(0x2800U, fdes[1]->pc_end);
182 EXPECT_EQ(0x3500U, fdes[2]->pc_start);
183 EXPECT_EQ(0x3900U, fdes[2]->pc_end);
184 EXPECT_EQ(0x4500U, fdes[3]->pc_start);
185 EXPECT_EQ(0x4a00U, fdes[3]->pc_end);
130} 186}
131 187
132TYPED_TEST_P(DwarfDebugFrameTest, Init32_fde_not_following_cie) { 188TYPED_TEST_P(DwarfDebugFrameTest, GetFdes32_not_in_section) {
133 // CIE 32 information. 189 SetFourFdes32(&this->memory_);
134 this->memory_.SetData32(0x5000, 0xfc); 190 ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x500, 0));
135 this->memory_.SetData32(0x5004, 0xffffffff);
136 this->memory_.SetData8(0x5008, 1);
137 this->memory_.SetData8(0x5009, '\0');
138 191
139 // FDE 32 information. 192 std::vector<const DwarfFde*> fdes;
140 this->memory_.SetData32(0x5100, 0xfc); 193 this->debug_frame_->GetFdes(&fdes);
141 this->memory_.SetData32(0x5104, 0x1000);
142 this->memory_.SetData32(0x5108, 0x1500);
143 this->memory_.SetData32(0x510c, 0x200);
144 194
145 ASSERT_FALSE(this->debug_frame_->Init(0x5000, 0x600, 0)); 195 ASSERT_EQ(3U, fdes.size());
146 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->debug_frame_->LastErrorCode());
147} 196}
148 197
149TYPED_TEST_P(DwarfDebugFrameTest, Init32_do_not_fail_on_bad_next_entry) { 198TYPED_TEST_P(DwarfDebugFrameTest, GetFdeFromPc32) {
150 // CIE 32 information. 199 SetFourFdes32(&this->memory_);
151 this->memory_.SetData32(0x5000, 0xfc); 200 ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x600, 0));
152 this->memory_.SetData32(0x5004, 0xffffffff);
153 this->memory_.SetData8(0x5008, 1);
154 this->memory_.SetData8(0x5009, '\0');
155
156 // FDE 32 information.
157 this->memory_.SetData32(0x5100, 0xfc);
158 this->memory_.SetData32(0x5104, 0);
159 this->memory_.SetData32(0x5108, 0x1500);
160 this->memory_.SetData32(0x510c, 0x200);
161 201
162 this->memory_.SetData32(0x5200, 0xfc); 202 const DwarfFde* fde = this->debug_frame_->GetFdeFromPc(0x1600);
163 this->memory_.SetData32(0x5204, 0); 203 ASSERT_TRUE(fde != nullptr);
164 this->memory_.SetData32(0x5208, 0x2500); 204 EXPECT_EQ(0x1500U, fde->pc_start);
165 this->memory_.SetData32(0x520c, 0x300);
166 205
167 // CIE 32 information. 206 fde = this->debug_frame_->GetFdeFromPc(0x2600);
168 this->memory_.SetData32(0x5300, 0); 207 ASSERT_TRUE(fde != nullptr);
169 this->memory_.SetData32(0x5304, 0xffffffff); 208 EXPECT_EQ(0x2500U, fde->pc_start);
170 this->memory_.SetData8(0x5308, 1);
171 this->memory_.SetData8(0x5309, '\0');
172 209
173 // FDE 32 information. 210 fde = this->debug_frame_->GetFdeFromPc(0x3600);
174 this->memory_.SetData32(0x5400, 0xfc); 211 ASSERT_TRUE(fde != nullptr);
175 this->memory_.SetData32(0x5404, 0x300); 212 EXPECT_EQ(0x3500U, fde->pc_start);
176 this->memory_.SetData32(0x5408, 0x3500);
177 this->memory_.SetData32(0x540c, 0x400);
178 213
179 this->memory_.SetData32(0x5500, 0xfc); 214 fde = this->debug_frame_->GetFdeFromPc(0x4600);
180 this->memory_.SetData32(0x5504, 0x300); 215 ASSERT_TRUE(fde != nullptr);
181 this->memory_.SetData32(0x5508, 0x4500); 216 EXPECT_EQ(0x4500U, fde->pc_start);
182 this->memory_.SetData32(0x550c, 0x500);
183 217
184 ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x600, 0)); 218 fde = this->debug_frame_->GetFdeFromPc(0);
185 ASSERT_EQ(2U, this->debug_frame_->TestGetFdeCount()); 219 ASSERT_TRUE(fde == nullptr);
186} 220}
187 221
188TYPED_TEST_P(DwarfDebugFrameTest, Init64) { 222TYPED_TEST_P(DwarfDebugFrameTest, GetFdeFromPc32_reverse) {
189 // CIE 64 information. 223 SetFourFdes32(&this->memory_);
190 this->memory_.SetData32(0x5000, 0xffffffff);
191 this->memory_.SetData64(0x5004, 0xf4);
192 this->memory_.SetData64(0x500c, 0xffffffffffffffffULL);
193 this->memory_.SetData8(0x5014, 1);
194 this->memory_.SetData8(0x5015, '\0');
195
196 // FDE 64 information.
197 this->memory_.SetData32(0x5100, 0xffffffff);
198 this->memory_.SetData64(0x5104, 0xf4);
199 this->memory_.SetData64(0x510c, 0);
200 this->memory_.SetData64(0x5114, 0x1500);
201 this->memory_.SetData64(0x511c, 0x200);
202
203 this->memory_.SetData32(0x5200, 0xffffffff);
204 this->memory_.SetData64(0x5204, 0xf4);
205 this->memory_.SetData64(0x520c, 0);
206 this->memory_.SetData64(0x5214, 0x2500);
207 this->memory_.SetData64(0x521c, 0x300);
208
209 // CIE 64 information.
210 this->memory_.SetData32(0x5300, 0xffffffff);
211 this->memory_.SetData64(0x5304, 0xf4);
212 this->memory_.SetData64(0x530c, 0xffffffffffffffffULL);
213 this->memory_.SetData8(0x5314, 1);
214 this->memory_.SetData8(0x5315, '\0');
215
216 // FDE 64 information.
217 this->memory_.SetData32(0x5400, 0xffffffff);
218 this->memory_.SetData64(0x5404, 0xf4);
219 this->memory_.SetData64(0x540c, 0x300);
220 this->memory_.SetData64(0x5414, 0x3500);
221 this->memory_.SetData64(0x541c, 0x400);
222
223 this->memory_.SetData32(0x5500, 0xffffffff);
224 this->memory_.SetData64(0x5504, 0xf4);
225 this->memory_.SetData64(0x550c, 0x300);
226 this->memory_.SetData64(0x5514, 0x4500);
227 this->memory_.SetData64(0x551c, 0x500);
228
229 ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x600, 0)); 224 ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x600, 0));
230 ASSERT_EQ(4U, this->debug_frame_->TestGetFdeCount());
231 225
232 typename DwarfDebugFrame<TypeParam>::FdeInfo info(0, 0, 0); 226 const DwarfFde* fde = this->debug_frame_->GetFdeFromPc(0x4600);
227 ASSERT_TRUE(fde != nullptr);
228 EXPECT_EQ(0x4500U, fde->pc_start);
233 229
234 this->debug_frame_->TestGetFdeInfo(0, &info); 230 fde = this->debug_frame_->GetFdeFromPc(0x3600);
235 EXPECT_EQ(0x5100U, info.offset); 231 ASSERT_TRUE(fde != nullptr);
236 EXPECT_EQ(0x1500U, info.start); 232 EXPECT_EQ(0x3500U, fde->pc_start);
237 EXPECT_EQ(0x1700U, info.end);
238 233
239 this->debug_frame_->TestGetFdeInfo(1, &info); 234 fde = this->debug_frame_->GetFdeFromPc(0x2600);
240 EXPECT_EQ(0x5200U, info.offset); 235 ASSERT_TRUE(fde != nullptr);
241 EXPECT_EQ(0x2500U, info.start); 236 EXPECT_EQ(0x2500U, fde->pc_start);
242 EXPECT_EQ(0x2800U, info.end);
243 237
244 this->debug_frame_->TestGetFdeInfo(2, &info); 238 fde = this->debug_frame_->GetFdeFromPc(0x1600);
245 EXPECT_EQ(0x5400U, info.offset); 239 ASSERT_TRUE(fde != nullptr);
246 EXPECT_EQ(0x3500U, info.start); 240 EXPECT_EQ(0x1500U, fde->pc_start);
247 EXPECT_EQ(0x3900U, info.end);
248 241
249 this->debug_frame_->TestGetFdeInfo(3, &info); 242 fde = this->debug_frame_->GetFdeFromPc(0);
250 EXPECT_EQ(0x5500U, info.offset); 243 ASSERT_TRUE(fde == nullptr);
251 EXPECT_EQ(0x4500U, info.start);
252 EXPECT_EQ(0x4a00U, info.end);
253} 244}
254 245
255TYPED_TEST_P(DwarfDebugFrameTest, Init64_fde_not_following_cie) { 246TYPED_TEST_P(DwarfDebugFrameTest, GetFdeFromPc32_not_in_section) {
256 // CIE 64 information. 247 SetFourFdes32(&this->memory_);
257 this->memory_.SetData32(0x5000, 0xffffffff); 248 ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x500, 0));
258 this->memory_.SetData64(0x5004, 0xf4);
259 this->memory_.SetData64(0x500c, 0xffffffffffffffffULL);
260 this->memory_.SetData8(0x5014, 1);
261 this->memory_.SetData8(0x5015, '\0');
262
263 // FDE 64 information.
264 this->memory_.SetData32(0x5100, 0xffffffff);
265 this->memory_.SetData64(0x5104, 0xf4);
266 this->memory_.SetData64(0x510c, 0x1000);
267 this->memory_.SetData64(0x5114, 0x1500);
268 this->memory_.SetData64(0x511c, 0x200);
269 249
270 ASSERT_FALSE(this->debug_frame_->Init(0x5000, 0x600, 0)); 250 const DwarfFde* fde = this->debug_frame_->GetFdeFromPc(0x4600);
271 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->debug_frame_->LastErrorCode()); 251 ASSERT_TRUE(fde == nullptr);
272} 252}
273 253
274TYPED_TEST_P(DwarfDebugFrameTest, Init64_do_not_fail_on_bad_next_entry) { 254static void SetFourFdes64(MemoryFake* memory) {
275 // CIE 64 information. 255 // CIE 64 information.
276 this->memory_.SetData32(0x5000, 0xffffffff); 256 SetCie64(memory, 0x5000, 0xf4, std::vector<uint8_t>{1, '\0', 0, 0, 1});
277 this->memory_.SetData64(0x5004, 0xf4);
278 this->memory_.SetData64(0x500c, 0xffffffffffffffffULL);
279 this->memory_.SetData8(0x5014, 1);
280 this->memory_.SetData8(0x5015, '\0');
281 257
282 // FDE 64 information. 258 // FDE 64 information.
283 this->memory_.SetData32(0x5100, 0xffffffff); 259 SetFde64(memory, 0x5100, 0xf4, 0, 0x1500, 0x200);
284 this->memory_.SetData64(0x5104, 0xf4); 260 SetFde64(memory, 0x5200, 0xf4, 0, 0x2500, 0x300);
285 this->memory_.SetData64(0x510c, 0);
286 this->memory_.SetData64(0x5114, 0x1500);
287 this->memory_.SetData64(0x511c, 0x200);
288
289 this->memory_.SetData32(0x5200, 0xffffffff);
290 this->memory_.SetData64(0x5204, 0xf4);
291 this->memory_.SetData64(0x520c, 0);
292 this->memory_.SetData64(0x5214, 0x2500);
293 this->memory_.SetData64(0x521c, 0x300);
294 261
295 // CIE 64 information. 262 // CIE 64 information.
296 this->memory_.SetData32(0x5300, 0xffffffff); 263 SetCie64(memory, 0x5300, 0xf4, std::vector<uint8_t>{1, '\0', 0, 0, 1});
297 this->memory_.SetData64(0x5304, 0);
298 this->memory_.SetData64(0x530c, 0xffffffffffffffffULL);
299 this->memory_.SetData8(0x5314, 1);
300 this->memory_.SetData8(0x5315, '\0');
301 264
302 // FDE 64 information. 265 // FDE 64 information.
303 this->memory_.SetData32(0x5400, 0xffffffff); 266 SetFde64(memory, 0x5400, 0xf4, 0x300, 0x3500, 0x400);
304 this->memory_.SetData64(0x5404, 0xf4); 267 SetFde64(memory, 0x5500, 0xf4, 0x300, 0x4500, 0x500);
305 this->memory_.SetData64(0x540c, 0x300); 268}
306 this->memory_.SetData64(0x5414, 0x3500);
307 this->memory_.SetData64(0x541c, 0x400);
308
309 this->memory_.SetData32(0x5500, 0xffffffff);
310 this->memory_.SetData64(0x5504, 0xf4);
311 this->memory_.SetData64(0x550c, 0x300);
312 this->memory_.SetData64(0x5514, 0x4500);
313 this->memory_.SetData64(0x551c, 0x500);
314 269
270TYPED_TEST_P(DwarfDebugFrameTest, GetFdes64) {
271 SetFourFdes64(&this->memory_);
315 ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x600, 0)); 272 ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x600, 0));
316 ASSERT_EQ(2U, this->debug_frame_->TestGetFdeCount()); 273
274 std::vector<const DwarfFde*> fdes;
275 this->debug_frame_->GetFdes(&fdes);
276
277 ASSERT_EQ(4U, fdes.size());
278
279 EXPECT_EQ(0x5000U, fdes[0]->cie_offset);
280 EXPECT_EQ(0x5124U, fdes[0]->cfa_instructions_offset);
281 EXPECT_EQ(0x5200U, fdes[0]->cfa_instructions_end);
282 EXPECT_EQ(0x1500U, fdes[0]->pc_start);
283 EXPECT_EQ(0x1700U, fdes[0]->pc_end);
284 EXPECT_EQ(0U, fdes[0]->lsda_address);
285 EXPECT_TRUE(fdes[0]->cie != nullptr);
286
287 EXPECT_EQ(0x5000U, fdes[1]->cie_offset);
288 EXPECT_EQ(0x5224U, fdes[1]->cfa_instructions_offset);
289 EXPECT_EQ(0x5300U, fdes[1]->cfa_instructions_end);
290 EXPECT_EQ(0x2500U, fdes[1]->pc_start);
291 EXPECT_EQ(0x2800U, fdes[1]->pc_end);
292 EXPECT_EQ(0U, fdes[1]->lsda_address);
293 EXPECT_TRUE(fdes[1]->cie != nullptr);
294
295 EXPECT_EQ(0x5300U, fdes[2]->cie_offset);
296 EXPECT_EQ(0x5424U, fdes[2]->cfa_instructions_offset);
297 EXPECT_EQ(0x5500U, fdes[2]->cfa_instructions_end);
298 EXPECT_EQ(0x3500U, fdes[2]->pc_start);
299 EXPECT_EQ(0x3900U, fdes[2]->pc_end);
300 EXPECT_EQ(0U, fdes[2]->lsda_address);
301 EXPECT_TRUE(fdes[2]->cie != nullptr);
302
303 EXPECT_EQ(0x5300U, fdes[3]->cie_offset);
304 EXPECT_EQ(0x5524U, fdes[3]->cfa_instructions_offset);
305 EXPECT_EQ(0x5600U, fdes[3]->cfa_instructions_end);
306 EXPECT_EQ(0x4500U, fdes[3]->pc_start);
307 EXPECT_EQ(0x4a00U, fdes[3]->pc_end);
308 EXPECT_EQ(0U, fdes[3]->lsda_address);
309 EXPECT_TRUE(fdes[3]->cie != nullptr);
317} 310}
318 311
319TYPED_TEST_P(DwarfDebugFrameTest, Init_non_zero_load_bias) { 312TYPED_TEST_P(DwarfDebugFrameTest, GetFdes64_after_GetFdeFromPc) {
320 // CIE 32 information. 313 SetFourFdes64(&this->memory_);
321 this->memory_.SetData32(0x5000, 0xfc); 314 ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x600, 0));
322 this->memory_.SetData32(0x5004, 0xffffffff);
323 this->memory_.SetData8(0x5008, 1);
324 this->memory_.SetData8(0x5009, 'z');
325 this->memory_.SetData8(0x500a, 'R');
326 this->memory_.SetData8(0x500b, '\0');
327 this->memory_.SetData8(0x500c, 0);
328 this->memory_.SetData8(0x500d, 0);
329 this->memory_.SetData8(0x500e, 0);
330 this->memory_.SetData8(0x500f, 0);
331 this->memory_.SetData8(0x5010, 0x1b);
332 315
333 // FDE 32 information. 316 const DwarfFde* fde = this->debug_frame_->GetFdeFromPc(0x2600);
334 this->memory_.SetData32(0x5100, 0xfc); 317 ASSERT_TRUE(fde != nullptr);
335 this->memory_.SetData32(0x5104, 0); 318 EXPECT_EQ(0x2500U, fde->pc_start);
336 this->memory_.SetData32(0x5108, 0x1500); 319 EXPECT_EQ(0x2800U, fde->pc_end);
337 this->memory_.SetData32(0x510c, 0x200); 320
338 this->memory_.SetData8(0x5110, 0); 321 std::vector<const DwarfFde*> fdes;
339 this->memory_.SetData8(0x5111, 0); 322 this->debug_frame_->GetFdes(&fdes);
323 ASSERT_EQ(4U, fdes.size());
324
325 // Verify that they got added in the correct order.
326 EXPECT_EQ(0x1500U, fdes[0]->pc_start);
327 EXPECT_EQ(0x1700U, fdes[0]->pc_end);
328 EXPECT_EQ(0x2500U, fdes[1]->pc_start);
329 EXPECT_EQ(0x2800U, fdes[1]->pc_end);
330 EXPECT_EQ(0x3500U, fdes[2]->pc_start);
331 EXPECT_EQ(0x3900U, fdes[2]->pc_end);
332 EXPECT_EQ(0x4500U, fdes[3]->pc_start);
333 EXPECT_EQ(0x4a00U, fdes[3]->pc_end);
334}
335
336TYPED_TEST_P(DwarfDebugFrameTest, GetFdes64_not_in_section) {
337 SetFourFdes64(&this->memory_);
338 ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x500, 0));
340 339
341 ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x200, 0x1000)); 340 std::vector<const DwarfFde*> fdes;
342 ASSERT_EQ(1U, this->debug_frame_->TestGetFdeCount()); 341 this->debug_frame_->GetFdes(&fdes);
343 342
344 typename DwarfDebugFrame<TypeParam>::FdeInfo info(0, 0, 0); 343 ASSERT_EQ(3U, fdes.size());
344}
345 345
346 this->debug_frame_->TestGetFdeInfo(0, &info); 346TYPED_TEST_P(DwarfDebugFrameTest, GetFdeFromPc64) {
347 EXPECT_EQ(0x5100U, info.offset); 347 SetFourFdes64(&this->memory_);
348 EXPECT_EQ(0x2500U, info.start); 348 ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x600, 0));
349 EXPECT_EQ(0x2700U, info.end);
350 349
351 const DwarfFde* fde = this->debug_frame_->GetFdeFromPc(0x2504); 350 const DwarfFde* fde = this->debug_frame_->GetFdeFromPc(0x1600);
352 ASSERT_TRUE(fde != nullptr); 351 ASSERT_TRUE(fde != nullptr);
353 EXPECT_EQ(0x2500U, fde->pc_start); 352 EXPECT_EQ(0x1500U, fde->pc_start);
354 EXPECT_EQ(0x2700U, fde->pc_end);
355}
356 353
357TYPED_TEST_P(DwarfDebugFrameTest, Init_version1) { 354 fde = this->debug_frame_->GetFdeFromPc(0x2600);
358 // CIE 32 information. 355 ASSERT_TRUE(fde != nullptr);
359 this->memory_.SetData32(0x5000, 0xfc); 356 EXPECT_EQ(0x2500U, fde->pc_start);
360 this->memory_.SetData32(0x5004, 0xffffffff);
361 this->memory_.SetData8(0x5008, 1);
362 // Augment string.
363 this->memory_.SetMemory(0x5009, std::vector<uint8_t>{'z', 'R', 'P', 'L', '\0'});
364 // Code alignment factor.
365 this->memory_.SetMemory(0x500e, std::vector<uint8_t>{0x80, 0x00});
366 // Data alignment factor.
367 this->memory_.SetMemory(0x5010, std::vector<uint8_t>{0x81, 0x80, 0x80, 0x00});
368 // Return address register
369 this->memory_.SetData8(0x5014, 0x84);
370 // Augmentation length
371 this->memory_.SetMemory(0x5015, std::vector<uint8_t>{0x84, 0x00});
372 // R data.
373 this->memory_.SetData8(0x5017, DW_EH_PE_pcrel | DW_EH_PE_udata2);
374 357
375 // FDE 32 information. 358 fde = this->debug_frame_->GetFdeFromPc(0x3600);
376 this->memory_.SetData32(0x5100, 0xfc); 359 ASSERT_TRUE(fde != nullptr);
377 this->memory_.SetData32(0x5104, 0); 360 EXPECT_EQ(0x3500U, fde->pc_start);
378 this->memory_.SetData16(0x5108, 0x1500);
379 this->memory_.SetData16(0x510a, 0x200);
380 361
381 ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x200, 0)); 362 fde = this->debug_frame_->GetFdeFromPc(0x4600);
382 ASSERT_EQ(1U, this->debug_frame_->TestGetFdeCount()); 363 ASSERT_TRUE(fde != nullptr);
364 EXPECT_EQ(0x4500U, fde->pc_start);
383 365
384 typename DwarfDebugFrame<TypeParam>::FdeInfo info(0, 0, 0); 366 fde = this->debug_frame_->GetFdeFromPc(0);
385 this->debug_frame_->TestGetFdeInfo(0, &info); 367 ASSERT_TRUE(fde == nullptr);
386 EXPECT_EQ(0x5100U, info.offset);
387 EXPECT_EQ(0x1500U, info.start);
388 EXPECT_EQ(0x1700U, info.end);
389} 368}
390 369
391TYPED_TEST_P(DwarfDebugFrameTest, Init_version4) { 370TYPED_TEST_P(DwarfDebugFrameTest, GetFdeFromPc64_reverse) {
392 // CIE 32 information. 371 SetFourFdes64(&this->memory_);
393 this->memory_.SetData32(0x5000, 0xfc); 372 ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x600, 0));
394 this->memory_.SetData32(0x5004, 0xffffffff);
395 this->memory_.SetData8(0x5008, 4);
396 // Augment string.
397 this->memory_.SetMemory(0x5009, std::vector<uint8_t>{'z', 'L', 'P', 'R', '\0'});
398 // Address size.
399 this->memory_.SetData8(0x500e, 4);
400 // Segment size.
401 this->memory_.SetData8(0x500f, 0);
402 // Code alignment factor.
403 this->memory_.SetMemory(0x5010, std::vector<uint8_t>{0x80, 0x00});
404 // Data alignment factor.
405 this->memory_.SetMemory(0x5012, std::vector<uint8_t>{0x81, 0x80, 0x80, 0x00});
406 // Return address register
407 this->memory_.SetMemory(0x5016, std::vector<uint8_t>{0x85, 0x10});
408 // Augmentation length
409 this->memory_.SetMemory(0x5018, std::vector<uint8_t>{0x84, 0x00});
410 // L data.
411 this->memory_.SetData8(0x501a, 0x10);
412 // P data.
413 this->memory_.SetData8(0x501b, DW_EH_PE_udata4);
414 this->memory_.SetData32(0x501c, 0x100);
415 // R data.
416 this->memory_.SetData8(0x5020, DW_EH_PE_pcrel | DW_EH_PE_udata2);
417 373
418 // FDE 32 information. 374 const DwarfFde* fde = this->debug_frame_->GetFdeFromPc(0x4600);
419 this->memory_.SetData32(0x5100, 0xfc); 375 ASSERT_TRUE(fde != nullptr);
420 this->memory_.SetData32(0x5104, 0); 376 EXPECT_EQ(0x4500U, fde->pc_start);
421 this->memory_.SetData16(0x5108, 0x1500);
422 this->memory_.SetData16(0x510a, 0x200);
423
424 ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x200, 0));
425 ASSERT_EQ(1U, this->debug_frame_->TestGetFdeCount());
426
427 typename DwarfDebugFrame<TypeParam>::FdeInfo info(0, 0, 0);
428 this->debug_frame_->TestGetFdeInfo(0, &info);
429 EXPECT_EQ(0x5100U, info.offset);
430 EXPECT_EQ(0x1500U, info.start);
431 EXPECT_EQ(0x1700U, info.end);
432}
433
434TYPED_TEST_P(DwarfDebugFrameTest, GetFdeOffsetFromPc) {
435 typename DwarfDebugFrame<TypeParam>::FdeInfo info(0, 0, 0);
436 for (size_t i = 0; i < 9; i++) {
437 info.start = 0x1000 * (i + 1);
438 info.end = 0x1000 * (i + 2) - 0x10;
439 info.offset = 0x5000 + i * 0x20;
440 this->debug_frame_->TestPushFdeInfo(info);
441 }
442 377
443 this->debug_frame_->TestSetFdeCount(0); 378 fde = this->debug_frame_->GetFdeFromPc(0x3600);
444 uint64_t fde_offset; 379 ASSERT_TRUE(fde != nullptr);
445 ASSERT_FALSE(this->debug_frame_->GetFdeOffsetFromPc(0x1000, &fde_offset)); 380 EXPECT_EQ(0x3500U, fde->pc_start);
446 ASSERT_EQ(DWARF_ERROR_NONE, this->debug_frame_->LastErrorCode());
447
448 this->debug_frame_->TestSetFdeCount(9);
449 ASSERT_FALSE(this->debug_frame_->GetFdeOffsetFromPc(0x100, &fde_offset));
450 ASSERT_EQ(DWARF_ERROR_NONE, this->debug_frame_->LastErrorCode());
451 // Odd number of elements.
452 for (size_t i = 0; i < 9; i++) {
453 TypeParam pc = 0x1000 * (i + 1);
454 ASSERT_TRUE(this->debug_frame_->GetFdeOffsetFromPc(pc, &fde_offset)) << "Failed at index " << i;
455 EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i;
456 ASSERT_TRUE(this->debug_frame_->GetFdeOffsetFromPc(pc + 1, &fde_offset)) << "Failed at index "
457 << i;
458 EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i;
459 ASSERT_TRUE(this->debug_frame_->GetFdeOffsetFromPc(pc + 0xeff, &fde_offset))
460 << "Failed at index " << i;
461 EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i;
462 ASSERT_FALSE(this->debug_frame_->GetFdeOffsetFromPc(pc + 0xfff, &fde_offset))
463 << "Failed at index " << i;
464 ASSERT_EQ(DWARF_ERROR_NONE, this->debug_frame_->LastErrorCode());
465 }
466 381
467 // Even number of elements. 382 fde = this->debug_frame_->GetFdeFromPc(0x2600);
468 this->debug_frame_->TestSetFdeCount(10); 383 ASSERT_TRUE(fde != nullptr);
469 info.start = 0xa000; 384 EXPECT_EQ(0x2500U, fde->pc_start);
470 info.end = 0xaff0; 385
471 info.offset = 0x5120; 386 fde = this->debug_frame_->GetFdeFromPc(0x1600);
472 this->debug_frame_->TestPushFdeInfo(info); 387 ASSERT_TRUE(fde != nullptr);
473 388 EXPECT_EQ(0x1500U, fde->pc_start);
474 for (size_t i = 0; i < 10; i++) { 389
475 TypeParam pc = 0x1000 * (i + 1); 390 fde = this->debug_frame_->GetFdeFromPc(0);
476 ASSERT_TRUE(this->debug_frame_->GetFdeOffsetFromPc(pc, &fde_offset)) << "Failed at index " << i; 391 ASSERT_TRUE(fde == nullptr);
477 EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i;
478 ASSERT_TRUE(this->debug_frame_->GetFdeOffsetFromPc(pc + 1, &fde_offset)) << "Failed at index "
479 << i;
480 EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i;
481 ASSERT_TRUE(this->debug_frame_->GetFdeOffsetFromPc(pc + 0xeff, &fde_offset))
482 << "Failed at index " << i;
483 EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i;
484 ASSERT_FALSE(this->debug_frame_->GetFdeOffsetFromPc(pc + 0xfff, &fde_offset))
485 << "Failed at index " << i;
486 ASSERT_EQ(DWARF_ERROR_NONE, this->debug_frame_->LastErrorCode());
487 }
488} 392}
489 393
490TYPED_TEST_P(DwarfDebugFrameTest, GetCieFde32) { 394TYPED_TEST_P(DwarfDebugFrameTest, GetFdeFromPc64_not_in_section) {
491 this->debug_frame_->TestSetOffset(0x4000); 395 SetFourFdes64(&this->memory_);
396 ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x500, 0));
492 397
493 // CIE 32 information. 398 const DwarfFde* fde = this->debug_frame_->GetFdeFromPc(0x4600);
494 this->memory_.SetData32(0xf000, 0x100); 399 ASSERT_TRUE(fde == nullptr);
495 this->memory_.SetData32(0xf004, 0xffffffff); 400}
496 this->memory_.SetData8(0xf008, 0x1);
497 this->memory_.SetData8(0xf009, '\0');
498 this->memory_.SetData8(0xf00a, 4);
499 this->memory_.SetData8(0xf00b, 8);
500 this->memory_.SetData8(0xf00c, 0x20);
501 401
502 // FDE 32 information. 402TYPED_TEST_P(DwarfDebugFrameTest, GetCieFde32) {
503 this->memory_.SetData32(0x14000, 0x20); 403 SetCie32(&this->memory_, 0xf000, 0x100, std::vector<uint8_t>{1, '\0', 4, 8, 0x20});
504 this->memory_.SetData32(0x14004, 0xb000); 404 SetFde32(&this->memory_, 0x14000, 0x20, 0xf000, 0x9000, 0x100);
505 this->memory_.SetData32(0x14008, 0x9000);
506 this->memory_.SetData32(0x1400c, 0x100);
507 405
508 const DwarfFde* fde = this->debug_frame_->GetFdeFromOffset(0x14000); 406 const DwarfFde* fde = this->debug_frame_->GetFdeFromOffset(0x14000);
509 ASSERT_TRUE(fde != nullptr); 407 ASSERT_TRUE(fde != nullptr);
@@ -530,24 +428,8 @@ TYPED_TEST_P(DwarfDebugFrameTest, GetCieFde32) {
530} 428}
531 429
532TYPED_TEST_P(DwarfDebugFrameTest, GetCieFde64) { 430TYPED_TEST_P(DwarfDebugFrameTest, GetCieFde64) {
533 this->debug_frame_->TestSetOffset(0x2000); 431 SetCie64(&this->memory_, 0x6000, 0x100, std::vector<uint8_t>{1, '\0', 4, 8, 0x20});
534 432 SetFde64(&this->memory_, 0x8000, 0x200, 0x6000, 0x5000, 0x300);
535 // CIE 64 information.
536 this->memory_.SetData32(0x6000, 0xffffffff);
537 this->memory_.SetData64(0x6004, 0x100);
538 this->memory_.SetData64(0x600c, 0xffffffffffffffffULL);
539 this->memory_.SetData8(0x6014, 0x1);
540 this->memory_.SetData8(0x6015, '\0');
541 this->memory_.SetData8(0x6016, 4);
542 this->memory_.SetData8(0x6017, 8);
543 this->memory_.SetData8(0x6018, 0x20);
544
545 // FDE 64 information.
546 this->memory_.SetData32(0x8000, 0xffffffff);
547 this->memory_.SetData64(0x8004, 0x200);
548 this->memory_.SetData64(0x800c, 0x4000);
549 this->memory_.SetData64(0x8014, 0x5000);
550 this->memory_.SetData64(0x801c, 0x300);
551 433
552 const DwarfFde* fde = this->debug_frame_->GetFdeFromOffset(0x8000); 434 const DwarfFde* fde = this->debug_frame_->GetFdeFromOffset(0x8000);
553 ASSERT_TRUE(fde != nullptr); 435 ASSERT_TRUE(fde != nullptr);
@@ -573,11 +455,357 @@ TYPED_TEST_P(DwarfDebugFrameTest, GetCieFde64) {
573 EXPECT_EQ(0x20U, fde->cie->return_address_register); 455 EXPECT_EQ(0x20U, fde->cie->return_address_register);
574} 456}
575 457
576REGISTER_TYPED_TEST_CASE_P(DwarfDebugFrameTest, Init32, Init32_fde_not_following_cie, 458static void VerifyCieVersion(const DwarfCie* cie, uint8_t version, uint8_t segment_size,
577 Init32_do_not_fail_on_bad_next_entry, Init64, 459 uint8_t fde_encoding, uint64_t return_address, uint64_t start_offset,
578 Init64_do_not_fail_on_bad_next_entry, Init64_fde_not_following_cie, 460 uint64_t end_offset) {
579 Init_non_zero_load_bias, Init_version1, Init_version4, 461 EXPECT_EQ(version, cie->version);
580 GetFdeOffsetFromPc, GetCieFde32, GetCieFde64); 462 EXPECT_EQ(fde_encoding, cie->fde_address_encoding);
463 EXPECT_EQ(DW_EH_PE_omit, cie->lsda_encoding);
464 EXPECT_EQ(segment_size, cie->segment_size);
465 EXPECT_EQ(1U, cie->augmentation_string.size());
466 EXPECT_EQ('\0', cie->augmentation_string[0]);
467 EXPECT_EQ(0U, cie->personality_handler);
468 EXPECT_EQ(4U, cie->code_alignment_factor);
469 EXPECT_EQ(8, cie->data_alignment_factor);
470 EXPECT_EQ(return_address, cie->return_address_register);
471 EXPECT_EQ(0x5000U + start_offset, cie->cfa_instructions_offset);
472 EXPECT_EQ(0x5000U + end_offset, cie->cfa_instructions_end);
473}
474
475TYPED_TEST_P(DwarfDebugFrameTest, GetCieFromOffset32_cie_cached) {
476 SetCie32(&this->memory_, 0x5000, 0x100, std::vector<uint8_t>{1, '\0', 4, 8, 0x20});
477 const DwarfCie* cie = this->debug_frame_->GetCieFromOffset(0x5000);
478 EXPECT_EQ(DWARF_ERROR_NONE, this->debug_frame_->LastErrorCode());
479 ASSERT_TRUE(cie != nullptr);
480 VerifyCieVersion(cie, 1, 0, DW_EH_PE_sdata4, 0x20, 0xd, 0x104);
481
482 std::vector<uint8_t> zero(0x100, 0);
483 this->memory_.SetMemory(0x5000, zero);
484 cie = this->debug_frame_->GetCieFromOffset(0x5000);
485 EXPECT_EQ(DWARF_ERROR_NONE, this->debug_frame_->LastErrorCode());
486 ASSERT_TRUE(cie != nullptr);
487 VerifyCieVersion(cie, 1, 0, DW_EH_PE_sdata4, 0x20, 0xd, 0x104);
488}
489
490TYPED_TEST_P(DwarfDebugFrameTest, GetCieFromOffset64_cie_cached) {
491 SetCie64(&this->memory_, 0x5000, 0x100, std::vector<uint8_t>{1, '\0', 4, 8, 0x20});
492 const DwarfCie* cie = this->debug_frame_->GetCieFromOffset(0x5000);
493 EXPECT_EQ(DWARF_ERROR_NONE, this->debug_frame_->LastErrorCode());
494 ASSERT_TRUE(cie != nullptr);
495 VerifyCieVersion(cie, 1, 0, DW_EH_PE_sdata8, 0x20, 0x19, 0x10c);
496
497 std::vector<uint8_t> zero(0x100, 0);
498 this->memory_.SetMemory(0x5000, zero);
499 cie = this->debug_frame_->GetCieFromOffset(0x5000);
500 EXPECT_EQ(DWARF_ERROR_NONE, this->debug_frame_->LastErrorCode());
501 ASSERT_TRUE(cie != nullptr);
502 VerifyCieVersion(cie, 1, 0, DW_EH_PE_sdata8, 0x20, 0x19, 0x10c);
503}
504
505TYPED_TEST_P(DwarfDebugFrameTest, GetCieFromOffset32_version1) {
506 SetCie32(&this->memory_, 0x5000, 0x100, std::vector<uint8_t>{1, '\0', 4, 8, 0x20});
507 const DwarfCie* cie = this->debug_frame_->GetCieFromOffset(0x5000);
508 EXPECT_EQ(DWARF_ERROR_NONE, this->debug_frame_->LastErrorCode());
509 ASSERT_TRUE(cie != nullptr);
510 VerifyCieVersion(cie, 1, 0, DW_EH_PE_sdata4, 0x20, 0xd, 0x104);
511}
512
513TYPED_TEST_P(DwarfDebugFrameTest, GetCieFromOffset64_version1) {
514 SetCie64(&this->memory_, 0x5000, 0x100, std::vector<uint8_t>{1, '\0', 4, 8, 0x20});
515 const DwarfCie* cie = this->debug_frame_->GetCieFromOffset(0x5000);
516 EXPECT_EQ(DWARF_ERROR_NONE, this->debug_frame_->LastErrorCode());
517 ASSERT_TRUE(cie != nullptr);
518 VerifyCieVersion(cie, 1, 0, DW_EH_PE_sdata8, 0x20, 0x19, 0x10c);
519}
520
521TYPED_TEST_P(DwarfDebugFrameTest, GetCieFromOffset32_version3) {
522 SetCie32(&this->memory_, 0x5000, 0x100, std::vector<uint8_t>{3, '\0', 4, 8, 0x81, 3});
523 const DwarfCie* cie = this->debug_frame_->GetCieFromOffset(0x5000);
524 EXPECT_EQ(DWARF_ERROR_NONE, this->debug_frame_->LastErrorCode());
525 ASSERT_TRUE(cie != nullptr);
526 VerifyCieVersion(cie, 3, 0, DW_EH_PE_sdata4, 0x181, 0xe, 0x104);
527}
528
529TYPED_TEST_P(DwarfDebugFrameTest, GetCieFromOffset64_version3) {
530 SetCie64(&this->memory_, 0x5000, 0x100, std::vector<uint8_t>{3, '\0', 4, 8, 0x81, 3});
531 const DwarfCie* cie = this->debug_frame_->GetCieFromOffset(0x5000);
532 EXPECT_EQ(DWARF_ERROR_NONE, this->debug_frame_->LastErrorCode());
533 ASSERT_TRUE(cie != nullptr);
534 VerifyCieVersion(cie, 3, 0, DW_EH_PE_sdata8, 0x181, 0x1a, 0x10c);
535}
536
537TYPED_TEST_P(DwarfDebugFrameTest, GetCieFromOffset32_version4) {
538 SetCie32(&this->memory_, 0x5000, 0x100, std::vector<uint8_t>{4, '\0', 0, 10, 4, 8, 0x81, 3});
539 const DwarfCie* cie = this->debug_frame_->GetCieFromOffset(0x5000);
540 EXPECT_EQ(DWARF_ERROR_NONE, this->debug_frame_->LastErrorCode());
541 ASSERT_TRUE(cie != nullptr);
542 VerifyCieVersion(cie, 4, 10, DW_EH_PE_sdata4, 0x181, 0x10, 0x104);
543}
544
545TYPED_TEST_P(DwarfDebugFrameTest, GetCieFromOffset64_version4) {
546 SetCie64(&this->memory_, 0x5000, 0x100, std::vector<uint8_t>{4, '\0', 0, 10, 4, 8, 0x81, 3});
547 const DwarfCie* cie = this->debug_frame_->GetCieFromOffset(0x5000);
548 EXPECT_EQ(DWARF_ERROR_NONE, this->debug_frame_->LastErrorCode());
549 ASSERT_TRUE(cie != nullptr);
550 VerifyCieVersion(cie, 4, 10, DW_EH_PE_sdata8, 0x181, 0x1c, 0x10c);
551}
552
553TYPED_TEST_P(DwarfDebugFrameTest, GetCieFromOffset_version_invalid) {
554 SetCie32(&this->memory_, 0x5000, 0x100, std::vector<uint8_t>{0, '\0', 1, 2, 3, 4, 5, 6, 7});
555 ASSERT_TRUE(this->debug_frame_->GetCieFromOffset(0x5000) == nullptr);
556 EXPECT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->debug_frame_->LastErrorCode());
557 SetCie64(&this->memory_, 0x6000, 0x100, std::vector<uint8_t>{0, '\0', 1, 2, 3, 4, 5, 6, 7});
558 ASSERT_TRUE(this->debug_frame_->GetCieFromOffset(0x6000) == nullptr);
559 EXPECT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->debug_frame_->LastErrorCode());
560
561 SetCie32(&this->memory_, 0x7000, 0x100, std::vector<uint8_t>{5, '\0', 1, 2, 3, 4, 5, 6, 7});
562 ASSERT_TRUE(this->debug_frame_->GetCieFromOffset(0x7000) == nullptr);
563 EXPECT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->debug_frame_->LastErrorCode());
564 SetCie64(&this->memory_, 0x8000, 0x100, std::vector<uint8_t>{5, '\0', 1, 2, 3, 4, 5, 6, 7});
565 ASSERT_TRUE(this->debug_frame_->GetCieFromOffset(0x8000) == nullptr);
566 EXPECT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->debug_frame_->LastErrorCode());
567}
568
569static void VerifyCieAugment(const DwarfCie* cie, uint64_t inst_offset, uint64_t inst_end) {
570 EXPECT_EQ(1U, cie->version);
571 EXPECT_EQ(DW_EH_PE_udata2, cie->fde_address_encoding);
572 EXPECT_EQ(DW_EH_PE_textrel | DW_EH_PE_udata2, cie->lsda_encoding);
573 EXPECT_EQ(0U, cie->segment_size);
574 EXPECT_EQ(5U, cie->augmentation_string.size());
575 EXPECT_EQ('z', cie->augmentation_string[0]);
576 EXPECT_EQ('L', cie->augmentation_string[1]);
577 EXPECT_EQ('P', cie->augmentation_string[2]);
578 EXPECT_EQ('R', cie->augmentation_string[3]);
579 EXPECT_EQ('\0', cie->augmentation_string[4]);
580 EXPECT_EQ(0x12345678U, cie->personality_handler);
581 EXPECT_EQ(4U, cie->code_alignment_factor);
582 EXPECT_EQ(8, cie->data_alignment_factor);
583 EXPECT_EQ(0x10U, cie->return_address_register);
584 EXPECT_EQ(inst_offset, cie->cfa_instructions_offset);
585 EXPECT_EQ(inst_end, cie->cfa_instructions_end);
586}
587
588TYPED_TEST_P(DwarfDebugFrameTest, GetCieFromOffset32_augment) {
589 SetCie32(&this->memory_, 0x5000, 0x100,
590 std::vector<uint8_t>{/* version */ 1,
591 /* augment string */ 'z', 'L', 'P', 'R', '\0',
592 /* code alignment factor */ 4,
593 /* data alignment factor */ 8,
594 /* return address register */ 0x10,
595 /* augment length */ 0xf,
596 /* L data */ DW_EH_PE_textrel | DW_EH_PE_udata2,
597 /* P data */ DW_EH_PE_udata4, 0x78, 0x56, 0x34, 0x12,
598 /* R data */ DW_EH_PE_udata2});
599
600 const DwarfCie* cie = this->debug_frame_->GetCieFromOffset(0x5000);
601 ASSERT_TRUE(cie != nullptr);
602 VerifyCieAugment(cie, 0x5021, 0x5104);
603}
604
605TYPED_TEST_P(DwarfDebugFrameTest, GetCieFromOffset64_augment) {
606 SetCie64(&this->memory_, 0x5000, 0x100,
607 std::vector<uint8_t>{/* version */ 1,
608 /* augment string */ 'z', 'L', 'P', 'R', '\0',
609 /* code alignment factor */ 4,
610 /* data alignment factor */ 8,
611 /* return address register */ 0x10,
612 /* augment length */ 0xf,
613 /* L data */ DW_EH_PE_textrel | DW_EH_PE_udata2,
614 /* P data */ DW_EH_PE_udata4, 0x78, 0x56, 0x34, 0x12,
615 /* R data */ DW_EH_PE_udata2});
616
617 const DwarfCie* cie = this->debug_frame_->GetCieFromOffset(0x5000);
618 ASSERT_TRUE(cie != nullptr);
619 VerifyCieAugment(cie, 0x502d, 0x510c);
620}
621
622TYPED_TEST_P(DwarfDebugFrameTest, GetFdeFromOffset32_augment) {
623 SetCie32(&this->memory_, 0x5000, 0xfc,
624 std::vector<uint8_t>{/* version */ 4,
625 /* augment string */ 'z', '\0',
626 /* address size */ 8,
627 /* segment size */ 0x10,
628 /* code alignment factor */ 16,
629 /* data alignment factor */ 32,
630 /* return address register */ 10,
631 /* augment length */ 0x0});
632
633 std::vector<uint8_t> data{/* augment length */ 0x80, 0x3};
634 SetFde32(&this->memory_, 0x5200, 0x300, 0x5000, 0x4300, 0x300, 0x10, &data);
635
636 const DwarfFde* fde = this->debug_frame_->GetFdeFromOffset(0x5200);
637 ASSERT_TRUE(fde != nullptr);
638 ASSERT_TRUE(fde->cie != nullptr);
639 EXPECT_EQ(4U, fde->cie->version);
640 EXPECT_EQ(0x5000U, fde->cie_offset);
641 EXPECT_EQ(0x53a2U, fde->cfa_instructions_offset);
642 EXPECT_EQ(0x5504U, fde->cfa_instructions_end);
643 EXPECT_EQ(0x4300U, fde->pc_start);
644 EXPECT_EQ(0x4600U, fde->pc_end);
645 EXPECT_EQ(0U, fde->lsda_address);
646}
647
648TYPED_TEST_P(DwarfDebugFrameTest, GetFdeFromOffset64_augment) {
649 SetCie64(&this->memory_, 0x5000, 0xfc,
650 std::vector<uint8_t>{/* version */ 4,
651 /* augment string */ 'z', '\0',
652 /* address size */ 8,
653 /* segment size */ 0x10,
654 /* code alignment factor */ 16,
655 /* data alignment factor */ 32,
656 /* return address register */ 10,
657 /* augment length */ 0x0});
658
659 std::vector<uint8_t> data{/* augment length */ 0x80, 0x3};
660 SetFde64(&this->memory_, 0x5200, 0x300, 0x5000, 0x4300, 0x300, 0x10, &data);
661
662 const DwarfFde* fde = this->debug_frame_->GetFdeFromOffset(0x5200);
663 ASSERT_TRUE(fde != nullptr);
664 ASSERT_TRUE(fde->cie != nullptr);
665 EXPECT_EQ(4U, fde->cie->version);
666 EXPECT_EQ(0x5000U, fde->cie_offset);
667 EXPECT_EQ(0x53b6U, fde->cfa_instructions_offset);
668 EXPECT_EQ(0x550cU, fde->cfa_instructions_end);
669 EXPECT_EQ(0x4300U, fde->pc_start);
670 EXPECT_EQ(0x4600U, fde->pc_end);
671 EXPECT_EQ(0U, fde->lsda_address);
672}
673
674TYPED_TEST_P(DwarfDebugFrameTest, GetFdeFromOffset32_lsda_address) {
675 SetCie32(&this->memory_, 0x5000, 0xfc,
676 std::vector<uint8_t>{/* version */ 1,
677 /* augment string */ 'z', 'L', '\0',
678 /* address size */ 8,
679 /* code alignment factor */ 16,
680 /* data alignment factor */ 32,
681 /* return address register */ 10,
682 /* augment length */ 0x2,
683 /* L data */ DW_EH_PE_udata2});
684
685 std::vector<uint8_t> data{/* augment length */ 0x80, 0x3,
686 /* lsda address */ 0x20, 0x45};
687 SetFde32(&this->memory_, 0x5200, 0x300, 0x5000, 0x4300, 0x300, 0, &data);
688
689 const DwarfFde* fde = this->debug_frame_->GetFdeFromOffset(0x5200);
690 ASSERT_TRUE(fde != nullptr);
691 ASSERT_TRUE(fde->cie != nullptr);
692 EXPECT_EQ(1U, fde->cie->version);
693 EXPECT_EQ(0x5000U, fde->cie_offset);
694 EXPECT_EQ(0x5392U, fde->cfa_instructions_offset);
695 EXPECT_EQ(0x5504U, fde->cfa_instructions_end);
696 EXPECT_EQ(0x4300U, fde->pc_start);
697 EXPECT_EQ(0x4600U, fde->pc_end);
698 EXPECT_EQ(0x4520U, fde->lsda_address);
699}
700
701TYPED_TEST_P(DwarfDebugFrameTest, GetFdeFromOffset64_lsda_address) {
702 SetCie64(&this->memory_, 0x5000, 0xfc,
703 std::vector<uint8_t>{/* version */ 1,
704 /* augment string */ 'z', 'L', '\0',
705 /* address size */ 8,
706 /* code alignment factor */ 16,
707 /* data alignment factor */ 32,
708 /* return address register */ 10,
709 /* augment length */ 0x2,
710 /* L data */ DW_EH_PE_udata2});
711
712 std::vector<uint8_t> data{/* augment length */ 0x80, 0x3,
713 /* lsda address */ 0x20, 0x45};
714 SetFde64(&this->memory_, 0x5200, 0x300, 0x5000, 0x4300, 0x300, 0, &data);
715
716 const DwarfFde* fde = this->debug_frame_->GetFdeFromOffset(0x5200);
717 ASSERT_TRUE(fde != nullptr);
718 ASSERT_TRUE(fde->cie != nullptr);
719 EXPECT_EQ(1U, fde->cie->version);
720 EXPECT_EQ(0x5000U, fde->cie_offset);
721 EXPECT_EQ(0x53a6U, fde->cfa_instructions_offset);
722 EXPECT_EQ(0x550cU, fde->cfa_instructions_end);
723 EXPECT_EQ(0x4300U, fde->pc_start);
724 EXPECT_EQ(0x4600U, fde->pc_end);
725 EXPECT_EQ(0x4520U, fde->lsda_address);
726}
727
728TYPED_TEST_P(DwarfDebugFrameTest, GetFdeFromPc_interleaved) {
729 SetCie32(&this->memory_, 0x5000, 0xfc, std::vector<uint8_t>{1, '\0', 0, 0, 1});
730
731 // FDE 0 (0x100 - 0x200)
732 SetFde32(&this->memory_, 0x5100, 0xfc, 0, 0x100, 0x100);
733 // FDE 1 (0x300 - 0x500)
734 SetFde32(&this->memory_, 0x5200, 0xfc, 0, 0x300, 0x200);
735 // FDE 2 (0x700 - 0x800)
736 SetFde32(&this->memory_, 0x5300, 0xfc, 0, 0x700, 0x100);
737 // FDE 3 (0xa00 - 0xb00)
738 SetFde32(&this->memory_, 0x5400, 0xfc, 0, 0xa00, 0x100);
739 // FDE 4 (0x100 - 0xb00)
740 SetFde32(&this->memory_, 0x5500, 0xfc, 0, 0x150, 0xa00);
741 // FDE 5 (0x0 - 0x50)
742 SetFde32(&this->memory_, 0x5600, 0xfc, 0, 0, 0x50);
743
744 this->debug_frame_->Init(0x5000, 0x700, 0);
745
746 // Force reading all entries so no entries are found.
747 const DwarfFde* fde = this->debug_frame_->GetFdeFromPc(0xfffff);
748 ASSERT_TRUE(fde == nullptr);
749
750 // 0x0 - 0x50 FDE 5
751 fde = this->debug_frame_->GetFdeFromPc(0x10);
752 ASSERT_TRUE(fde != nullptr);
753 EXPECT_EQ(0U, fde->pc_start);
754 EXPECT_EQ(0x50U, fde->pc_end);
755
756 // 0x100 - 0x200 FDE 0
757 fde = this->debug_frame_->GetFdeFromPc(0x170);
758 ASSERT_TRUE(fde != nullptr);
759 EXPECT_EQ(0x100U, fde->pc_start);
760 EXPECT_EQ(0x200U, fde->pc_end);
761
762 // 0x200 - 0x300 FDE 4
763 fde = this->debug_frame_->GetFdeFromPc(0x210);
764 ASSERT_TRUE(fde != nullptr);
765 EXPECT_EQ(0x150U, fde->pc_start);
766 EXPECT_EQ(0xb50U, fde->pc_end);
767
768 // 0x300 - 0x500 FDE 1
769 fde = this->debug_frame_->GetFdeFromPc(0x310);
770 ASSERT_TRUE(fde != nullptr);
771 EXPECT_EQ(0x300U, fde->pc_start);
772 EXPECT_EQ(0x500U, fde->pc_end);
773
774 // 0x700 - 0x800 FDE 2
775 fde = this->debug_frame_->GetFdeFromPc(0x790);
776 ASSERT_TRUE(fde != nullptr);
777 EXPECT_EQ(0x700U, fde->pc_start);
778 EXPECT_EQ(0x800U, fde->pc_end);
779
780 // 0x800 - 0x900 FDE 4
781 fde = this->debug_frame_->GetFdeFromPc(0x850);
782 ASSERT_TRUE(fde != nullptr);
783 EXPECT_EQ(0x150U, fde->pc_start);
784 EXPECT_EQ(0xb50U, fde->pc_end);
785
786 // 0xa00 - 0xb00 FDE 3
787 fde = this->debug_frame_->GetFdeFromPc(0xa35);
788 ASSERT_TRUE(fde != nullptr);
789 EXPECT_EQ(0xa00U, fde->pc_start);
790 EXPECT_EQ(0xb00U, fde->pc_end);
791
792 // 0xb00 - 0xb50 FDE 4
793 fde = this->debug_frame_->GetFdeFromPc(0xb20);
794 ASSERT_TRUE(fde != nullptr);
795 EXPECT_EQ(0x150U, fde->pc_start);
796 EXPECT_EQ(0xb50U, fde->pc_end);
797}
798
799REGISTER_TYPED_TEST_CASE_P(
800 DwarfDebugFrameTest, GetFdes32, GetFdes32_after_GetFdeFromPc, GetFdes32_not_in_section,
801 GetFdeFromPc32, GetFdeFromPc32_reverse, GetFdeFromPc32_not_in_section, GetFdes64,
802 GetFdes64_after_GetFdeFromPc, GetFdes64_not_in_section, GetFdeFromPc64, GetFdeFromPc64_reverse,
803 GetFdeFromPc64_not_in_section, GetCieFde32, GetCieFde64, GetCieFromOffset32_cie_cached,
804 GetCieFromOffset64_cie_cached, GetCieFromOffset32_version1, GetCieFromOffset64_version1,
805 GetCieFromOffset32_version3, GetCieFromOffset64_version3, GetCieFromOffset32_version4,
806 GetCieFromOffset64_version4, GetCieFromOffset_version_invalid, GetCieFromOffset32_augment,
807 GetCieFromOffset64_augment, GetFdeFromOffset32_augment, GetFdeFromOffset64_augment,
808 GetFdeFromOffset32_lsda_address, GetFdeFromOffset64_lsda_address, GetFdeFromPc_interleaved);
581 809
582typedef ::testing::Types<uint32_t, uint64_t> DwarfDebugFrameTestTypes; 810typedef ::testing::Types<uint32_t, uint64_t> DwarfDebugFrameTestTypes;
583INSTANTIATE_TYPED_TEST_CASE_P(, DwarfDebugFrameTest, DwarfDebugFrameTestTypes); 811INSTANTIATE_TYPED_TEST_CASE_P(, DwarfDebugFrameTest, DwarfDebugFrameTestTypes);
diff --git a/libunwindstack/tests/DwarfEhFrameTest.cpp b/libunwindstack/tests/DwarfEhFrameTest.cpp
index e8d53e647..9cac6e8ee 100644
--- a/libunwindstack/tests/DwarfEhFrameTest.cpp
+++ b/libunwindstack/tests/DwarfEhFrameTest.cpp
@@ -16,7 +16,6 @@
16 16
17#include <stdint.h> 17#include <stdint.h>
18 18
19#include <gmock/gmock.h>
20#include <gtest/gtest.h> 19#include <gtest/gtest.h>
21 20
22#include <unwindstack/DwarfError.h> 21#include <unwindstack/DwarfError.h>
@@ -30,50 +29,32 @@
30namespace unwindstack { 29namespace unwindstack {
31 30
32template <typename TypeParam> 31template <typename TypeParam>
33class MockDwarfEhFrame : public DwarfEhFrame<TypeParam> {
34 public:
35 MockDwarfEhFrame(Memory* memory) : DwarfEhFrame<TypeParam>(memory) {}
36 ~MockDwarfEhFrame() = default;
37
38 void TestSetFdeCount(uint64_t count) { this->fde_count_ = count; }
39 void TestSetOffset(uint64_t offset) { this->entries_offset_ = offset; }
40 void TestSetEndOffset(uint64_t offset) { this->entries_end_ = offset; }
41 void TestPushFdeInfo(const typename DwarfEhFrame<TypeParam>::FdeInfo& info) {
42 this->fdes_.push_back(info);
43 }
44
45 uint64_t TestGetFdeCount() { return this->fde_count_; }
46 uint8_t TestGetOffset() { return this->offset_; }
47 uint8_t TestGetEndOffset() { return this->end_offset_; }
48 void TestGetFdeInfo(size_t index, typename DwarfEhFrame<TypeParam>::FdeInfo* info) {
49 *info = this->fdes_[index];
50 }
51};
52
53template <typename TypeParam>
54class DwarfEhFrameTest : public ::testing::Test { 32class DwarfEhFrameTest : public ::testing::Test {
55 protected: 33 protected:
56 void SetUp() override { 34 void SetUp() override {
57 memory_.Clear(); 35 memory_.Clear();
58 eh_frame_ = new MockDwarfEhFrame<TypeParam>(&memory_); 36 eh_frame_ = new DwarfEhFrame<TypeParam>(&memory_);
59 ResetLogs(); 37 ResetLogs();
60 } 38 }
61 39
62 void TearDown() override { delete eh_frame_; } 40 void TearDown() override { delete eh_frame_; }
63 41
64 MemoryFake memory_; 42 MemoryFake memory_;
65 MockDwarfEhFrame<TypeParam>* eh_frame_ = nullptr; 43 DwarfEhFrame<TypeParam>* eh_frame_ = nullptr;
66}; 44};
67TYPED_TEST_CASE_P(DwarfEhFrameTest); 45TYPED_TEST_CASE_P(DwarfEhFrameTest);
68 46
69// NOTE: All test class variables need to be referenced as this->. 47// NOTE: All test class variables need to be referenced as this->.
70 48
71TYPED_TEST_P(DwarfEhFrameTest, Init32) { 49// Only verify different cie/fde format. All other DwarfSection corner
50// cases are tested in DwarfDebugFrameTest.cpp.
51
52TYPED_TEST_P(DwarfEhFrameTest, GetFdeCieFromOffset32) {
72 // CIE 32 information. 53 // CIE 32 information.
73 this->memory_.SetData32(0x5000, 0xfc); 54 this->memory_.SetData32(0x5000, 0xfc);
55 // Indicates this is a cie for eh_frame.
74 this->memory_.SetData32(0x5004, 0); 56 this->memory_.SetData32(0x5004, 0);
75 this->memory_.SetData8(0x5008, 1); 57 this->memory_.SetMemory(0x5008, std::vector<uint8_t>{1, '\0', 16, 32, 1});
76 this->memory_.SetData8(0x5009, '\0');
77 58
78 // FDE 32 information. 59 // FDE 32 information.
79 this->memory_.SetData32(0x5100, 0xfc); 60 this->memory_.SetData32(0x5100, 0xfc);
@@ -81,415 +62,70 @@ TYPED_TEST_P(DwarfEhFrameTest, Init32) {
81 this->memory_.SetData32(0x5108, 0x1500); 62 this->memory_.SetData32(0x5108, 0x1500);
82 this->memory_.SetData32(0x510c, 0x200); 63 this->memory_.SetData32(0x510c, 0x200);
83 64
84 this->memory_.SetData32(0x5200, 0xfc); 65 const DwarfFde* fde = this->eh_frame_->GetFdeFromOffset(0x5100);
85 this->memory_.SetData32(0x5204, 0x204); 66 ASSERT_TRUE(fde != nullptr);
86 this->memory_.SetData32(0x5208, 0x2500); 67 EXPECT_EQ(0x5000U, fde->cie_offset);
87 this->memory_.SetData32(0x520c, 0x300); 68 EXPECT_EQ(0x5110U, fde->cfa_instructions_offset);
88 69 EXPECT_EQ(0x5200U, fde->cfa_instructions_end);
89 // CIE 32 information. 70 EXPECT_EQ(0x6608U, fde->pc_start);
90 this->memory_.SetData32(0x5300, 0xfc); 71 EXPECT_EQ(0x6808U, fde->pc_end);
91 this->memory_.SetData32(0x5304, 0); 72 EXPECT_EQ(0U, fde->lsda_address);
92 this->memory_.SetData8(0x5308, 1);
93 this->memory_.SetData8(0x5309, '\0');
94
95 // FDE 32 information.
96 this->memory_.SetData32(0x5400, 0xfc);
97 this->memory_.SetData32(0x5404, 0x104);
98 this->memory_.SetData32(0x5408, 0x3500);
99 this->memory_.SetData32(0x540c, 0x400);
100
101 this->memory_.SetData32(0x5500, 0xfc);
102 this->memory_.SetData32(0x5504, 0x204);
103 this->memory_.SetData32(0x5508, 0x4500);
104 this->memory_.SetData32(0x550c, 0x500);
105
106 ASSERT_TRUE(this->eh_frame_->Init(0x5000, 0x600, 0));
107 ASSERT_EQ(4U, this->eh_frame_->TestGetFdeCount());
108
109 typename DwarfEhFrame<TypeParam>::FdeInfo info(0, 0, 0);
110
111 this->eh_frame_->TestGetFdeInfo(0, &info);
112 EXPECT_EQ(0x5100U, info.offset);
113 EXPECT_EQ(0x6608U, info.start);
114 EXPECT_EQ(0x6808U, info.end);
115
116 this->eh_frame_->TestGetFdeInfo(1, &info);
117 EXPECT_EQ(0x5200U, info.offset);
118 EXPECT_EQ(0x7708U, info.start);
119 EXPECT_EQ(0x7a08U, info.end);
120
121 this->eh_frame_->TestGetFdeInfo(2, &info);
122 EXPECT_EQ(0x5400U, info.offset);
123 EXPECT_EQ(0x8908U, info.start);
124 EXPECT_EQ(0x8d08U, info.end);
125
126 this->eh_frame_->TestGetFdeInfo(3, &info);
127 EXPECT_EQ(0x5500U, info.offset);
128 EXPECT_EQ(0x9a08U, info.start);
129 EXPECT_EQ(0x9f08U, info.end);
130}
131
132TYPED_TEST_P(DwarfEhFrameTest, Init32_fde_not_following_cie) {
133 // CIE 32 information.
134 this->memory_.SetData32(0x5000, 0xfc);
135 this->memory_.SetData32(0x5004, 0);
136 this->memory_.SetData8(0x5008, 1);
137 this->memory_.SetData8(0x5009, '\0');
138
139 // FDE 32 information.
140 this->memory_.SetData32(0x5100, 0xfc);
141 this->memory_.SetData32(0x5104, 0x1000);
142 this->memory_.SetData32(0x5108, 0x1500);
143 this->memory_.SetData32(0x510c, 0x200);
144 73
145 ASSERT_FALSE(this->eh_frame_->Init(0x5000, 0x600, 0)); 74 const DwarfCie* cie = fde->cie;
146 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->eh_frame_->LastErrorCode()); 75 ASSERT_TRUE(cie != nullptr);
76 EXPECT_EQ(1U, cie->version);
77 EXPECT_EQ(DW_EH_PE_sdata4, cie->fde_address_encoding);
78 EXPECT_EQ(DW_EH_PE_omit, cie->lsda_encoding);
79 EXPECT_EQ(0U, cie->segment_size);
80 EXPECT_EQ('\0', cie->augmentation_string[0]);
81 EXPECT_EQ(0U, cie->personality_handler);
82 EXPECT_EQ(0x500dU, cie->cfa_instructions_offset);
83 EXPECT_EQ(0x5100U, cie->cfa_instructions_end);
84 EXPECT_EQ(16U, cie->code_alignment_factor);
85 EXPECT_EQ(32U, cie->data_alignment_factor);
86 EXPECT_EQ(1U, cie->return_address_register);
147} 87}
148 88
149TYPED_TEST_P(DwarfEhFrameTest, Init64) { 89TYPED_TEST_P(DwarfEhFrameTest, GetFdeCieFromOffset64) {
150 // CIE 64 information. 90 // CIE 64 information.
151 this->memory_.SetData32(0x5000, 0xffffffff); 91 this->memory_.SetData32(0x5000, 0xffffffff);
152 this->memory_.SetData64(0x5004, 0xf4); 92 this->memory_.SetData64(0x5004, 0xfc);
93 // Indicates this is a cie for eh_frame.
153 this->memory_.SetData64(0x500c, 0); 94 this->memory_.SetData64(0x500c, 0);
154 this->memory_.SetData8(0x5014, 1); 95 this->memory_.SetMemory(0x5014, std::vector<uint8_t>{1, '\0', 16, 32, 1});
155 this->memory_.SetData8(0x5015, '\0');
156 96
157 // FDE 64 information. 97 // FDE 64 information.
158 this->memory_.SetData32(0x5100, 0xffffffff); 98 this->memory_.SetData32(0x5100, 0xffffffff);
159 this->memory_.SetData64(0x5104, 0xf4); 99 this->memory_.SetData64(0x5104, 0xfc);
160 this->memory_.SetData64(0x510c, 0x10c); 100 this->memory_.SetData64(0x510c, 0x10c);
161 this->memory_.SetData64(0x5114, 0x1500); 101 this->memory_.SetData64(0x5114, 0x1500);
162 this->memory_.SetData64(0x511c, 0x200); 102 this->memory_.SetData64(0x511c, 0x200);
163 103
164 this->memory_.SetData32(0x5200, 0xffffffff); 104 const DwarfFde* fde = this->eh_frame_->GetFdeFromOffset(0x5100);
165 this->memory_.SetData64(0x5204, 0xf4);
166 this->memory_.SetData64(0x520c, 0x20c);
167 this->memory_.SetData64(0x5214, 0x2500);
168 this->memory_.SetData64(0x521c, 0x300);
169
170 // CIE 64 information.
171 this->memory_.SetData32(0x5300, 0xffffffff);
172 this->memory_.SetData64(0x5304, 0xf4);
173 this->memory_.SetData64(0x530c, 0);
174 this->memory_.SetData8(0x5314, 1);
175 this->memory_.SetData8(0x5315, '\0');
176
177 // FDE 64 information.
178 this->memory_.SetData32(0x5400, 0xffffffff);
179 this->memory_.SetData64(0x5404, 0xf4);
180 this->memory_.SetData64(0x540c, 0x10c);
181 this->memory_.SetData64(0x5414, 0x3500);
182 this->memory_.SetData64(0x541c, 0x400);
183
184 this->memory_.SetData32(0x5500, 0xffffffff);
185 this->memory_.SetData64(0x5504, 0xf4);
186 this->memory_.SetData64(0x550c, 0x20c);
187 this->memory_.SetData64(0x5514, 0x4500);
188 this->memory_.SetData64(0x551c, 0x500);
189
190 ASSERT_TRUE(this->eh_frame_->Init(0x5000, 0x600, 0));
191 ASSERT_EQ(4U, this->eh_frame_->TestGetFdeCount());
192
193 typename DwarfEhFrame<TypeParam>::FdeInfo info(0, 0, 0);
194
195 this->eh_frame_->TestGetFdeInfo(0, &info);
196 EXPECT_EQ(0x5100U, info.offset);
197 EXPECT_EQ(0x6618U, info.start);
198 EXPECT_EQ(0x6818U, info.end);
199
200 this->eh_frame_->TestGetFdeInfo(1, &info);
201 EXPECT_EQ(0x5200U, info.offset);
202 EXPECT_EQ(0x7718U, info.start);
203 EXPECT_EQ(0x7a18U, info.end);
204
205 this->eh_frame_->TestGetFdeInfo(2, &info);
206 EXPECT_EQ(0x5400U, info.offset);
207 EXPECT_EQ(0x8918U, info.start);
208 EXPECT_EQ(0x8d18U, info.end);
209
210 this->eh_frame_->TestGetFdeInfo(3, &info);
211 EXPECT_EQ(0x5500U, info.offset);
212 EXPECT_EQ(0x9a18U, info.start);
213 EXPECT_EQ(0x9f18U, info.end);
214}
215
216TYPED_TEST_P(DwarfEhFrameTest, Init64_fde_not_following_cie) {
217 // CIE 64 information.
218 this->memory_.SetData32(0x5000, 0xffffffff);
219 this->memory_.SetData64(0x5004, 0xf4);
220 this->memory_.SetData64(0x500c, 0);
221 this->memory_.SetData8(0x5014, 1);
222 this->memory_.SetData8(0x5015, '\0');
223
224 // FDE 64 information.
225 this->memory_.SetData32(0x5100, 0xffffffff);
226 this->memory_.SetData64(0x5104, 0xf4);
227 this->memory_.SetData64(0x510c, 0x1000);
228 this->memory_.SetData64(0x5114, 0x1500);
229 this->memory_.SetData64(0x511c, 0x200);
230
231 ASSERT_FALSE(this->eh_frame_->Init(0x5000, 0x600, 0));
232 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->eh_frame_->LastErrorCode());
233}
234
235TYPED_TEST_P(DwarfEhFrameTest, Init_non_zero_load_bias) {
236 // CIE 32 information.
237 this->memory_.SetData32(0x5000, 0xfc);
238 this->memory_.SetData32(0x5004, 0);
239 this->memory_.SetData8(0x5008, 1);
240 this->memory_.SetData8(0x5009, 'z');
241 this->memory_.SetData8(0x500a, 'R');
242 this->memory_.SetData8(0x500b, '\0');
243 this->memory_.SetData8(0x500c, 0);
244 this->memory_.SetData8(0x500d, 0);
245 this->memory_.SetData8(0x500e, 0);
246 this->memory_.SetData8(0x500f, 0);
247 this->memory_.SetData8(0x5010, 0x1b);
248
249 // FDE 32 information.
250 this->memory_.SetData32(0x5100, 0xfc);
251 this->memory_.SetData32(0x5104, 0x104);
252 this->memory_.SetData32(0x5108, 0x1500);
253 this->memory_.SetData32(0x510c, 0x200);
254 this->memory_.SetData8(0x5110, 0);
255 this->memory_.SetData8(0x5111, 0);
256
257 ASSERT_TRUE(this->eh_frame_->Init(0x5000, 0x200, 0x2000));
258 ASSERT_EQ(1U, this->eh_frame_->TestGetFdeCount());
259
260 typename DwarfEhFrame<TypeParam>::FdeInfo info(0, 0, 0);
261
262 this->eh_frame_->TestGetFdeInfo(0, &info);
263 EXPECT_EQ(0x5100U, info.offset);
264 EXPECT_EQ(0x8608U, info.start);
265 EXPECT_EQ(0x8808U, info.end);
266
267 const DwarfFde* fde = this->eh_frame_->GetFdeFromPc(0x8700);
268 ASSERT_TRUE(fde != nullptr);
269 EXPECT_EQ(0x8608U, fde->pc_start);
270 EXPECT_EQ(0x8808U, fde->pc_end);
271}
272
273TYPED_TEST_P(DwarfEhFrameTest, Init_version1) {
274 // CIE 32 information.
275 this->memory_.SetData32(0x5000, 0xfc);
276 this->memory_.SetData32(0x5004, 0);
277 this->memory_.SetData8(0x5008, 1);
278 // Augment string.
279 this->memory_.SetMemory(0x5009, std::vector<uint8_t>{'z', 'R', 'P', 'L', '\0'});
280 // Code alignment factor.
281 this->memory_.SetMemory(0x500e, std::vector<uint8_t>{0x80, 0x00});
282 // Data alignment factor.
283 this->memory_.SetMemory(0x5010, std::vector<uint8_t>{0x81, 0x80, 0x80, 0x00});
284 // Return address register
285 this->memory_.SetData8(0x5014, 0x84);
286 // Augmentation length
287 this->memory_.SetMemory(0x5015, std::vector<uint8_t>{0x84, 0x00});
288 // R data.
289 this->memory_.SetData8(0x5017, DW_EH_PE_pcrel | DW_EH_PE_udata2);
290
291 // FDE 32 information.
292 this->memory_.SetData32(0x5100, 0xfc);
293 this->memory_.SetData32(0x5104, 0x104);
294 this->memory_.SetData16(0x5108, 0x1500);
295 this->memory_.SetData16(0x510a, 0x200);
296
297 ASSERT_TRUE(this->eh_frame_->Init(0x5000, 0x200, 0));
298 ASSERT_EQ(1U, this->eh_frame_->TestGetFdeCount());
299
300 typename DwarfEhFrame<TypeParam>::FdeInfo info(0, 0, 0);
301 this->eh_frame_->TestGetFdeInfo(0, &info);
302 EXPECT_EQ(0x5100U, info.offset);
303 EXPECT_EQ(0x6606U, info.start);
304 EXPECT_EQ(0x6806U, info.end);
305}
306
307TYPED_TEST_P(DwarfEhFrameTest, Init_version4) {
308 // CIE 32 information.
309 this->memory_.SetData32(0x5000, 0xfc);
310 this->memory_.SetData32(0x5004, 0);
311 this->memory_.SetData8(0x5008, 4);
312 // Augment string.
313 this->memory_.SetMemory(0x5009, std::vector<uint8_t>{'z', 'L', 'P', 'R', '\0'});
314 // Address size.
315 this->memory_.SetData8(0x500e, 4);
316 // Segment size.
317 this->memory_.SetData8(0x500f, 0);
318 // Code alignment factor.
319 this->memory_.SetMemory(0x5010, std::vector<uint8_t>{0x80, 0x00});
320 // Data alignment factor.
321 this->memory_.SetMemory(0x5012, std::vector<uint8_t>{0x81, 0x80, 0x80, 0x00});
322 // Return address register
323 this->memory_.SetMemory(0x5016, std::vector<uint8_t>{0x85, 0x10});
324 // Augmentation length
325 this->memory_.SetMemory(0x5018, std::vector<uint8_t>{0x84, 0x00});
326 // L data.
327 this->memory_.SetData8(0x501a, 0x10);
328 // P data.
329 this->memory_.SetData8(0x501b, DW_EH_PE_udata4);
330 this->memory_.SetData32(0x501c, 0x100);
331 // R data.
332 this->memory_.SetData8(0x5020, DW_EH_PE_pcrel | DW_EH_PE_udata2);
333
334 // FDE 32 information.
335 this->memory_.SetData32(0x5100, 0xfc);
336 this->memory_.SetData32(0x5104, 0x104);
337 this->memory_.SetData16(0x5108, 0x1500);
338 this->memory_.SetData16(0x510a, 0x200);
339
340 ASSERT_TRUE(this->eh_frame_->Init(0x5000, 0x200, 0));
341 ASSERT_EQ(1U, this->eh_frame_->TestGetFdeCount());
342
343 typename DwarfEhFrame<TypeParam>::FdeInfo info(0, 0, 0);
344 this->eh_frame_->TestGetFdeInfo(0, &info);
345 EXPECT_EQ(0x5100U, info.offset);
346 EXPECT_EQ(0x6606U, info.start);
347 EXPECT_EQ(0x6806U, info.end);
348}
349
350TYPED_TEST_P(DwarfEhFrameTest, GetFdeOffsetFromPc) {
351 typename DwarfEhFrame<TypeParam>::FdeInfo info(0, 0, 0);
352 for (size_t i = 0; i < 9; i++) {
353 info.start = 0x1000 * (i + 1);
354 info.end = 0x1000 * (i + 2) - 0x10;
355 info.offset = 0x5000 + i * 0x20;
356 this->eh_frame_->TestPushFdeInfo(info);
357 }
358
359 this->eh_frame_->TestSetFdeCount(0);
360 uint64_t fde_offset;
361 ASSERT_FALSE(this->eh_frame_->GetFdeOffsetFromPc(0x1000, &fde_offset));
362 ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->LastErrorCode());
363
364 this->eh_frame_->TestSetFdeCount(9);
365 ASSERT_FALSE(this->eh_frame_->GetFdeOffsetFromPc(0x100, &fde_offset));
366 ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->LastErrorCode());
367 // Odd number of elements.
368 for (size_t i = 0; i < 9; i++) {
369 TypeParam pc = 0x1000 * (i + 1);
370 ASSERT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc, &fde_offset)) << "Failed at index " << i;
371 EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i;
372 ASSERT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc + 1, &fde_offset)) << "Failed at index " << i;
373 EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i;
374 ASSERT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc + 0xeff, &fde_offset))
375 << "Failed at index " << i;
376 EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i;
377 ASSERT_FALSE(this->eh_frame_->GetFdeOffsetFromPc(pc + 0xfff, &fde_offset))
378 << "Failed at index " << i;
379 ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->LastErrorCode());
380 }
381
382 // Even number of elements.
383 this->eh_frame_->TestSetFdeCount(10);
384 info.start = 0xa000;
385 info.end = 0xaff0;
386 info.offset = 0x5120;
387 this->eh_frame_->TestPushFdeInfo(info);
388
389 for (size_t i = 0; i < 10; i++) {
390 TypeParam pc = 0x1000 * (i + 1);
391 ASSERT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc, &fde_offset)) << "Failed at index " << i;
392 EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i;
393 ASSERT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc + 1, &fde_offset)) << "Failed at index " << i;
394 EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i;
395 ASSERT_TRUE(this->eh_frame_->GetFdeOffsetFromPc(pc + 0xeff, &fde_offset))
396 << "Failed at index " << i;
397 EXPECT_EQ(0x5000 + i * 0x20, fde_offset) << "Failed at index " << i;
398 ASSERT_FALSE(this->eh_frame_->GetFdeOffsetFromPc(pc + 0xfff, &fde_offset))
399 << "Failed at index " << i;
400 ASSERT_EQ(DWARF_ERROR_NONE, this->eh_frame_->LastErrorCode());
401 }
402}
403
404TYPED_TEST_P(DwarfEhFrameTest, GetCieFde32) {
405 this->eh_frame_->TestSetOffset(0x4000);
406
407 // CIE 32 information.
408 this->memory_.SetData32(0xf000, 0x100);
409 this->memory_.SetData32(0xf004, 0);
410 this->memory_.SetData8(0xf008, 0x1);
411 this->memory_.SetData8(0xf009, '\0');
412 this->memory_.SetData8(0xf00a, 4);
413 this->memory_.SetData8(0xf00b, 8);
414 this->memory_.SetData8(0xf00c, 0x20);
415
416 // FDE 32 information.
417 this->memory_.SetData32(0x14000, 0x20);
418 this->memory_.SetData32(0x14004, 0x5004);
419 this->memory_.SetData32(0x14008, 0x9000);
420 this->memory_.SetData32(0x1400c, 0x100);
421
422 const DwarfFde* fde = this->eh_frame_->GetFdeFromOffset(0x14000);
423 ASSERT_TRUE(fde != nullptr);
424 EXPECT_EQ(0x14010U, fde->cfa_instructions_offset);
425 EXPECT_EQ(0x14024U, fde->cfa_instructions_end);
426 EXPECT_EQ(0x1d008U, fde->pc_start);
427 EXPECT_EQ(0x1d108U, fde->pc_end);
428 EXPECT_EQ(0xf000U, fde->cie_offset);
429 EXPECT_EQ(0U, fde->lsda_address);
430
431 ASSERT_TRUE(fde->cie != nullptr);
432 EXPECT_EQ(1U, fde->cie->version);
433 EXPECT_EQ(DW_EH_PE_sdata4, fde->cie->fde_address_encoding);
434 EXPECT_EQ(DW_EH_PE_omit, fde->cie->lsda_encoding);
435 EXPECT_EQ(0U, fde->cie->segment_size);
436 EXPECT_EQ(1U, fde->cie->augmentation_string.size());
437 EXPECT_EQ('\0', fde->cie->augmentation_string[0]);
438 EXPECT_EQ(0U, fde->cie->personality_handler);
439 EXPECT_EQ(0xf00dU, fde->cie->cfa_instructions_offset);
440 EXPECT_EQ(0xf104U, fde->cie->cfa_instructions_end);
441 EXPECT_EQ(4U, fde->cie->code_alignment_factor);
442 EXPECT_EQ(8, fde->cie->data_alignment_factor);
443 EXPECT_EQ(0x20U, fde->cie->return_address_register);
444}
445
446TYPED_TEST_P(DwarfEhFrameTest, GetCieFde64) {
447 this->eh_frame_->TestSetOffset(0x2000);
448
449 // CIE 64 information.
450 this->memory_.SetData32(0x6000, 0xffffffff);
451 this->memory_.SetData64(0x6004, 0x100);
452 this->memory_.SetData64(0x600c, 0);
453 this->memory_.SetData8(0x6014, 0x1);
454 this->memory_.SetData8(0x6015, '\0');
455 this->memory_.SetData8(0x6016, 4);
456 this->memory_.SetData8(0x6017, 8);
457 this->memory_.SetData8(0x6018, 0x20);
458
459 // FDE 64 information.
460 this->memory_.SetData32(0x8000, 0xffffffff);
461 this->memory_.SetData64(0x8004, 0x200);
462 this->memory_.SetData64(0x800c, 0x200c);
463 this->memory_.SetData64(0x8014, 0x5000);
464 this->memory_.SetData64(0x801c, 0x300);
465
466 const DwarfFde* fde = this->eh_frame_->GetFdeFromOffset(0x8000);
467 ASSERT_TRUE(fde != nullptr); 105 ASSERT_TRUE(fde != nullptr);
468 EXPECT_EQ(0x8024U, fde->cfa_instructions_offset); 106 EXPECT_EQ(0x5000U, fde->cie_offset);
469 EXPECT_EQ(0x820cU, fde->cfa_instructions_end); 107 EXPECT_EQ(0x5124U, fde->cfa_instructions_offset);
470 EXPECT_EQ(0xd018U, fde->pc_start); 108 EXPECT_EQ(0x5208U, fde->cfa_instructions_end);
471 EXPECT_EQ(0xd318U, fde->pc_end); 109 EXPECT_EQ(0x6618U, fde->pc_start);
472 EXPECT_EQ(0x6000U, fde->cie_offset); 110 EXPECT_EQ(0x6818U, fde->pc_end);
473 EXPECT_EQ(0U, fde->lsda_address); 111 EXPECT_EQ(0U, fde->lsda_address);
474 112
475 ASSERT_TRUE(fde->cie != nullptr); 113 const DwarfCie* cie = fde->cie;
476 EXPECT_EQ(1U, fde->cie->version); 114 ASSERT_TRUE(cie != nullptr);
477 EXPECT_EQ(DW_EH_PE_sdata8, fde->cie->fde_address_encoding); 115 EXPECT_EQ(1U, cie->version);
478 EXPECT_EQ(DW_EH_PE_omit, fde->cie->lsda_encoding); 116 EXPECT_EQ(DW_EH_PE_sdata8, cie->fde_address_encoding);
479 EXPECT_EQ(0U, fde->cie->segment_size); 117 EXPECT_EQ(DW_EH_PE_omit, cie->lsda_encoding);
480 EXPECT_EQ(1U, fde->cie->augmentation_string.size()); 118 EXPECT_EQ(0U, cie->segment_size);
481 EXPECT_EQ('\0', fde->cie->augmentation_string[0]); 119 EXPECT_EQ('\0', cie->augmentation_string[0]);
482 EXPECT_EQ(0U, fde->cie->personality_handler); 120 EXPECT_EQ(0U, cie->personality_handler);
483 EXPECT_EQ(0x6019U, fde->cie->cfa_instructions_offset); 121 EXPECT_EQ(0x5019U, cie->cfa_instructions_offset);
484 EXPECT_EQ(0x610cU, fde->cie->cfa_instructions_end); 122 EXPECT_EQ(0x5108U, cie->cfa_instructions_end);
485 EXPECT_EQ(4U, fde->cie->code_alignment_factor); 123 EXPECT_EQ(16U, cie->code_alignment_factor);
486 EXPECT_EQ(8, fde->cie->data_alignment_factor); 124 EXPECT_EQ(32U, cie->data_alignment_factor);
487 EXPECT_EQ(0x20U, fde->cie->return_address_register); 125 EXPECT_EQ(1U, cie->return_address_register);
488} 126}
489 127
490REGISTER_TYPED_TEST_CASE_P(DwarfEhFrameTest, Init32, Init32_fde_not_following_cie, Init64, 128REGISTER_TYPED_TEST_CASE_P(DwarfEhFrameTest, GetFdeCieFromOffset32, GetFdeCieFromOffset64);
491 Init64_fde_not_following_cie, Init_non_zero_load_bias, Init_version1,
492 Init_version4, GetFdeOffsetFromPc, GetCieFde32, GetCieFde64);
493 129
494typedef ::testing::Types<uint32_t, uint64_t> DwarfEhFrameTestTypes; 130typedef ::testing::Types<uint32_t, uint64_t> DwarfEhFrameTestTypes;
495INSTANTIATE_TYPED_TEST_CASE_P(, DwarfEhFrameTest, DwarfEhFrameTestTypes); 131INSTANTIATE_TYPED_TEST_CASE_P(, DwarfEhFrameTest, DwarfEhFrameTestTypes);
diff --git a/libunwindstack/tests/DwarfEhFrameWithHdrTest.cpp b/libunwindstack/tests/DwarfEhFrameWithHdrTest.cpp
index 19c7b98a2..910ae363b 100644
--- a/libunwindstack/tests/DwarfEhFrameWithHdrTest.cpp
+++ b/libunwindstack/tests/DwarfEhFrameWithHdrTest.cpp
@@ -30,10 +30,10 @@
30namespace unwindstack { 30namespace unwindstack {
31 31
32template <typename TypeParam> 32template <typename TypeParam>
33class MockDwarfEhFrameWithHdr : public DwarfEhFrameWithHdr<TypeParam> { 33class TestDwarfEhFrameWithHdr : public DwarfEhFrameWithHdr<TypeParam> {
34 public: 34 public:
35 MockDwarfEhFrameWithHdr(Memory* memory) : DwarfEhFrameWithHdr<TypeParam>(memory) {} 35 TestDwarfEhFrameWithHdr(Memory* memory) : DwarfEhFrameWithHdr<TypeParam>(memory) {}
36 ~MockDwarfEhFrameWithHdr() = default; 36 ~TestDwarfEhFrameWithHdr() = default;
37 37
38 void TestSetTableEncoding(uint8_t encoding) { this->table_encoding_ = encoding; } 38 void TestSetTableEncoding(uint8_t encoding) { this->table_encoding_ = encoding; }
39 void TestSetEntriesOffset(uint64_t offset) { this->entries_offset_ = offset; } 39 void TestSetEntriesOffset(uint64_t offset) { this->entries_offset_ = offset; }
@@ -64,14 +64,14 @@ class DwarfEhFrameWithHdrTest : public ::testing::Test {
64 protected: 64 protected:
65 void SetUp() override { 65 void SetUp() override {
66 memory_.Clear(); 66 memory_.Clear();
67 eh_frame_ = new MockDwarfEhFrameWithHdr<TypeParam>(&memory_); 67 eh_frame_ = new TestDwarfEhFrameWithHdr<TypeParam>(&memory_);
68 ResetLogs(); 68 ResetLogs();
69 } 69 }
70 70
71 void TearDown() override { delete eh_frame_; } 71 void TearDown() override { delete eh_frame_; }
72 72
73 MemoryFake memory_; 73 MemoryFake memory_;
74 MockDwarfEhFrameWithHdr<TypeParam>* eh_frame_ = nullptr; 74 TestDwarfEhFrameWithHdr<TypeParam>* eh_frame_ = nullptr;
75}; 75};
76TYPED_TEST_CASE_P(DwarfEhFrameWithHdrTest); 76TYPED_TEST_CASE_P(DwarfEhFrameWithHdrTest);
77 77
@@ -121,23 +121,14 @@ TYPED_TEST_P(DwarfEhFrameWithHdrTest, Init_non_zero_load_bias) {
121 // CIE 32 information. 121 // CIE 32 information.
122 this->memory_.SetData32(0x1300, 0xfc); 122 this->memory_.SetData32(0x1300, 0xfc);
123 this->memory_.SetData32(0x1304, 0); 123 this->memory_.SetData32(0x1304, 0);
124 this->memory_.SetData8(0x1308, 1); 124 this->memory_.SetMemory(0x1308, std::vector<uint8_t>{1, 'z', 'R', '\0', 0, 0, 0, 0, 0x1b});
125 this->memory_.SetData8(0x1309, 'z');
126 this->memory_.SetData8(0x130a, 'R');
127 this->memory_.SetData8(0x130b, '\0');
128 this->memory_.SetData8(0x130c, 0);
129 this->memory_.SetData8(0x130d, 0);
130 this->memory_.SetData8(0x130e, 0);
131 this->memory_.SetData8(0x130f, 0);
132 this->memory_.SetData8(0x1310, 0x1b);
133 125
134 // FDE 32 information. 126 // FDE 32 information.
135 this->memory_.SetData32(0x1400, 0xfc); 127 this->memory_.SetData32(0x1400, 0xfc);
136 this->memory_.SetData32(0x1404, 0x104); 128 this->memory_.SetData32(0x1404, 0x104);
137 this->memory_.SetData32(0x1408, 0x10f8); 129 this->memory_.SetData32(0x1408, 0x10f8);
138 this->memory_.SetData32(0x140c, 0x200); 130 this->memory_.SetData32(0x140c, 0x200);
139 this->memory_.SetData8(0x1410, 0); 131 this->memory_.SetData16(0x1410, 0);
140 this->memory_.SetData8(0x1411, 0);
141 132
142 ASSERT_TRUE(this->eh_frame_->Init(0x1000, 0x100, 0x2000)); 133 ASSERT_TRUE(this->eh_frame_->Init(0x1000, 0x100, 0x2000));
143 EXPECT_EQ(1U, this->eh_frame_->TestGetVersion()); 134 EXPECT_EQ(1U, this->eh_frame_->TestGetVersion());
@@ -157,6 +148,68 @@ TYPED_TEST_P(DwarfEhFrameWithHdrTest, Init_non_zero_load_bias) {
157 EXPECT_EQ(0x4700U, fde->pc_end); 148 EXPECT_EQ(0x4700U, fde->pc_end);
158} 149}
159 150
151TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdes) {
152 this->memory_.SetMemory(
153 0x1000, std::vector<uint8_t>{1, DW_EH_PE_udata2, DW_EH_PE_udata4, DW_EH_PE_sdata4});
154 this->memory_.SetData16(0x1004, 0x500);
155 this->memory_.SetData32(0x1006, 4);
156
157 // Header information.
158 this->memory_.SetData32(0x100a, 0x4600);
159 this->memory_.SetData32(0x100e, 0x1500);
160 this->memory_.SetData32(0x1012, 0x5500);
161 this->memory_.SetData32(0x1016, 0x1400);
162 this->memory_.SetData32(0x101a, 0x6800);
163 this->memory_.SetData32(0x101e, 0x1700);
164 this->memory_.SetData32(0x1022, 0x7700);
165 this->memory_.SetData32(0x1026, 0x1600);
166
167 // CIE 32 information.
168 this->memory_.SetData32(0x1300, 0xfc);
169 this->memory_.SetData32(0x1304, 0);
170 this->memory_.SetMemory(0x1308, std::vector<uint8_t>{1, '\0', 0, 0, 0});
171
172 // FDE 32 information.
173 // pc 0x5500 - 0x5700
174 this->memory_.SetData32(0x1400, 0xfc);
175 this->memory_.SetData32(0x1404, 0x104);
176 this->memory_.SetData32(0x1408, 0x40f8);
177 this->memory_.SetData32(0x140c, 0x200);
178
179 // pc 0x4600 - 0x4800
180 this->memory_.SetData32(0x1500, 0xfc);
181 this->memory_.SetData32(0x1504, 0x204);
182 this->memory_.SetData32(0x1508, 0x30f8);
183 this->memory_.SetData32(0x150c, 0x200);
184
185 // pc 0x7700 - 0x7900
186 this->memory_.SetData32(0x1600, 0xfc);
187 this->memory_.SetData32(0x1604, 0x304);
188 this->memory_.SetData32(0x1608, 0x60f8);
189 this->memory_.SetData32(0x160c, 0x200);
190
191 // pc 0x6800 - 0x6a00
192 this->memory_.SetData32(0x1700, 0xfc);
193 this->memory_.SetData32(0x1704, 0x404);
194 this->memory_.SetData32(0x1708, 0x50f8);
195 this->memory_.SetData32(0x170c, 0x200);
196
197 ASSERT_TRUE(this->eh_frame_->Init(0x1000, 0x100, 0));
198
199 std::vector<const DwarfFde*> fdes;
200 this->eh_frame_->GetFdes(&fdes);
201 ASSERT_EQ(4U, fdes.size());
202
203 EXPECT_EQ(0x4600U, fdes[0]->pc_start);
204 EXPECT_EQ(0x4800U, fdes[0]->pc_end);
205 EXPECT_EQ(0x5500U, fdes[1]->pc_start);
206 EXPECT_EQ(0x5700U, fdes[1]->pc_end);
207 EXPECT_EQ(0x6800U, fdes[2]->pc_start);
208 EXPECT_EQ(0x6a00U, fdes[2]->pc_end);
209 EXPECT_EQ(0x7700U, fdes[3]->pc_start);
210 EXPECT_EQ(0x7900U, fdes[3]->pc_end);
211}
212
160TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeInfoFromIndex_expect_cache_fail) { 213TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeInfoFromIndex_expect_cache_fail) {
161 this->eh_frame_->TestSetTableEntrySize(0x10); 214 this->eh_frame_->TestSetTableEntrySize(0x10);
162 this->eh_frame_->TestSetTableEncoding(DW_EH_PE_udata4); 215 this->eh_frame_->TestSetTableEncoding(DW_EH_PE_udata4);
@@ -388,11 +441,7 @@ TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetCieFde32) {
388 // CIE 32 information. 441 // CIE 32 information.
389 this->memory_.SetData32(0xf000, 0x100); 442 this->memory_.SetData32(0xf000, 0x100);
390 this->memory_.SetData32(0xf004, 0); 443 this->memory_.SetData32(0xf004, 0);
391 this->memory_.SetData8(0xf008, 0x1); 444 this->memory_.SetMemory(0xf008, std::vector<uint8_t>{1, '\0', 4, 8, 0x20});
392 this->memory_.SetData8(0xf009, '\0');
393 this->memory_.SetData8(0xf00a, 4);
394 this->memory_.SetData8(0xf00b, 8);
395 this->memory_.SetData8(0xf00c, 0x20);
396 445
397 // FDE 32 information. 446 // FDE 32 information.
398 this->memory_.SetData32(0x14000, 0x20); 447 this->memory_.SetData32(0x14000, 0x20);
@@ -429,11 +478,7 @@ TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetCieFde64) {
429 this->memory_.SetData32(0x6000, 0xffffffff); 478 this->memory_.SetData32(0x6000, 0xffffffff);
430 this->memory_.SetData64(0x6004, 0x100); 479 this->memory_.SetData64(0x6004, 0x100);
431 this->memory_.SetData64(0x600c, 0); 480 this->memory_.SetData64(0x600c, 0);
432 this->memory_.SetData8(0x6014, 0x1); 481 this->memory_.SetMemory(0x6014, std::vector<uint8_t>{1, '\0', 4, 8, 0x20});
433 this->memory_.SetData8(0x6015, '\0');
434 this->memory_.SetData8(0x6016, 4);
435 this->memory_.SetData8(0x6017, 8);
436 this->memory_.SetData8(0x6018, 0x20);
437 482
438 // FDE 64 information. 483 // FDE 64 information.
439 this->memory_.SetData32(0x8000, 0xffffffff); 484 this->memory_.SetData32(0x8000, 0xffffffff);
@@ -478,7 +523,7 @@ TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeFromPc_fde_not_found) {
478 ASSERT_EQ(nullptr, this->eh_frame_->GetFdeFromPc(0x800)); 523 ASSERT_EQ(nullptr, this->eh_frame_->GetFdeFromPc(0x800));
479} 524}
480 525
481REGISTER_TYPED_TEST_CASE_P(DwarfEhFrameWithHdrTest, Init, Init_non_zero_load_bias, 526REGISTER_TYPED_TEST_CASE_P(DwarfEhFrameWithHdrTest, Init, Init_non_zero_load_bias, GetFdes,
482 GetFdeInfoFromIndex_expect_cache_fail, GetFdeInfoFromIndex_read_pcrel, 527 GetFdeInfoFromIndex_expect_cache_fail, GetFdeInfoFromIndex_read_pcrel,
483 GetFdeInfoFromIndex_read_datarel, GetFdeInfoFromIndex_cached, 528 GetFdeInfoFromIndex_read_datarel, GetFdeInfoFromIndex_cached,
484 GetFdeOffsetBinary_verify, GetFdeOffsetBinary_index_fail, 529 GetFdeOffsetBinary_verify, GetFdeOffsetBinary_index_fail,
diff --git a/libunwindstack/tests/DwarfSectionImplTest.cpp b/libunwindstack/tests/DwarfSectionImplTest.cpp
index 414f2f248..46f555a6f 100644
--- a/libunwindstack/tests/DwarfSectionImplTest.cpp
+++ b/libunwindstack/tests/DwarfSectionImplTest.cpp
@@ -16,7 +16,6 @@
16 16
17#include <stdint.h> 17#include <stdint.h>
18 18
19#include <gmock/gmock.h>
20#include <gtest/gtest.h> 19#include <gtest/gtest.h>
21 20
22#include <unwindstack/DwarfError.h> 21#include <unwindstack/DwarfError.h>
@@ -31,42 +30,27 @@
31namespace unwindstack { 30namespace unwindstack {
32 31
33template <typename TypeParam> 32template <typename TypeParam>
34class MockDwarfSectionImpl : public DwarfSectionImpl<TypeParam> { 33class TestDwarfSectionImpl : public DwarfSectionImpl<TypeParam> {
35 public: 34 public:
36 MockDwarfSectionImpl(Memory* memory) : DwarfSectionImpl<TypeParam>(memory) {} 35 TestDwarfSectionImpl(Memory* memory) : DwarfSectionImpl<TypeParam>(memory) {}
37 virtual ~MockDwarfSectionImpl() = default; 36 virtual ~TestDwarfSectionImpl() = default;
38 37
39 MOCK_METHOD3(Init, bool(uint64_t, uint64_t, uint64_t)); 38 bool Init(uint64_t, uint64_t, uint64_t) override { return false; }
40 39
41 MOCK_METHOD2(GetFdeOffsetFromPc, bool(uint64_t, uint64_t*)); 40 void GetFdes(std::vector<const DwarfFde*>*) override {}
42 41
43 MOCK_METHOD1(GetFdeFromIndex, const DwarfFde*(size_t)); 42 const DwarfFde* GetFdeFromPc(uint64_t) override { return nullptr; }
44 43
45 MOCK_METHOD1(GetCieOffsetFromFde32, uint64_t(uint32_t)); 44 uint64_t GetCieOffsetFromFde32(uint32_t) { return 0; }
46 45
47 MOCK_METHOD1(GetCieOffsetFromFde64, uint64_t(uint64_t)); 46 uint64_t GetCieOffsetFromFde64(uint64_t) { return 0; }
48 47
49 MOCK_METHOD1(AdjustPcFromFde, uint64_t(uint64_t)); 48 uint64_t AdjustPcFromFde(uint64_t) override { return 0; }
50
51 void TestSetCie32Value(uint32_t value32) { this->cie32_value_ = value32; }
52
53 void TestSetCie64Value(uint64_t value64) { this->cie64_value_ = value64; }
54
55 void TestSetCachedCieEntry(uint64_t offset, const DwarfCie& cie) {
56 this->cie_entries_[offset] = cie;
57 }
58 void TestClearCachedCieEntry() { this->cie_entries_.clear(); }
59
60 void TestSetCachedFdeEntry(uint64_t offset, const DwarfFde& fde) {
61 this->fde_entries_[offset] = fde;
62 }
63 void TestClearCachedFdeEntry() { this->fde_entries_.clear(); }
64 49
65 void TestSetCachedCieLocRegs(uint64_t offset, const dwarf_loc_regs_t& loc_regs) { 50 void TestSetCachedCieLocRegs(uint64_t offset, const dwarf_loc_regs_t& loc_regs) {
66 this->cie_loc_regs_[offset] = loc_regs; 51 this->cie_loc_regs_[offset] = loc_regs;
67 } 52 }
68 void TestClearCachedCieLocRegs() { this->cie_loc_regs_.clear(); } 53 void TestClearCachedCieLocRegs() { this->cie_loc_regs_.clear(); }
69
70 void TestClearError() { this->last_error_.code = DWARF_ERROR_NONE; } 54 void TestClearError() { this->last_error_.code = DWARF_ERROR_NONE; }
71}; 55};
72 56
@@ -75,21 +59,41 @@ class DwarfSectionImplTest : public ::testing::Test {
75 protected: 59 protected:
76 void SetUp() override { 60 void SetUp() override {
77 memory_.Clear(); 61 memory_.Clear();
78 section_ = new MockDwarfSectionImpl<TypeParam>(&memory_); 62 section_ = new TestDwarfSectionImpl<TypeParam>(&memory_);
79 ResetLogs(); 63 ResetLogs();
80 section_->TestSetCie32Value(static_cast<uint32_t>(-1));
81 section_->TestSetCie64Value(static_cast<uint64_t>(-1));
82 } 64 }
83 65
84 void TearDown() override { delete section_; } 66 void TearDown() override { delete section_; }
85 67
86 MemoryFake memory_; 68 MemoryFake memory_;
87 MockDwarfSectionImpl<TypeParam>* section_ = nullptr; 69 TestDwarfSectionImpl<TypeParam>* section_ = nullptr;
88}; 70};
89TYPED_TEST_CASE_P(DwarfSectionImplTest); 71TYPED_TEST_CASE_P(DwarfSectionImplTest);
90 72
91// NOTE: All test class variables need to be referenced as this->. 73// NOTE: All test class variables need to be referenced as this->.
92 74
75TYPED_TEST_P(DwarfSectionImplTest, GetCieFromOffset_fail_should_not_cache) {
76 ASSERT_TRUE(this->section_->GetCieFromOffset(0x4000) == nullptr);
77 EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode());
78 EXPECT_EQ(0x4000U, this->section_->LastErrorAddress());
79
80 this->section_->TestClearError();
81 ASSERT_TRUE(this->section_->GetCieFromOffset(0x4000) == nullptr);
82 EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode());
83 EXPECT_EQ(0x4000U, this->section_->LastErrorAddress());
84}
85
86TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_fail_should_not_cache) {
87 ASSERT_TRUE(this->section_->GetFdeFromOffset(0x4000) == nullptr);
88 EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode());
89 EXPECT_EQ(0x4000U, this->section_->LastErrorAddress());
90
91 this->section_->TestClearError();
92 ASSERT_TRUE(this->section_->GetFdeFromOffset(0x4000) == nullptr);
93 EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode());
94 EXPECT_EQ(0x4000U, this->section_->LastErrorAddress());
95}
96
93TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_eval_fail) { 97TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_eval_fail) {
94 DwarfCie cie{.version = 3, .return_address_register = 5}; 98 DwarfCie cie{.version = 3, .return_address_register = 5};
95 RegsImplFake<TypeParam> regs(10); 99 RegsImplFake<TypeParam> regs(10);
@@ -487,334 +491,6 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_reg_val_expr) {
487 EXPECT_EQ(0x80000000U, regs.pc()); 491 EXPECT_EQ(0x80000000U, regs.pc());
488} 492}
489 493
490TYPED_TEST_P(DwarfSectionImplTest, GetCie_fail_should_not_cache) {
491 ASSERT_TRUE(this->section_->GetCie(0x4000) == nullptr);
492 EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode());
493 EXPECT_EQ(0x4000U, this->section_->LastErrorAddress());
494 this->section_->TestClearError();
495 ASSERT_TRUE(this->section_->GetCie(0x4000) == nullptr);
496 EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode());
497 EXPECT_EQ(0x4000U, this->section_->LastErrorAddress());
498}
499
500TYPED_TEST_P(DwarfSectionImplTest, GetCie_32_version_check) {
501 this->memory_.SetData32(0x5000, 0x100);
502 this->memory_.SetData32(0x5004, 0xffffffff);
503 this->memory_.SetData8(0x5008, 0x1);
504 this->memory_.SetData8(0x5009, '\0');
505 this->memory_.SetData8(0x500a, 4);
506 this->memory_.SetData8(0x500b, 8);
507 this->memory_.SetData8(0x500c, 0x20);
508
509 const DwarfCie* cie = this->section_->GetCie(0x5000);
510 ASSERT_TRUE(cie != nullptr);
511 EXPECT_EQ(1U, cie->version);
512 EXPECT_EQ(DW_EH_PE_sdata4, cie->fde_address_encoding);
513 EXPECT_EQ(DW_EH_PE_omit, cie->lsda_encoding);
514 EXPECT_EQ(0U, cie->segment_size);
515 EXPECT_EQ(1U, cie->augmentation_string.size());
516 EXPECT_EQ('\0', cie->augmentation_string[0]);
517 EXPECT_EQ(0U, cie->personality_handler);
518 EXPECT_EQ(0x500dU, cie->cfa_instructions_offset);
519 EXPECT_EQ(0x5104U, cie->cfa_instructions_end);
520 EXPECT_EQ(4U, cie->code_alignment_factor);
521 EXPECT_EQ(8, cie->data_alignment_factor);
522 EXPECT_EQ(0x20U, cie->return_address_register);
523 EXPECT_EQ(DWARF_ERROR_NONE, this->section_->LastErrorCode());
524
525 this->section_->TestClearCachedCieEntry();
526 // Set version to 0, 2, 5 and verify we fail.
527 this->memory_.SetData8(0x5008, 0x0);
528 this->section_->TestClearError();
529 ASSERT_TRUE(this->section_->GetCie(0x5000) == nullptr);
530 EXPECT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->section_->LastErrorCode());
531
532 this->memory_.SetData8(0x5008, 0x2);
533 this->section_->TestClearError();
534 ASSERT_TRUE(this->section_->GetCie(0x5000) == nullptr);
535 EXPECT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->section_->LastErrorCode());
536
537 this->memory_.SetData8(0x5008, 0x5);
538 this->section_->TestClearError();
539 ASSERT_TRUE(this->section_->GetCie(0x5000) == nullptr);
540 EXPECT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->section_->LastErrorCode());
541}
542
543TYPED_TEST_P(DwarfSectionImplTest, GetCie_negative_data_alignment_factor) {
544 this->memory_.SetData32(0x5000, 0x100);
545 this->memory_.SetData32(0x5004, 0xffffffff);
546 this->memory_.SetData8(0x5008, 0x1);
547 this->memory_.SetData8(0x5009, '\0');
548 this->memory_.SetData8(0x500a, 4);
549 this->memory_.SetMemory(0x500b, std::vector<uint8_t>{0xfc, 0xff, 0xff, 0xff, 0x7f});
550 this->memory_.SetData8(0x5010, 0x20);
551
552 const DwarfCie* cie = this->section_->GetCie(0x5000);
553 ASSERT_TRUE(cie != nullptr);
554 EXPECT_EQ(1U, cie->version);
555 EXPECT_EQ(DW_EH_PE_sdata4, cie->fde_address_encoding);
556 EXPECT_EQ(DW_EH_PE_omit, cie->lsda_encoding);
557 EXPECT_EQ(0U, cie->segment_size);
558 EXPECT_EQ(1U, cie->augmentation_string.size());
559 EXPECT_EQ('\0', cie->augmentation_string[0]);
560 EXPECT_EQ(0U, cie->personality_handler);
561 EXPECT_EQ(0x5011U, cie->cfa_instructions_offset);
562 EXPECT_EQ(0x5104U, cie->cfa_instructions_end);
563 EXPECT_EQ(4U, cie->code_alignment_factor);
564 EXPECT_EQ(-4, cie->data_alignment_factor);
565 EXPECT_EQ(0x20U, cie->return_address_register);
566}
567
568TYPED_TEST_P(DwarfSectionImplTest, GetCie_64_no_augment) {
569 this->memory_.SetData32(0x8000, 0xffffffff);
570 this->memory_.SetData64(0x8004, 0x200);
571 this->memory_.SetData64(0x800c, 0xffffffffffffffffULL);
572 this->memory_.SetData8(0x8014, 0x1);
573 this->memory_.SetData8(0x8015, '\0');
574 this->memory_.SetData8(0x8016, 4);
575 this->memory_.SetData8(0x8017, 8);
576 this->memory_.SetData8(0x8018, 0x20);
577
578 const DwarfCie* cie = this->section_->GetCie(0x8000);
579 ASSERT_TRUE(cie != nullptr);
580 EXPECT_EQ(1U, cie->version);
581 EXPECT_EQ(DW_EH_PE_sdata8, cie->fde_address_encoding);
582 EXPECT_EQ(DW_EH_PE_omit, cie->lsda_encoding);
583 EXPECT_EQ(0U, cie->segment_size);
584 EXPECT_EQ(1U, cie->augmentation_string.size());
585 EXPECT_EQ('\0', cie->augmentation_string[0]);
586 EXPECT_EQ(0U, cie->personality_handler);
587 EXPECT_EQ(0x8019U, cie->cfa_instructions_offset);
588 EXPECT_EQ(0x820cU, cie->cfa_instructions_end);
589 EXPECT_EQ(4U, cie->code_alignment_factor);
590 EXPECT_EQ(8, cie->data_alignment_factor);
591 EXPECT_EQ(0x20U, cie->return_address_register);
592}
593
594TYPED_TEST_P(DwarfSectionImplTest, GetCie_augment) {
595 this->memory_.SetData32(0x5000, 0x100);
596 this->memory_.SetData32(0x5004, 0xffffffff);
597 this->memory_.SetData8(0x5008, 0x1);
598 this->memory_.SetMemory(0x5009, std::vector<uint8_t>{'z', 'L', 'P', 'R', '\0'});
599 this->memory_.SetData8(0x500e, 4);
600 this->memory_.SetData8(0x500f, 8);
601 this->memory_.SetData8(0x5010, 0x10);
602 // Augment length.
603 this->memory_.SetData8(0x5011, 0xf);
604 // L data.
605 this->memory_.SetData8(0x5012, DW_EH_PE_textrel | DW_EH_PE_udata2);
606 // P data.
607 this->memory_.SetData8(0x5013, DW_EH_PE_udata4);
608 this->memory_.SetData32(0x5014, 0x12345678);
609 // R data.
610 this->memory_.SetData8(0x5018, DW_EH_PE_udata2);
611
612 const DwarfCie* cie = this->section_->GetCie(0x5000);
613 ASSERT_TRUE(cie != nullptr);
614 EXPECT_EQ(1U, cie->version);
615 EXPECT_EQ(DW_EH_PE_udata2, cie->fde_address_encoding);
616 EXPECT_EQ(DW_EH_PE_textrel | DW_EH_PE_udata2, cie->lsda_encoding);
617 EXPECT_EQ(0U, cie->segment_size);
618 EXPECT_EQ(5U, cie->augmentation_string.size());
619 EXPECT_EQ('z', cie->augmentation_string[0]);
620 EXPECT_EQ('L', cie->augmentation_string[1]);
621 EXPECT_EQ('P', cie->augmentation_string[2]);
622 EXPECT_EQ('R', cie->augmentation_string[3]);
623 EXPECT_EQ('\0', cie->augmentation_string[4]);
624 EXPECT_EQ(0x12345678U, cie->personality_handler);
625 EXPECT_EQ(0x5021U, cie->cfa_instructions_offset);
626 EXPECT_EQ(0x5104U, cie->cfa_instructions_end);
627 EXPECT_EQ(4U, cie->code_alignment_factor);
628 EXPECT_EQ(8, cie->data_alignment_factor);
629 EXPECT_EQ(0x10U, cie->return_address_register);
630}
631
632TYPED_TEST_P(DwarfSectionImplTest, GetCie_version_3) {
633 this->memory_.SetData32(0x5000, 0x100);
634 this->memory_.SetData32(0x5004, 0xffffffff);
635 this->memory_.SetData8(0x5008, 0x3);
636 this->memory_.SetData8(0x5009, '\0');
637 this->memory_.SetData8(0x500a, 4);
638 this->memory_.SetData8(0x500b, 8);
639 this->memory_.SetMemory(0x500c, std::vector<uint8_t>{0x81, 0x03});
640
641 const DwarfCie* cie = this->section_->GetCie(0x5000);
642 ASSERT_TRUE(cie != nullptr);
643 EXPECT_EQ(3U, cie->version);
644 EXPECT_EQ(DW_EH_PE_sdata4, cie->fde_address_encoding);
645 EXPECT_EQ(DW_EH_PE_omit, cie->lsda_encoding);
646 EXPECT_EQ(0U, cie->segment_size);
647 EXPECT_EQ(1U, cie->augmentation_string.size());
648 EXPECT_EQ('\0', cie->augmentation_string[0]);
649 EXPECT_EQ(0U, cie->personality_handler);
650 EXPECT_EQ(0x500eU, cie->cfa_instructions_offset);
651 EXPECT_EQ(0x5104U, cie->cfa_instructions_end);
652 EXPECT_EQ(4U, cie->code_alignment_factor);
653 EXPECT_EQ(8, cie->data_alignment_factor);
654 EXPECT_EQ(0x181U, cie->return_address_register);
655}
656
657TYPED_TEST_P(DwarfSectionImplTest, GetCie_version_4) {
658 this->memory_.SetData32(0x5000, 0x100);
659 this->memory_.SetData32(0x5004, 0xffffffff);
660 this->memory_.SetData8(0x5008, 0x4);
661 this->memory_.SetData8(0x5009, '\0');
662 this->memory_.SetData8(0x500a, 4);
663 this->memory_.SetData8(0x500b, 0x13);
664 this->memory_.SetData8(0x500c, 4);
665 this->memory_.SetData8(0x500d, 8);
666 this->memory_.SetMemory(0x500e, std::vector<uint8_t>{0x81, 0x03});
667
668 const DwarfCie* cie = this->section_->GetCie(0x5000);
669 ASSERT_TRUE(cie != nullptr);
670 EXPECT_EQ(4U, cie->version);
671 EXPECT_EQ(DW_EH_PE_sdata4, cie->fde_address_encoding);
672 EXPECT_EQ(DW_EH_PE_omit, cie->lsda_encoding);
673 EXPECT_EQ(0x13U, cie->segment_size);
674 EXPECT_EQ(1U, cie->augmentation_string.size());
675 EXPECT_EQ('\0', cie->augmentation_string[0]);
676 EXPECT_EQ(0U, cie->personality_handler);
677 EXPECT_EQ(0x5010U, cie->cfa_instructions_offset);
678 EXPECT_EQ(0x5104U, cie->cfa_instructions_end);
679 EXPECT_EQ(4U, cie->code_alignment_factor);
680 EXPECT_EQ(8, cie->data_alignment_factor);
681 EXPECT_EQ(0x181U, cie->return_address_register);
682}
683
684TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_fail_should_not_cache) {
685 ASSERT_TRUE(this->section_->GetFdeFromOffset(0x4000) == nullptr);
686 EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode());
687 EXPECT_EQ(0x4000U, this->section_->LastErrorAddress());
688 this->section_->TestClearError();
689 ASSERT_TRUE(this->section_->GetFdeFromOffset(0x4000) == nullptr);
690 EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode());
691 EXPECT_EQ(0x4000U, this->section_->LastErrorAddress());
692}
693
694TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_32_no_augment) {
695 this->memory_.SetData32(0x4000, 0x20);
696 this->memory_.SetData32(0x4004, 0x8000);
697 this->memory_.SetData32(0x4008, 0x5000);
698 this->memory_.SetData32(0x400c, 0x100);
699
700 EXPECT_CALL(*this->section_, GetCieOffsetFromFde32(0x8000)).WillOnce(::testing::Return(0x8000));
701 DwarfCie cie{};
702 cie.fde_address_encoding = DW_EH_PE_udata4;
703 this->section_->TestSetCachedCieEntry(0x8000, cie);
704 EXPECT_CALL(*this->section_, AdjustPcFromFde(0x5000)).WillOnce(::testing::Return(0x5000));
705
706 const DwarfFde* fde = this->section_->GetFdeFromOffset(0x4000);
707 ASSERT_TRUE(fde != nullptr);
708 ASSERT_TRUE(fde->cie != nullptr);
709 EXPECT_EQ(0x4010U, fde->cfa_instructions_offset);
710 EXPECT_EQ(0x4024U, fde->cfa_instructions_end);
711 EXPECT_EQ(0x5000U, fde->pc_start);
712 EXPECT_EQ(0x5100U, fde->pc_end);
713 EXPECT_EQ(0x8000U, fde->cie_offset);
714 EXPECT_EQ(0U, fde->lsda_address);
715}
716
717TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_32_no_augment_non_zero_segment_size) {
718 this->memory_.SetData32(0x4000, 0x30);
719 this->memory_.SetData32(0x4004, 0x8000);
720 this->memory_.SetData32(0x4018, 0x5000);
721 this->memory_.SetData32(0x401c, 0x100);
722
723 EXPECT_CALL(*this->section_, GetCieOffsetFromFde32(0x8000)).WillOnce(::testing::Return(0x8000));
724 DwarfCie cie{};
725 cie.fde_address_encoding = DW_EH_PE_udata4;
726 cie.segment_size = 0x10;
727 this->section_->TestSetCachedCieEntry(0x8000, cie);
728 EXPECT_CALL(*this->section_, AdjustPcFromFde(0x5000)).WillOnce(::testing::Return(0x5000));
729
730 const DwarfFde* fde = this->section_->GetFdeFromOffset(0x4000);
731 ASSERT_TRUE(fde != nullptr);
732 ASSERT_TRUE(fde->cie != nullptr);
733 EXPECT_EQ(0x4020U, fde->cfa_instructions_offset);
734 EXPECT_EQ(0x4034U, fde->cfa_instructions_end);
735 EXPECT_EQ(0x5000U, fde->pc_start);
736 EXPECT_EQ(0x5100U, fde->pc_end);
737 EXPECT_EQ(0x8000U, fde->cie_offset);
738 EXPECT_EQ(0U, fde->lsda_address);
739}
740
741TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_32_augment) {
742 this->memory_.SetData32(0x4000, 0x100);
743 this->memory_.SetData32(0x4004, 0x8000);
744 this->memory_.SetData32(0x4008, 0x5000);
745 this->memory_.SetData32(0x400c, 0x100);
746 this->memory_.SetMemory(0x4010, std::vector<uint8_t>{0x82, 0x01});
747 this->memory_.SetData16(0x4012, 0x1234);
748
749 EXPECT_CALL(*this->section_, GetCieOffsetFromFde32(0x8000)).WillOnce(::testing::Return(0x8000));
750 DwarfCie cie{};
751 cie.fde_address_encoding = DW_EH_PE_udata4;
752 cie.augmentation_string.push_back('z');
753 cie.lsda_encoding = DW_EH_PE_udata2;
754 this->section_->TestSetCachedCieEntry(0x8000, cie);
755 EXPECT_CALL(*this->section_, AdjustPcFromFde(0x5000)).WillOnce(::testing::Return(0x5000));
756
757 const DwarfFde* fde = this->section_->GetFdeFromOffset(0x4000);
758 ASSERT_TRUE(fde != nullptr);
759 ASSERT_TRUE(fde->cie != nullptr);
760 EXPECT_EQ(0x4094U, fde->cfa_instructions_offset);
761 EXPECT_EQ(0x4104U, fde->cfa_instructions_end);
762 EXPECT_EQ(0x5000U, fde->pc_start);
763 EXPECT_EQ(0x5100U, fde->pc_end);
764 EXPECT_EQ(0x8000U, fde->cie_offset);
765 EXPECT_EQ(0x1234U, fde->lsda_address);
766}
767
768TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_64_no_augment) {
769 this->memory_.SetData32(0x4000, 0xffffffff);
770 this->memory_.SetData64(0x4004, 0x100);
771 this->memory_.SetData64(0x400c, 0x12345678);
772 this->memory_.SetData32(0x4014, 0x5000);
773 this->memory_.SetData32(0x4018, 0x100);
774
775 EXPECT_CALL(*this->section_, GetCieOffsetFromFde64(0x12345678))
776 .WillOnce(::testing::Return(0x12345678));
777 DwarfCie cie{};
778 cie.fde_address_encoding = DW_EH_PE_udata4;
779 this->section_->TestSetCachedCieEntry(0x12345678, cie);
780 EXPECT_CALL(*this->section_, AdjustPcFromFde(0x5000)).WillOnce(::testing::Return(0x5000));
781
782 const DwarfFde* fde = this->section_->GetFdeFromOffset(0x4000);
783 ASSERT_TRUE(fde != nullptr);
784 ASSERT_TRUE(fde->cie != nullptr);
785 EXPECT_EQ(0x401cU, fde->cfa_instructions_offset);
786 EXPECT_EQ(0x410cU, fde->cfa_instructions_end);
787 EXPECT_EQ(0x5000U, fde->pc_start);
788 EXPECT_EQ(0x5100U, fde->pc_end);
789 EXPECT_EQ(0x12345678U, fde->cie_offset);
790 EXPECT_EQ(0U, fde->lsda_address);
791}
792
793TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_cached) {
794 DwarfCie cie{};
795 cie.fde_address_encoding = DW_EH_PE_udata4;
796 cie.augmentation_string.push_back('z');
797 cie.lsda_encoding = DW_EH_PE_udata2;
798
799 DwarfFde fde_cached{};
800 fde_cached.cfa_instructions_offset = 0x1000;
801 fde_cached.cfa_instructions_end = 0x1100;
802 fde_cached.pc_start = 0x9000;
803 fde_cached.pc_end = 0x9400;
804 fde_cached.cie_offset = 0x30000;
805 fde_cached.cie = &cie;
806 this->section_->TestSetCachedFdeEntry(0x6000, fde_cached);
807
808 const DwarfFde* fde = this->section_->GetFdeFromOffset(0x6000);
809 ASSERT_TRUE(fde != nullptr);
810 ASSERT_EQ(&cie, fde->cie);
811 EXPECT_EQ(0x1000U, fde->cfa_instructions_offset);
812 EXPECT_EQ(0x1100U, fde->cfa_instructions_end);
813 EXPECT_EQ(0x9000U, fde->pc_start);
814 EXPECT_EQ(0x9400U, fde->pc_end);
815 EXPECT_EQ(0x30000U, fde->cie_offset);
816}
817
818TYPED_TEST_P(DwarfSectionImplTest, GetCfaLocationInfo_cie_not_cached) { 494TYPED_TEST_P(DwarfSectionImplTest, GetCfaLocationInfo_cie_not_cached) {
819 DwarfCie cie{}; 495 DwarfCie cie{};
820 cie.cfa_instructions_offset = 0x3000; 496 cie.cfa_instructions_offset = 0x3000;
@@ -895,18 +571,16 @@ TYPED_TEST_P(DwarfSectionImplTest, Log) {
895 ASSERT_EQ("", GetFakeLogBuf()); 571 ASSERT_EQ("", GetFakeLogBuf());
896} 572}
897 573
898REGISTER_TYPED_TEST_CASE_P( 574REGISTER_TYPED_TEST_CASE_P(DwarfSectionImplTest, GetCieFromOffset_fail_should_not_cache,
899 DwarfSectionImplTest, Eval_cfa_expr_eval_fail, Eval_cfa_expr_no_stack, 575 GetFdeFromOffset_fail_should_not_cache, Eval_cfa_expr_eval_fail,
900 Eval_cfa_expr_is_register, Eval_cfa_expr, Eval_cfa_val_expr, Eval_bad_regs, Eval_no_cfa, 576 Eval_cfa_expr_no_stack, Eval_cfa_expr_is_register, Eval_cfa_expr,
901 Eval_cfa_bad, Eval_cfa_register_prev, Eval_cfa_register_from_value, Eval_double_indirection, 577 Eval_cfa_val_expr, Eval_bad_regs, Eval_no_cfa, Eval_cfa_bad,
902 Eval_register_reference_chain, Eval_dex_pc, Eval_invalid_register, Eval_different_reg_locations, 578 Eval_cfa_register_prev, Eval_cfa_register_from_value,
903 Eval_return_address_undefined, Eval_pc_zero, Eval_return_address, Eval_ignore_large_reg_loc, 579 Eval_double_indirection, Eval_register_reference_chain, Eval_dex_pc,
904 Eval_reg_expr, Eval_reg_val_expr, GetCie_fail_should_not_cache, GetCie_32_version_check, 580 Eval_invalid_register, Eval_different_reg_locations,
905 GetCie_negative_data_alignment_factor, GetCie_64_no_augment, GetCie_augment, GetCie_version_3, 581 Eval_return_address_undefined, Eval_pc_zero, Eval_return_address,
906 GetCie_version_4, GetFdeFromOffset_fail_should_not_cache, GetFdeFromOffset_32_no_augment, 582 Eval_ignore_large_reg_loc, Eval_reg_expr, Eval_reg_val_expr,
907 GetFdeFromOffset_32_no_augment_non_zero_segment_size, GetFdeFromOffset_32_augment, 583 GetCfaLocationInfo_cie_not_cached, GetCfaLocationInfo_cie_cached, Log);
908 GetFdeFromOffset_64_no_augment, GetFdeFromOffset_cached, GetCfaLocationInfo_cie_not_cached,
909 GetCfaLocationInfo_cie_cached, Log);
910 584
911typedef ::testing::Types<uint32_t, uint64_t> DwarfSectionImplTestTypes; 585typedef ::testing::Types<uint32_t, uint64_t> DwarfSectionImplTestTypes;
912INSTANTIATE_TYPED_TEST_CASE_P(, DwarfSectionImplTest, DwarfSectionImplTestTypes); 586INSTANTIATE_TYPED_TEST_CASE_P(, DwarfSectionImplTest, DwarfSectionImplTestTypes);
diff --git a/libunwindstack/tests/DwarfSectionTest.cpp b/libunwindstack/tests/DwarfSectionTest.cpp
index 2c6c8790a..d754fcc50 100644
--- a/libunwindstack/tests/DwarfSectionTest.cpp
+++ b/libunwindstack/tests/DwarfSectionTest.cpp
@@ -30,23 +30,17 @@ class MockDwarfSection : public DwarfSection {
30 MockDwarfSection(Memory* memory) : DwarfSection(memory) {} 30 MockDwarfSection(Memory* memory) : DwarfSection(memory) {}
31 virtual ~MockDwarfSection() = default; 31 virtual ~MockDwarfSection() = default;
32 32
33 MOCK_METHOD3(Log, bool(uint8_t, uint64_t, const DwarfFde*));
34
35 MOCK_METHOD5(Eval, bool(const DwarfCie*, Memory*, const dwarf_loc_regs_t&, Regs*, bool*));
36
37 MOCK_METHOD3(GetCfaLocationInfo, bool(uint64_t, const DwarfFde*, dwarf_loc_regs_t*));
38
39 MOCK_METHOD3(Init, bool(uint64_t, uint64_t, uint64_t)); 33 MOCK_METHOD3(Init, bool(uint64_t, uint64_t, uint64_t));
40 34
41 MOCK_METHOD2(GetFdeOffsetFromPc, bool(uint64_t, uint64_t*)); 35 MOCK_METHOD5(Eval, bool(const DwarfCie*, Memory*, const dwarf_loc_regs_t&, Regs*, bool*));
42 36
43 MOCK_METHOD1(GetFdeFromOffset, const DwarfFde*(uint64_t)); 37 MOCK_METHOD3(Log, bool(uint8_t, uint64_t, const DwarfFde*));
44 38
45 MOCK_METHOD1(GetFdeFromIndex, const DwarfFde*(size_t)); 39 MOCK_METHOD1(GetFdes, void(std::vector<const DwarfFde*>*));
46 40
47 MOCK_METHOD1(IsCie32, bool(uint32_t)); 41 MOCK_METHOD1(GetFdeFromPc, const DwarfFde*(uint64_t));
48 42
49 MOCK_METHOD1(IsCie64, bool(uint64_t)); 43 MOCK_METHOD3(GetCfaLocationInfo, bool(uint64_t, const DwarfFde*, dwarf_loc_regs_t*));
50 44
51 MOCK_METHOD1(GetCieOffsetFromFde32, uint64_t(uint32_t)); 45 MOCK_METHOD1(GetCieOffsetFromFde32, uint64_t(uint32_t));
52 46
@@ -57,112 +51,60 @@ class MockDwarfSection : public DwarfSection {
57 51
58class DwarfSectionTest : public ::testing::Test { 52class DwarfSectionTest : public ::testing::Test {
59 protected: 53 protected:
54 void SetUp() override { section_.reset(new MockDwarfSection(&memory_)); }
55
60 MemoryFake memory_; 56 MemoryFake memory_;
57 std::unique_ptr<MockDwarfSection> section_;
61}; 58};
62 59
63TEST_F(DwarfSectionTest, GetFdeOffsetFromPc_fail_from_pc) {
64 MockDwarfSection mock_section(&memory_);
65
66 EXPECT_CALL(mock_section, GetFdeOffsetFromPc(0x1000, ::testing::_))
67 .WillOnce(::testing::Return(false));
68
69 // Verify nullptr when GetFdeOffsetFromPc fails.
70 ASSERT_TRUE(mock_section.GetFdeFromPc(0x1000) == nullptr);
71}
72
73TEST_F(DwarfSectionTest, GetFdeOffsetFromPc_fail_fde_pc_end) {
74 MockDwarfSection mock_section(&memory_);
75
76 DwarfFde fde{};
77 fde.pc_end = 0x500;
78
79 EXPECT_CALL(mock_section, GetFdeOffsetFromPc(0x1000, ::testing::_))
80 .WillOnce(::testing::Return(true));
81 EXPECT_CALL(mock_section, GetFdeFromOffset(::testing::_)).WillOnce(::testing::Return(&fde));
82
83 // Verify nullptr when GetFdeOffsetFromPc fails.
84 ASSERT_TRUE(mock_section.GetFdeFromPc(0x1000) == nullptr);
85}
86
87TEST_F(DwarfSectionTest, GetFdeOffsetFromPc_pass) {
88 MockDwarfSection mock_section(&memory_);
89
90 DwarfFde fde{};
91 fde.pc_end = 0x2000;
92
93 EXPECT_CALL(mock_section, GetFdeOffsetFromPc(0x1000, ::testing::_))
94 .WillOnce(::testing::Return(true));
95 EXPECT_CALL(mock_section, GetFdeFromOffset(::testing::_)).WillOnce(::testing::Return(&fde));
96
97 // Verify nullptr when GetFdeOffsetFromPc fails.
98 ASSERT_EQ(&fde, mock_section.GetFdeFromPc(0x1000));
99}
100
101TEST_F(DwarfSectionTest, Step_fail_fde) { 60TEST_F(DwarfSectionTest, Step_fail_fde) {
102 MockDwarfSection mock_section(&memory_); 61 EXPECT_CALL(*section_, GetFdeFromPc(0x1000)).WillOnce(::testing::Return(nullptr));
103
104 EXPECT_CALL(mock_section, GetFdeOffsetFromPc(0x1000, ::testing::_))
105 .WillOnce(::testing::Return(false));
106 62
107 bool finished; 63 bool finished;
108 ASSERT_FALSE(mock_section.Step(0x1000, nullptr, nullptr, &finished)); 64 ASSERT_FALSE(section_->Step(0x1000, nullptr, nullptr, &finished));
109} 65}
110 66
111TEST_F(DwarfSectionTest, Step_fail_cie_null) { 67TEST_F(DwarfSectionTest, Step_fail_cie_null) {
112 MockDwarfSection mock_section(&memory_);
113
114 DwarfFde fde{}; 68 DwarfFde fde{};
115 fde.pc_end = 0x2000; 69 fde.pc_end = 0x2000;
116 fde.cie = nullptr; 70 fde.cie = nullptr;
117 71
118 EXPECT_CALL(mock_section, GetFdeOffsetFromPc(0x1000, ::testing::_)) 72 EXPECT_CALL(*section_, GetFdeFromPc(0x1000)).WillOnce(::testing::Return(&fde));
119 .WillOnce(::testing::Return(true));
120 EXPECT_CALL(mock_section, GetFdeFromOffset(::testing::_)).WillOnce(::testing::Return(&fde));
121 73
122 bool finished; 74 bool finished;
123 ASSERT_FALSE(mock_section.Step(0x1000, nullptr, nullptr, &finished)); 75 ASSERT_FALSE(section_->Step(0x1000, nullptr, nullptr, &finished));
124} 76}
125 77
126TEST_F(DwarfSectionTest, Step_fail_cfa_location) { 78TEST_F(DwarfSectionTest, Step_fail_cfa_location) {
127 MockDwarfSection mock_section(&memory_);
128
129 DwarfCie cie{}; 79 DwarfCie cie{};
130 DwarfFde fde{}; 80 DwarfFde fde{};
131 fde.pc_end = 0x2000; 81 fde.pc_end = 0x2000;
132 fde.cie = &cie; 82 fde.cie = &cie;
133 83
134 EXPECT_CALL(mock_section, GetFdeOffsetFromPc(0x1000, ::testing::_)) 84 EXPECT_CALL(*section_, GetFdeFromPc(0x1000)).WillOnce(::testing::Return(&fde));
135 .WillOnce(::testing::Return(true)); 85 EXPECT_CALL(*section_, GetCfaLocationInfo(0x1000, &fde, ::testing::_))
136 EXPECT_CALL(mock_section, GetFdeFromOffset(::testing::_)).WillOnce(::testing::Return(&fde));
137
138 EXPECT_CALL(mock_section, GetCfaLocationInfo(0x1000, &fde, ::testing::_))
139 .WillOnce(::testing::Return(false)); 86 .WillOnce(::testing::Return(false));
140 87
141 bool finished; 88 bool finished;
142 ASSERT_FALSE(mock_section.Step(0x1000, nullptr, nullptr, &finished)); 89 ASSERT_FALSE(section_->Step(0x1000, nullptr, nullptr, &finished));
143} 90}
144 91
145TEST_F(DwarfSectionTest, Step_pass) { 92TEST_F(DwarfSectionTest, Step_pass) {
146 MockDwarfSection mock_section(&memory_);
147
148 DwarfCie cie{}; 93 DwarfCie cie{};
149 DwarfFde fde{}; 94 DwarfFde fde{};
150 fde.pc_end = 0x2000; 95 fde.pc_end = 0x2000;
151 fde.cie = &cie; 96 fde.cie = &cie;
152 97
153 EXPECT_CALL(mock_section, GetFdeOffsetFromPc(0x1000, ::testing::_)) 98 EXPECT_CALL(*section_, GetFdeFromPc(0x1000)).WillOnce(::testing::Return(&fde));
154 .WillOnce(::testing::Return(true)); 99 EXPECT_CALL(*section_, GetCfaLocationInfo(0x1000, &fde, ::testing::_))
155 EXPECT_CALL(mock_section, GetFdeFromOffset(::testing::_)).WillOnce(::testing::Return(&fde));
156
157 EXPECT_CALL(mock_section, GetCfaLocationInfo(0x1000, &fde, ::testing::_))
158 .WillOnce(::testing::Return(true)); 100 .WillOnce(::testing::Return(true));
159 101
160 MemoryFake process; 102 MemoryFake process;
161 EXPECT_CALL(mock_section, Eval(&cie, &process, ::testing::_, nullptr, ::testing::_)) 103 EXPECT_CALL(*section_, Eval(&cie, &process, ::testing::_, nullptr, ::testing::_))
162 .WillOnce(::testing::Return(true)); 104 .WillOnce(::testing::Return(true));
163 105
164 bool finished; 106 bool finished;
165 ASSERT_TRUE(mock_section.Step(0x1000, nullptr, &process, &finished)); 107 ASSERT_TRUE(section_->Step(0x1000, nullptr, &process, &finished));
166} 108}
167 109
168static bool MockGetCfaLocationInfo(::testing::Unused, const DwarfFde* fde, 110static bool MockGetCfaLocationInfo(::testing::Unused, const DwarfFde* fde,
@@ -173,64 +115,53 @@ static bool MockGetCfaLocationInfo(::testing::Unused, const DwarfFde* fde,
173} 115}
174 116
175TEST_F(DwarfSectionTest, Step_cache) { 117TEST_F(DwarfSectionTest, Step_cache) {
176 MockDwarfSection mock_section(&memory_);
177
178 DwarfCie cie{}; 118 DwarfCie cie{};
179 DwarfFde fde{}; 119 DwarfFde fde{};
180 fde.pc_start = 0x500; 120 fde.pc_start = 0x500;
181 fde.pc_end = 0x2000; 121 fde.pc_end = 0x2000;
182 fde.cie = &cie; 122 fde.cie = &cie;
183 123
184 EXPECT_CALL(mock_section, GetFdeOffsetFromPc(0x1000, ::testing::_)) 124 EXPECT_CALL(*section_, GetFdeFromPc(0x1000)).WillOnce(::testing::Return(&fde));
185 .WillOnce(::testing::Return(true)); 125 EXPECT_CALL(*section_, GetCfaLocationInfo(0x1000, &fde, ::testing::_))
186 EXPECT_CALL(mock_section, GetFdeFromOffset(::testing::_)).WillOnce(::testing::Return(&fde));
187
188 EXPECT_CALL(mock_section, GetCfaLocationInfo(0x1000, &fde, ::testing::_))
189 .WillOnce(::testing::Invoke(MockGetCfaLocationInfo)); 126 .WillOnce(::testing::Invoke(MockGetCfaLocationInfo));
190 127
191 MemoryFake process; 128 MemoryFake process;
192 EXPECT_CALL(mock_section, Eval(&cie, &process, ::testing::_, nullptr, ::testing::_)) 129 EXPECT_CALL(*section_, Eval(&cie, &process, ::testing::_, nullptr, ::testing::_))
193 .WillRepeatedly(::testing::Return(true)); 130 .WillRepeatedly(::testing::Return(true));
194 131
195 bool finished; 132 bool finished;
196 ASSERT_TRUE(mock_section.Step(0x1000, nullptr, &process, &finished)); 133 ASSERT_TRUE(section_->Step(0x1000, nullptr, &process, &finished));
197 ASSERT_TRUE(mock_section.Step(0x1000, nullptr, &process, &finished)); 134 ASSERT_TRUE(section_->Step(0x1000, nullptr, &process, &finished));
198 ASSERT_TRUE(mock_section.Step(0x1500, nullptr, &process, &finished)); 135 ASSERT_TRUE(section_->Step(0x1500, nullptr, &process, &finished));
199} 136}
200 137
201TEST_F(DwarfSectionTest, Step_cache_not_in_pc) { 138TEST_F(DwarfSectionTest, Step_cache_not_in_pc) {
202 MockDwarfSection mock_section(&memory_);
203
204 DwarfCie cie{}; 139 DwarfCie cie{};
205 DwarfFde fde0{}; 140 DwarfFde fde0{};
206 fde0.pc_start = 0x1000; 141 fde0.pc_start = 0x1000;
207 fde0.pc_end = 0x2000; 142 fde0.pc_end = 0x2000;
208 fde0.cie = &cie; 143 fde0.cie = &cie;
209 EXPECT_CALL(mock_section, GetFdeOffsetFromPc(0x1000, ::testing::_)) 144 EXPECT_CALL(*section_, GetFdeFromPc(0x1000)).WillOnce(::testing::Return(&fde0));
210 .WillOnce(::testing::Return(true)); 145 EXPECT_CALL(*section_, GetCfaLocationInfo(0x1000, &fde0, ::testing::_))
211 EXPECT_CALL(mock_section, GetFdeFromOffset(::testing::_)).WillOnce(::testing::Return(&fde0));
212 EXPECT_CALL(mock_section, GetCfaLocationInfo(0x1000, &fde0, ::testing::_))
213 .WillOnce(::testing::Invoke(MockGetCfaLocationInfo)); 146 .WillOnce(::testing::Invoke(MockGetCfaLocationInfo));
214 147
215 MemoryFake process; 148 MemoryFake process;
216 EXPECT_CALL(mock_section, Eval(&cie, &process, ::testing::_, nullptr, ::testing::_)) 149 EXPECT_CALL(*section_, Eval(&cie, &process, ::testing::_, nullptr, ::testing::_))
217 .WillRepeatedly(::testing::Return(true)); 150 .WillRepeatedly(::testing::Return(true));
218 151
219 bool finished; 152 bool finished;
220 ASSERT_TRUE(mock_section.Step(0x1000, nullptr, &process, &finished)); 153 ASSERT_TRUE(section_->Step(0x1000, nullptr, &process, &finished));
221 154
222 DwarfFde fde1{}; 155 DwarfFde fde1{};
223 fde1.pc_start = 0x500; 156 fde1.pc_start = 0x500;
224 fde1.pc_end = 0x800; 157 fde1.pc_end = 0x800;
225 fde1.cie = &cie; 158 fde1.cie = &cie;
226 EXPECT_CALL(mock_section, GetFdeOffsetFromPc(0x600, ::testing::_)) 159 EXPECT_CALL(*section_, GetFdeFromPc(0x600)).WillOnce(::testing::Return(&fde1));
227 .WillOnce(::testing::Return(true)); 160 EXPECT_CALL(*section_, GetCfaLocationInfo(0x600, &fde1, ::testing::_))
228 EXPECT_CALL(mock_section, GetFdeFromOffset(::testing::_)).WillOnce(::testing::Return(&fde1));
229 EXPECT_CALL(mock_section, GetCfaLocationInfo(0x600, &fde1, ::testing::_))
230 .WillOnce(::testing::Invoke(MockGetCfaLocationInfo)); 161 .WillOnce(::testing::Invoke(MockGetCfaLocationInfo));
231 162
232 ASSERT_TRUE(mock_section.Step(0x600, nullptr, &process, &finished)); 163 ASSERT_TRUE(section_->Step(0x600, nullptr, &process, &finished));
233 ASSERT_TRUE(mock_section.Step(0x700, nullptr, &process, &finished)); 164 ASSERT_TRUE(section_->Step(0x700, nullptr, &process, &finished));
234} 165}
235 166
236} // namespace unwindstack 167} // namespace unwindstack
diff --git a/libunwindstack/tests/ElfInterfaceTest.cpp b/libunwindstack/tests/ElfInterfaceTest.cpp
index 487d39c87..aa6df8412 100644
--- a/libunwindstack/tests/ElfInterfaceTest.cpp
+++ b/libunwindstack/tests/ElfInterfaceTest.cpp
@@ -656,8 +656,7 @@ void ElfInterfaceTest::InitHeadersDebugFrame() {
656 656
657 memory_.SetData32(0x5000, 0xfc); 657 memory_.SetData32(0x5000, 0xfc);
658 memory_.SetData32(0x5004, 0xffffffff); 658 memory_.SetData32(0x5004, 0xffffffff);
659 memory_.SetData8(0x5008, 1); 659 memory_.SetMemory(0x5008, std::vector<uint8_t>{1, '\0', 4, 8, 2});
660 memory_.SetData8(0x5009, '\0');
661 660
662 memory_.SetData32(0x5100, 0xfc); 661 memory_.SetData32(0x5100, 0xfc);
663 memory_.SetData32(0x5104, 0); 662 memory_.SetData32(0x5104, 0);
@@ -678,56 +677,6 @@ TEST_F(ElfInterfaceTest, init_headers_debug_frame64) {
678 InitHeadersDebugFrame<ElfInterface64Fake>(); 677 InitHeadersDebugFrame<ElfInterface64Fake>();
679} 678}
680 679
681template <typename ElfType>
682void ElfInterfaceTest::InitHeadersEhFrameFail() {
683 ElfType elf(&memory_);
684
685 elf.FakeSetEhFrameOffset(0x1000);
686 elf.FakeSetEhFrameSize(0x100);
687 elf.FakeSetDebugFrameOffset(0);
688 elf.FakeSetDebugFrameSize(0);
689
690 elf.InitHeaders(0);
691
692 EXPECT_TRUE(elf.eh_frame() == nullptr);
693 EXPECT_EQ(0U, elf.eh_frame_offset());
694 EXPECT_EQ(static_cast<uint64_t>(-1), elf.eh_frame_size());
695 EXPECT_TRUE(elf.debug_frame() == nullptr);
696}
697
698TEST_F(ElfInterfaceTest, init_headers_eh_frame32_fail) {
699 InitHeadersEhFrameFail<ElfInterface32Fake>();
700}
701
702TEST_F(ElfInterfaceTest, init_headers_eh_frame64_fail) {
703 InitHeadersEhFrameFail<ElfInterface64Fake>();
704}
705
706template <typename ElfType>
707void ElfInterfaceTest::InitHeadersDebugFrameFail() {
708 ElfType elf(&memory_);
709
710 elf.FakeSetEhFrameOffset(0);
711 elf.FakeSetEhFrameSize(0);
712 elf.FakeSetDebugFrameOffset(0x1000);
713 elf.FakeSetDebugFrameSize(0x100);
714
715 elf.InitHeaders(0);
716
717 EXPECT_TRUE(elf.eh_frame() == nullptr);
718 EXPECT_TRUE(elf.debug_frame() == nullptr);
719 EXPECT_EQ(0U, elf.debug_frame_offset());
720 EXPECT_EQ(static_cast<uint64_t>(-1), elf.debug_frame_size());
721}
722
723TEST_F(ElfInterfaceTest, init_headers_debug_frame32_fail) {
724 InitHeadersDebugFrameFail<ElfInterface32Fake>();
725}
726
727TEST_F(ElfInterfaceTest, init_headers_debug_frame64_fail) {
728 InitHeadersDebugFrameFail<ElfInterface64Fake>();
729}
730
731template <typename Ehdr, typename Shdr, typename ElfInterfaceType> 680template <typename Ehdr, typename Shdr, typename ElfInterfaceType>
732void ElfInterfaceTest::InitSectionHeadersMalformed() { 681void ElfInterfaceTest::InitSectionHeadersMalformed() {
733 std::unique_ptr<ElfInterfaceType> elf(new ElfInterfaceType(&memory_)); 682 std::unique_ptr<ElfInterfaceType> elf(new ElfInterfaceType(&memory_));
@@ -1024,11 +973,7 @@ TEST_F(ElfInterfaceTest, is_valid_pc_from_debug_frame) {
1024 // CIE 32. 973 // CIE 32.
1025 memory_.SetData32(0x600, 0xfc); 974 memory_.SetData32(0x600, 0xfc);
1026 memory_.SetData32(0x604, 0xffffffff); 975 memory_.SetData32(0x604, 0xffffffff);
1027 memory_.SetData8(0x608, 1); 976 memory_.SetMemory(0x608, std::vector<uint8_t>{1, '\0', 4, 4, 1});
1028 memory_.SetData8(0x609, '\0');
1029 memory_.SetData8(0x60a, 0x4);
1030 memory_.SetData8(0x60b, 0x4);
1031 memory_.SetData8(0x60c, 0x1);
1032 977
1033 // FDE 32. 978 // FDE 32.
1034 memory_.SetData32(0x700, 0xfc); 979 memory_.SetData32(0x700, 0xfc);
@@ -1085,11 +1030,7 @@ TEST_F(ElfInterfaceTest, is_valid_pc_from_eh_frame) {
1085 // CIE 32. 1030 // CIE 32.
1086 memory_.SetData32(0x600, 0xfc); 1031 memory_.SetData32(0x600, 0xfc);
1087 memory_.SetData32(0x604, 0); 1032 memory_.SetData32(0x604, 0);
1088 memory_.SetData8(0x608, 1); 1033 memory_.SetMemory(0x608, std::vector<uint8_t>{1, '\0', 4, 4, 1});
1089 memory_.SetData8(0x609, '\0');
1090 memory_.SetData8(0x60a, 0x4);
1091 memory_.SetData8(0x60b, 0x4);
1092 memory_.SetData8(0x60c, 0x1);
1093 1034
1094 // FDE 32. 1035 // FDE 32.
1095 memory_.SetData32(0x700, 0xfc); 1036 memory_.SetData32(0x700, 0xfc);