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