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