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