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