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