• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <unordered_map>
21 
22 #include <gtest/gtest.h>
23 
24 #include <unwindstack/DwarfError.h>
25 #include <unwindstack/DwarfLocation.h>
26 #include <unwindstack/DwarfMemory.h>
27 #include <unwindstack/DwarfStructs.h>
28 #include <unwindstack/Elf.h>
29 #include <unwindstack/Log.h>
30 #include <unwindstack/MachineArm64.h>
31 
32 #include "DwarfCfa.h"
33 
34 #include "LogFake.h"
35 #include "MemoryFake.h"
36 
37 namespace unwindstack {
38 
39 template <typename TypeParam>
40 class DwarfCfaTest : public ::testing::Test {
41  protected:
SetUp()42   void SetUp() override {
43     ResetLogs();
44     memory_.Clear();
45 
46     dmem_.reset(new DwarfMemory(&memory_));
47 
48     cie_.cfa_instructions_offset = 0x1000;
49     cie_.cfa_instructions_end = 0x1030;
50     // These two values should be different to distinguish between
51     // operations that deal with code versus data.
52     cie_.code_alignment_factor = 4;
53     cie_.data_alignment_factor = 8;
54 
55     fde_.cfa_instructions_offset = 0x2000;
56     fde_.cfa_instructions_end = 0x2030;
57     fde_.pc_start = 0x2000;
58     fde_.cie = &cie_;
59 
60     cfa_.reset(new DwarfCfa<TypeParam>(dmem_.get(), &fde_, ARCH_UNKNOWN));
61   }
62 
63   MemoryFake memory_;
64   std::unique_ptr<DwarfMemory> dmem_;
65   std::unique_ptr<DwarfCfa<TypeParam>> cfa_;
66   DwarfCie cie_;
67   DwarfFde fde_;
68 };
69 TYPED_TEST_SUITE_P(DwarfCfaTest);
70 
71 // NOTE: All test class variables need to be referenced as this->.
72 
TYPED_TEST_P(DwarfCfaTest,cfa_illegal)73 TYPED_TEST_P(DwarfCfaTest, cfa_illegal) {
74   for (uint8_t i = 0x17; i < 0x3f; i++) {
75     if (i == 0x2d || i == 0x2e || i == 0x2f) {
76       // Skip gnu extension ops and aarch64 specialized op.
77       continue;
78     }
79     this->memory_.SetMemory(0x2000, std::vector<uint8_t>{i});
80     DwarfLocations loc_regs;
81 
82     ASSERT_FALSE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x2000, 0x2001, &loc_regs));
83     ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->cfa_->LastErrorCode());
84     ASSERT_EQ(0x2001U, this->dmem_->cur_offset());
85 
86     ASSERT_EQ("", GetFakeLogPrint());
87     ASSERT_EQ("", GetFakeLogBuf());
88   }
89 }
90 
TYPED_TEST_P(DwarfCfaTest,cfa_nop)91 TYPED_TEST_P(DwarfCfaTest, cfa_nop) {
92   this->memory_.SetMemory(0x2000, std::vector<uint8_t>{0x00});
93   DwarfLocations loc_regs;
94 
95   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x2000, 0x2001, &loc_regs));
96   ASSERT_EQ(0x2001U, this->dmem_->cur_offset());
97   ASSERT_EQ(0U, loc_regs.size());
98 
99   ASSERT_EQ("", GetFakeLogPrint());
100   ASSERT_EQ("", GetFakeLogBuf());
101 }
102 
103 // This test needs to be examined.
TYPED_TEST_P(DwarfCfaTest,cfa_offset)104 TYPED_TEST_P(DwarfCfaTest, cfa_offset) {
105   this->memory_.SetMemory(0x2000, std::vector<uint8_t>{0x83, 0x04});
106   DwarfLocations loc_regs;
107 
108   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x2000, 0x2002, &loc_regs));
109   ASSERT_EQ(0x2002U, this->dmem_->cur_offset());
110   ASSERT_EQ(1U, loc_regs.size());
111   auto location = loc_regs.find(3);
112   ASSERT_NE(loc_regs.end(), location);
113   ASSERT_EQ(DWARF_LOCATION_OFFSET, location->second.type);
114   ASSERT_EQ(32U, location->second.values[0]);
115 
116   ASSERT_EQ("", GetFakeLogPrint());
117   ASSERT_EQ("", GetFakeLogBuf());
118 
119   ResetLogs();
120   this->memory_.SetMemory(0x2100, std::vector<uint8_t>{0x83, 0x84, 0x01});
121   loc_regs.clear();
122 
123   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x2100, 0x2103, &loc_regs));
124   ASSERT_EQ(0x2103U, this->dmem_->cur_offset());
125   ASSERT_EQ(1U, loc_regs.size());
126   location = loc_regs.find(3);
127   ASSERT_NE(loc_regs.end(), location);
128   ASSERT_EQ(DWARF_LOCATION_OFFSET, location->second.type);
129   ASSERT_EQ(1056U, location->second.values[0]);
130 
131   ASSERT_EQ("", GetFakeLogPrint());
132   ASSERT_EQ("", GetFakeLogBuf());
133 }
134 
TYPED_TEST_P(DwarfCfaTest,cfa_offset_extended)135 TYPED_TEST_P(DwarfCfaTest, cfa_offset_extended) {
136   this->memory_.SetMemory(0x500, std::vector<uint8_t>{0x05, 0x03, 0x02});
137   DwarfLocations loc_regs;
138 
139   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x500, 0x503, &loc_regs));
140   ASSERT_EQ(0x503U, this->dmem_->cur_offset());
141   ASSERT_EQ(1U, loc_regs.size());
142   auto location = loc_regs.find(3);
143   ASSERT_NE(loc_regs.end(), location);
144   ASSERT_EQ(DWARF_LOCATION_OFFSET, location->second.type);
145   ASSERT_EQ(2U, location->second.values[0]);
146 
147   ASSERT_EQ("", GetFakeLogPrint());
148   ASSERT_EQ("", GetFakeLogBuf());
149 
150   ResetLogs();
151   loc_regs.clear();
152   this->memory_.SetMemory(0x1500, std::vector<uint8_t>{0x05, 0x81, 0x01, 0x82, 0x12});
153 
154   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x1500, 0x1505, &loc_regs));
155   ASSERT_EQ(0x1505U, this->dmem_->cur_offset());
156   ASSERT_EQ(1U, loc_regs.size());
157   location = loc_regs.find(129);
158   ASSERT_NE(loc_regs.end(), location);
159   ASSERT_EQ(DWARF_LOCATION_OFFSET, location->second.type);
160   ASSERT_EQ(2306U, location->second.values[0]);
161 
162   ASSERT_EQ("", GetFakeLogPrint());
163   ASSERT_EQ("", GetFakeLogBuf());
164 }
165 
TYPED_TEST_P(DwarfCfaTest,cfa_offset_extended_sf)166 TYPED_TEST_P(DwarfCfaTest, cfa_offset_extended_sf) {
167   this->memory_.SetMemory(0x500, std::vector<uint8_t>{0x11, 0x05, 0x10});
168   DwarfLocations loc_regs;
169 
170   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x500, 0x503, &loc_regs));
171   ASSERT_EQ(0x503U, this->dmem_->cur_offset());
172   ASSERT_EQ(1U, loc_regs.size());
173   auto location = loc_regs.find(5);
174   ASSERT_NE(loc_regs.end(), location);
175   ASSERT_EQ(DWARF_LOCATION_OFFSET, location->second.type);
176   ASSERT_EQ(0x80U, location->second.values[0]);
177 
178   ASSERT_EQ("", GetFakeLogPrint());
179   ASSERT_EQ("", GetFakeLogBuf());
180 
181   // Check a negative value for the offset.
182   ResetLogs();
183   loc_regs.clear();
184   this->memory_.SetMemory(0x1500, std::vector<uint8_t>{0x11, 0x86, 0x01, 0xff, 0x7f});
185 
186   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x1500, 0x1505, &loc_regs));
187   ASSERT_EQ(0x1505U, this->dmem_->cur_offset());
188   ASSERT_EQ(1U, loc_regs.size());
189   location = loc_regs.find(134);
190   ASSERT_NE(loc_regs.end(), location);
191   ASSERT_EQ(DWARF_LOCATION_OFFSET, location->second.type);
192   ASSERT_EQ(static_cast<uint64_t>(-8), location->second.values[0]);
193 
194   ASSERT_EQ("", GetFakeLogPrint());
195   ASSERT_EQ("", GetFakeLogBuf());
196 }
197 
TYPED_TEST_P(DwarfCfaTest,cfa_restore)198 TYPED_TEST_P(DwarfCfaTest, cfa_restore) {
199   this->memory_.SetMemory(0x2000, std::vector<uint8_t>{0xc2});
200   DwarfLocations loc_regs;
201 
202   ASSERT_FALSE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x2000, 0x2001, &loc_regs));
203   ASSERT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->cfa_->LastErrorCode());
204   ASSERT_EQ(0x2001U, this->dmem_->cur_offset());
205   ASSERT_EQ(0U, loc_regs.size());
206 
207   ASSERT_EQ("4 unwind restore while processing cie\n", GetFakeLogPrint());
208   ASSERT_EQ("", GetFakeLogBuf());
209 
210   ResetLogs();
211   DwarfLocations cie_loc_regs;
212   cie_loc_regs[2] = {.type = DWARF_LOCATION_REGISTER, .values = {0, 0}};
213   this->cfa_->set_cie_loc_regs(&cie_loc_regs);
214   this->memory_.SetMemory(0x3000, std::vector<uint8_t>{0x82, 0x04, 0xc2});
215 
216   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x3000, 0x3003, &loc_regs));
217   ASSERT_EQ(0x3003U, this->dmem_->cur_offset());
218   ASSERT_EQ(1U, loc_regs.size());
219   auto location = loc_regs.find(2);
220   ASSERT_NE(loc_regs.end(), location);
221   ASSERT_EQ(DWARF_LOCATION_REGISTER, location->second.type);
222 
223   ASSERT_EQ("", GetFakeLogPrint());
224   ASSERT_EQ("", GetFakeLogBuf());
225 }
226 
TYPED_TEST_P(DwarfCfaTest,cfa_restore_extended)227 TYPED_TEST_P(DwarfCfaTest, cfa_restore_extended) {
228   this->memory_.SetMemory(0x4000, std::vector<uint8_t>{0x06, 0x08});
229   DwarfLocations loc_regs;
230 
231   ASSERT_FALSE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x4000, 0x4002, &loc_regs));
232   ASSERT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->cfa_->LastErrorCode());
233   ASSERT_EQ(0x4002U, this->dmem_->cur_offset());
234   ASSERT_EQ(0U, loc_regs.size());
235 
236   ASSERT_EQ("4 unwind restore while processing cie\n", GetFakeLogPrint());
237   ASSERT_EQ("", GetFakeLogBuf());
238 
239   ResetLogs();
240   loc_regs.clear();
241   this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x05, 0x82, 0x02, 0x04, 0x06, 0x82, 0x02});
242   DwarfLocations cie_loc_regs;
243   cie_loc_regs[258] = {.type = DWARF_LOCATION_REGISTER, .values = {0, 0}};
244   this->cfa_->set_cie_loc_regs(&cie_loc_regs);
245 
246   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x5000, 0x5007, &loc_regs));
247   ASSERT_EQ(0x5007U, this->dmem_->cur_offset());
248   ASSERT_EQ(1U, loc_regs.size());
249   auto location = loc_regs.find(258);
250   ASSERT_NE(loc_regs.end(), location);
251   ASSERT_EQ(DWARF_LOCATION_REGISTER, location->second.type);
252 
253   ASSERT_EQ("", GetFakeLogPrint());
254   ASSERT_EQ("", GetFakeLogBuf());
255 }
256 
TYPED_TEST_P(DwarfCfaTest,cfa_set_loc)257 TYPED_TEST_P(DwarfCfaTest, cfa_set_loc) {
258   uint8_t buffer[1 + sizeof(TypeParam)];
259   buffer[0] = 0x1;
260   TypeParam address;
261   std::string raw_data("Raw Data: 0x01 ");
262   std::string address_str;
263   if (sizeof(TypeParam) == 4) {
264     address = 0x81234578U;
265     address_str = "0x81234578";
266     raw_data += "0x78 0x45 0x23 0x81";
267   } else {
268     address = 0x8123456712345678ULL;
269     address_str = "0x8123456712345678";
270     raw_data += "0x78 0x56 0x34 0x12 0x67 0x45 0x23 0x81";
271   }
272   memcpy(&buffer[1], &address, sizeof(address));
273 
274   this->memory_.SetMemory(0x50, buffer, sizeof(buffer));
275   ResetLogs();
276   DwarfLocations loc_regs;
277   ASSERT_TRUE(
278       this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x50, 0x51 + sizeof(TypeParam), &loc_regs));
279   ASSERT_EQ(0x51 + sizeof(TypeParam), this->dmem_->cur_offset());
280   ASSERT_EQ(address, this->cfa_->cur_pc());
281   ASSERT_EQ(0U, loc_regs.size());
282 
283   ASSERT_EQ("", GetFakeLogPrint());
284   ASSERT_EQ("", GetFakeLogBuf());
285 
286   // Check for a set going back.
287   ResetLogs();
288   loc_regs.clear();
289   this->fde_.pc_start = address + 0x10;
290   ASSERT_TRUE(
291       this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x50, 0x51 + sizeof(TypeParam), &loc_regs));
292   ASSERT_EQ(0x51 + sizeof(TypeParam), this->dmem_->cur_offset());
293   ASSERT_EQ(address, this->cfa_->cur_pc());
294   ASSERT_EQ(0U, loc_regs.size());
295 
296   std::string cur_address_str(address_str);
297   cur_address_str[cur_address_str.size() - 2] = '8';
298   std::string expected = "4 unwind Warning: PC is moving backwards: old " + cur_address_str +
299                          " new " + address_str + "\n";
300   ASSERT_EQ(expected, GetFakeLogPrint());
301   ASSERT_EQ("", GetFakeLogBuf());
302 }
303 
TYPED_TEST_P(DwarfCfaTest,cfa_advance_loc1)304 TYPED_TEST_P(DwarfCfaTest, cfa_advance_loc1) {
305   this->memory_.SetMemory(0x200, std::vector<uint8_t>{0x02, 0x04});
306   DwarfLocations loc_regs;
307 
308   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x200, 0x202, &loc_regs));
309   ASSERT_EQ(0x202U, this->dmem_->cur_offset());
310   ASSERT_EQ(this->fde_.pc_start + 0x10, this->cfa_->cur_pc());
311   ASSERT_EQ(0U, loc_regs.size());
312 
313   ASSERT_EQ("", GetFakeLogPrint());
314   ASSERT_EQ("", GetFakeLogBuf());
315 }
316 
TYPED_TEST_P(DwarfCfaTest,cfa_advance_loc2)317 TYPED_TEST_P(DwarfCfaTest, cfa_advance_loc2) {
318   this->memory_.SetMemory(0x600, std::vector<uint8_t>{0x03, 0x04, 0x03});
319   DwarfLocations loc_regs;
320 
321   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x600, 0x603, &loc_regs));
322   ASSERT_EQ(0x603U, this->dmem_->cur_offset());
323   ASSERT_EQ(this->fde_.pc_start + 0xc10U, this->cfa_->cur_pc());
324   ASSERT_EQ(0U, loc_regs.size());
325 
326   ASSERT_EQ("", GetFakeLogPrint());
327   ASSERT_EQ("", GetFakeLogBuf());
328 }
329 
TYPED_TEST_P(DwarfCfaTest,cfa_advance_loc4)330 TYPED_TEST_P(DwarfCfaTest, cfa_advance_loc4) {
331   this->memory_.SetMemory(0x500, std::vector<uint8_t>{0x04, 0x04, 0x03, 0x02, 0x01});
332   DwarfLocations loc_regs;
333 
334   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x500, 0x505, &loc_regs));
335   ASSERT_EQ(0x505U, this->dmem_->cur_offset());
336   ASSERT_EQ(this->fde_.pc_start + 0x4080c10, this->cfa_->cur_pc());
337   ASSERT_EQ(0U, loc_regs.size());
338 
339   ASSERT_EQ("", GetFakeLogPrint());
340   ASSERT_EQ("", GetFakeLogBuf());
341 }
342 
TYPED_TEST_P(DwarfCfaTest,cfa_undefined)343 TYPED_TEST_P(DwarfCfaTest, cfa_undefined) {
344   this->memory_.SetMemory(0xa00, std::vector<uint8_t>{0x07, 0x09});
345   DwarfLocations loc_regs;
346 
347   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0xa00, 0xa02, &loc_regs));
348   ASSERT_EQ(0xa02U, this->dmem_->cur_offset());
349   ASSERT_EQ(1U, loc_regs.size());
350   auto location = loc_regs.find(9);
351   ASSERT_NE(loc_regs.end(), location);
352   ASSERT_EQ(DWARF_LOCATION_UNDEFINED, location->second.type);
353 
354   ASSERT_EQ("", GetFakeLogPrint());
355   ASSERT_EQ("", GetFakeLogBuf());
356 
357   ResetLogs();
358   loc_regs.clear();
359   this->memory_.SetMemory(0x1a00, std::vector<uint8_t>{0x07, 0x81, 0x01});
360 
361   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x1a00, 0x1a03, &loc_regs));
362   ASSERT_EQ(0x1a03U, this->dmem_->cur_offset());
363   ASSERT_EQ(1U, loc_regs.size());
364   location = loc_regs.find(129);
365   ASSERT_NE(loc_regs.end(), location);
366   ASSERT_EQ(DWARF_LOCATION_UNDEFINED, location->second.type);
367 
368   ASSERT_EQ("", GetFakeLogPrint());
369   ASSERT_EQ("", GetFakeLogBuf());
370 }
371 
TYPED_TEST_P(DwarfCfaTest,cfa_same)372 TYPED_TEST_P(DwarfCfaTest, cfa_same) {
373   this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x08, 0x7f});
374   DwarfLocations loc_regs;
375 
376   loc_regs[127] = {.type = DWARF_LOCATION_REGISTER, .values = {0, 0}};
377   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x102, &loc_regs));
378   ASSERT_EQ(0x102U, this->dmem_->cur_offset());
379   ASSERT_EQ(0U, loc_regs.size());
380   ASSERT_EQ(0U, loc_regs.count(127));
381 
382   ASSERT_EQ("", GetFakeLogPrint());
383   ASSERT_EQ("", GetFakeLogBuf());
384 
385   ResetLogs();
386   loc_regs.clear();
387   this->memory_.SetMemory(0x2100, std::vector<uint8_t>{0x08, 0xff, 0x01});
388 
389   loc_regs[255] = {.type = DWARF_LOCATION_REGISTER, .values = {0, 0}};
390   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x2100, 0x2103, &loc_regs));
391   ASSERT_EQ(0x2103U, this->dmem_->cur_offset());
392   ASSERT_EQ(0U, loc_regs.size());
393   ASSERT_EQ(0U, loc_regs.count(255));
394 
395   ASSERT_EQ("", GetFakeLogPrint());
396   ASSERT_EQ("", GetFakeLogBuf());
397 }
398 
TYPED_TEST_P(DwarfCfaTest,cfa_register)399 TYPED_TEST_P(DwarfCfaTest, cfa_register) {
400   this->memory_.SetMemory(0x300, std::vector<uint8_t>{0x09, 0x02, 0x01});
401   DwarfLocations loc_regs;
402 
403   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x300, 0x303, &loc_regs));
404   ASSERT_EQ(0x303U, this->dmem_->cur_offset());
405   ASSERT_EQ(1U, loc_regs.size());
406   auto location = loc_regs.find(2);
407   ASSERT_NE(loc_regs.end(), location);
408   ASSERT_EQ(DWARF_LOCATION_REGISTER, location->second.type);
409   ASSERT_EQ(1U, location->second.values[0]);
410 
411   ASSERT_EQ("", GetFakeLogPrint());
412   ASSERT_EQ("", GetFakeLogBuf());
413 
414   ResetLogs();
415   loc_regs.clear();
416   this->memory_.SetMemory(0x4300, std::vector<uint8_t>{0x09, 0xff, 0x01, 0xff, 0x03});
417 
418   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x4300, 0x4305, &loc_regs));
419   ASSERT_EQ(0x4305U, this->dmem_->cur_offset());
420   ASSERT_EQ(1U, loc_regs.size());
421   location = loc_regs.find(255);
422   ASSERT_NE(loc_regs.end(), location);
423   ASSERT_EQ(DWARF_LOCATION_REGISTER, location->second.type);
424   ASSERT_EQ(511U, location->second.values[0]);
425 
426   ASSERT_EQ("", GetFakeLogPrint());
427   ASSERT_EQ("", GetFakeLogBuf());
428 }
429 
TYPED_TEST_P(DwarfCfaTest,cfa_state)430 TYPED_TEST_P(DwarfCfaTest, cfa_state) {
431   this->memory_.SetMemory(0x300, std::vector<uint8_t>{0x0a});
432   DwarfLocations loc_regs;
433 
434   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x300, 0x301, &loc_regs));
435   ASSERT_EQ(0x301U, this->dmem_->cur_offset());
436   ASSERT_EQ(0U, loc_regs.size());
437 
438   ASSERT_EQ("", GetFakeLogPrint());
439   ASSERT_EQ("", GetFakeLogBuf());
440 
441   ResetLogs();
442   this->memory_.SetMemory(0x4300, std::vector<uint8_t>{0x0b});
443 
444   loc_regs.clear();
445   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x4300, 0x4301, &loc_regs));
446   ASSERT_EQ(0x4301U, this->dmem_->cur_offset());
447   ASSERT_EQ(0U, loc_regs.size());
448 
449   ASSERT_EQ("", GetFakeLogPrint());
450   ASSERT_EQ("", GetFakeLogBuf());
451 
452   ResetLogs();
453   this->memory_.SetMemory(0x2000, std::vector<uint8_t>{0x85, 0x02, 0x0a, 0x86, 0x04, 0x0b});
454 
455   loc_regs.clear();
456   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x2000, 0x2005, &loc_regs));
457   ASSERT_EQ(0x2005U, this->dmem_->cur_offset());
458   ASSERT_EQ(2U, loc_regs.size());
459   ASSERT_NE(loc_regs.end(), loc_regs.find(5));
460   ASSERT_NE(loc_regs.end(), loc_regs.find(6));
461 
462   loc_regs.clear();
463   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x2000, 0x2006, &loc_regs));
464   ASSERT_EQ(0x2006U, this->dmem_->cur_offset());
465   ASSERT_EQ(1U, loc_regs.size());
466   ASSERT_NE(loc_regs.end(), loc_regs.find(5));
467 
468   ResetLogs();
469   this->memory_.SetMemory(
470       0x6000, std::vector<uint8_t>{0x0a, 0x85, 0x02, 0x0a, 0x86, 0x04, 0x0a, 0x87, 0x01, 0x0a, 0x89,
471                                    0x05, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b});
472 
473   loc_regs.clear();
474   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x6000, 0x600c, &loc_regs));
475   ASSERT_EQ(0x600cU, this->dmem_->cur_offset());
476   ASSERT_EQ(4U, loc_regs.size());
477   ASSERT_NE(loc_regs.end(), loc_regs.find(5));
478   ASSERT_NE(loc_regs.end(), loc_regs.find(6));
479   ASSERT_NE(loc_regs.end(), loc_regs.find(7));
480   ASSERT_NE(loc_regs.end(), loc_regs.find(9));
481 
482   loc_regs.clear();
483   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x6000, 0x600d, &loc_regs));
484   ASSERT_EQ(0x600dU, this->dmem_->cur_offset());
485   ASSERT_EQ(3U, loc_regs.size());
486   ASSERT_NE(loc_regs.end(), loc_regs.find(5));
487   ASSERT_NE(loc_regs.end(), loc_regs.find(6));
488   ASSERT_NE(loc_regs.end(), loc_regs.find(7));
489 
490   loc_regs.clear();
491   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x6000, 0x600e, &loc_regs));
492   ASSERT_EQ(0x600eU, this->dmem_->cur_offset());
493   ASSERT_EQ(2U, loc_regs.size());
494   ASSERT_NE(loc_regs.end(), loc_regs.find(5));
495   ASSERT_NE(loc_regs.end(), loc_regs.find(6));
496 
497   loc_regs.clear();
498   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x6000, 0x600f, &loc_regs));
499   ASSERT_EQ(0x600fU, this->dmem_->cur_offset());
500   ASSERT_EQ(1U, loc_regs.size());
501   ASSERT_NE(loc_regs.end(), loc_regs.find(5));
502 
503   loc_regs.clear();
504   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x6000, 0x6010, &loc_regs));
505   ASSERT_EQ(0x6010U, this->dmem_->cur_offset());
506   ASSERT_EQ(0U, loc_regs.size());
507 
508   loc_regs.clear();
509   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x6000, 0x6011, &loc_regs));
510   ASSERT_EQ(0x6011U, this->dmem_->cur_offset());
511   ASSERT_EQ(0U, loc_regs.size());
512 }
513 
514 // This test verifies that the cfa offset is saved and restored properly.
515 // Even though the spec is not clear about whether the offset is also
516 // restored, the gcc unwinder does, and libunwind does too.
TYPED_TEST_P(DwarfCfaTest,cfa_state_cfa_offset_restore)517 TYPED_TEST_P(DwarfCfaTest, cfa_state_cfa_offset_restore) {
518   this->memory_.SetMemory(0x3000, std::vector<uint8_t>{0x0a, 0x0e, 0x40, 0x0b});
519   DwarfLocations loc_regs;
520   loc_regs[CFA_REG] = {.type = DWARF_LOCATION_REGISTER, .values = {5, 100}};
521 
522   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x3000, 0x3004, &loc_regs));
523   ASSERT_EQ(0x3004U, this->dmem_->cur_offset());
524   ASSERT_EQ(1U, loc_regs.size());
525   ASSERT_EQ(DWARF_LOCATION_REGISTER, loc_regs[CFA_REG].type);
526   ASSERT_EQ(5U, loc_regs[CFA_REG].values[0]);
527   ASSERT_EQ(100U, loc_regs[CFA_REG].values[1]);
528 
529   ASSERT_EQ("", GetFakeLogPrint());
530   ASSERT_EQ("", GetFakeLogBuf());
531 }
532 
TYPED_TEST_P(DwarfCfaTest,cfa_def_cfa)533 TYPED_TEST_P(DwarfCfaTest, cfa_def_cfa) {
534   this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x0c, 0x7f, 0x74});
535   DwarfLocations loc_regs;
536 
537   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x103, &loc_regs));
538   ASSERT_EQ(0x103U, this->dmem_->cur_offset());
539   ASSERT_EQ(1U, loc_regs.size());
540   ASSERT_EQ(DWARF_LOCATION_REGISTER, loc_regs[CFA_REG].type);
541   ASSERT_EQ(0x7fU, loc_regs[CFA_REG].values[0]);
542   ASSERT_EQ(0x74U, loc_regs[CFA_REG].values[1]);
543 
544   ASSERT_EQ("", GetFakeLogPrint());
545   ASSERT_EQ("", GetFakeLogBuf());
546 
547   ResetLogs();
548   loc_regs.clear();
549   this->memory_.SetMemory(0x200, std::vector<uint8_t>{0x0c, 0xff, 0x02, 0xf4, 0x04});
550 
551   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x200, 0x205, &loc_regs));
552   ASSERT_EQ(0x205U, this->dmem_->cur_offset());
553   ASSERT_EQ(1U, loc_regs.size());
554   ASSERT_EQ(DWARF_LOCATION_REGISTER, loc_regs[CFA_REG].type);
555   ASSERT_EQ(0x17fU, loc_regs[CFA_REG].values[0]);
556   ASSERT_EQ(0x274U, loc_regs[CFA_REG].values[1]);
557 
558   ASSERT_EQ("", GetFakeLogPrint());
559   ASSERT_EQ("", GetFakeLogBuf());
560 }
561 
TYPED_TEST_P(DwarfCfaTest,cfa_def_cfa_sf)562 TYPED_TEST_P(DwarfCfaTest, cfa_def_cfa_sf) {
563   this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x12, 0x30, 0x25});
564   DwarfLocations loc_regs;
565 
566   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x103, &loc_regs));
567   ASSERT_EQ(0x103U, this->dmem_->cur_offset());
568   ASSERT_EQ(1U, loc_regs.size());
569   ASSERT_EQ(DWARF_LOCATION_REGISTER, loc_regs[CFA_REG].type);
570   ASSERT_EQ(0x30U, loc_regs[CFA_REG].values[0]);
571   ASSERT_EQ(0x128U, loc_regs[CFA_REG].values[1]);
572 
573   ASSERT_EQ("", GetFakeLogPrint());
574   ASSERT_EQ("", GetFakeLogBuf());
575 
576   // Test a negative value.
577   ResetLogs();
578   loc_regs.clear();
579   this->memory_.SetMemory(0x200, std::vector<uint8_t>{0x12, 0xa3, 0x01, 0xfa, 0x7f});
580 
581   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x200, 0x205, &loc_regs));
582   ASSERT_EQ(0x205U, this->dmem_->cur_offset());
583   ASSERT_EQ(1U, loc_regs.size());
584   ASSERT_EQ(DWARF_LOCATION_REGISTER, loc_regs[CFA_REG].type);
585   ASSERT_EQ(0xa3U, loc_regs[CFA_REG].values[0]);
586   ASSERT_EQ(static_cast<uint64_t>(-48), loc_regs[CFA_REG].values[1]);
587 
588   ASSERT_EQ("", GetFakeLogPrint());
589   ASSERT_EQ("", GetFakeLogBuf());
590 }
591 
TYPED_TEST_P(DwarfCfaTest,cfa_def_cfa_register)592 TYPED_TEST_P(DwarfCfaTest, cfa_def_cfa_register) {
593   this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x0d, 0x72});
594   DwarfLocations loc_regs;
595 
596   // This fails because the cfa is not defined as a register.
597   ASSERT_FALSE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x102, &loc_regs));
598   ASSERT_EQ(0U, loc_regs.size());
599   ASSERT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->cfa_->LastErrorCode());
600 
601   ASSERT_EQ("4 unwind Attempt to set new register, but cfa is not already set to a register.\n",
602             GetFakeLogPrint());
603   ASSERT_EQ("", GetFakeLogBuf());
604 
605   ResetLogs();
606   loc_regs.clear();
607   loc_regs[CFA_REG] = {.type = DWARF_LOCATION_REGISTER, .values = {3, 20}};
608 
609   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x102, &loc_regs));
610   ASSERT_EQ(0x102U, this->dmem_->cur_offset());
611   ASSERT_EQ(1U, loc_regs.size());
612   ASSERT_EQ(DWARF_LOCATION_REGISTER, loc_regs[CFA_REG].type);
613   ASSERT_EQ(0x72U, loc_regs[CFA_REG].values[0]);
614   ASSERT_EQ(20U, loc_regs[CFA_REG].values[1]);
615 
616   ASSERT_EQ("", GetFakeLogPrint());
617   ASSERT_EQ("", GetFakeLogBuf());
618 
619   ResetLogs();
620   this->memory_.SetMemory(0x200, std::vector<uint8_t>{0x0d, 0xf9, 0x20});
621   loc_regs.clear();
622   loc_regs[CFA_REG] = {.type = DWARF_LOCATION_REGISTER, .values = {3, 60}};
623 
624   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x200, 0x203, &loc_regs));
625   ASSERT_EQ(0x203U, this->dmem_->cur_offset());
626   ASSERT_EQ(1U, loc_regs.size());
627   ASSERT_EQ(DWARF_LOCATION_REGISTER, loc_regs[CFA_REG].type);
628   ASSERT_EQ(0x1079U, loc_regs[CFA_REG].values[0]);
629   ASSERT_EQ(60U, loc_regs[CFA_REG].values[1]);
630 
631   ASSERT_EQ("", GetFakeLogPrint());
632   ASSERT_EQ("", GetFakeLogBuf());
633 }
634 
TYPED_TEST_P(DwarfCfaTest,cfa_def_cfa_offset)635 TYPED_TEST_P(DwarfCfaTest, cfa_def_cfa_offset) {
636   this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x0e, 0x59});
637   DwarfLocations loc_regs;
638 
639   // This fails because the cfa is not defined as a register.
640   ASSERT_FALSE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x102, &loc_regs));
641   ASSERT_EQ(0U, loc_regs.size());
642   ASSERT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->cfa_->LastErrorCode());
643 
644   ASSERT_EQ("4 unwind Attempt to set offset, but cfa is not set to a register.\n",
645             GetFakeLogPrint());
646   ASSERT_EQ("", GetFakeLogBuf());
647 
648   ResetLogs();
649   loc_regs.clear();
650   loc_regs[CFA_REG] = {.type = DWARF_LOCATION_REGISTER, .values = {3}};
651 
652   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x102, &loc_regs));
653   ASSERT_EQ(0x102U, this->dmem_->cur_offset());
654   ASSERT_EQ(1U, loc_regs.size());
655   ASSERT_EQ(DWARF_LOCATION_REGISTER, loc_regs[CFA_REG].type);
656   ASSERT_EQ(3U, loc_regs[CFA_REG].values[0]);
657   ASSERT_EQ(0x59U, loc_regs[CFA_REG].values[1]);
658 
659   ASSERT_EQ("", GetFakeLogPrint());
660   ASSERT_EQ("", GetFakeLogBuf());
661 
662   ResetLogs();
663   this->memory_.SetMemory(0x200, std::vector<uint8_t>{0x0e, 0xd4, 0x0a});
664   loc_regs.clear();
665   loc_regs[CFA_REG] = {.type = DWARF_LOCATION_REGISTER, .values = {3}};
666 
667   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x200, 0x203, &loc_regs));
668   ASSERT_EQ(0x203U, this->dmem_->cur_offset());
669   ASSERT_EQ(1U, loc_regs.size());
670   ASSERT_EQ(DWARF_LOCATION_REGISTER, loc_regs[CFA_REG].type);
671   ASSERT_EQ(3U, loc_regs[CFA_REG].values[0]);
672   ASSERT_EQ(0x554U, loc_regs[CFA_REG].values[1]);
673 
674   ASSERT_EQ("", GetFakeLogPrint());
675   ASSERT_EQ("", GetFakeLogBuf());
676 }
677 
TYPED_TEST_P(DwarfCfaTest,cfa_def_cfa_offset_sf)678 TYPED_TEST_P(DwarfCfaTest, cfa_def_cfa_offset_sf) {
679   this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x13, 0x23});
680   DwarfLocations loc_regs;
681 
682   // This fails because the cfa is not defined as a register.
683   ASSERT_FALSE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x102, &loc_regs));
684   ASSERT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->cfa_->LastErrorCode());
685 
686   ASSERT_EQ("4 unwind Attempt to set offset, but cfa is not set to a register.\n",
687             GetFakeLogPrint());
688   ASSERT_EQ("", GetFakeLogBuf());
689 
690   ResetLogs();
691   loc_regs.clear();
692   loc_regs[CFA_REG] = {.type = DWARF_LOCATION_REGISTER, .values = {3}};
693 
694   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x102, &loc_regs));
695   ASSERT_EQ(0x102U, this->dmem_->cur_offset());
696   ASSERT_EQ(1U, loc_regs.size());
697   ASSERT_EQ(DWARF_LOCATION_REGISTER, loc_regs[CFA_REG].type);
698   ASSERT_EQ(3U, loc_regs[CFA_REG].values[0]);
699   ASSERT_EQ(0x118U, loc_regs[CFA_REG].values[1]);
700 
701   ASSERT_EQ("", GetFakeLogPrint());
702   ASSERT_EQ("", GetFakeLogBuf());
703 
704   // Negative offset.
705   ResetLogs();
706   this->memory_.SetMemory(0x200, std::vector<uint8_t>{0x13, 0xf6, 0x7f});
707   loc_regs.clear();
708   loc_regs[CFA_REG] = {.type = DWARF_LOCATION_REGISTER, .values = {3}};
709 
710   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x200, 0x203, &loc_regs));
711   ASSERT_EQ(0x203U, this->dmem_->cur_offset());
712   ASSERT_EQ(1U, loc_regs.size());
713   ASSERT_EQ(DWARF_LOCATION_REGISTER, loc_regs[CFA_REG].type);
714   ASSERT_EQ(3U, loc_regs[CFA_REG].values[0]);
715   ASSERT_EQ(static_cast<TypeParam>(-80), static_cast<TypeParam>(loc_regs[CFA_REG].values[1]));
716 
717   ASSERT_EQ("", GetFakeLogPrint());
718   ASSERT_EQ("", GetFakeLogBuf());
719 }
720 
TYPED_TEST_P(DwarfCfaTest,cfa_def_cfa_expression)721 TYPED_TEST_P(DwarfCfaTest, cfa_def_cfa_expression) {
722   this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x0f, 0x04, 0x01, 0x02, 0x03, 0x04});
723   DwarfLocations loc_regs;
724 
725   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x106, &loc_regs));
726   ASSERT_EQ(0x106U, this->dmem_->cur_offset());
727   ASSERT_EQ(1U, loc_regs.size());
728 
729   ASSERT_EQ("", GetFakeLogPrint());
730   ASSERT_EQ("", GetFakeLogBuf());
731 
732   ResetLogs();
733   std::vector<uint8_t> ops{0x0f, 0x81, 0x01};
734   for (uint8_t i = 3; i < 132; i++) {
735     ops.push_back(i - 1);
736   }
737   this->memory_.SetMemory(0x200, ops);
738   loc_regs.clear();
739   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x200, 0x284, &loc_regs));
740   ASSERT_EQ(0x284U, this->dmem_->cur_offset());
741   ASSERT_EQ(1U, loc_regs.size());
742   ASSERT_EQ(DWARF_LOCATION_VAL_EXPRESSION, loc_regs[CFA_REG].type);
743   ASSERT_EQ(0x81U, loc_regs[CFA_REG].values[0]);
744 
745   ASSERT_EQ("", GetFakeLogPrint());
746   ASSERT_EQ("", GetFakeLogBuf());
747 }
748 
TYPED_TEST_P(DwarfCfaTest,cfa_expression)749 TYPED_TEST_P(DwarfCfaTest, cfa_expression) {
750   this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x10, 0x04, 0x02, 0x40, 0x20});
751   DwarfLocations loc_regs;
752 
753   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x105, &loc_regs));
754   ASSERT_EQ(0x105U, this->dmem_->cur_offset());
755   ASSERT_EQ(1U, loc_regs.size());
756   auto location = loc_regs.find(4);
757   ASSERT_NE(loc_regs.end(), location);
758   ASSERT_EQ(DWARF_LOCATION_EXPRESSION, location->second.type);
759   ASSERT_EQ(2U, location->second.values[0]);
760   ASSERT_EQ(0x105U, location->second.values[1]);
761 
762   ASSERT_EQ("", GetFakeLogPrint());
763   ASSERT_EQ("", GetFakeLogBuf());
764 
765   ResetLogs();
766   std::vector<uint8_t> ops{0x10, 0xff, 0x01, 0x82, 0x01};
767   for (uint8_t i = 5; i < 135; i++) {
768     ops.push_back(i - 4);
769   }
770 
771   this->memory_.SetMemory(0x200, ops);
772   loc_regs.clear();
773   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x200, 0x287, &loc_regs));
774   ASSERT_EQ(0x287U, this->dmem_->cur_offset());
775   ASSERT_EQ(1U, loc_regs.size());
776   location = loc_regs.find(255);
777   ASSERT_NE(loc_regs.end(), location);
778   ASSERT_EQ(DWARF_LOCATION_EXPRESSION, location->second.type);
779   ASSERT_EQ(130U, location->second.values[0]);
780   ASSERT_EQ(0x287U, location->second.values[1]);
781 
782   ASSERT_EQ("", GetFakeLogPrint());
783   ASSERT_EQ("", GetFakeLogBuf());
784 }
785 
TYPED_TEST_P(DwarfCfaTest,cfa_val_offset)786 TYPED_TEST_P(DwarfCfaTest, cfa_val_offset) {
787   this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x14, 0x45, 0x54});
788   DwarfLocations loc_regs;
789 
790   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x103, &loc_regs));
791   ASSERT_EQ(0x103U, this->dmem_->cur_offset());
792   ASSERT_EQ(1U, loc_regs.size());
793   auto location = loc_regs.find(69);
794   ASSERT_NE(loc_regs.end(), location);
795   ASSERT_EQ(DWARF_LOCATION_VAL_OFFSET, location->second.type);
796   ASSERT_EQ(0x2a0U, location->second.values[0]);
797 
798   ASSERT_EQ("", GetFakeLogPrint());
799   ASSERT_EQ("", GetFakeLogBuf());
800 
801   ResetLogs();
802   loc_regs.clear();
803   this->memory_.SetMemory(0x400, std::vector<uint8_t>{0x14, 0xa2, 0x02, 0xb4, 0x05});
804 
805   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x400, 0x405, &loc_regs));
806   ASSERT_EQ(0x405U, this->dmem_->cur_offset());
807   ASSERT_EQ(1U, loc_regs.size());
808   location = loc_regs.find(290);
809   ASSERT_NE(loc_regs.end(), location);
810   ASSERT_EQ(DWARF_LOCATION_VAL_OFFSET, location->second.type);
811   ASSERT_EQ(0x15a0U, location->second.values[0]);
812 
813   ASSERT_EQ("", GetFakeLogPrint());
814   ASSERT_EQ("", GetFakeLogBuf());
815 }
816 
TYPED_TEST_P(DwarfCfaTest,cfa_val_offset_sf)817 TYPED_TEST_P(DwarfCfaTest, cfa_val_offset_sf) {
818   this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x15, 0x56, 0x12});
819   DwarfLocations loc_regs;
820 
821   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x103, &loc_regs));
822   ASSERT_EQ(0x103U, this->dmem_->cur_offset());
823   ASSERT_EQ(1U, loc_regs.size());
824   auto location = loc_regs.find(86);
825   ASSERT_NE(loc_regs.end(), location);
826   ASSERT_EQ(DWARF_LOCATION_VAL_OFFSET, location->second.type);
827   ASSERT_EQ(0x90U, location->second.values[0]);
828 
829   ASSERT_EQ("", GetFakeLogPrint());
830   ASSERT_EQ("", GetFakeLogBuf());
831 
832   // Negative value.
833   ResetLogs();
834   loc_regs.clear();
835   this->memory_.SetMemory(0xa00, std::vector<uint8_t>{0x15, 0xff, 0x01, 0xc0, 0x7f});
836 
837   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0xa00, 0xa05, &loc_regs));
838   ASSERT_EQ(0xa05U, this->dmem_->cur_offset());
839   ASSERT_EQ(1U, loc_regs.size());
840   location = loc_regs.find(255);
841   ASSERT_NE(loc_regs.end(), location);
842   ASSERT_EQ(DWARF_LOCATION_VAL_OFFSET, location->second.type);
843   ASSERT_EQ(static_cast<uint64_t>(-512), location->second.values[0]);
844 
845   ASSERT_EQ("", GetFakeLogPrint());
846   ASSERT_EQ("", GetFakeLogBuf());
847 }
848 
TYPED_TEST_P(DwarfCfaTest,cfa_val_expression)849 TYPED_TEST_P(DwarfCfaTest, cfa_val_expression) {
850   this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x16, 0x05, 0x02, 0x10, 0x20});
851   DwarfLocations loc_regs;
852 
853   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x100, 0x105, &loc_regs));
854   ASSERT_EQ(0x105U, this->dmem_->cur_offset());
855   ASSERT_EQ(1U, loc_regs.size());
856   auto location = loc_regs.find(5);
857   ASSERT_NE(loc_regs.end(), location);
858   ASSERT_EQ(DWARF_LOCATION_VAL_EXPRESSION, location->second.type);
859   ASSERT_EQ(2U, location->second.values[0]);
860   ASSERT_EQ(0x105U, location->second.values[1]);
861 
862   ASSERT_EQ("", GetFakeLogPrint());
863   ASSERT_EQ("", GetFakeLogBuf());
864 
865   ResetLogs();
866   std::vector<uint8_t> ops{0x16, 0x83, 0x10, 0xa8, 0x01};
867   for (uint8_t i = 0; i < 168; i++) {
868     ops.push_back(i);
869   }
870 
871   this->memory_.SetMemory(0xa00, ops);
872   loc_regs.clear();
873 
874   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0xa00, 0xaad, &loc_regs));
875   ASSERT_EQ(0xaadU, this->dmem_->cur_offset());
876   ASSERT_EQ(1U, loc_regs.size());
877   location = loc_regs.find(2051);
878   ASSERT_NE(loc_regs.end(), location);
879   ASSERT_EQ(DWARF_LOCATION_VAL_EXPRESSION, location->second.type);
880   ASSERT_EQ(168U, location->second.values[0]);
881   ASSERT_EQ(0xaadU, location->second.values[1]);
882 
883   ASSERT_EQ("", GetFakeLogPrint());
884   ASSERT_EQ("", GetFakeLogBuf());
885 }
886 
TYPED_TEST_P(DwarfCfaTest,cfa_gnu_args_size)887 TYPED_TEST_P(DwarfCfaTest, cfa_gnu_args_size) {
888   this->memory_.SetMemory(0x2000, std::vector<uint8_t>{0x2e, 0x04});
889   DwarfLocations loc_regs;
890 
891   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x2000, 0x2002, &loc_regs));
892   ASSERT_EQ(0x2002U, this->dmem_->cur_offset());
893   ASSERT_EQ(0U, loc_regs.size());
894 
895   ASSERT_EQ("", GetFakeLogPrint());
896   ASSERT_EQ("", GetFakeLogBuf());
897 
898   ResetLogs();
899   loc_regs.clear();
900   this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x2e, 0xa4, 0x80, 0x04});
901 
902   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x5000, 0x5004, &loc_regs));
903   ASSERT_EQ(0x5004U, this->dmem_->cur_offset());
904   ASSERT_EQ(0U, loc_regs.size());
905 
906   ASSERT_EQ("", GetFakeLogPrint());
907   ASSERT_EQ("", GetFakeLogBuf());
908 }
909 
TYPED_TEST_P(DwarfCfaTest,cfa_gnu_negative_offset_extended)910 TYPED_TEST_P(DwarfCfaTest, cfa_gnu_negative_offset_extended) {
911   this->memory_.SetMemory(0x500, std::vector<uint8_t>{0x2f, 0x08, 0x10});
912   DwarfLocations loc_regs;
913 
914   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x500, 0x503, &loc_regs));
915   ASSERT_EQ(0x503U, this->dmem_->cur_offset());
916   ASSERT_EQ(1U, loc_regs.size());
917   auto location = loc_regs.find(8);
918   ASSERT_NE(loc_regs.end(), location);
919   ASSERT_EQ(DWARF_LOCATION_OFFSET, location->second.type);
920   ASSERT_EQ(static_cast<uint64_t>(-16), location->second.values[0]);
921 
922   ASSERT_EQ("", GetFakeLogPrint());
923   ASSERT_EQ("", GetFakeLogBuf());
924 
925   ResetLogs();
926   loc_regs.clear();
927   this->memory_.SetMemory(0x1500, std::vector<uint8_t>{0x2f, 0x81, 0x02, 0xff, 0x01});
928 
929   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x1500, 0x1505, &loc_regs));
930   ASSERT_EQ(0x1505U, this->dmem_->cur_offset());
931   ASSERT_EQ(1U, loc_regs.size());
932   location = loc_regs.find(257);
933   ASSERT_NE(loc_regs.end(), location);
934   ASSERT_EQ(DWARF_LOCATION_OFFSET, location->second.type);
935   ASSERT_EQ(static_cast<uint64_t>(-255), location->second.values[0]);
936 
937   ASSERT_EQ("", GetFakeLogPrint());
938   ASSERT_EQ("", GetFakeLogBuf());
939 }
940 
TYPED_TEST_P(DwarfCfaTest,cfa_register_override)941 TYPED_TEST_P(DwarfCfaTest, cfa_register_override) {
942   this->memory_.SetMemory(0x300, std::vector<uint8_t>{0x09, 0x02, 0x01, 0x09, 0x02, 0x04});
943   DwarfLocations loc_regs;
944 
945   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x300, 0x306, &loc_regs));
946   ASSERT_EQ(0x306U, this->dmem_->cur_offset());
947   ASSERT_EQ(1U, loc_regs.size());
948   auto location = loc_regs.find(2);
949   ASSERT_NE(loc_regs.end(), location);
950   ASSERT_EQ(DWARF_LOCATION_REGISTER, location->second.type);
951   ASSERT_EQ(4U, location->second.values[0]);
952 
953   ASSERT_EQ("", GetFakeLogPrint());
954   ASSERT_EQ("", GetFakeLogBuf());
955 }
956 
TYPED_TEST_P(DwarfCfaTest,cfa_aarch64_negate_ra_state)957 TYPED_TEST_P(DwarfCfaTest, cfa_aarch64_negate_ra_state) {
958   this->memory_.SetMemory(0x2000, std::vector<uint8_t>{0x2d});
959   DwarfLocations loc_regs;
960 
961   ASSERT_FALSE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x2000, 0x2001, &loc_regs));
962   ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->cfa_->LastErrorCode());
963   ASSERT_EQ(0x2001U, this->dmem_->cur_offset());
964 
965   ASSERT_EQ("", GetFakeLogPrint());
966   ASSERT_EQ("", GetFakeLogBuf());
967 
968   ResetLogs();
969   this->cfa_.reset(new DwarfCfa<TypeParam>(this->dmem_.get(), &this->fde_, ARCH_ARM64));
970   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x2000, 0x2001, &loc_regs));
971   ASSERT_EQ(0x2001U, this->dmem_->cur_offset());
972 
973   auto location = loc_regs.find(Arm64Reg::ARM64_PREG_RA_SIGN_STATE);
974   ASSERT_NE(loc_regs.end(), location);
975   ASSERT_EQ(DWARF_LOCATION_PSEUDO_REGISTER, location->second.type);
976   ASSERT_EQ(1U, location->second.values[0]);
977 
978   ASSERT_EQ("", GetFakeLogPrint());
979   ASSERT_EQ("", GetFakeLogBuf());
980 
981   // Verify that the value is set to 0 after another evaluation.
982   ResetLogs();
983   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x2000, 0x2001, &loc_regs));
984   ASSERT_EQ(0x2001U, this->dmem_->cur_offset());
985 
986   location = loc_regs.find(Arm64Reg::ARM64_PREG_RA_SIGN_STATE);
987   ASSERT_NE(loc_regs.end(), location);
988   ASSERT_EQ(DWARF_LOCATION_PSEUDO_REGISTER, location->second.type);
989   ASSERT_EQ(0U, location->second.values[0]);
990 
991   ASSERT_EQ("", GetFakeLogPrint());
992   ASSERT_EQ("", GetFakeLogBuf());
993 
994   // Verify that the value is set to 1 again after a third op.
995   ResetLogs();
996   ASSERT_TRUE(this->cfa_->GetLocationInfo(this->fde_.pc_start, 0x2000, 0x2001, &loc_regs));
997   ASSERT_EQ(0x2001U, this->dmem_->cur_offset());
998 
999   location = loc_regs.find(Arm64Reg::ARM64_PREG_RA_SIGN_STATE);
1000   ASSERT_NE(loc_regs.end(), location);
1001   ASSERT_EQ(DWARF_LOCATION_PSEUDO_REGISTER, location->second.type);
1002   ASSERT_EQ(1U, location->second.values[0]);
1003 
1004   ASSERT_EQ("", GetFakeLogPrint());
1005   ASSERT_EQ("", GetFakeLogBuf());
1006 }
1007 
1008 REGISTER_TYPED_TEST_SUITE_P(DwarfCfaTest, cfa_illegal, cfa_nop, cfa_offset, cfa_offset_extended,
1009                             cfa_offset_extended_sf, cfa_restore, cfa_restore_extended, cfa_set_loc,
1010                             cfa_advance_loc1, cfa_advance_loc2, cfa_advance_loc4, cfa_undefined,
1011                             cfa_same, cfa_register, cfa_state, cfa_state_cfa_offset_restore,
1012                             cfa_def_cfa, cfa_def_cfa_sf, cfa_def_cfa_register, cfa_def_cfa_offset,
1013                             cfa_def_cfa_offset_sf, cfa_def_cfa_expression, cfa_expression,
1014                             cfa_val_offset, cfa_val_offset_sf, cfa_val_expression,
1015                             cfa_gnu_args_size, cfa_gnu_negative_offset_extended,
1016                             cfa_register_override, cfa_aarch64_negate_ra_state);
1017 
1018 typedef ::testing::Types<uint32_t, uint64_t> DwarfCfaTestTypes;
1019 INSTANTIATE_TYPED_TEST_SUITE_P(Libunwindstack, DwarfCfaTest, DwarfCfaTestTypes);
1020 
1021 }  // namespace unwindstack
1022