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