blob: 3b78918c08b09a93e771d1d1b8161f862cc9aa61 [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 <assert.h>
18#include <stdint.h>
19
20#include <deque>
21#include <string>
22
23#include <android-base/stringprintf.h>
24
25#include "ArmExidx.h"
26#include "Log.h"
27#include "Machine.h"
28
29void ArmExidx::LogRawData() {
30 std::string log_str("Raw Data:");
31 for (const uint8_t data : data_) {
32 log_str += android::base::StringPrintf(" 0x%02x", data);
33 }
34 log(log_indent_, log_str.c_str());
35}
36
37bool ArmExidx::ExtractEntryData(uint32_t entry_offset) {
38 data_.clear();
39 status_ = ARM_STATUS_NONE;
40
41 if (entry_offset & 1) {
42 // The offset needs to be at least two byte aligned.
43 status_ = ARM_STATUS_INVALID_ALIGNMENT;
44 return false;
45 }
46
47 // Each entry is a 32 bit prel31 offset followed by 32 bits
48 // of unwind information. If bit 31 of the unwind data is zero,
49 // then this is a prel31 offset to the start of the unwind data.
50 // If the unwind data is 1, then this is a cant unwind entry.
51 // Otherwise, this data is the compact form of the unwind information.
52 uint32_t data;
53 if (!elf_memory_->Read32(entry_offset + 4, &data)) {
54 status_ = ARM_STATUS_READ_FAILED;
55 return false;
56 }
57 if (data == 1) {
58 // This is a CANT UNWIND entry.
59 status_ = ARM_STATUS_NO_UNWIND;
60 if (log_) {
61 log(log_indent_, "Raw Data: 0x00 0x00 0x00 0x01");
62 log(log_indent_, "[cantunwind]");
63 }
64 return false;
65 }
66
67 if (data & (1UL << 31)) {
68 // This is a compact table entry.
69 if ((data >> 24) & 0xf) {
70 // This is a non-zero index, this code doesn't support
71 // other formats.
72 status_ = ARM_STATUS_INVALID_PERSONALITY;
73 return false;
74 }
75 data_.push_back((data >> 16) & 0xff);
76 data_.push_back((data >> 8) & 0xff);
77 uint8_t last_op = data & 0xff;
78 data_.push_back(last_op);
79 if (last_op != ARM_OP_FINISH) {
80 // If this didn't end with a finish op, add one.
81 data_.push_back(ARM_OP_FINISH);
82 }
83 if (log_) {
84 LogRawData();
85 }
86 return true;
87 }
88
89 // Get the address of the ops.
90 // Sign extend the data value if necessary.
91 int32_t signed_data = static_cast<int32_t>(data << 1) >> 1;
92 uint32_t addr = (entry_offset + 4) + signed_data;
93 if (!elf_memory_->Read32(addr, &data)) {
94 status_ = ARM_STATUS_READ_FAILED;
95 return false;
96 }
97
98 size_t num_table_words;
99 if (data & (1UL << 31)) {
100 // Compact model.
101 switch ((data >> 24) & 0xf) {
102 case 0:
103 num_table_words = 0;
104 data_.push_back((data >> 16) & 0xff);
105 break;
106 case 1:
107 case 2:
108 num_table_words = (data >> 16) & 0xff;
109 addr += 4;
110 break;
111 default:
112 // Only a personality of 0, 1, 2 is valid.
113 status_ = ARM_STATUS_INVALID_PERSONALITY;
114 return false;
115 }
116 data_.push_back((data >> 8) & 0xff);
117 data_.push_back(data & 0xff);
118 } else {
119 // Generic model.
120
121 // Skip the personality routine data, it doesn't contain any data
122 // needed to decode the unwind information.
123 addr += 4;
124 if (!elf_memory_->Read32(addr, &data)) {
125 status_ = ARM_STATUS_READ_FAILED;
126 return false;
127 }
128 num_table_words = (data >> 24) & 0xff;
129 data_.push_back((data >> 16) & 0xff);
130 data_.push_back((data >> 8) & 0xff);
131 data_.push_back(data & 0xff);
132 addr += 4;
133 }
134
135 if (num_table_words > 5) {
136 status_ = ARM_STATUS_MALFORMED;
137 return false;
138 }
139
140 for (size_t i = 0; i < num_table_words; i++) {
141 if (!elf_memory_->Read32(addr, &data)) {
142 status_ = ARM_STATUS_READ_FAILED;
143 return false;
144 }
145 data_.push_back((data >> 24) & 0xff);
146 data_.push_back((data >> 16) & 0xff);
147 data_.push_back((data >> 8) & 0xff);
148 data_.push_back(data & 0xff);
149 addr += 4;
150 }
151
152 if (data_.back() != ARM_OP_FINISH) {
153 // If this didn't end with a finish op, add one.
154 data_.push_back(ARM_OP_FINISH);
155 }
156
157 if (log_) {
158 LogRawData();
159 }
160 return true;
161}
162
163inline bool ArmExidx::GetByte(uint8_t* byte) {
164 if (data_.empty()) {
165 status_ = ARM_STATUS_TRUNCATED;
166 return false;
167 }
168 *byte = data_.front();
169 data_.pop_front();
170 return true;
171}
172
173inline bool ArmExidx::DecodePrefix_10_00(uint8_t byte) {
174 assert((byte >> 4) == 0x8);
175
176 uint16_t registers = (byte & 0xf) << 8;
177 if (!GetByte(&byte)) {
178 return false;
179 }
180
181 registers |= byte;
182 if (registers == 0) {
183 // 10000000 00000000: Refuse to unwind
184 if (log_) {
185 log(log_indent_, "Refuse to unwind");
186 }
187 status_ = ARM_STATUS_NO_UNWIND;
188 return false;
189 }
190 // 1000iiii iiiiiiii: Pop up to 12 integer registers under masks {r15-r12}, {r11-r4}
191 if (log_) {
192 bool add_comma = false;
193 std::string msg = "pop {";
194 for (size_t i = 0; i < 12; i++) {
195 if (registers & (1 << i)) {
196 if (add_comma) {
197 msg += ", ";
198 }
199 msg += android::base::StringPrintf("r%zu", i + 4);
200 add_comma = true;
201 }
202 }
203 log(log_indent_, "%s}", msg.c_str());
204 if (log_skip_execution_) {
205 return true;
206 }
207 }
208
209 registers <<= 4;
210 for (size_t reg = 4; reg < 16; reg++) {
211 if (registers & (1 << reg)) {
212 if (!process_memory_->Read32(cfa_, &(*regs_)[reg])) {
213 status_ = ARM_STATUS_READ_FAILED;
214 return false;
215 }
216 cfa_ += 4;
217 }
218 }
219 // If the sp register is modified, change the cfa value.
220 if (registers & (1 << ARM_REG_SP)) {
221 cfa_ = (*regs_)[ARM_REG_SP];
222 }
223 return true;
224}
225
226inline bool ArmExidx::DecodePrefix_10_01(uint8_t byte) {
227 assert((byte >> 4) == 0x9);
228
229 uint8_t bits = byte & 0xf;
230 if (bits == 13 || bits == 15) {
231 // 10011101: Reserved as prefix for ARM register to register moves
232 // 10011111: Reserved as prefix for Intel Wireless MMX register to register moves
233 if (log_) {
234 log(log_indent_, "[Reserved]");
235 }
236 status_ = ARM_STATUS_RESERVED;
237 return false;
238 }
239 // 1001nnnn: Set vsp = r[nnnn] (nnnn != 13, 15)
240 if (log_) {
241 log(log_indent_, "vsp = r%d", bits);
242 if (log_skip_execution_) {
243 return true;
244 }
245 }
246 // It is impossible for bits to be larger than the total number of
247 // arm registers, so don't bother checking if bits is a valid register.
248 cfa_ = (*regs_)[bits];
249 return true;
250}
251
252inline bool ArmExidx::DecodePrefix_10_10(uint8_t byte) {
253 assert((byte >> 4) == 0xa);
254
255 // 10100nnn: Pop r4-r[4+nnn]
256 // 10101nnn: Pop r4-r[4+nnn], r14
257 if (log_) {
258 std::string msg = "pop {r4";
259 uint8_t end_reg = byte & 0x7;
260 if (end_reg) {
261 msg += android::base::StringPrintf("-r%d", 4 + end_reg);
262 }
263 if (byte & 0x8) {
264 log(log_indent_, "%s, r14}", msg.c_str());
265 } else {
266 log(log_indent_, "%s}", msg.c_str());
267 }
268 if (log_skip_execution_) {
269 return true;
270 }
271 }
272
273 for (size_t i = 4; i <= 4 + (byte & 0x7); i++) {
274 if (!process_memory_->Read32(cfa_, &(*regs_)[i])) {
275 status_ = ARM_STATUS_READ_FAILED;
276 return false;
277 }
278 cfa_ += 4;
279 }
280 if (byte & 0x8) {
281 if (!process_memory_->Read32(cfa_, &(*regs_)[ARM_REG_R14])) {
282 status_ = ARM_STATUS_READ_FAILED;
283 return false;
284 }
285 cfa_ += 4;
286 }
287 return true;
288}
289
290inline bool ArmExidx::DecodePrefix_10_11_0000() {
291 // 10110000: Finish
292 if (log_) {
293 log(log_indent_, "finish");
294 if (log_skip_execution_) {
295 status_ = ARM_STATUS_FINISH;
296 return false;
297 }
298 }
299 if (!(*regs_)[ARM_REG_PC]) {
300 (*regs_)[ARM_REG_PC] = (*regs_)[ARM_REG_LR];
301 }
302 status_ = ARM_STATUS_FINISH;
303 return false;
304}
305
306inline bool ArmExidx::DecodePrefix_10_11_0001() {
307 uint8_t byte;
308 if (!GetByte(&byte)) {
309 return false;
310 }
311
312 if (byte == 0) {
313 // 10110001 00000000: Spare
314 if (log_) {
315 log(log_indent_, "Spare");
316 }
317 status_ = ARM_STATUS_SPARE;
318 return false;
319 }
320 if (byte >> 4) {
321 // 10110001 xxxxyyyy: Spare (xxxx != 0000)
322 if (log_) {
323 log(log_indent_, "Spare");
324 }
325 status_ = ARM_STATUS_SPARE;
326 return false;
327 }
328
329 // 10110001 0000iiii: Pop integer registers under mask {r3, r2, r1, r0}
330 if (log_) {
331 bool add_comma = false;
332 std::string msg = "pop {";
333 for (size_t i = 0; i < 4; i++) {
334 if (byte & (1 << i)) {
335 if (add_comma) {
336 msg += ", ";
337 }
338 msg += android::base::StringPrintf("r%zu", i);
339 add_comma = true;
340 }
341 }
342 log(log_indent_, "%s}", msg.c_str());
343 if (log_skip_execution_) {
344 return true;
345 }
346 }
347
348 for (size_t reg = 0; reg < 4; reg++) {
349 if (byte & (1 << reg)) {
350 if (!process_memory_->Read32(cfa_, &(*regs_)[reg])) {
351 status_ = ARM_STATUS_READ_FAILED;
352 return false;
353 }
354 cfa_ += 4;
355 }
356 }
357 return true;
358}
359
360inline bool ArmExidx::DecodePrefix_10_11_0010() {
361 // 10110010 uleb128: vsp = vsp + 0x204 + (uleb128 << 2)
362 uint32_t result = 0;
363 uint32_t shift = 0;
364 uint8_t byte;
365 do {
366 if (!GetByte(&byte)) {
367 return false;
368 }
369
370 result |= (byte & 0x7f) << shift;
371 shift += 7;
372 } while (byte & 0x80);
373 result <<= 2;
374 if (log_) {
375 log(log_indent_, "vsp = vsp + %d", 0x204 + result);
376 if (log_skip_execution_) {
377 return true;
378 }
379 }
380 cfa_ += 0x204 + result;
381 return true;
382}
383
384inline bool ArmExidx::DecodePrefix_10_11_0011() {
385 // 10110011 sssscccc: Pop VFP double precision registers D[ssss]-D[ssss+cccc] by FSTMFDX
386 uint8_t byte;
387 if (!GetByte(&byte)) {
388 return false;
389 }
390
391 if (log_) {
392 uint8_t start_reg = byte >> 4;
393 std::string msg = android::base::StringPrintf("pop {d%d", start_reg);
394 uint8_t end_reg = start_reg + (byte & 0xf);
395 if (end_reg) {
396 msg += android::base::StringPrintf("-d%d", end_reg);
397 }
398 log(log_indent_, "%s}", msg.c_str());
399 if (log_skip_execution_) {
400 return true;
401 }
402 }
403 cfa_ += (byte & 0xf) * 8 + 12;
404 return true;
405}
406
407inline bool ArmExidx::DecodePrefix_10_11_01nn() {
408 // 101101nn: Spare
409 if (log_) {
410 log(log_indent_, "Spare");
411 }
412 status_ = ARM_STATUS_SPARE;
413 return false;
414}
415
416inline bool ArmExidx::DecodePrefix_10_11_1nnn(uint8_t byte) {
417 assert((byte & ~0x07) == 0xb8);
418
419 // 10111nnn: Pop VFP double-precision registers D[8]-D[8+nnn] by FSTMFDX
420 if (log_) {
421 std::string msg = "pop {d8";
422 uint8_t last_reg = (byte & 0x7);
423 if (last_reg) {
424 msg += android::base::StringPrintf("-d%d", last_reg + 8);
425 }
426 log(log_indent_, "%s}", msg.c_str());
427 if (log_skip_execution_) {
428 return true;
429 }
430 }
431 // Only update the cfa.
432 cfa_ += (byte & 0x7) * 8 + 12;
433 return true;
434}
435
436inline bool ArmExidx::DecodePrefix_10(uint8_t byte) {
437 assert((byte >> 6) == 0x2);
438
439 switch ((byte >> 4) & 0x3) {
440 case 0:
441 return DecodePrefix_10_00(byte);
442 case 1:
443 return DecodePrefix_10_01(byte);
444 case 2:
445 return DecodePrefix_10_10(byte);
446 default:
447 switch (byte & 0xf) {
448 case 0:
449 return DecodePrefix_10_11_0000();
450 case 1:
451 return DecodePrefix_10_11_0001();
452 case 2:
453 return DecodePrefix_10_11_0010();
454 case 3:
455 return DecodePrefix_10_11_0011();
456 default:
457 if (byte & 0x8) {
458 return DecodePrefix_10_11_1nnn(byte);
459 } else {
460 return DecodePrefix_10_11_01nn();
461 }
462 }
463 }
464}
465
466inline bool ArmExidx::DecodePrefix_11_000(uint8_t byte) {
467 assert((byte & ~0x07) == 0xc0);
468
469 uint8_t bits = byte & 0x7;
470 if (bits == 6) {
471 if (!GetByte(&byte)) {
472 return false;
473 }
474
475 // 11000110 sssscccc: Intel Wireless MMX pop wR[ssss]-wR[ssss+cccc]
476 if (log_) {
477 uint8_t start_reg = byte >> 4;
478 std::string msg = android::base::StringPrintf("pop {wR%d", start_reg);
479 uint8_t end_reg = byte & 0xf;
480 if (end_reg) {
481 msg += android::base::StringPrintf("-wR%d", start_reg + end_reg);
482 }
483 log(log_indent_, "%s}", msg.c_str());
484 if (log_skip_execution_) {
485 return true;
486 }
487 }
488 // Only update the cfa.
489 cfa_ += (byte & 0xf) * 8 + 8;
490 } else if (bits == 7) {
491 if (!GetByte(&byte)) {
492 return false;
493 }
494
495 if (byte == 0) {
496 // 11000111 00000000: Spare
497 if (log_) {
498 log(log_indent_, "Spare");
499 }
500 status_ = ARM_STATUS_SPARE;
501 return false;
502 } else if ((byte >> 4) == 0) {
503 // 11000111 0000iiii: Intel Wireless MMX pop wCGR registers {wCGR0,1,2,3}
504 if (log_) {
505 bool add_comma = false;
506 std::string msg = "pop {";
507 for (size_t i = 0; i < 4; i++) {
508 if (byte & (1 << i)) {
509 if (add_comma) {
510 msg += ", ";
511 }
512 msg += android::base::StringPrintf("wCGR%zu", i);
513 add_comma = true;
514 }
515 }
516 log(log_indent_, "%s}", msg.c_str());
517 }
518 // Only update the cfa.
519 cfa_ += __builtin_popcount(byte) * 4;
520 } else {
521 // 11000111 xxxxyyyy: Spare (xxxx != 0000)
522 if (log_) {
523 log(log_indent_, "Spare");
524 }
525 status_ = ARM_STATUS_SPARE;
526 return false;
527 }
528 } else {
529 // 11000nnn: Intel Wireless MMX pop wR[10]-wR[10+nnn] (nnn != 6, 7)
530 if (log_) {
531 std::string msg = "pop {wR10";
532 uint8_t nnn = byte & 0x7;
533 if (nnn) {
534 msg += android::base::StringPrintf("-wR%d", 10 + nnn);
535 }
536 log(log_indent_, "%s}", msg.c_str());
537 if (log_skip_execution_) {
538 return true;
539 }
540 }
541 // Only update the cfa.
542 cfa_ += (byte & 0x7) * 8 + 8;
543 }
544 return true;
545}
546
547inline bool ArmExidx::DecodePrefix_11_001(uint8_t byte) {
548 assert((byte & ~0x07) == 0xc8);
549
550 uint8_t bits = byte & 0x7;
551 if (bits == 0) {
552 // 11001000 sssscccc: Pop VFP double precision registers D[16+ssss]-D[16+ssss+cccc] by VPUSH
553 if (!GetByte(&byte)) {
554 return false;
555 }
556
557 if (log_) {
558 uint8_t start_reg = byte >> 4;
559 std::string msg = android::base::StringPrintf("pop {d%d", 16 + start_reg);
560 uint8_t end_reg = byte & 0xf;
561 if (end_reg) {
562 msg += android::base::StringPrintf("-d%d", 16 + start_reg + end_reg);
563 }
564 log(log_indent_, "%s}", msg.c_str());
565 if (log_skip_execution_) {
566 return true;
567 }
568 }
569 // Only update the cfa.
570 cfa_ += (byte & 0xf) * 8 + 8;
571 } else if (bits == 1) {
572 // 11001001 sssscccc: Pop VFP double precision registers D[ssss]-D[ssss+cccc] by VPUSH
573 if (!GetByte(&byte)) {
574 return false;
575 }
576
577 if (log_) {
578 uint8_t start_reg = byte >> 4;
579 std::string msg = android::base::StringPrintf("pop {d%d", start_reg);
580 uint8_t end_reg = byte & 0xf;
581 if (end_reg) {
582 msg += android::base::StringPrintf("-d%d", start_reg + end_reg);
583 }
584 log(log_indent_, "%s}", msg.c_str());
585 if (log_skip_execution_) {
586 return true;
587 }
588 }
589 // Only update the cfa.
590 cfa_ += (byte & 0xf) * 8 + 8;
591 } else {
592 // 11001yyy: Spare (yyy != 000, 001)
593 if (log_) {
594 log(log_indent_, "Spare");
595 }
596 status_ = ARM_STATUS_SPARE;
597 return false;
598 }
599 return true;
600}
601
602inline bool ArmExidx::DecodePrefix_11_010(uint8_t byte) {
603 assert((byte & ~0x07) == 0xd0);
604
605 // 11010nnn: Pop VFP double precision registers D[8]-D[8+nnn] by VPUSH
606 if (log_) {
607 std::string msg = "pop {d8";
608 uint8_t end_reg = byte & 0x7;
609 if (end_reg) {
610 msg += android::base::StringPrintf("-d%d", 8 + end_reg);
611 }
612 log(log_indent_, "%s}", msg.c_str());
613 if (log_skip_execution_) {
614 return true;
615 }
616 }
617 cfa_ += (byte & 0x7) * 8 + 8;
618 return true;
619}
620
621inline bool ArmExidx::DecodePrefix_11(uint8_t byte) {
622 assert((byte >> 6) == 0x3);
623
624 switch ((byte >> 3) & 0x7) {
625 case 0:
626 return DecodePrefix_11_000(byte);
627 case 1:
628 return DecodePrefix_11_001(byte);
629 case 2:
630 return DecodePrefix_11_010(byte);
631 default:
632 // 11xxxyyy: Spare (xxx != 000, 001, 010)
633 if (log_) {
634 log(log_indent_, "Spare");
635 }
636 status_ = ARM_STATUS_SPARE;
637 return false;
638 }
639}
640
641bool ArmExidx::Decode() {
642 status_ = ARM_STATUS_NONE;
643 uint8_t byte;
644 if (!GetByte(&byte)) {
645 return false;
646 }
647
648 switch (byte >> 6) {
649 case 0:
650 // 00xxxxxx: vsp = vsp + (xxxxxxx << 2) + 4
651 if (log_) {
652 log(log_indent_, "vsp = vsp + %d", ((byte & 0x3f) << 2) + 4);
653 if (log_skip_execution_) {
654 break;
655 }
656 }
657 cfa_ += ((byte & 0x3f) << 2) + 4;
658 break;
659 case 1:
660 // 01xxxxxx: vsp = vsp - (xxxxxxx << 2) + 4
661 if (log_) {
662 log(log_indent_, "vsp = vsp - %d", ((byte & 0x3f) << 2) + 4);
663 if (log_skip_execution_) {
664 break;
665 }
666 }
667 cfa_ -= ((byte & 0x3f) << 2) + 4;
668 break;
669 case 2:
670 return DecodePrefix_10(byte);
671 default:
672 return DecodePrefix_11(byte);
673 }
674 return true;
675}
676
677bool ArmExidx::Eval() {
678 while (Decode());
679 return status_ == ARM_STATUS_FINISH;
680}