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