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