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