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