diff options
author | Christopher Ferris | 2018-06-21 12:44:02 -0500 |
---|---|---|
committer | Christopher Ferris | 2018-06-27 16:52:21 -0500 |
commit | 92acaac8c713c3e1828948064ebca055dc00a723 (patch) | |
tree | d50cf188a4df626b8e9718469575e7ff17671dd7 /libunwindstack | |
parent | fc1cf90741e59d5615a7dcea1813f38bfa3a2eec (diff) | |
download | platform-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.h | 4 | ||||
-rw-r--r-- | libunwindstack/DwarfEhFrame.h | 4 | ||||
-rw-r--r-- | libunwindstack/DwarfEhFrameWithHdr.cpp | 34 | ||||
-rw-r--r-- | libunwindstack/DwarfEhFrameWithHdr.h | 28 | ||||
-rw-r--r-- | libunwindstack/DwarfSection.cpp | 787 | ||||
-rw-r--r-- | libunwindstack/include/unwindstack/DwarfSection.h | 97 | ||||
-rw-r--r-- | libunwindstack/tests/DwarfDebugFrameTest.cpp | 1064 | ||||
-rw-r--r-- | libunwindstack/tests/DwarfEhFrameTest.cpp | 472 | ||||
-rw-r--r-- | libunwindstack/tests/DwarfEhFrameWithHdrTest.cpp | 99 | ||||
-rw-r--r-- | libunwindstack/tests/DwarfSectionImplTest.cpp | 412 | ||||
-rw-r--r-- | libunwindstack/tests/DwarfSectionTest.cpp | 135 | ||||
-rw-r--r-- | libunwindstack/tests/ElfInterfaceTest.cpp | 65 |
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 @@ | |||
26 | namespace unwindstack { | 26 | namespace unwindstack { |
27 | 27 | ||
28 | template <typename AddressType> | 28 | template <typename AddressType> |
29 | class DwarfDebugFrame : public DwarfSectionImpl<AddressType> { | 29 | class 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 @@ | |||
25 | namespace unwindstack { | 25 | namespace unwindstack { |
26 | 26 | ||
27 | template <typename AddressType> | 27 | template <typename AddressType> |
28 | class DwarfEhFrame : public DwarfSectionImpl<AddressType> { | 28 | class 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 | ||
90 | template <typename AddressType> | 91 | template <typename AddressType> |
91 | const DwarfFde* DwarfEhFrameWithHdr<AddressType>::GetFdeFromIndex(size_t index) { | 92 | const 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 | ||
99 | template <typename AddressType> | 110 | template <typename AddressType> |
@@ -241,6 +252,21 @@ bool DwarfEhFrameWithHdr<AddressType>::GetFdeOffsetFromPc(uint64_t pc, uint64_t* | |||
241 | } | 252 | } |
242 | } | 253 | } |
243 | 254 | ||
255 | template <typename AddressType> | ||
256 | void 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 |
245 | template class DwarfEhFrameWithHdr<uint32_t>; | 271 | template class DwarfEhFrameWithHdr<uint32_t>; |
246 | template class DwarfEhFrameWithHdr<uint64_t>; | 272 | template 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 | ||
26 | namespace unwindstack { | 26 | namespace unwindstack { |
27 | 27 | ||
@@ -29,12 +29,12 @@ namespace unwindstack { | |||
29 | class Memory; | 29 | class Memory; |
30 | 30 | ||
31 | template <typename AddressType> | 31 | template <typename AddressType> |
32 | class DwarfEhFrameWithHdr : public DwarfEhFrame<AddressType> { | 32 | class 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 | ||
37 | DwarfSection::DwarfSection(Memory* memory) : memory_(memory) {} | 37 | DwarfSection::DwarfSection(Memory* memory) : memory_(memory) {} |
38 | 38 | ||
39 | const 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 | |||
57 | bool DwarfSection::Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished) { | 39 | bool 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 | ||
83 | template <typename AddressType> | 65 | template <typename AddressType> |
84 | bool DwarfSectionImpl<AddressType>::EvalExpression(const DwarfLocation& loc, Memory* regular_memory, | 66 | const 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 | |||
114 | template <typename AddressType> | ||
115 | struct 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 | |||
124 | template <typename AddressType> | ||
125 | bool 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 | |||
181 | template <typename AddressType> | ||
182 | bool 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 | |||
262 | template <typename AddressType> | ||
263 | const 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 | ||
278 | template <typename AddressType> | 81 | template <typename AddressType> |
279 | bool DwarfSectionImpl<AddressType>::FillInCie(DwarfCie* cie) { | 82 | bool 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 | ||
133 | template <typename AddressType> | ||
134 | bool 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 | ||
457 | template <typename AddressType> | 262 | template <typename AddressType> |
458 | bool DwarfSectionImpl<AddressType>::FillInFde(DwarfFde* fde) { | 263 | bool 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 | |||
319 | template <typename AddressType> | ||
320 | bool 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 | ||
563 | template <typename AddressType> | 373 | template <typename AddressType> |
374 | bool 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 | |||
404 | template <typename AddressType> | ||
405 | struct 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 | |||
414 | template <typename AddressType> | ||
415 | bool 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 | |||
471 | template <typename AddressType> | ||
472 | bool 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 | |||
552 | template <typename AddressType> | ||
564 | bool DwarfSectionImpl<AddressType>::GetCfaLocationInfo(uint64_t pc, const DwarfFde* fde, | 553 | bool 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 | ||
603 | template <typename AddressType> | 592 | template <typename AddressType> |
604 | bool DwarfSectionImpl<AddressType>::Init(uint64_t offset, uint64_t size, uint64_t load_bias) { | 593 | bool 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. | ||
618 | template <typename AddressType> | 617 | template <typename AddressType> |
619 | bool DwarfSectionImpl<AddressType>::GetCieInfo(uint8_t* segment_size, uint8_t* encoding) { | 618 | void 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) { | 654 | template <typename AddressType> |
657 | // No encoding | 655 | bool 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_; | |
735 | template <typename AddressType> | 714 | cie->fde_address_encoding = cie_fde_encoding; |
736 | bool 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 | ||
761 | template <typename AddressType> | 735 | template <typename AddressType> |
762 | bool DwarfSectionImpl<AddressType>::CreateSortedFdeList() { | 736 | void 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 | ||
870 | template <typename AddressType> | 771 | template <typename AddressType> |
871 | bool DwarfSectionImpl<AddressType>::GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) { | 772 | const 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 | |||
895 | template <typename AddressType> | ||
896 | const 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 |
904 | template class DwarfSectionImpl<uint32_t>; | 805 | template class DwarfSectionImpl<uint32_t>; |
905 | template class DwarfSectionImpl<uint64_t>; | 806 | template class DwarfSectionImpl<uint64_t>; |
906 | 807 | ||
808 | // Explicitly instantiate DwarfSectionImplNoHdr | ||
809 | template class DwarfSectionImplNoHdr<uint32_t>; | ||
810 | template class DwarfSectionImplNoHdr<uint64_t>; | ||
811 | |||
907 | // Explicitly instantiate DwarfDebugFrame | 812 | // Explicitly instantiate DwarfDebugFrame |
908 | template class DwarfDebugFrame<uint32_t>; | 813 | template class DwarfDebugFrame<uint32_t>; |
909 | template class DwarfDebugFrame<uint64_t>; | 814 | template 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 { | |||
119 | template <typename AddressType> | 122 | template <typename AddressType> |
120 | class DwarfSectionImpl : public DwarfSection { | 123 | class 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 | |||
159 | template <typename AddressType> | ||
160 | class 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 @@ | |||
30 | namespace unwindstack { | 31 | namespace unwindstack { |
31 | 32 | ||
32 | template <typename TypeParam> | 33 | template <typename TypeParam> |
33 | class 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 | |||
53 | template <typename TypeParam> | ||
54 | class DwarfDebugFrameTest : public ::testing::Test { | 34 | class 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 | }; |
67 | TYPED_TEST_CASE_P(DwarfDebugFrameTest); | 47 | TYPED_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 | ||
71 | TYPED_TEST_P(DwarfDebugFrameTest, Init32) { | 51 | static 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. | 61 | static 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); | 73 | static 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. | 89 | static 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. | 107 | static 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); | 122 | TYPED_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); | 164 | TYPED_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 | ||
132 | TYPED_TEST_P(DwarfDebugFrameTest, Init32_fde_not_following_cie) { | 188 | TYPED_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 | ||
149 | TYPED_TEST_P(DwarfDebugFrameTest, Init32_do_not_fail_on_bad_next_entry) { | 198 | TYPED_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 | ||
188 | TYPED_TEST_P(DwarfDebugFrameTest, Init64) { | 222 | TYPED_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 | ||
255 | TYPED_TEST_P(DwarfDebugFrameTest, Init64_fde_not_following_cie) { | 246 | TYPED_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 | ||
274 | TYPED_TEST_P(DwarfDebugFrameTest, Init64_do_not_fail_on_bad_next_entry) { | 254 | static 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 | ||
270 | TYPED_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 | ||
319 | TYPED_TEST_P(DwarfDebugFrameTest, Init_non_zero_load_bias) { | 312 | TYPED_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 | |||
336 | TYPED_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); | 346 | TYPED_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 | ||
357 | TYPED_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 | ||
391 | TYPED_TEST_P(DwarfDebugFrameTest, Init_version4) { | 370 | TYPED_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 | |||
434 | TYPED_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 | ||
490 | TYPED_TEST_P(DwarfDebugFrameTest, GetCieFde32) { | 394 | TYPED_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. | 402 | TYPED_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 | ||
532 | TYPED_TEST_P(DwarfDebugFrameTest, GetCieFde64) { | 430 | TYPED_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 | ||
576 | REGISTER_TYPED_TEST_CASE_P(DwarfDebugFrameTest, Init32, Init32_fde_not_following_cie, | 458 | static 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 | |||
475 | TYPED_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 | |||
490 | TYPED_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 | |||
505 | TYPED_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 | |||
513 | TYPED_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 | |||
521 | TYPED_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 | |||
529 | TYPED_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 | |||
537 | TYPED_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 | |||
545 | TYPED_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 | |||
553 | TYPED_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 | |||
569 | static 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 | |||
588 | TYPED_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 | |||
605 | TYPED_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 | |||
622 | TYPED_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 | |||
648 | TYPED_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 | |||
674 | TYPED_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 | |||
701 | TYPED_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 | |||
728 | TYPED_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 | |||
799 | REGISTER_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 | ||
582 | typedef ::testing::Types<uint32_t, uint64_t> DwarfDebugFrameTestTypes; | 810 | typedef ::testing::Types<uint32_t, uint64_t> DwarfDebugFrameTestTypes; |
583 | INSTANTIATE_TYPED_TEST_CASE_P(, DwarfDebugFrameTest, DwarfDebugFrameTestTypes); | 811 | INSTANTIATE_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 @@ | |||
30 | namespace unwindstack { | 29 | namespace unwindstack { |
31 | 30 | ||
32 | template <typename TypeParam> | 31 | template <typename TypeParam> |
33 | class 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 | |||
53 | template <typename TypeParam> | ||
54 | class DwarfEhFrameTest : public ::testing::Test { | 32 | class 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 | }; |
67 | TYPED_TEST_CASE_P(DwarfEhFrameTest); | 45 | TYPED_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 | ||
71 | TYPED_TEST_P(DwarfEhFrameTest, Init32) { | 49 | // Only verify different cie/fde format. All other DwarfSection corner |
50 | // cases are tested in DwarfDebugFrameTest.cpp. | ||
51 | |||
52 | TYPED_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 | |||
132 | TYPED_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 | ||
149 | TYPED_TEST_P(DwarfEhFrameTest, Init64) { | 89 | TYPED_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 | |||
216 | TYPED_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 | |||
235 | TYPED_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 | |||
273 | TYPED_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 | |||
307 | TYPED_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 | |||
350 | TYPED_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 | |||
404 | TYPED_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 | |||
446 | TYPED_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 | ||
490 | REGISTER_TYPED_TEST_CASE_P(DwarfEhFrameTest, Init32, Init32_fde_not_following_cie, Init64, | 128 | REGISTER_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 | ||
494 | typedef ::testing::Types<uint32_t, uint64_t> DwarfEhFrameTestTypes; | 130 | typedef ::testing::Types<uint32_t, uint64_t> DwarfEhFrameTestTypes; |
495 | INSTANTIATE_TYPED_TEST_CASE_P(, DwarfEhFrameTest, DwarfEhFrameTestTypes); | 131 | INSTANTIATE_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 @@ | |||
30 | namespace unwindstack { | 30 | namespace unwindstack { |
31 | 31 | ||
32 | template <typename TypeParam> | 32 | template <typename TypeParam> |
33 | class MockDwarfEhFrameWithHdr : public DwarfEhFrameWithHdr<TypeParam> { | 33 | class 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 | }; |
76 | TYPED_TEST_CASE_P(DwarfEhFrameWithHdrTest); | 76 | TYPED_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 | ||
151 | TYPED_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 | |||
160 | TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeInfoFromIndex_expect_cache_fail) { | 213 | TYPED_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 | ||
481 | REGISTER_TYPED_TEST_CASE_P(DwarfEhFrameWithHdrTest, Init, Init_non_zero_load_bias, | 526 | REGISTER_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 @@ | |||
31 | namespace unwindstack { | 30 | namespace unwindstack { |
32 | 31 | ||
33 | template <typename TypeParam> | 32 | template <typename TypeParam> |
34 | class MockDwarfSectionImpl : public DwarfSectionImpl<TypeParam> { | 33 | class 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 | }; |
89 | TYPED_TEST_CASE_P(DwarfSectionImplTest); | 71 | TYPED_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 | ||
75 | TYPED_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 | |||
86 | TYPED_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 | |||
93 | TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_eval_fail) { | 97 | TYPED_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 | ||
490 | TYPED_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 | |||
500 | TYPED_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 | |||
543 | TYPED_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 | |||
568 | TYPED_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 | |||
594 | TYPED_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 | |||
632 | TYPED_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 | |||
657 | TYPED_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 | |||
684 | TYPED_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 | |||
694 | TYPED_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 | |||
717 | TYPED_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 | |||
741 | TYPED_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 | |||
768 | TYPED_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 | |||
793 | TYPED_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 | |||
818 | TYPED_TEST_P(DwarfSectionImplTest, GetCfaLocationInfo_cie_not_cached) { | 494 | TYPED_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 | ||
898 | REGISTER_TYPED_TEST_CASE_P( | 574 | REGISTER_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 | ||
911 | typedef ::testing::Types<uint32_t, uint64_t> DwarfSectionImplTestTypes; | 585 | typedef ::testing::Types<uint32_t, uint64_t> DwarfSectionImplTestTypes; |
912 | INSTANTIATE_TYPED_TEST_CASE_P(, DwarfSectionImplTest, DwarfSectionImplTestTypes); | 586 | INSTANTIATE_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 | ||
58 | class DwarfSectionTest : public ::testing::Test { | 52 | class 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 | ||
63 | TEST_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 | |||
73 | TEST_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 | |||
87 | TEST_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 | |||
101 | TEST_F(DwarfSectionTest, Step_fail_fde) { | 60 | TEST_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 | ||
111 | TEST_F(DwarfSectionTest, Step_fail_cie_null) { | 67 | TEST_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 | ||
126 | TEST_F(DwarfSectionTest, Step_fail_cfa_location) { | 78 | TEST_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 | ||
145 | TEST_F(DwarfSectionTest, Step_pass) { | 92 | TEST_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 | ||
168 | static bool MockGetCfaLocationInfo(::testing::Unused, const DwarfFde* fde, | 110 | static bool MockGetCfaLocationInfo(::testing::Unused, const DwarfFde* fde, |
@@ -173,64 +115,53 @@ static bool MockGetCfaLocationInfo(::testing::Unused, const DwarfFde* fde, | |||
173 | } | 115 | } |
174 | 116 | ||
175 | TEST_F(DwarfSectionTest, Step_cache) { | 117 | TEST_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 | ||
201 | TEST_F(DwarfSectionTest, Step_cache_not_in_pc) { | 138 | TEST_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 | ||
681 | template <typename ElfType> | ||
682 | void 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 | |||
698 | TEST_F(ElfInterfaceTest, init_headers_eh_frame32_fail) { | ||
699 | InitHeadersEhFrameFail<ElfInterface32Fake>(); | ||
700 | } | ||
701 | |||
702 | TEST_F(ElfInterfaceTest, init_headers_eh_frame64_fail) { | ||
703 | InitHeadersEhFrameFail<ElfInterface64Fake>(); | ||
704 | } | ||
705 | |||
706 | template <typename ElfType> | ||
707 | void 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 | |||
723 | TEST_F(ElfInterfaceTest, init_headers_debug_frame32_fail) { | ||
724 | InitHeadersDebugFrameFail<ElfInterface32Fake>(); | ||
725 | } | ||
726 | |||
727 | TEST_F(ElfInterfaceTest, init_headers_debug_frame64_fail) { | ||
728 | InitHeadersDebugFrameFail<ElfInterface64Fake>(); | ||
729 | } | ||
730 | |||
731 | template <typename Ehdr, typename Shdr, typename ElfInterfaceType> | 680 | template <typename Ehdr, typename Shdr, typename ElfInterfaceType> |
732 | void ElfInterfaceTest::InitSectionHeadersMalformed() { | 681 | void 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); |