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