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, &regs, &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, &regs, &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, &regs, &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, &regs, &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, &regs, &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, &regs, &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, &regs, &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, &regs, &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, &regs, &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, &regs, &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, &regs, &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, &regs, &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, &regs, &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, &regs, &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, &regs, &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, &regs, &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, &regs, &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, &regs, &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, &regs, &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, &regs, &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, &regs, &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, &regs, &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, &regs, &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, &regs, &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, &regs, &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, &regs, &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, &regs, &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