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 <deque>
20#include <ios>
21#include <memory>
22#include <string>
23
24#include <gtest/gtest.h>
25
26#include <unwindstack/Log.h>
27#include <unwindstack/Regs.h>
28
29#include "ArmExidx.h"
30
31#include "LogFake.h"
32#include "MemoryFake.h"
33
34namespace unwindstack {
35
36class ArmExidxDecodeTest : public ::testing::TestWithParam<std::string> {
37 protected:
38  void Init(Memory* process_memory = nullptr) {
39    TearDown();
40
41    if (process_memory == nullptr) {
42      process_memory = &process_memory_;
43    }
44
45    regs_arm_.reset(new RegsArm());
46    for (size_t i = 0; i < regs_arm_->total_regs(); i++) {
47      (*regs_arm_)[i] = 0;
48    }
49    regs_arm_->set_pc(0);
50    regs_arm_->set_sp(0);
51
52    exidx_.reset(new ArmExidx(regs_arm_.get(), &elf_memory_, process_memory));
53    if (log_) {
54      exidx_->set_log(true);
55      exidx_->set_log_indent(0);
56      exidx_->set_log_skip_execution(false);
57    }
58    data_ = exidx_->data();
59    exidx_->set_cfa(0x10000);
60  }
61
62  void SetUp() override {
63    if (GetParam() != "no_logging") {
64      log_ = false;
65    } else {
66      log_ = true;
67    }
68    ResetLogs();
69    elf_memory_.Clear();
70    process_memory_.Clear();
71    Init();
72  }
73
74  std::unique_ptr<ArmExidx> exidx_;
75  std::unique_ptr<RegsArm> regs_arm_;
76  std::deque<uint8_t>* data_;
77
78  MemoryFake elf_memory_;
79  MemoryFake process_memory_;
80  bool log_;
81};
82
83TEST_P(ArmExidxDecodeTest, vsp_incr) {
84  // 00xxxxxx: vsp = vsp + (xxxxxx << 2) + 4
85  data_->push_back(0x00);
86  ASSERT_TRUE(exidx_->Decode());
87  ASSERT_FALSE(exidx_->pc_set());
88  ASSERT_EQ("", GetFakeLogBuf());
89  if (log_) {
90    ASSERT_EQ("4 unwind vsp = vsp + 4\n", GetFakeLogPrint());
91  } else {
92    ASSERT_EQ("", GetFakeLogPrint());
93  }
94  ASSERT_EQ(0x10004U, exidx_->cfa());
95
96  ResetLogs();
97  data_->clear();
98  data_->push_back(0x01);
99  ASSERT_TRUE(exidx_->Decode());
100  ASSERT_FALSE(exidx_->pc_set());
101  ASSERT_EQ("", GetFakeLogBuf());
102  if (log_) {
103    ASSERT_EQ("4 unwind vsp = vsp + 8\n", GetFakeLogPrint());
104  } else {
105    ASSERT_EQ("", GetFakeLogPrint());
106  }
107  ASSERT_EQ(0x1000cU, exidx_->cfa());
108
109  ResetLogs();
110  data_->clear();
111  data_->push_back(0x3f);
112  ASSERT_TRUE(exidx_->Decode());
113  ASSERT_FALSE(exidx_->pc_set());
114  ASSERT_EQ("", GetFakeLogBuf());
115  if (log_) {
116    ASSERT_EQ("4 unwind vsp = vsp + 256\n", GetFakeLogPrint());
117  } else {
118    ASSERT_EQ("", GetFakeLogPrint());
119  }
120  ASSERT_EQ(0x1010cU, exidx_->cfa());
121}
122
123TEST_P(ArmExidxDecodeTest, vsp_decr) {
124  // 01xxxxxx: vsp = vsp - (xxxxxx << 2) + 4
125  data_->push_back(0x40);
126  ASSERT_TRUE(exidx_->Decode());
127  ASSERT_FALSE(exidx_->pc_set());
128  ASSERT_EQ("", GetFakeLogBuf());
129  if (log_) {
130    ASSERT_EQ("4 unwind vsp = vsp - 4\n", GetFakeLogPrint());
131  } else {
132    ASSERT_EQ("", GetFakeLogPrint());
133  }
134  ASSERT_EQ(0xfffcU, exidx_->cfa());
135
136  ResetLogs();
137  data_->clear();
138  data_->push_back(0x41);
139  ASSERT_TRUE(exidx_->Decode());
140  ASSERT_FALSE(exidx_->pc_set());
141  ASSERT_EQ("", GetFakeLogBuf());
142  if (log_) {
143    ASSERT_EQ("4 unwind vsp = vsp - 8\n", GetFakeLogPrint());
144  } else {
145    ASSERT_EQ("", GetFakeLogPrint());
146  }
147  ASSERT_EQ(0xfff4U, exidx_->cfa());
148
149  ResetLogs();
150  data_->clear();
151  data_->push_back(0x7f);
152  ASSERT_TRUE(exidx_->Decode());
153  ASSERT_FALSE(exidx_->pc_set());
154  ASSERT_EQ("", GetFakeLogBuf());
155  if (log_) {
156    ASSERT_EQ("4 unwind vsp = vsp - 256\n", GetFakeLogPrint());
157  } else {
158    ASSERT_EQ("", GetFakeLogPrint());
159  }
160  ASSERT_EQ(0xfef4U, exidx_->cfa());
161}
162
163TEST_P(ArmExidxDecodeTest, refuse_unwind) {
164  // 10000000 00000000: Refuse to unwind
165  data_->push_back(0x80);
166  data_->push_back(0x00);
167  ASSERT_FALSE(exidx_->Decode());
168  ASSERT_EQ("", GetFakeLogBuf());
169  if (log_) {
170    ASSERT_EQ("4 unwind Refuse to unwind\n", GetFakeLogPrint());
171  } else {
172    ASSERT_EQ("", GetFakeLogPrint());
173  }
174  ASSERT_EQ(ARM_STATUS_NO_UNWIND, exidx_->status());
175}
176
177TEST_P(ArmExidxDecodeTest, pop_up_to_12) {
178  // 1000iiii iiiiiiii: Pop up to 12 integer registers
179  data_->push_back(0x88);
180  data_->push_back(0x00);
181  process_memory_.SetData32(0x10000, 0x10);
182  ASSERT_TRUE(exidx_->Decode());
183  ASSERT_TRUE(exidx_->pc_set());
184  ASSERT_EQ("", GetFakeLogBuf());
185  if (log_) {
186    ASSERT_EQ("4 unwind pop {r15}\n", GetFakeLogPrint());
187  } else {
188    ASSERT_EQ("", GetFakeLogPrint());
189  }
190  ASSERT_EQ(0x10004U, exidx_->cfa());
191  ASSERT_EQ(0x10U, (*exidx_->regs())[15]);
192
193  ResetLogs();
194  data_->push_back(0x8f);
195  data_->push_back(0xff);
196  for (size_t i = 0; i < 12; i++) {
197    process_memory_.SetData32(0x10004 + i * 4, i + 0x20);
198  }
199  exidx_->set_pc_set(false);
200  ASSERT_TRUE(exidx_->Decode());
201  ASSERT_TRUE(exidx_->pc_set());
202  ASSERT_EQ("", GetFakeLogBuf());
203  if (log_) {
204    ASSERT_EQ("4 unwind pop {r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15}\n",
205              GetFakeLogPrint());
206  } else {
207    ASSERT_EQ("", GetFakeLogPrint());
208  }
209  // Popping r13 results in a modified cfa.
210  ASSERT_EQ(0x29U, exidx_->cfa());
211
212  ASSERT_EQ(0x20U, (*exidx_->regs())[4]);
213  ASSERT_EQ(0x21U, (*exidx_->regs())[5]);
214  ASSERT_EQ(0x22U, (*exidx_->regs())[6]);
215  ASSERT_EQ(0x23U, (*exidx_->regs())[7]);
216  ASSERT_EQ(0x24U, (*exidx_->regs())[8]);
217  ASSERT_EQ(0x25U, (*exidx_->regs())[9]);
218  ASSERT_EQ(0x26U, (*exidx_->regs())[10]);
219  ASSERT_EQ(0x27U, (*exidx_->regs())[11]);
220  ASSERT_EQ(0x28U, (*exidx_->regs())[12]);
221  ASSERT_EQ(0x29U, (*exidx_->regs())[13]);
222  ASSERT_EQ(0x2aU, (*exidx_->regs())[14]);
223  ASSERT_EQ(0x2bU, (*exidx_->regs())[15]);
224
225  ResetLogs();
226  exidx_->set_cfa(0x10034);
227  data_->push_back(0x81);
228  data_->push_back(0x28);
229  process_memory_.SetData32(0x10034, 0x11);
230  process_memory_.SetData32(0x10038, 0x22);
231  process_memory_.SetData32(0x1003c, 0x33);
232  exidx_->set_pc_set(false);
233  ASSERT_TRUE(exidx_->Decode());
234  ASSERT_FALSE(exidx_->pc_set());
235  ASSERT_EQ("", GetFakeLogBuf());
236  if (log_) {
237    ASSERT_EQ("4 unwind pop {r7, r9, r12}\n", GetFakeLogPrint());
238  } else {
239    ASSERT_EQ("", GetFakeLogPrint());
240  }
241  ASSERT_EQ(0x10040U, exidx_->cfa());
242  ASSERT_EQ(0x11U, (*exidx_->regs())[7]);
243  ASSERT_EQ(0x22U, (*exidx_->regs())[9]);
244  ASSERT_EQ(0x33U, (*exidx_->regs())[12]);
245}
246
247TEST_P(ArmExidxDecodeTest, set_vsp_from_register) {
248  // 1001nnnn: Set vsp = r[nnnn] (nnnn != 13, 15)
249  exidx_->set_cfa(0x100);
250  for (size_t i = 0; i < 15; i++) {
251    (*regs_arm_)[i] = i + 1;
252  }
253
254  data_->push_back(0x90);
255  ASSERT_TRUE(exidx_->Decode());
256  ASSERT_FALSE(exidx_->pc_set());
257  ASSERT_EQ("", GetFakeLogBuf());
258  if (log_) {
259    ASSERT_EQ("4 unwind vsp = r0\n", GetFakeLogPrint());
260  } else {
261    ASSERT_EQ("", GetFakeLogPrint());
262  }
263  ASSERT_EQ(1U, exidx_->cfa());
264
265  ResetLogs();
266  data_->push_back(0x93);
267  ASSERT_TRUE(exidx_->Decode());
268  ASSERT_FALSE(exidx_->pc_set());
269  ASSERT_EQ("", GetFakeLogBuf());
270  if (log_) {
271    ASSERT_EQ("4 unwind vsp = r3\n", GetFakeLogPrint());
272  } else {
273    ASSERT_EQ("", GetFakeLogPrint());
274  }
275  ASSERT_EQ(4U, exidx_->cfa());
276
277  ResetLogs();
278  data_->push_back(0x9e);
279  ASSERT_TRUE(exidx_->Decode());
280  ASSERT_FALSE(exidx_->pc_set());
281  ASSERT_EQ("", GetFakeLogBuf());
282  if (log_) {
283    ASSERT_EQ("4 unwind vsp = r14\n", GetFakeLogPrint());
284  } else {
285    ASSERT_EQ("", GetFakeLogPrint());
286  }
287  ASSERT_EQ(15U, exidx_->cfa());
288}
289
290TEST_P(ArmExidxDecodeTest, reserved_prefix) {
291  // 10011101: Reserved as prefix for ARM register to register moves
292  data_->push_back(0x9d);
293  ASSERT_FALSE(exidx_->Decode());
294  ASSERT_EQ("", GetFakeLogBuf());
295  if (log_) {
296    ASSERT_EQ("4 unwind [Reserved]\n", GetFakeLogPrint());
297  } else {
298    ASSERT_EQ("", GetFakeLogPrint());
299  }
300  ASSERT_EQ(ARM_STATUS_RESERVED, exidx_->status());
301
302  // 10011111: Reserved as prefix for Intel Wireless MMX register to register moves
303  ResetLogs();
304  data_->push_back(0x9f);
305  ASSERT_FALSE(exidx_->Decode());
306  ASSERT_EQ("", GetFakeLogBuf());
307  if (log_) {
308    ASSERT_EQ("4 unwind [Reserved]\n", GetFakeLogPrint());
309  } else {
310    ASSERT_EQ("", GetFakeLogPrint());
311  }
312  ASSERT_EQ(ARM_STATUS_RESERVED, exidx_->status());
313}
314
315TEST_P(ArmExidxDecodeTest, pop_registers) {
316  // 10100nnn: Pop r4-r[4+nnn]
317  data_->push_back(0xa0);
318  process_memory_.SetData32(0x10000, 0x14);
319  ASSERT_TRUE(exidx_->Decode());
320  ASSERT_FALSE(exidx_->pc_set());
321  ASSERT_EQ("", GetFakeLogBuf());
322  if (log_) {
323    ASSERT_EQ("4 unwind pop {r4}\n", GetFakeLogPrint());
324  } else {
325    ASSERT_EQ("", GetFakeLogPrint());
326  }
327  ASSERT_EQ(0x10004U, exidx_->cfa());
328  ASSERT_EQ(0x14U, (*exidx_->regs())[4]);
329
330  ResetLogs();
331  data_->push_back(0xa3);
332  process_memory_.SetData32(0x10004, 0x20);
333  process_memory_.SetData32(0x10008, 0x30);
334  process_memory_.SetData32(0x1000c, 0x40);
335  process_memory_.SetData32(0x10010, 0x50);
336  ASSERT_TRUE(exidx_->Decode());
337  ASSERT_FALSE(exidx_->pc_set());
338  ASSERT_EQ("", GetFakeLogBuf());
339  if (log_) {
340    ASSERT_EQ("4 unwind pop {r4-r7}\n", GetFakeLogPrint());
341  } else {
342    ASSERT_EQ("", GetFakeLogPrint());
343  }
344  ASSERT_EQ(0x10014U, exidx_->cfa());
345  ASSERT_EQ(0x20U, (*exidx_->regs())[4]);
346  ASSERT_EQ(0x30U, (*exidx_->regs())[5]);
347  ASSERT_EQ(0x40U, (*exidx_->regs())[6]);
348  ASSERT_EQ(0x50U, (*exidx_->regs())[7]);
349
350  ResetLogs();
351  data_->push_back(0xa7);
352  process_memory_.SetData32(0x10014, 0x41);
353  process_memory_.SetData32(0x10018, 0x51);
354  process_memory_.SetData32(0x1001c, 0x61);
355  process_memory_.SetData32(0x10020, 0x71);
356  process_memory_.SetData32(0x10024, 0x81);
357  process_memory_.SetData32(0x10028, 0x91);
358  process_memory_.SetData32(0x1002c, 0xa1);
359  process_memory_.SetData32(0x10030, 0xb1);
360  ASSERT_TRUE(exidx_->Decode());
361  ASSERT_FALSE(exidx_->pc_set());
362  ASSERT_EQ("", GetFakeLogBuf());
363  if (log_) {
364    ASSERT_EQ("4 unwind pop {r4-r11}\n", GetFakeLogPrint());
365  } else {
366    ASSERT_EQ("", GetFakeLogPrint());
367  }
368  ASSERT_EQ(0x10034U, exidx_->cfa());
369  ASSERT_EQ(0x41U, (*exidx_->regs())[4]);
370  ASSERT_EQ(0x51U, (*exidx_->regs())[5]);
371  ASSERT_EQ(0x61U, (*exidx_->regs())[6]);
372  ASSERT_EQ(0x71U, (*exidx_->regs())[7]);
373  ASSERT_EQ(0x81U, (*exidx_->regs())[8]);
374  ASSERT_EQ(0x91U, (*exidx_->regs())[9]);
375  ASSERT_EQ(0xa1U, (*exidx_->regs())[10]);
376  ASSERT_EQ(0xb1U, (*exidx_->regs())[11]);
377}
378
379TEST_P(ArmExidxDecodeTest, pop_registers_with_r14) {
380  // 10101nnn: Pop r4-r[4+nnn], r14
381  data_->push_back(0xa8);
382  process_memory_.SetData32(0x10000, 0x12);
383  process_memory_.SetData32(0x10004, 0x22);
384  ASSERT_TRUE(exidx_->Decode());
385  ASSERT_FALSE(exidx_->pc_set());
386  ASSERT_EQ("", GetFakeLogBuf());
387  if (log_) {
388    ASSERT_EQ("4 unwind pop {r4, r14}\n", GetFakeLogPrint());
389  } else {
390    ASSERT_EQ("", GetFakeLogPrint());
391  }
392  ASSERT_EQ(0x10008U, exidx_->cfa());
393  ASSERT_EQ(0x12U, (*exidx_->regs())[4]);
394  ASSERT_EQ(0x22U, (*exidx_->regs())[14]);
395
396  ResetLogs();
397  data_->push_back(0xab);
398  process_memory_.SetData32(0x10008, 0x1);
399  process_memory_.SetData32(0x1000c, 0x2);
400  process_memory_.SetData32(0x10010, 0x3);
401  process_memory_.SetData32(0x10014, 0x4);
402  process_memory_.SetData32(0x10018, 0x5);
403  ASSERT_TRUE(exidx_->Decode());
404  ASSERT_FALSE(exidx_->pc_set());
405  ASSERT_EQ("", GetFakeLogBuf());
406  if (log_) {
407    ASSERT_EQ("4 unwind pop {r4-r7, r14}\n", GetFakeLogPrint());
408  } else {
409    ASSERT_EQ("", GetFakeLogPrint());
410  }
411  ASSERT_EQ(0x1001cU, exidx_->cfa());
412  ASSERT_EQ(0x1U, (*exidx_->regs())[4]);
413  ASSERT_EQ(0x2U, (*exidx_->regs())[5]);
414  ASSERT_EQ(0x3U, (*exidx_->regs())[6]);
415  ASSERT_EQ(0x4U, (*exidx_->regs())[7]);
416  ASSERT_EQ(0x5U, (*exidx_->regs())[14]);
417
418  ResetLogs();
419  data_->push_back(0xaf);
420  process_memory_.SetData32(0x1001c, 0x1a);
421  process_memory_.SetData32(0x10020, 0x2a);
422  process_memory_.SetData32(0x10024, 0x3a);
423  process_memory_.SetData32(0x10028, 0x4a);
424  process_memory_.SetData32(0x1002c, 0x5a);
425  process_memory_.SetData32(0x10030, 0x6a);
426  process_memory_.SetData32(0x10034, 0x7a);
427  process_memory_.SetData32(0x10038, 0x8a);
428  process_memory_.SetData32(0x1003c, 0x9a);
429  ASSERT_TRUE(exidx_->Decode());
430  ASSERT_FALSE(exidx_->pc_set());
431  ASSERT_EQ("", GetFakeLogBuf());
432  if (log_) {
433    ASSERT_EQ("4 unwind pop {r4-r11, r14}\n", GetFakeLogPrint());
434  } else {
435    ASSERT_EQ("", GetFakeLogPrint());
436  }
437  ASSERT_EQ(0x10040U, exidx_->cfa());
438  ASSERT_EQ(0x1aU, (*exidx_->regs())[4]);
439  ASSERT_EQ(0x2aU, (*exidx_->regs())[5]);
440  ASSERT_EQ(0x3aU, (*exidx_->regs())[6]);
441  ASSERT_EQ(0x4aU, (*exidx_->regs())[7]);
442  ASSERT_EQ(0x5aU, (*exidx_->regs())[8]);
443  ASSERT_EQ(0x6aU, (*exidx_->regs())[9]);
444  ASSERT_EQ(0x7aU, (*exidx_->regs())[10]);
445  ASSERT_EQ(0x8aU, (*exidx_->regs())[11]);
446  ASSERT_EQ(0x9aU, (*exidx_->regs())[14]);
447}
448
449TEST_P(ArmExidxDecodeTest, finish) {
450  // 10110000: Finish
451  data_->push_back(0xb0);
452  ASSERT_FALSE(exidx_->Decode());
453  ASSERT_EQ("", GetFakeLogBuf());
454  if (log_) {
455    ASSERT_EQ("4 unwind finish\n", GetFakeLogPrint());
456  } else {
457    ASSERT_EQ("", GetFakeLogPrint());
458  }
459  ASSERT_EQ(0x10000U, exidx_->cfa());
460  ASSERT_EQ(ARM_STATUS_FINISH, exidx_->status());
461}
462
463TEST_P(ArmExidxDecodeTest, spare) {
464  // 10110001 00000000: Spare
465  data_->push_back(0xb1);
466  data_->push_back(0x00);
467  ASSERT_FALSE(exidx_->Decode());
468  ASSERT_EQ("", GetFakeLogBuf());
469  if (log_) {
470    ASSERT_EQ("4 unwind Spare\n", GetFakeLogPrint());
471  } else {
472    ASSERT_EQ("", GetFakeLogPrint());
473  }
474  ASSERT_EQ(0x10000U, exidx_->cfa());
475  ASSERT_EQ(ARM_STATUS_SPARE, exidx_->status());
476
477  // 10110001 xxxxyyyy: Spare (xxxx != 0000)
478  for (size_t x = 1; x < 16; x++) {
479    for (size_t y = 0; y < 16; y++) {
480      ResetLogs();
481      data_->push_back(0xb1);
482      data_->push_back((x << 4) | y);
483      ASSERT_FALSE(exidx_->Decode()) << "x, y = " << x << ", " << y;
484      ASSERT_EQ("", GetFakeLogBuf()) << "x, y = " << x << ", " << y;
485      if (log_) {
486        ASSERT_EQ("4 unwind Spare\n", GetFakeLogPrint()) << "x, y = " << x << ", " << y;
487      } else {
488        ASSERT_EQ("", GetFakeLogPrint());
489      }
490      ASSERT_EQ(0x10000U, exidx_->cfa()) << "x, y = " << x << ", " << y;
491      ASSERT_EQ(ARM_STATUS_SPARE, exidx_->status());
492    }
493  }
494
495  // 101101nn: Spare
496  for (size_t n = 0; n < 4; n++) {
497    ResetLogs();
498    data_->push_back(0xb4 | n);
499    ASSERT_FALSE(exidx_->Decode()) << "n = " << n;
500    ASSERT_EQ("", GetFakeLogBuf()) << "n = " << n;
501    if (log_) {
502      ASSERT_EQ("4 unwind Spare\n", GetFakeLogPrint()) << "n = " << n;
503    } else {
504      ASSERT_EQ("", GetFakeLogPrint());
505    }
506    ASSERT_EQ(0x10000U, exidx_->cfa()) << "n = " << n;
507    ASSERT_EQ(ARM_STATUS_SPARE, exidx_->status());
508  }
509
510  // 11000111 00000000: Spare
511  ResetLogs();
512  data_->push_back(0xc7);
513  data_->push_back(0x00);
514  ASSERT_FALSE(exidx_->Decode());
515  ASSERT_EQ("", GetFakeLogBuf());
516  if (log_) {
517    ASSERT_EQ("4 unwind Spare\n", GetFakeLogPrint());
518  } else {
519    ASSERT_EQ("", GetFakeLogPrint());
520  }
521  ASSERT_EQ(0x10000U, exidx_->cfa());
522  ASSERT_EQ(ARM_STATUS_SPARE, exidx_->status());
523
524  // 11000111 xxxxyyyy: Spare (xxxx != 0000)
525  for (size_t x = 1; x < 16; x++) {
526    for (size_t y = 0; y < 16; y++) {
527      ResetLogs();
528      data_->push_back(0xc7);
529      data_->push_back(0x10);
530      ASSERT_FALSE(exidx_->Decode()) << "x, y = " << x << ", " << y;
531      ASSERT_EQ("", GetFakeLogBuf()) << "x, y = " << x << ", " << y;
532      if (log_) {
533        ASSERT_EQ("4 unwind Spare\n", GetFakeLogPrint()) << "x, y = " << x << ", " << y;
534      } else {
535        ASSERT_EQ("", GetFakeLogPrint());
536      }
537      ASSERT_EQ(0x10000U, exidx_->cfa()) << "x, y = " << x << ", " << y;
538      ASSERT_EQ(ARM_STATUS_SPARE, exidx_->status());
539    }
540  }
541
542  // 11001yyy: Spare (yyy != 000, 001)
543  for (size_t y = 2; y < 8; y++) {
544    ResetLogs();
545    data_->push_back(0xc8 | y);
546    ASSERT_FALSE(exidx_->Decode()) << "y = " << y;
547    ASSERT_EQ("", GetFakeLogBuf()) << "y = " << y;
548    if (log_) {
549      ASSERT_EQ("4 unwind Spare\n", GetFakeLogPrint()) << "y = " << y;
550    } else {
551      ASSERT_EQ("", GetFakeLogPrint());
552    }
553    ASSERT_EQ(0x10000U, exidx_->cfa()) << "y = " << y;
554    ASSERT_EQ(ARM_STATUS_SPARE, exidx_->status());
555  }
556
557  // 11xxxyyy: Spare (xxx != 000, 001, 010)
558  for (size_t x = 3; x < 8; x++) {
559    for (size_t y = 0; y < 8; y++) {
560      ResetLogs();
561      data_->push_back(0xc0 | (x << 3) | y);
562      ASSERT_FALSE(exidx_->Decode()) << "x, y = " << x << ", " << y;
563      ASSERT_EQ("", GetFakeLogBuf()) << "x, y = " << x << ", " << y;
564      if (log_) {
565        ASSERT_EQ("4 unwind Spare\n", GetFakeLogPrint()) << "x, y = " << x << ", " << y;
566      } else {
567        ASSERT_EQ("", GetFakeLogPrint());
568      }
569      ASSERT_EQ(0x10000U, exidx_->cfa()) << "x, y = " << x << ", " << y;
570      ASSERT_EQ(ARM_STATUS_SPARE, exidx_->status());
571    }
572  }
573}
574
575TEST_P(ArmExidxDecodeTest, pop_registers_under_mask) {
576  // 10110001 0000iiii: Pop integer registers {r0, r1, r2, r3}
577  data_->push_back(0xb1);
578  data_->push_back(0x01);
579  process_memory_.SetData32(0x10000, 0x45);
580  ASSERT_TRUE(exidx_->Decode());
581  ASSERT_FALSE(exidx_->pc_set());
582  ASSERT_EQ("", GetFakeLogBuf());
583  if (log_) {
584    ASSERT_EQ("4 unwind pop {r0}\n", GetFakeLogPrint());
585  } else {
586    ASSERT_EQ("", GetFakeLogPrint());
587  }
588  ASSERT_EQ(0x10004U, exidx_->cfa());
589  ASSERT_EQ(0x45U, (*exidx_->regs())[0]);
590
591  ResetLogs();
592  data_->push_back(0xb1);
593  data_->push_back(0x0a);
594  process_memory_.SetData32(0x10004, 0x23);
595  process_memory_.SetData32(0x10008, 0x24);
596  ASSERT_TRUE(exidx_->Decode());
597  ASSERT_FALSE(exidx_->pc_set());
598  ASSERT_EQ("", GetFakeLogBuf());
599  if (log_) {
600    ASSERT_EQ("4 unwind pop {r1, r3}\n", GetFakeLogPrint());
601  } else {
602    ASSERT_EQ("", GetFakeLogPrint());
603  }
604  ASSERT_EQ(0x1000cU, exidx_->cfa());
605  ASSERT_EQ(0x23U, (*exidx_->regs())[1]);
606  ASSERT_EQ(0x24U, (*exidx_->regs())[3]);
607
608  ResetLogs();
609  data_->push_back(0xb1);
610  data_->push_back(0x0f);
611  process_memory_.SetData32(0x1000c, 0x65);
612  process_memory_.SetData32(0x10010, 0x54);
613  process_memory_.SetData32(0x10014, 0x43);
614  process_memory_.SetData32(0x10018, 0x32);
615  ASSERT_TRUE(exidx_->Decode());
616  ASSERT_FALSE(exidx_->pc_set());
617  ASSERT_EQ("", GetFakeLogBuf());
618  if (log_) {
619    ASSERT_EQ("4 unwind pop {r0, r1, r2, r3}\n", GetFakeLogPrint());
620  } else {
621    ASSERT_EQ("", GetFakeLogPrint());
622  }
623  ASSERT_EQ(0x1001cU, exidx_->cfa());
624  ASSERT_EQ(0x65U, (*exidx_->regs())[0]);
625  ASSERT_EQ(0x54U, (*exidx_->regs())[1]);
626  ASSERT_EQ(0x43U, (*exidx_->regs())[2]);
627  ASSERT_EQ(0x32U, (*exidx_->regs())[3]);
628}
629
630TEST_P(ArmExidxDecodeTest, vsp_large_incr) {
631  // 10110010 uleb128: vsp = vsp + 0x204 + (uleb128 << 2)
632  data_->push_back(0xb2);
633  data_->push_back(0x7f);
634  ASSERT_TRUE(exidx_->Decode());
635  ASSERT_FALSE(exidx_->pc_set());
636  ASSERT_EQ("", GetFakeLogBuf());
637  if (log_) {
638    ASSERT_EQ("4 unwind vsp = vsp + 1024\n", GetFakeLogPrint());
639  } else {
640    ASSERT_EQ("", GetFakeLogPrint());
641  }
642  ASSERT_EQ(0x10400U, exidx_->cfa());
643
644  ResetLogs();
645  data_->push_back(0xb2);
646  data_->push_back(0xff);
647  data_->push_back(0x02);
648  ASSERT_TRUE(exidx_->Decode());
649  ASSERT_FALSE(exidx_->pc_set());
650  ASSERT_EQ("", GetFakeLogBuf());
651  if (log_) {
652    ASSERT_EQ("4 unwind vsp = vsp + 2048\n", GetFakeLogPrint());
653  } else {
654    ASSERT_EQ("", GetFakeLogPrint());
655  }
656  ASSERT_EQ(0x10c00U, exidx_->cfa());
657
658  ResetLogs();
659  data_->push_back(0xb2);
660  data_->push_back(0xff);
661  data_->push_back(0x82);
662  data_->push_back(0x30);
663  ASSERT_TRUE(exidx_->Decode());
664  ASSERT_FALSE(exidx_->pc_set());
665  ASSERT_EQ("", GetFakeLogBuf());
666  if (log_) {
667    ASSERT_EQ("4 unwind vsp = vsp + 3147776\n", GetFakeLogPrint());
668  } else {
669    ASSERT_EQ("", GetFakeLogPrint());
670  }
671  ASSERT_EQ(0x311400U, exidx_->cfa());
672}
673
674TEST_P(ArmExidxDecodeTest, pop_vfp_fstmfdx) {
675  // 10110011 sssscccc: Pop VFP double precision registers D[ssss]-D[ssss+cccc] by FSTMFDX
676  data_->push_back(0xb3);
677  data_->push_back(0x00);
678  ASSERT_TRUE(exidx_->Decode());
679  ASSERT_FALSE(exidx_->pc_set());
680  ASSERT_EQ("", GetFakeLogBuf());
681  if (log_) {
682    ASSERT_EQ("4 unwind pop {d0}\n", GetFakeLogPrint());
683  } else {
684    ASSERT_EQ("", GetFakeLogPrint());
685  }
686  ASSERT_EQ(0x1000cU, exidx_->cfa());
687
688  ResetLogs();
689  data_->push_back(0xb3);
690  data_->push_back(0x48);
691  ASSERT_TRUE(exidx_->Decode());
692  ASSERT_FALSE(exidx_->pc_set());
693  ASSERT_EQ("", GetFakeLogBuf());
694  if (log_) {
695    ASSERT_EQ("4 unwind pop {d4-d12}\n", GetFakeLogPrint());
696  } else {
697    ASSERT_EQ("", GetFakeLogPrint());
698  }
699  ASSERT_EQ(0x10058U, exidx_->cfa());
700}
701
702TEST_P(ArmExidxDecodeTest, pop_vfp8_fstmfdx) {
703  // 10111nnn: Pop VFP double precision registers D[8]-D[8+nnn] by FSTMFDX
704  data_->push_back(0xb8);
705  ASSERT_TRUE(exidx_->Decode());
706  ASSERT_FALSE(exidx_->pc_set());
707  ASSERT_EQ("", GetFakeLogBuf());
708  if (log_) {
709    ASSERT_EQ("4 unwind pop {d8}\n", GetFakeLogPrint());
710  } else {
711    ASSERT_EQ("", GetFakeLogPrint());
712  }
713  ASSERT_EQ(0x1000cU, exidx_->cfa());
714
715  ResetLogs();
716  data_->push_back(0xbb);
717  ASSERT_TRUE(exidx_->Decode());
718  ASSERT_FALSE(exidx_->pc_set());
719  ASSERT_EQ("", GetFakeLogBuf());
720  if (log_) {
721    ASSERT_EQ("4 unwind pop {d8-d11}\n", GetFakeLogPrint());
722  } else {
723    ASSERT_EQ("", GetFakeLogPrint());
724  }
725  ASSERT_EQ(0x10030U, exidx_->cfa());
726
727  ResetLogs();
728  data_->push_back(0xbf);
729  ASSERT_TRUE(exidx_->Decode());
730  ASSERT_FALSE(exidx_->pc_set());
731  ASSERT_EQ("", GetFakeLogBuf());
732  if (log_) {
733    ASSERT_EQ("4 unwind pop {d8-d15}\n", GetFakeLogPrint());
734  } else {
735    ASSERT_EQ("", GetFakeLogPrint());
736  }
737  ASSERT_EQ(0x10074U, exidx_->cfa());
738}
739
740TEST_P(ArmExidxDecodeTest, pop_mmx_wr10) {
741  // 11000nnn: Intel Wireless MMX pop wR[10]-wR[10+nnn] (nnn != 6, 7)
742  data_->push_back(0xc0);
743  ASSERT_TRUE(exidx_->Decode());
744  ASSERT_FALSE(exidx_->pc_set());
745  ASSERT_EQ("", GetFakeLogBuf());
746  if (log_) {
747    ASSERT_EQ("4 unwind pop {wR10}\n", GetFakeLogPrint());
748  } else {
749    ASSERT_EQ("", GetFakeLogPrint());
750  }
751  ASSERT_EQ(0x10008U, exidx_->cfa());
752
753  ResetLogs();
754  data_->push_back(0xc2);
755  ASSERT_TRUE(exidx_->Decode());
756  ASSERT_FALSE(exidx_->pc_set());
757  ASSERT_EQ("", GetFakeLogBuf());
758  if (log_) {
759    ASSERT_EQ("4 unwind pop {wR10-wR12}\n", GetFakeLogPrint());
760  } else {
761    ASSERT_EQ("", GetFakeLogPrint());
762  }
763  ASSERT_EQ(0x10020U, exidx_->cfa());
764
765  ResetLogs();
766  data_->push_back(0xc5);
767  ASSERT_TRUE(exidx_->Decode());
768  ASSERT_FALSE(exidx_->pc_set());
769  ASSERT_EQ("", GetFakeLogBuf());
770  if (log_) {
771    ASSERT_EQ("4 unwind pop {wR10-wR15}\n", GetFakeLogPrint());
772  } else {
773    ASSERT_EQ("", GetFakeLogPrint());
774  }
775  ASSERT_EQ(0x10050U, exidx_->cfa());
776}
777
778TEST_P(ArmExidxDecodeTest, pop_mmx_wr) {
779  // 11000110 sssscccc: Intel Wireless MMX pop wR[ssss]-wR[ssss+cccc]
780  data_->push_back(0xc6);
781  data_->push_back(0x00);
782  ASSERT_TRUE(exidx_->Decode());
783  ASSERT_FALSE(exidx_->pc_set());
784  ASSERT_EQ("", GetFakeLogBuf());
785  if (log_) {
786    ASSERT_EQ("4 unwind pop {wR0}\n", GetFakeLogPrint());
787  } else {
788    ASSERT_EQ("", GetFakeLogPrint());
789  }
790  ASSERT_EQ(0x10008U, exidx_->cfa());
791
792  ResetLogs();
793  data_->push_back(0xc6);
794  data_->push_back(0x25);
795  ASSERT_TRUE(exidx_->Decode());
796  ASSERT_FALSE(exidx_->pc_set());
797  ASSERT_EQ("", GetFakeLogBuf());
798  if (log_) {
799    ASSERT_EQ("4 unwind pop {wR2-wR7}\n", GetFakeLogPrint());
800  } else {
801    ASSERT_EQ("", GetFakeLogPrint());
802  }
803  ASSERT_EQ(0x10038U, exidx_->cfa());
804
805  ResetLogs();
806  data_->push_back(0xc6);
807  data_->push_back(0xff);
808  ASSERT_TRUE(exidx_->Decode());
809  ASSERT_FALSE(exidx_->pc_set());
810  ASSERT_EQ("", GetFakeLogBuf());
811  if (log_) {
812    ASSERT_EQ("4 unwind pop {wR15-wR30}\n", GetFakeLogPrint());
813  } else {
814    ASSERT_EQ("", GetFakeLogPrint());
815  }
816  ASSERT_EQ(0x100b8U, exidx_->cfa());
817}
818
819TEST_P(ArmExidxDecodeTest, pop_mmx_wcgr) {
820  // 11000111 0000iiii: Intel Wireless MMX pop wCGR registes {wCGR0,1,2,3}
821  data_->push_back(0xc7);
822  data_->push_back(0x01);
823  ASSERT_TRUE(exidx_->Decode());
824  ASSERT_FALSE(exidx_->pc_set());
825  ASSERT_EQ("", GetFakeLogBuf());
826  if (log_) {
827    ASSERT_EQ("4 unwind pop {wCGR0}\n", GetFakeLogPrint());
828  } else {
829    ASSERT_EQ("", GetFakeLogPrint());
830  }
831  ASSERT_EQ(0x10004U, exidx_->cfa());
832
833  ResetLogs();
834  data_->push_back(0xc7);
835  data_->push_back(0x0a);
836  ASSERT_TRUE(exidx_->Decode());
837  ASSERT_FALSE(exidx_->pc_set());
838  ASSERT_EQ("", GetFakeLogBuf());
839  if (log_) {
840    ASSERT_EQ("4 unwind pop {wCGR1, wCGR3}\n", GetFakeLogPrint());
841  } else {
842    ASSERT_EQ("", GetFakeLogPrint());
843  }
844  ASSERT_EQ(0x1000cU, exidx_->cfa());
845
846  ResetLogs();
847  data_->push_back(0xc7);
848  data_->push_back(0x0f);
849  ASSERT_TRUE(exidx_->Decode());
850  ASSERT_FALSE(exidx_->pc_set());
851  ASSERT_EQ("", GetFakeLogBuf());
852  if (log_) {
853    ASSERT_EQ("4 unwind pop {wCGR0, wCGR1, wCGR2, wCGR3}\n", GetFakeLogPrint());
854  } else {
855    ASSERT_EQ("", GetFakeLogPrint());
856  }
857  ASSERT_EQ(0x1001cU, exidx_->cfa());
858}
859
860TEST_P(ArmExidxDecodeTest, pop_vfp16_vpush) {
861  // 11001000 sssscccc: Pop VFP double precision registers d[16+ssss]-D[16+ssss+cccc] by VPUSH
862  data_->push_back(0xc8);
863  data_->push_back(0x00);
864  ASSERT_TRUE(exidx_->Decode());
865  ASSERT_FALSE(exidx_->pc_set());
866  ASSERT_EQ("", GetFakeLogBuf());
867  if (log_) {
868    ASSERT_EQ("4 unwind pop {d16}\n", GetFakeLogPrint());
869  } else {
870    ASSERT_EQ("", GetFakeLogPrint());
871  }
872  ASSERT_EQ(0x10008U, exidx_->cfa());
873
874  ResetLogs();
875  data_->push_back(0xc8);
876  data_->push_back(0x14);
877  ASSERT_TRUE(exidx_->Decode());
878  ASSERT_FALSE(exidx_->pc_set());
879  ASSERT_EQ("", GetFakeLogBuf());
880  if (log_) {
881    ASSERT_EQ("4 unwind pop {d17-d21}\n", GetFakeLogPrint());
882  } else {
883    ASSERT_EQ("", GetFakeLogPrint());
884  }
885  ASSERT_EQ(0x10030U, exidx_->cfa());
886
887  ResetLogs();
888  data_->push_back(0xc8);
889  data_->push_back(0xff);
890  ASSERT_TRUE(exidx_->Decode());
891  ASSERT_FALSE(exidx_->pc_set());
892  ASSERT_EQ("", GetFakeLogBuf());
893  if (log_) {
894    ASSERT_EQ("4 unwind pop {d31-d46}\n", GetFakeLogPrint());
895  } else {
896    ASSERT_EQ("", GetFakeLogPrint());
897  }
898  ASSERT_EQ(0x100b0U, exidx_->cfa());
899}
900
901TEST_P(ArmExidxDecodeTest, pop_vfp_vpush) {
902  // 11001001 sssscccc: Pop VFP double precision registers d[ssss]-D[ssss+cccc] by VPUSH
903  data_->push_back(0xc9);
904  data_->push_back(0x00);
905  ASSERT_TRUE(exidx_->Decode());
906  ASSERT_FALSE(exidx_->pc_set());
907  ASSERT_EQ("", GetFakeLogBuf());
908  if (log_) {
909    ASSERT_EQ("4 unwind pop {d0}\n", GetFakeLogPrint());
910  } else {
911    ASSERT_EQ("", GetFakeLogPrint());
912  }
913  ASSERT_EQ(0x10008U, exidx_->cfa());
914
915  ResetLogs();
916  data_->push_back(0xc9);
917  data_->push_back(0x23);
918  ASSERT_TRUE(exidx_->Decode());
919  ASSERT_FALSE(exidx_->pc_set());
920  ASSERT_EQ("", GetFakeLogBuf());
921  if (log_) {
922    ASSERT_EQ("4 unwind pop {d2-d5}\n", GetFakeLogPrint());
923  } else {
924    ASSERT_EQ("", GetFakeLogPrint());
925  }
926  ASSERT_EQ(0x10028U, exidx_->cfa());
927
928  ResetLogs();
929  data_->push_back(0xc9);
930  data_->push_back(0xff);
931  ASSERT_TRUE(exidx_->Decode());
932  ASSERT_FALSE(exidx_->pc_set());
933  ASSERT_EQ("", GetFakeLogBuf());
934  if (log_) {
935    ASSERT_EQ("4 unwind pop {d15-d30}\n", GetFakeLogPrint());
936  } else {
937    ASSERT_EQ("", GetFakeLogPrint());
938  }
939  ASSERT_EQ(0x100a8U, exidx_->cfa());
940}
941
942TEST_P(ArmExidxDecodeTest, pop_vfp8_vpush) {
943  // 11010nnn: Pop VFP double precision registers D[8]-D[8+nnn] by VPUSH
944  data_->push_back(0xd0);
945  ASSERT_TRUE(exidx_->Decode());
946  ASSERT_FALSE(exidx_->pc_set());
947  ASSERT_EQ("", GetFakeLogBuf());
948  if (log_) {
949    ASSERT_EQ("4 unwind pop {d8}\n", GetFakeLogPrint());
950  } else {
951    ASSERT_EQ("", GetFakeLogPrint());
952  }
953  ASSERT_EQ(0x10008U, exidx_->cfa());
954
955  ResetLogs();
956  data_->push_back(0xd2);
957  ASSERT_TRUE(exidx_->Decode());
958  ASSERT_FALSE(exidx_->pc_set());
959  ASSERT_EQ("", GetFakeLogBuf());
960  if (log_) {
961    ASSERT_EQ("4 unwind pop {d8-d10}\n", GetFakeLogPrint());
962  } else {
963    ASSERT_EQ("", GetFakeLogPrint());
964  }
965  ASSERT_EQ(0x10020U, exidx_->cfa());
966
967  ResetLogs();
968  data_->push_back(0xd7);
969  ASSERT_TRUE(exidx_->Decode());
970  ASSERT_FALSE(exidx_->pc_set());
971  ASSERT_EQ("", GetFakeLogBuf());
972  if (log_) {
973    ASSERT_EQ("4 unwind pop {d8-d15}\n", GetFakeLogPrint());
974  } else {
975    ASSERT_EQ("", GetFakeLogPrint());
976  }
977  ASSERT_EQ(0x10060U, exidx_->cfa());
978}
979
980TEST_P(ArmExidxDecodeTest, expect_truncated) {
981  // This test verifies that any op that requires extra ops will
982  // fail if the data is not present.
983  data_->push_back(0x80);
984  ASSERT_FALSE(exidx_->Decode());
985  ASSERT_EQ(ARM_STATUS_TRUNCATED, exidx_->status());
986
987  data_->clear();
988  data_->push_back(0xb1);
989  ASSERT_FALSE(exidx_->Decode());
990  ASSERT_EQ(ARM_STATUS_TRUNCATED, exidx_->status());
991
992  data_->clear();
993  data_->push_back(0xb2);
994  ASSERT_FALSE(exidx_->Decode());
995  ASSERT_EQ(ARM_STATUS_TRUNCATED, exidx_->status());
996
997  data_->clear();
998  data_->push_back(0xb3);
999  ASSERT_FALSE(exidx_->Decode());
1000  ASSERT_EQ(ARM_STATUS_TRUNCATED, exidx_->status());
1001
1002  data_->clear();
1003  data_->push_back(0xc6);
1004  ASSERT_FALSE(exidx_->Decode());
1005  ASSERT_EQ(ARM_STATUS_TRUNCATED, exidx_->status());
1006
1007  data_->clear();
1008  data_->push_back(0xc7);
1009  ASSERT_FALSE(exidx_->Decode());
1010  ASSERT_EQ(ARM_STATUS_TRUNCATED, exidx_->status());
1011
1012  data_->clear();
1013  data_->push_back(0xc8);
1014  ASSERT_FALSE(exidx_->Decode());
1015  ASSERT_EQ(ARM_STATUS_TRUNCATED, exidx_->status());
1016
1017  data_->clear();
1018  data_->push_back(0xc9);
1019  ASSERT_FALSE(exidx_->Decode());
1020  ASSERT_EQ(ARM_STATUS_TRUNCATED, exidx_->status());
1021}
1022
1023TEST_P(ArmExidxDecodeTest, verify_no_truncated) {
1024  // This test verifies that no pattern results in a crash or truncation.
1025  MemoryFakeAlwaysReadZero memory_zero;
1026  Init(&memory_zero);
1027
1028  for (size_t x = 0; x < 256; x++) {
1029    if (x == 0xb2) {
1030      // This opcode is followed by an uleb128, so just skip this one.
1031      continue;
1032    }
1033    for (size_t y = 0; y < 256; y++) {
1034      data_->clear();
1035      data_->push_back(x);
1036      data_->push_back(y);
1037      if (!exidx_->Decode()) {
1038        ASSERT_NE(ARM_STATUS_TRUNCATED, exidx_->status())
1039            << "x y = 0x" << std::hex << x << " 0x" << y;
1040        ASSERT_NE(ARM_STATUS_READ_FAILED, exidx_->status())
1041            << "x y = 0x" << std::hex << x << " 0x" << y;
1042      }
1043    }
1044  }
1045}
1046
1047TEST_P(ArmExidxDecodeTest, eval_multiple_decodes) {
1048  // vsp = vsp + 4
1049  data_->push_back(0x00);
1050  // vsp = vsp + 8
1051  data_->push_back(0x02);
1052  // Finish
1053  data_->push_back(0xb0);
1054
1055  ASSERT_TRUE(exidx_->Eval());
1056  if (log_) {
1057    ASSERT_EQ("4 unwind vsp = vsp + 4\n"
1058              "4 unwind vsp = vsp + 12\n"
1059              "4 unwind finish\n", GetFakeLogPrint());
1060  } else {
1061    ASSERT_EQ("", GetFakeLogPrint());
1062  }
1063  ASSERT_EQ(0x10010U, exidx_->cfa());
1064  ASSERT_FALSE(exidx_->pc_set());
1065}
1066
1067TEST_P(ArmExidxDecodeTest, eval_pc_set) {
1068  // vsp = vsp + 4
1069  data_->push_back(0x00);
1070  // vsp = vsp + 8
1071  data_->push_back(0x02);
1072  // Pop {r15}
1073  data_->push_back(0x88);
1074  data_->push_back(0x00);
1075  // vsp = vsp + 8
1076  data_->push_back(0x02);
1077  // Finish
1078  data_->push_back(0xb0);
1079
1080  process_memory_.SetData32(0x10010, 0x10);
1081
1082  ASSERT_TRUE(exidx_->Eval());
1083  if (log_) {
1084    ASSERT_EQ("4 unwind vsp = vsp + 4\n"
1085              "4 unwind vsp = vsp + 12\n"
1086              "4 unwind pop {r15}\n"
1087              "4 unwind vsp = vsp + 12\n"
1088              "4 unwind finish\n", GetFakeLogPrint());
1089  } else {
1090    ASSERT_EQ("", GetFakeLogPrint());
1091  }
1092  ASSERT_EQ(0x10020U, exidx_->cfa());
1093  ASSERT_TRUE(exidx_->pc_set());
1094  ASSERT_EQ(0x10U, (*exidx_->regs())[15]);
1095}
1096
1097INSTANTIATE_TEST_CASE_P(, ArmExidxDecodeTest, ::testing::Values("logging", "no_logging"));
1098
1099}  // namespace unwindstack
1100