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