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