1 /*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <stdint.h>
18
19 #include <gtest/gtest.h>
20
21 #include <unwindstack/DwarfError.h>
22 #include <unwindstack/DwarfSection.h>
23
24 #include "DwarfEncoding.h"
25
26 #include "LogFake.h"
27 #include "MemoryFake.h"
28 #include "RegsFake.h"
29
30 namespace unwindstack {
31
32 template <typename TypeParam>
33 class TestDwarfSectionImpl : public DwarfSectionImpl<TypeParam> {
34 public:
TestDwarfSectionImpl(Memory * memory)35 TestDwarfSectionImpl(Memory* memory) : DwarfSectionImpl<TypeParam>(memory) {}
36 virtual ~TestDwarfSectionImpl() = default;
37
Init(uint64_t,uint64_t,int64_t)38 bool Init(uint64_t, uint64_t, int64_t) override { return false; }
39
GetFdes(std::vector<const DwarfFde * > *)40 void GetFdes(std::vector<const DwarfFde*>*) override {}
41
GetFdeFromPc(uint64_t)42 const DwarfFde* GetFdeFromPc(uint64_t) override { return nullptr; }
43
GetCieOffsetFromFde32(uint32_t)44 uint64_t GetCieOffsetFromFde32(uint32_t) { return 0; }
45
GetCieOffsetFromFde64(uint64_t)46 uint64_t GetCieOffsetFromFde64(uint64_t) { return 0; }
47
AdjustPcFromFde(uint64_t)48 uint64_t AdjustPcFromFde(uint64_t) override { return 0; }
49
TestSetCachedCieLocRegs(uint64_t offset,const dwarf_loc_regs_t & loc_regs)50 void TestSetCachedCieLocRegs(uint64_t offset, const dwarf_loc_regs_t& loc_regs) {
51 this->cie_loc_regs_[offset] = loc_regs;
52 }
TestClearCachedCieLocRegs()53 void TestClearCachedCieLocRegs() { this->cie_loc_regs_.clear(); }
TestClearError()54 void TestClearError() { this->last_error_.code = DWARF_ERROR_NONE; }
55 };
56
57 template <typename TypeParam>
58 class DwarfSectionImplTest : public ::testing::Test {
59 protected:
SetUp()60 void SetUp() override {
61 memory_.Clear();
62 section_ = new TestDwarfSectionImpl<TypeParam>(&memory_);
63 ResetLogs();
64 }
65
TearDown()66 void TearDown() override { delete section_; }
67
68 MemoryFake memory_;
69 TestDwarfSectionImpl<TypeParam>* section_ = nullptr;
70 };
71 TYPED_TEST_SUITE_P(DwarfSectionImplTest);
72
73 // NOTE: All test class variables need to be referenced as this->.
74
TYPED_TEST_P(DwarfSectionImplTest,GetCieFromOffset_fail_should_not_cache)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
TYPED_TEST_P(DwarfSectionImplTest,GetFdeFromOffset_fail_should_not_cache)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
TYPED_TEST_P(DwarfSectionImplTest,Eval_cfa_expr_eval_fail)97 TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_eval_fail) {
98 DwarfCie cie{.version = 3, .return_address_register = 5};
99 RegsImplFake<TypeParam> regs(10);
100 dwarf_loc_regs_t loc_regs;
101
102 regs.set_pc(0x100);
103 regs.set_sp(0x2000);
104 regs[5] = 0x20;
105 regs[9] = 0x3000;
106 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x2, 0x5002}};
107 bool finished;
108 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
109 EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode());
110 EXPECT_EQ(0x5000U, this->section_->LastErrorAddress());
111 }
112
TYPED_TEST_P(DwarfSectionImplTest,Eval_cfa_expr_no_stack)113 TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_no_stack) {
114 DwarfCie cie{.version = 3, .return_address_register = 5};
115 RegsImplFake<TypeParam> regs(10);
116 dwarf_loc_regs_t loc_regs;
117
118 regs.set_pc(0x100);
119 regs.set_sp(0x2000);
120 regs[5] = 0x20;
121 regs[9] = 0x3000;
122 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x96, 0x96, 0x96});
123 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x2, 0x5002}};
124 bool finished;
125 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
126 EXPECT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->section_->LastErrorCode());
127 }
128
TYPED_TEST_P(DwarfSectionImplTest,Eval_cfa_expr)129 TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr) {
130 DwarfCie cie{.version = 3, .return_address_register = 5};
131 RegsImplFake<TypeParam> regs(10);
132 dwarf_loc_regs_t loc_regs;
133
134 regs.set_pc(0x100);
135 regs.set_sp(0x2000);
136 regs[5] = 0x20;
137 regs[9] = 0x3000;
138 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x80});
139 TypeParam cfa_value = 0x12345;
140 this->memory_.SetMemory(0x80000000, &cfa_value, sizeof(cfa_value));
141 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x4, 0x5004}};
142 bool finished;
143 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
144 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
145 }
146
TYPED_TEST_P(DwarfSectionImplTest,Eval_cfa_val_expr)147 TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_val_expr) {
148 DwarfCie cie{.version = 3, .return_address_register = 5};
149 RegsImplFake<TypeParam> regs(10);
150 dwarf_loc_regs_t loc_regs;
151
152 regs.set_pc(0x100);
153 regs.set_sp(0x2000);
154 regs[5] = 0x20;
155 regs[9] = 0x3000;
156 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x80});
157 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x4, 0x5004}};
158 bool finished;
159 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
160 ASSERT_FALSE(finished);
161 EXPECT_EQ(0x80000000U, regs.sp());
162 EXPECT_EQ(0x20U, regs.pc());
163 }
164
TYPED_TEST_P(DwarfSectionImplTest,Eval_cfa_expr_is_register)165 TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_is_register) {
166 DwarfCie cie{.version = 3, .return_address_register = 5};
167 RegsImplFake<TypeParam> regs(10);
168 dwarf_loc_regs_t loc_regs;
169
170 regs.set_pc(0x100);
171 regs.set_sp(0x2000);
172 regs[5] = 0x20;
173 regs[9] = 0x3000;
174 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x50, 0x96, 0x96});
175 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x2, 0x5002}};
176 bool finished;
177 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
178 EXPECT_EQ(DWARF_ERROR_NOT_IMPLEMENTED, this->section_->LastErrorCode());
179 }
180
TYPED_TEST_P(DwarfSectionImplTest,Eval_bad_regs)181 TYPED_TEST_P(DwarfSectionImplTest, Eval_bad_regs) {
182 DwarfCie cie{.return_address_register = 60};
183 RegsImplFake<TypeParam> regs(10);
184 dwarf_loc_regs_t loc_regs;
185
186 bool finished;
187 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
188 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
189 }
190
TYPED_TEST_P(DwarfSectionImplTest,Eval_no_cfa)191 TYPED_TEST_P(DwarfSectionImplTest, Eval_no_cfa) {
192 DwarfCie cie{.return_address_register = 5};
193 RegsImplFake<TypeParam> regs(10);
194 dwarf_loc_regs_t loc_regs;
195
196 bool finished;
197 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
198 EXPECT_EQ(DWARF_ERROR_CFA_NOT_DEFINED, this->section_->LastErrorCode());
199 }
200
TYPED_TEST_P(DwarfSectionImplTest,Eval_cfa_bad)201 TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_bad) {
202 DwarfCie cie{.return_address_register = 5};
203 RegsImplFake<TypeParam> regs(10);
204 dwarf_loc_regs_t loc_regs;
205
206 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {20, 0}};
207 bool finished;
208 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
209 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
210
211 this->section_->TestClearError();
212 loc_regs.erase(CFA_REG);
213 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_INVALID, {0, 0}};
214 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
215 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
216
217 this->section_->TestClearError();
218 loc_regs.erase(CFA_REG);
219 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_OFFSET, {0, 0}};
220 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
221 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
222
223 this->section_->TestClearError();
224 loc_regs.erase(CFA_REG);
225 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_VAL_OFFSET, {0, 0}};
226 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
227 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
228 }
229
TYPED_TEST_P(DwarfSectionImplTest,Eval_cfa_register_prev)230 TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_register_prev) {
231 DwarfCie cie{.return_address_register = 5};
232 RegsImplFake<TypeParam> regs(10);
233 dwarf_loc_regs_t loc_regs;
234
235 regs.set_pc(0x100);
236 regs.set_sp(0x2000);
237 regs[5] = 0x20;
238 regs[9] = 0x3000;
239 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {9, 0}};
240 bool finished;
241 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
242 EXPECT_FALSE(finished);
243 EXPECT_EQ(0x20U, regs.pc());
244 EXPECT_EQ(0x3000U, regs.sp());
245 }
246
TYPED_TEST_P(DwarfSectionImplTest,Eval_cfa_register_from_value)247 TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_register_from_value) {
248 DwarfCie cie{.return_address_register = 5};
249 RegsImplFake<TypeParam> regs(10);
250 dwarf_loc_regs_t loc_regs;
251
252 regs.set_pc(0x100);
253 regs.set_sp(0x2000);
254 regs[5] = 0x20;
255 regs[6] = 0x4000;
256 regs[9] = 0x3000;
257 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {6, 0}};
258 bool finished;
259 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
260 EXPECT_FALSE(finished);
261 EXPECT_EQ(0x20U, regs.pc());
262 EXPECT_EQ(0x4000U, regs.sp());
263 }
264
TYPED_TEST_P(DwarfSectionImplTest,Eval_double_indirection)265 TYPED_TEST_P(DwarfSectionImplTest, Eval_double_indirection) {
266 DwarfCie cie{.return_address_register = 5};
267 RegsImplFake<TypeParam> regs(10);
268 dwarf_loc_regs_t loc_regs;
269
270 regs.set_pc(0x100);
271 regs.set_sp(0x2000);
272 regs[1] = 0x100;
273 regs[3] = 0x300;
274 regs[8] = 0x10;
275 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
276 loc_regs[1] = DwarfLocation{DWARF_LOCATION_REGISTER, {3, 1}};
277 loc_regs[9] = DwarfLocation{DWARF_LOCATION_REGISTER, {1, 2}};
278 bool finished;
279 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
280 EXPECT_EQ(0x301U, regs[1]);
281 EXPECT_EQ(0x300U, regs[3]);
282 EXPECT_EQ(0x10U, regs[8]);
283 EXPECT_EQ(0x102U, regs[9]);
284 }
285
TYPED_TEST_P(DwarfSectionImplTest,Eval_register_reference_chain)286 TYPED_TEST_P(DwarfSectionImplTest, Eval_register_reference_chain) {
287 DwarfCie cie{.return_address_register = 5};
288 RegsImplFake<TypeParam> regs(10);
289 dwarf_loc_regs_t loc_regs;
290
291 regs.set_pc(0x100);
292 regs.set_sp(0x2000);
293 regs[0] = 0x10;
294 regs[1] = 0x20;
295 regs[2] = 0x30;
296 regs[3] = 0x40;
297 regs[4] = 0x50;
298 regs[5] = 0x60;
299 regs[8] = 0x20;
300 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
301 loc_regs[1] = DwarfLocation{DWARF_LOCATION_REGISTER, {0, 1}};
302 loc_regs[2] = DwarfLocation{DWARF_LOCATION_REGISTER, {1, 2}};
303 loc_regs[3] = DwarfLocation{DWARF_LOCATION_REGISTER, {2, 3}};
304 loc_regs[4] = DwarfLocation{DWARF_LOCATION_REGISTER, {3, 4}};
305 loc_regs[5] = DwarfLocation{DWARF_LOCATION_REGISTER, {4, 5}};
306 bool finished;
307 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
308 EXPECT_EQ(0x10U, regs[0]);
309 EXPECT_EQ(0x11U, regs[1]);
310 EXPECT_EQ(0x22U, regs[2]);
311 EXPECT_EQ(0x33U, regs[3]);
312 EXPECT_EQ(0x44U, regs[4]);
313 EXPECT_EQ(0x55U, regs[5]);
314 EXPECT_EQ(0x20U, regs[8]);
315 }
316
TYPED_TEST_P(DwarfSectionImplTest,Eval_dex_pc)317 TYPED_TEST_P(DwarfSectionImplTest, Eval_dex_pc) {
318 DwarfCie cie{.return_address_register = 5};
319 RegsImplFake<TypeParam> regs(10);
320 dwarf_loc_regs_t loc_regs;
321
322 regs.set_pc(0x100);
323 regs.set_sp(0x2000);
324 regs[0] = 0x10;
325 regs[8] = 0x20;
326 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
327 loc_regs[1] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x8, 0x5008}};
328 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 'D', 'E', 'X', '1', 0x13, 0x08, 0x11});
329 bool finished;
330 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
331 EXPECT_EQ(0x10U, regs[0]);
332 EXPECT_EQ(0x20U, regs[8]);
333 EXPECT_EQ(0x11U, regs.dex_pc());
334 }
335
TYPED_TEST_P(DwarfSectionImplTest,Eval_invalid_register)336 TYPED_TEST_P(DwarfSectionImplTest, Eval_invalid_register) {
337 DwarfCie cie{.return_address_register = 5};
338 RegsImplFake<TypeParam> regs(10);
339 dwarf_loc_regs_t loc_regs;
340
341 regs.set_pc(0x100);
342 regs.set_sp(0x2000);
343 regs[8] = 0x10;
344 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
345 loc_regs[1] = DwarfLocation{DWARF_LOCATION_REGISTER, {10, 0}};
346 bool finished;
347 ASSERT_FALSE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
348 EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
349 }
350
TYPED_TEST_P(DwarfSectionImplTest,Eval_different_reg_locations)351 TYPED_TEST_P(DwarfSectionImplTest, Eval_different_reg_locations) {
352 DwarfCie cie{.return_address_register = 5};
353 RegsImplFake<TypeParam> regs(10);
354 dwarf_loc_regs_t loc_regs;
355
356 if (sizeof(TypeParam) == sizeof(uint64_t)) {
357 this->memory_.SetData64(0x2150, 0x12345678abcdef00ULL);
358 } else {
359 this->memory_.SetData32(0x2150, 0x12345678);
360 }
361
362 regs.set_pc(0x100);
363 regs.set_sp(0x2000);
364 regs[3] = 0x234;
365 regs[5] = 0x10;
366 regs[8] = 0x2100;
367 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
368 loc_regs[1] = DwarfLocation{DWARF_LOCATION_VAL_OFFSET, {0x100, 0}};
369 loc_regs[2] = DwarfLocation{DWARF_LOCATION_OFFSET, {0x50, 0}};
370 loc_regs[3] = DwarfLocation{DWARF_LOCATION_UNDEFINED, {0, 0}};
371 bool finished;
372 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
373 EXPECT_FALSE(finished);
374 EXPECT_EQ(0x10U, regs.pc());
375 EXPECT_EQ(0x2100U, regs.sp());
376 EXPECT_EQ(0x2200U, regs[1]);
377 EXPECT_EQ(0x234U, regs[3]);
378 if (sizeof(TypeParam) == sizeof(uint64_t)) {
379 EXPECT_EQ(0x12345678abcdef00ULL, regs[2]);
380 } else {
381 EXPECT_EQ(0x12345678U, regs[2]);
382 }
383 }
384
TYPED_TEST_P(DwarfSectionImplTest,Eval_return_address_undefined)385 TYPED_TEST_P(DwarfSectionImplTest, Eval_return_address_undefined) {
386 DwarfCie cie{.return_address_register = 5};
387 RegsImplFake<TypeParam> regs(10);
388 dwarf_loc_regs_t loc_regs;
389
390 regs.set_pc(0x100);
391 regs.set_sp(0x2000);
392 regs[5] = 0x20;
393 regs[8] = 0x10;
394 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
395 loc_regs[5] = DwarfLocation{DWARF_LOCATION_UNDEFINED, {0, 0}};
396 bool finished;
397 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
398 EXPECT_TRUE(finished);
399 EXPECT_EQ(0U, regs.pc());
400 EXPECT_EQ(0x10U, regs.sp());
401 }
402
TYPED_TEST_P(DwarfSectionImplTest,Eval_pc_zero)403 TYPED_TEST_P(DwarfSectionImplTest, Eval_pc_zero) {
404 DwarfCie cie{.return_address_register = 5};
405 RegsImplFake<TypeParam> regs(10);
406 dwarf_loc_regs_t loc_regs;
407
408 regs.set_pc(0x100);
409 regs.set_sp(0x2000);
410 regs[5] = 0;
411 regs[8] = 0x10;
412 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
413 bool finished;
414 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
415 EXPECT_TRUE(finished);
416 EXPECT_EQ(0U, regs.pc());
417 EXPECT_EQ(0x10U, regs.sp());
418 }
419
TYPED_TEST_P(DwarfSectionImplTest,Eval_return_address)420 TYPED_TEST_P(DwarfSectionImplTest, Eval_return_address) {
421 DwarfCie cie{.return_address_register = 5};
422 RegsImplFake<TypeParam> regs(10);
423 dwarf_loc_regs_t loc_regs;
424
425 regs.set_pc(0x100);
426 regs.set_sp(0x2000);
427 regs[5] = 0x20;
428 regs[8] = 0x10;
429 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
430 bool finished;
431 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
432 EXPECT_FALSE(finished);
433 EXPECT_EQ(0x20U, regs.pc());
434 EXPECT_EQ(0x10U, regs.sp());
435 }
436
TYPED_TEST_P(DwarfSectionImplTest,Eval_ignore_large_reg_loc)437 TYPED_TEST_P(DwarfSectionImplTest, Eval_ignore_large_reg_loc) {
438 DwarfCie cie{.return_address_register = 5};
439 RegsImplFake<TypeParam> regs(10);
440 dwarf_loc_regs_t loc_regs;
441
442 regs.set_pc(0x100);
443 regs.set_sp(0x2000);
444 regs[5] = 0x20;
445 regs[8] = 0x10;
446 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
447 // This should not result in any errors.
448 loc_regs[20] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
449 bool finished;
450 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
451 EXPECT_FALSE(finished);
452 EXPECT_EQ(0x20U, regs.pc());
453 EXPECT_EQ(0x10U, regs.sp());
454 }
455
TYPED_TEST_P(DwarfSectionImplTest,Eval_reg_expr)456 TYPED_TEST_P(DwarfSectionImplTest, Eval_reg_expr) {
457 DwarfCie cie{.version = 3, .return_address_register = 5};
458 RegsImplFake<TypeParam> regs(10);
459 dwarf_loc_regs_t loc_regs;
460
461 regs.set_pc(0x100);
462 regs.set_sp(0x2000);
463 regs[8] = 0x3000;
464 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x80});
465 TypeParam cfa_value = 0x12345;
466 this->memory_.SetMemory(0x80000000, &cfa_value, sizeof(cfa_value));
467 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
468 loc_regs[5] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x4, 0x5004}};
469 bool finished;
470 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
471 EXPECT_FALSE(finished);
472 EXPECT_EQ(0x3000U, regs.sp());
473 EXPECT_EQ(0x12345U, regs.pc());
474 }
475
TYPED_TEST_P(DwarfSectionImplTest,Eval_reg_val_expr)476 TYPED_TEST_P(DwarfSectionImplTest, Eval_reg_val_expr) {
477 DwarfCie cie{.version = 3, .return_address_register = 5};
478 RegsImplFake<TypeParam> regs(10);
479 dwarf_loc_regs_t loc_regs;
480
481 regs.set_pc(0x100);
482 regs.set_sp(0x2000);
483 regs[8] = 0x3000;
484 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x80});
485 loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
486 loc_regs[5] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x4, 0x5004}};
487 bool finished;
488 ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
489 EXPECT_FALSE(finished);
490 EXPECT_EQ(0x3000U, regs.sp());
491 EXPECT_EQ(0x80000000U, regs.pc());
492 }
493
TYPED_TEST_P(DwarfSectionImplTest,GetCfaLocationInfo_cie_not_cached)494 TYPED_TEST_P(DwarfSectionImplTest, GetCfaLocationInfo_cie_not_cached) {
495 DwarfCie cie{};
496 cie.cfa_instructions_offset = 0x3000;
497 cie.cfa_instructions_end = 0x3002;
498 DwarfFde fde{};
499 fde.cie = &cie;
500 fde.cie_offset = 0x8000;
501 fde.cfa_instructions_offset = 0x6000;
502 fde.cfa_instructions_end = 0x6002;
503
504 this->memory_.SetMemory(0x3000, std::vector<uint8_t>{0x09, 0x02, 0x01});
505 this->memory_.SetMemory(0x6000, std::vector<uint8_t>{0x09, 0x04, 0x03});
506
507 dwarf_loc_regs_t loc_regs;
508 ASSERT_TRUE(this->section_->GetCfaLocationInfo(0x100, &fde, &loc_regs));
509 ASSERT_EQ(2U, loc_regs.size());
510
511 auto entry = loc_regs.find(2);
512 ASSERT_NE(entry, loc_regs.end());
513 ASSERT_EQ(DWARF_LOCATION_REGISTER, entry->second.type);
514 ASSERT_EQ(1U, entry->second.values[0]);
515
516 entry = loc_regs.find(4);
517 ASSERT_NE(entry, loc_regs.end());
518 ASSERT_EQ(DWARF_LOCATION_REGISTER, entry->second.type);
519 ASSERT_EQ(3U, entry->second.values[0]);
520 }
521
TYPED_TEST_P(DwarfSectionImplTest,GetCfaLocationInfo_cie_cached)522 TYPED_TEST_P(DwarfSectionImplTest, GetCfaLocationInfo_cie_cached) {
523 DwarfCie cie{};
524 cie.cfa_instructions_offset = 0x3000;
525 cie.cfa_instructions_end = 0x3002;
526 DwarfFde fde{};
527 fde.cie = &cie;
528 fde.cie_offset = 0x8000;
529 fde.cfa_instructions_offset = 0x6000;
530 fde.cfa_instructions_end = 0x6002;
531
532 dwarf_loc_regs_t cie_loc_regs;
533 cie_loc_regs[6] = DwarfLocation{DWARF_LOCATION_REGISTER, {4, 0}};
534 this->section_->TestSetCachedCieLocRegs(0x8000, cie_loc_regs);
535 this->memory_.SetMemory(0x6000, std::vector<uint8_t>{0x09, 0x04, 0x03});
536
537 dwarf_loc_regs_t loc_regs;
538 ASSERT_TRUE(this->section_->GetCfaLocationInfo(0x100, &fde, &loc_regs));
539 ASSERT_EQ(2U, loc_regs.size());
540
541 auto entry = loc_regs.find(6);
542 ASSERT_NE(entry, loc_regs.end());
543 ASSERT_EQ(DWARF_LOCATION_REGISTER, entry->second.type);
544 ASSERT_EQ(4U, entry->second.values[0]);
545
546 entry = loc_regs.find(4);
547 ASSERT_NE(entry, loc_regs.end());
548 ASSERT_EQ(DWARF_LOCATION_REGISTER, entry->second.type);
549 ASSERT_EQ(3U, entry->second.values[0]);
550 }
551
TYPED_TEST_P(DwarfSectionImplTest,Log)552 TYPED_TEST_P(DwarfSectionImplTest, Log) {
553 DwarfCie cie{};
554 cie.cfa_instructions_offset = 0x5000;
555 cie.cfa_instructions_end = 0x5001;
556 DwarfFde fde{};
557 fde.cie = &cie;
558 fde.cfa_instructions_offset = 0x6000;
559 fde.cfa_instructions_end = 0x6001;
560
561 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x00});
562 this->memory_.SetMemory(0x6000, std::vector<uint8_t>{0xc2});
563 ASSERT_TRUE(this->section_->Log(2, 0x1000, &fde));
564
565 ASSERT_EQ(
566 "4 unwind DW_CFA_nop\n"
567 "4 unwind Raw Data: 0x00\n"
568 "4 unwind DW_CFA_restore register(2)\n"
569 "4 unwind Raw Data: 0xc2\n",
570 GetFakeLogPrint());
571 ASSERT_EQ("", GetFakeLogBuf());
572 }
573
574 REGISTER_TYPED_TEST_SUITE_P(DwarfSectionImplTest, GetCieFromOffset_fail_should_not_cache,
575 GetFdeFromOffset_fail_should_not_cache, Eval_cfa_expr_eval_fail,
576 Eval_cfa_expr_no_stack, Eval_cfa_expr_is_register, Eval_cfa_expr,
577 Eval_cfa_val_expr, Eval_bad_regs, Eval_no_cfa, Eval_cfa_bad,
578 Eval_cfa_register_prev, Eval_cfa_register_from_value,
579 Eval_double_indirection, Eval_register_reference_chain, Eval_dex_pc,
580 Eval_invalid_register, Eval_different_reg_locations,
581 Eval_return_address_undefined, Eval_pc_zero, Eval_return_address,
582 Eval_ignore_large_reg_loc, Eval_reg_expr, Eval_reg_val_expr,
583 GetCfaLocationInfo_cie_not_cached, GetCfaLocationInfo_cie_cached, Log);
584
585 typedef ::testing::Types<uint32_t, uint64_t> DwarfSectionImplTestTypes;
586 INSTANTIATE_TYPED_TEST_SUITE_P(, DwarfSectionImplTest, DwarfSectionImplTestTypes);
587
588 } // namespace unwindstack
589