Mercurial > hg > CbC > CbC_llvm
comparison tools/llvm-readobj/ARMWinEHPrinter.cpp @ 148:63bd29f05246
merged
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Wed, 14 Aug 2019 19:46:37 +0900 |
parents | c2174574ed3a |
children |
comparison
equal
deleted
inserted
replaced
146:3fc4d5c3e21e | 148:63bd29f05246 |
---|---|
1 //===-- ARMWinEHPrinter.cpp - Windows on ARM EH Data Printer ----*- C++ -*-===// | 1 //===-- ARMWinEHPrinter.cpp - Windows on ARM EH Data Printer ----*- C++ -*-===// |
2 // | 2 // |
3 // The LLVM Compiler Infrastructure | 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 // | 4 // See https://llvm.org/LICENSE.txt for license information. |
5 // This file is distributed under the University of Illinois Open Source | 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 // License. See LICENSE.TXT for details. | |
7 // | 6 // |
8 //===----------------------------------------------------------------------===// | 7 //===----------------------------------------------------------------------===// |
9 | 8 |
10 // Windows on ARM uses a series of serialised data structures (RuntimeFunction) | 9 // Windows on ARM uses a series of serialised data structures (RuntimeFunction) |
11 // to create a table of information for unwinding. In order to conserve space, | 10 // to create a table of information for unwinding. In order to conserve space, |
31 // split up into two portions, with the actual data residing in the "exception | 30 // split up into two portions, with the actual data residing in the "exception |
32 // data" table (.xdata) with a reference to the entry from the "procedure data" | 31 // data" table (.xdata) with a reference to the entry from the "procedure data" |
33 // (.pdata) entry. | 32 // (.pdata) entry. |
34 // | 33 // |
35 // The exception data contains information about the frame setup, all of the | 34 // The exception data contains information about the frame setup, all of the |
36 // epilouge scopes (for functions for which there are multiple exit points) and | 35 // epilogue scopes (for functions for which there are multiple exit points) and |
37 // the associated exception handler. Additionally, the entry contains byte-code | 36 // the associated exception handler. Additionally, the entry contains byte-code |
38 // describing how to unwind the function (c.f. Decoder::decodeOpcodes). | 37 // describing how to unwind the function (c.f. Decoder::decodeOpcodes). |
39 // | 38 // |
40 // +---------------------------------------+ | 39 // +---------------------------------------+ |
41 // | Function Entry Address | | 40 // | Function Entry Address | |
116 namespace WinEH { | 115 namespace WinEH { |
117 const size_t Decoder::PDataEntrySize = sizeof(RuntimeFunction); | 116 const size_t Decoder::PDataEntrySize = sizeof(RuntimeFunction); |
118 | 117 |
119 // TODO name the uops more appropriately | 118 // TODO name the uops more appropriately |
120 const Decoder::RingEntry Decoder::Ring[] = { | 119 const Decoder::RingEntry Decoder::Ring[] = { |
121 { 0x80, 0x00, &Decoder::opcode_0xxxxxxx }, // UOP_STACK_FREE (16-bit) | 120 { 0x80, 0x00, 1, &Decoder::opcode_0xxxxxxx }, // UOP_STACK_FREE (16-bit) |
122 { 0xc0, 0x80, &Decoder::opcode_10Lxxxxx }, // UOP_POP (32-bit) | 121 { 0xc0, 0x80, 2, &Decoder::opcode_10Lxxxxx }, // UOP_POP (32-bit) |
123 { 0xf0, 0xc0, &Decoder::opcode_1100xxxx }, // UOP_STACK_SAVE (16-bit) | 122 { 0xf0, 0xc0, 1, &Decoder::opcode_1100xxxx }, // UOP_STACK_SAVE (16-bit) |
124 { 0xf8, 0xd0, &Decoder::opcode_11010Lxx }, // UOP_POP (16-bit) | 123 { 0xf8, 0xd0, 1, &Decoder::opcode_11010Lxx }, // UOP_POP (16-bit) |
125 { 0xf8, 0xd8, &Decoder::opcode_11011Lxx }, // UOP_POP (32-bit) | 124 { 0xf8, 0xd8, 1, &Decoder::opcode_11011Lxx }, // UOP_POP (32-bit) |
126 { 0xf8, 0xe0, &Decoder::opcode_11100xxx }, // UOP_VPOP (32-bit) | 125 { 0xf8, 0xe0, 1, &Decoder::opcode_11100xxx }, // UOP_VPOP (32-bit) |
127 { 0xfc, 0xe8, &Decoder::opcode_111010xx }, // UOP_STACK_FREE (32-bit) | 126 { 0xfc, 0xe8, 2, &Decoder::opcode_111010xx }, // UOP_STACK_FREE (32-bit) |
128 { 0xfe, 0xec, &Decoder::opcode_1110110L }, // UOP_POP (16-bit) | 127 { 0xfe, 0xec, 2, &Decoder::opcode_1110110L }, // UOP_POP (16-bit) |
129 { 0xff, 0xee, &Decoder::opcode_11101110 }, // UOP_MICROSOFT_SPECIFIC (16-bit) | 128 { 0xff, 0xee, 2, &Decoder::opcode_11101110 }, // UOP_MICROSOFT_SPECIFIC (16-bit) |
130 // UOP_PUSH_MACHINE_FRAME | 129 // UOP_PUSH_MACHINE_FRAME |
131 // UOP_PUSH_CONTEXT | 130 // UOP_PUSH_CONTEXT |
132 // UOP_PUSH_TRAP_FRAME | 131 // UOP_PUSH_TRAP_FRAME |
133 // UOP_REDZONE_RESTORE_LR | 132 // UOP_REDZONE_RESTORE_LR |
134 { 0xff, 0xef, &Decoder::opcode_11101111 }, // UOP_LDRPC_POSTINC (32-bit) | 133 { 0xff, 0xef, 2, &Decoder::opcode_11101111 }, // UOP_LDRPC_POSTINC (32-bit) |
135 { 0xff, 0xf5, &Decoder::opcode_11110101 }, // UOP_VPOP (32-bit) | 134 { 0xff, 0xf5, 2, &Decoder::opcode_11110101 }, // UOP_VPOP (32-bit) |
136 { 0xff, 0xf6, &Decoder::opcode_11110110 }, // UOP_VPOP (32-bit) | 135 { 0xff, 0xf6, 2, &Decoder::opcode_11110110 }, // UOP_VPOP (32-bit) |
137 { 0xff, 0xf7, &Decoder::opcode_11110111 }, // UOP_STACK_RESTORE (16-bit) | 136 { 0xff, 0xf7, 3, &Decoder::opcode_11110111 }, // UOP_STACK_RESTORE (16-bit) |
138 { 0xff, 0xf8, &Decoder::opcode_11111000 }, // UOP_STACK_RESTORE (16-bit) | 137 { 0xff, 0xf8, 4, &Decoder::opcode_11111000 }, // UOP_STACK_RESTORE (16-bit) |
139 { 0xff, 0xf9, &Decoder::opcode_11111001 }, // UOP_STACK_RESTORE (32-bit) | 138 { 0xff, 0xf9, 3, &Decoder::opcode_11111001 }, // UOP_STACK_RESTORE (32-bit) |
140 { 0xff, 0xfa, &Decoder::opcode_11111010 }, // UOP_STACK_RESTORE (32-bit) | 139 { 0xff, 0xfa, 4, &Decoder::opcode_11111010 }, // UOP_STACK_RESTORE (32-bit) |
141 { 0xff, 0xfb, &Decoder::opcode_11111011 }, // UOP_NOP (16-bit) | 140 { 0xff, 0xfb, 1, &Decoder::opcode_11111011 }, // UOP_NOP (16-bit) |
142 { 0xff, 0xfc, &Decoder::opcode_11111100 }, // UOP_NOP (32-bit) | 141 { 0xff, 0xfc, 1, &Decoder::opcode_11111100 }, // UOP_NOP (32-bit) |
143 { 0xff, 0xfd, &Decoder::opcode_11111101 }, // UOP_NOP (16-bit) / END | 142 { 0xff, 0xfd, 1, &Decoder::opcode_11111101 }, // UOP_NOP (16-bit) / END |
144 { 0xff, 0xfe, &Decoder::opcode_11111110 }, // UOP_NOP (32-bit) / END | 143 { 0xff, 0xfe, 1, &Decoder::opcode_11111110 }, // UOP_NOP (32-bit) / END |
145 { 0xff, 0xff, &Decoder::opcode_11111111 }, // UOP_END | 144 { 0xff, 0xff, 1, &Decoder::opcode_11111111 }, // UOP_END |
145 }; | |
146 | |
147 | |
148 // Unwind opcodes for ARM64. | |
149 // https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling | |
150 const Decoder::RingEntry Decoder::Ring64[] = { | |
151 { 0xe0, 0x00, 1, &Decoder::opcode_alloc_s }, | |
152 { 0xe0, 0x20, 1, &Decoder::opcode_save_r19r20_x }, | |
153 { 0xc0, 0x40, 1, &Decoder::opcode_save_fplr }, | |
154 { 0xc0, 0x80, 1, &Decoder::opcode_save_fplr_x }, | |
155 { 0xf8, 0xc0, 2, &Decoder::opcode_alloc_m }, | |
156 { 0xfc, 0xc8, 2, &Decoder::opcode_save_regp }, | |
157 { 0xfc, 0xcc, 2, &Decoder::opcode_save_regp_x }, | |
158 { 0xfc, 0xd0, 2, &Decoder::opcode_save_reg }, | |
159 { 0xfe, 0xd4, 2, &Decoder::opcode_save_reg_x }, | |
160 { 0xfe, 0xd6, 2, &Decoder::opcode_save_lrpair }, | |
161 { 0xfe, 0xd8, 2, &Decoder::opcode_save_fregp }, | |
162 { 0xfe, 0xda, 2, &Decoder::opcode_save_fregp_x }, | |
163 { 0xfe, 0xdc, 2, &Decoder::opcode_save_freg }, | |
164 { 0xff, 0xde, 2, &Decoder::opcode_save_freg_x }, | |
165 { 0xff, 0xe0, 4, &Decoder::opcode_alloc_l }, | |
166 { 0xff, 0xe1, 1, &Decoder::opcode_setfp }, | |
167 { 0xff, 0xe2, 2, &Decoder::opcode_addfp }, | |
168 { 0xff, 0xe3, 1, &Decoder::opcode_nop }, | |
169 { 0xff, 0xe4, 1, &Decoder::opcode_end }, | |
170 { 0xff, 0xe5, 1, &Decoder::opcode_end_c }, | |
146 }; | 171 }; |
147 | 172 |
148 void Decoder::printRegisters(const std::pair<uint16_t, uint32_t> &RegisterMask) { | 173 void Decoder::printRegisters(const std::pair<uint16_t, uint32_t> &RegisterMask) { |
149 static const char * const GPRRegisterNames[16] = { | 174 static const char * const GPRRegisterNames[16] = { |
150 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", | 175 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", |
491 unsigned Length, bool Prologue) { | 516 unsigned Length, bool Prologue) { |
492 ++Offset; | 517 ++Offset; |
493 return true; | 518 return true; |
494 } | 519 } |
495 | 520 |
521 // ARM64 unwind codes start here. | |
522 bool Decoder::opcode_alloc_s(const uint8_t *OC, unsigned &Offset, | |
523 unsigned Length, bool Prologue) { | |
524 uint32_t NumBytes = (OC[Offset] & 0x1F) << 4; | |
525 SW.startLine() << format("0x%02x ; %s sp, #%u\n", OC[Offset], | |
526 static_cast<const char *>(Prologue ? "sub" : "add"), | |
527 NumBytes); | |
528 ++Offset; | |
529 return false; | |
530 } | |
531 | |
532 bool Decoder::opcode_save_r19r20_x(const uint8_t *OC, unsigned &Offset, | |
533 unsigned Length, bool Prologue) { | |
534 uint32_t Off = (OC[Offset] & 0x1F) << 3; | |
535 if (Prologue) | |
536 SW.startLine() << format( | |
537 "0x%02x ; stp x19, x20, [sp, #-%u]!\n", OC[Offset], Off); | |
538 else | |
539 SW.startLine() << format( | |
540 "0x%02x ; ldp x19, x20, [sp], #%u\n", OC[Offset], Off); | |
541 ++Offset; | |
542 return false; | |
543 } | |
544 | |
545 bool Decoder::opcode_save_fplr(const uint8_t *OC, unsigned &Offset, | |
546 unsigned Length, bool Prologue) { | |
547 uint32_t Off = (OC[Offset] & 0x3F) << 3; | |
548 SW.startLine() << format( | |
549 "0x%02x ; %s x29, x30, [sp, #%u]\n", OC[Offset], | |
550 static_cast<const char *>(Prologue ? "stp" : "ldp"), Off); | |
551 ++Offset; | |
552 return false; | |
553 } | |
554 | |
555 bool Decoder::opcode_save_fplr_x(const uint8_t *OC, unsigned &Offset, | |
556 unsigned Length, bool Prologue) { | |
557 uint32_t Off = ((OC[Offset] & 0x3F) + 1) << 3; | |
558 if (Prologue) | |
559 SW.startLine() << format( | |
560 "0x%02x ; stp x29, x30, [sp, #-%u]!\n", OC[Offset], Off); | |
561 else | |
562 SW.startLine() << format( | |
563 "0x%02x ; ldp x29, x30, [sp], #%u\n", OC[Offset], Off); | |
564 ++Offset; | |
565 return false; | |
566 } | |
567 | |
568 bool Decoder::opcode_alloc_m(const uint8_t *OC, unsigned &Offset, | |
569 unsigned Length, bool Prologue) { | |
570 uint32_t NumBytes = ((OC[Offset] & 0x07) << 8); | |
571 NumBytes |= (OC[Offset + 1] & 0xFF); | |
572 NumBytes <<= 4; | |
573 SW.startLine() << format("0x%02x%02x ; %s sp, #%u\n", | |
574 OC[Offset], OC[Offset + 1], | |
575 static_cast<const char *>(Prologue ? "sub" : "add"), | |
576 NumBytes); | |
577 Offset += 2; | |
578 return false; | |
579 } | |
580 | |
581 bool Decoder::opcode_save_regp(const uint8_t *OC, unsigned &Offset, | |
582 unsigned Length, bool Prologue) { | |
583 uint32_t Reg = ((OC[Offset] & 0x03) << 8); | |
584 Reg |= (OC[Offset + 1] & 0xC0); | |
585 Reg >>= 6; | |
586 Reg += 19; | |
587 uint32_t Off = (OC[Offset + 1] & 0x3F) << 3; | |
588 SW.startLine() << format( | |
589 "0x%02x%02x ; %s x%u, x%u, [sp, #%u]\n", | |
590 OC[Offset], OC[Offset + 1], | |
591 static_cast<const char *>(Prologue ? "stp" : "ldp"), Reg, Reg + 1, Off); | |
592 Offset += 2; | |
593 return false; | |
594 } | |
595 | |
596 bool Decoder::opcode_save_regp_x(const uint8_t *OC, unsigned &Offset, | |
597 unsigned Length, bool Prologue) { | |
598 uint32_t Reg = ((OC[Offset] & 0x03) << 8); | |
599 Reg |= (OC[Offset + 1] & 0xC0); | |
600 Reg >>= 6; | |
601 Reg += 19; | |
602 uint32_t Off = ((OC[Offset + 1] & 0x3F) + 1) << 3; | |
603 if (Prologue) | |
604 SW.startLine() << format( | |
605 "0x%02x%02x ; stp x%u, x%u, [sp, #-%u]!\n", | |
606 OC[Offset], OC[Offset + 1], Reg, | |
607 Reg + 1, Off); | |
608 else | |
609 SW.startLine() << format( | |
610 "0x%02x%02x ; ldp x%u, x%u, [sp], #%u\n", | |
611 OC[Offset], OC[Offset + 1], Reg, | |
612 Reg + 1, Off); | |
613 Offset += 2; | |
614 return false; | |
615 } | |
616 | |
617 bool Decoder::opcode_save_reg(const uint8_t *OC, unsigned &Offset, | |
618 unsigned Length, bool Prologue) { | |
619 uint32_t Reg = (OC[Offset] & 0x03) << 8; | |
620 Reg |= (OC[Offset + 1] & 0xC0); | |
621 Reg >>= 6; | |
622 Reg += 19; | |
623 uint32_t Off = (OC[Offset + 1] & 0x3F) << 3; | |
624 SW.startLine() << format("0x%02x%02x ; %s x%u, [sp, #%u]\n", | |
625 OC[Offset], OC[Offset + 1], | |
626 static_cast<const char *>(Prologue ? "str" : "ldr"), | |
627 Reg, Off); | |
628 Offset += 2; | |
629 return false; | |
630 } | |
631 | |
632 bool Decoder::opcode_save_reg_x(const uint8_t *OC, unsigned &Offset, | |
633 unsigned Length, bool Prologue) { | |
634 uint32_t Reg = (OC[Offset] & 0x01) << 8; | |
635 Reg |= (OC[Offset + 1] & 0xE0); | |
636 Reg >>= 5; | |
637 Reg += 19; | |
638 uint32_t Off = ((OC[Offset + 1] & 0x1F) + 1) << 3; | |
639 if (Prologue) | |
640 SW.startLine() << format("0x%02x%02x ; str x%u, [sp, #%u]!\n", | |
641 OC[Offset], OC[Offset + 1], Reg, Off); | |
642 else | |
643 SW.startLine() << format("0x%02x%02x ; ldr x%u, [sp], #%u\n", | |
644 OC[Offset], OC[Offset + 1], Reg, Off); | |
645 Offset += 2; | |
646 return false; | |
647 } | |
648 | |
649 bool Decoder::opcode_save_lrpair(const uint8_t *OC, unsigned &Offset, | |
650 unsigned Length, bool Prologue) { | |
651 uint32_t Reg = (OC[Offset] & 0x01) << 8; | |
652 Reg |= (OC[Offset + 1] & 0xC0); | |
653 Reg >>= 6; | |
654 Reg *= 2; | |
655 Reg += 19; | |
656 uint32_t Off = (OC[Offset + 1] & 0x3F) << 3; | |
657 SW.startLine() << format("0x%02x%02x ; %s x%u, lr, [sp, #%u]\n", | |
658 OC[Offset], OC[Offset + 1], | |
659 static_cast<const char *>(Prologue ? "stp" : "ldp"), | |
660 Reg, Off); | |
661 Offset += 2; | |
662 return false; | |
663 } | |
664 | |
665 bool Decoder::opcode_save_fregp(const uint8_t *OC, unsigned &Offset, | |
666 unsigned Length, bool Prologue) { | |
667 uint32_t Reg = (OC[Offset] & 0x01) << 8; | |
668 Reg |= (OC[Offset + 1] & 0xC0); | |
669 Reg >>= 6; | |
670 Reg += 8; | |
671 uint32_t Off = (OC[Offset + 1] & 0x3F) << 3; | |
672 SW.startLine() << format("0x%02x%02x ; %s d%u, d%u, [sp, #%u]\n", | |
673 OC[Offset], OC[Offset + 1], | |
674 static_cast<const char *>(Prologue ? "stp" : "ldp"), | |
675 Reg, Reg + 1, Off); | |
676 Offset += 2; | |
677 return false; | |
678 } | |
679 | |
680 bool Decoder::opcode_save_fregp_x(const uint8_t *OC, unsigned &Offset, | |
681 unsigned Length, bool Prologue) { | |
682 uint32_t Reg = (OC[Offset] & 0x01) << 8; | |
683 Reg |= (OC[Offset + 1] & 0xC0); | |
684 Reg >>= 6; | |
685 Reg += 8; | |
686 uint32_t Off = ((OC[Offset + 1] & 0x3F) + 1) << 3; | |
687 if (Prologue) | |
688 SW.startLine() << format( | |
689 "0x%02x%02x ; stp d%u, d%u, [sp, #-%u]!\n", OC[Offset], | |
690 OC[Offset + 1], Reg, Reg + 1, Off); | |
691 else | |
692 SW.startLine() << format( | |
693 "0x%02x%02x ; ldp d%u, d%u, [sp], #%u\n", OC[Offset], | |
694 OC[Offset + 1], Reg, Reg + 1, Off); | |
695 Offset += 2; | |
696 return false; | |
697 } | |
698 | |
699 bool Decoder::opcode_save_freg(const uint8_t *OC, unsigned &Offset, | |
700 unsigned Length, bool Prologue) { | |
701 uint32_t Reg = (OC[Offset] & 0x01) << 8; | |
702 Reg |= (OC[Offset + 1] & 0xC0); | |
703 Reg >>= 6; | |
704 Reg += 8; | |
705 uint32_t Off = (OC[Offset + 1] & 0x3F) << 3; | |
706 SW.startLine() << format("0x%02x%02x ; %s d%u, [sp, #%u]\n", | |
707 OC[Offset], OC[Offset + 1], | |
708 static_cast<const char *>(Prologue ? "str" : "ldr"), | |
709 Reg, Off); | |
710 Offset += 2; | |
711 return false; | |
712 } | |
713 | |
714 bool Decoder::opcode_save_freg_x(const uint8_t *OC, unsigned &Offset, | |
715 unsigned Length, bool Prologue) { | |
716 uint32_t Reg = ((OC[Offset + 1] & 0xE0) >> 5) + 8; | |
717 uint32_t Off = ((OC[Offset + 1] & 0x1F) + 1) << 3; | |
718 if (Prologue) | |
719 SW.startLine() << format( | |
720 "0x%02x%02x ; str d%u, [sp, #-%u]!\n", OC[Offset], | |
721 OC[Offset + 1], Reg, Off); | |
722 else | |
723 SW.startLine() << format( | |
724 "0x%02x%02x ; ldr d%u, [sp], #%u\n", OC[Offset], | |
725 OC[Offset + 1], Reg, Off); | |
726 Offset += 2; | |
727 return false; | |
728 } | |
729 | |
730 bool Decoder::opcode_alloc_l(const uint8_t *OC, unsigned &Offset, | |
731 unsigned Length, bool Prologue) { | |
732 unsigned Off = | |
733 (OC[Offset + 1] << 16) | (OC[Offset + 2] << 8) | (OC[Offset + 3] << 0); | |
734 Off <<= 4; | |
735 SW.startLine() << format( | |
736 "0x%02x%02x%02x%02x ; %s sp, #%u\n", OC[Offset], OC[Offset + 1], | |
737 OC[Offset + 2], OC[Offset + 3], | |
738 static_cast<const char *>(Prologue ? "sub" : "add"), Off); | |
739 Offset += 4; | |
740 return false; | |
741 } | |
742 | |
743 bool Decoder::opcode_setfp(const uint8_t *OC, unsigned &Offset, unsigned Length, | |
744 bool Prologue) { | |
745 SW.startLine() << format("0x%02x ; mov fp, sp\n", OC[Offset]); | |
746 ++Offset; | |
747 return false; | |
748 } | |
749 | |
750 bool Decoder::opcode_addfp(const uint8_t *OC, unsigned &Offset, unsigned Length, | |
751 bool Prologue) { | |
752 unsigned NumBytes = OC[Offset + 1] << 3; | |
753 SW.startLine() << format("0x%02x%02x ; add fp, sp, #%u\n", | |
754 OC[Offset], OC[Offset + 1], NumBytes); | |
755 Offset += 2; | |
756 return false; | |
757 } | |
758 | |
759 bool Decoder::opcode_nop(const uint8_t *OC, unsigned &Offset, unsigned Length, | |
760 bool Prologue) { | |
761 SW.startLine() << format("0x%02x ; nop\n", OC[Offset]); | |
762 ++Offset; | |
763 return false; | |
764 } | |
765 | |
766 bool Decoder::opcode_end(const uint8_t *OC, unsigned &Offset, unsigned Length, | |
767 bool Prologue) { | |
768 SW.startLine() << format("0x%02x ; end\n", OC[Offset]); | |
769 ++Offset; | |
770 return true; | |
771 } | |
772 | |
773 bool Decoder::opcode_end_c(const uint8_t *OC, unsigned &Offset, unsigned Length, | |
774 bool Prologue) { | |
775 SW.startLine() << format("0x%02x ; end_c\n", OC[Offset]); | |
776 ++Offset; | |
777 return true; | |
778 } | |
779 | |
496 void Decoder::decodeOpcodes(ArrayRef<uint8_t> Opcodes, unsigned Offset, | 780 void Decoder::decodeOpcodes(ArrayRef<uint8_t> Opcodes, unsigned Offset, |
497 bool Prologue) { | 781 bool Prologue) { |
498 assert((!Prologue || Offset == 0) && "prologue should always use offset 0"); | 782 assert((!Prologue || Offset == 0) && "prologue should always use offset 0"); |
499 | 783 const RingEntry* DecodeRing = isAArch64 ? Ring64 : Ring; |
500 bool Terminated = false; | 784 bool Terminated = false; |
501 for (unsigned OI = Offset, OE = Opcodes.size(); !Terminated && OI < OE; ) { | 785 for (unsigned OI = Offset, OE = Opcodes.size(); !Terminated && OI < OE; ) { |
502 for (unsigned DI = 0;; ++DI) { | 786 for (unsigned DI = 0;; ++DI) { |
503 if ((Opcodes[OI] & Ring[DI].Mask) == Ring[DI].Value) { | 787 if ((isAArch64 && (DI >= array_lengthof(Ring64))) || |
504 Terminated = (this->*Ring[DI].Routine)(Opcodes.data(), OI, 0, Prologue); | 788 (!isAArch64 && (DI >= array_lengthof(Ring)))) { |
789 SW.startLine() << format("0x%02x ; Bad opcode!\n", | |
790 Opcodes.data()[OI]); | |
791 ++OI; | |
505 break; | 792 break; |
506 } | 793 } |
507 assert(DI < array_lengthof(Ring) && "unhandled opcode"); | 794 |
795 if ((Opcodes[OI] & DecodeRing[DI].Mask) == DecodeRing[DI].Value) { | |
796 if (OI + DecodeRing[DI].Length > OE) { | |
797 SW.startLine() << format("Opcode 0x%02x goes past the unwind data\n", | |
798 Opcodes[OI]); | |
799 OI += DecodeRing[DI].Length; | |
800 break; | |
801 } | |
802 Terminated = | |
803 (this->*DecodeRing[DI].Routine)(Opcodes.data(), OI, 0, Prologue); | |
804 break; | |
805 } | |
508 } | 806 } |
509 } | 807 } |
510 } | 808 } |
511 | 809 |
512 bool Decoder::dumpXDataRecord(const COFFObjectFile &COFF, | 810 bool Decoder::dumpXDataRecord(const COFFObjectFile &COFF, |
518 | 816 |
519 uint64_t SectionVA = Section.getAddress(); | 817 uint64_t SectionVA = Section.getAddress(); |
520 uint64_t Offset = VA - SectionVA; | 818 uint64_t Offset = VA - SectionVA; |
521 const ulittle32_t *Data = | 819 const ulittle32_t *Data = |
522 reinterpret_cast<const ulittle32_t *>(Contents.data() + Offset); | 820 reinterpret_cast<const ulittle32_t *>(Contents.data() + Offset); |
523 const ExceptionDataRecord XData(Data); | 821 |
524 | 822 // Sanity check to ensure that the .xdata header is present. |
823 // A header is one or two words, followed by at least one word to describe | |
824 // the unwind codes. Applicable to both ARM and AArch64. | |
825 if (Contents.size() - Offset < 8) | |
826 report_fatal_error(".xdata must be at least 8 bytes in size"); | |
827 | |
828 const ExceptionDataRecord XData(Data, isAArch64); | |
525 DictScope XRS(SW, "ExceptionData"); | 829 DictScope XRS(SW, "ExceptionData"); |
526 SW.printNumber("FunctionLength", XData.FunctionLength() << 1); | 830 SW.printNumber("FunctionLength", |
831 isAArch64 ? XData.FunctionLengthInBytesAArch64() : | |
832 XData.FunctionLengthInBytesARM()); | |
527 SW.printNumber("Version", XData.Vers()); | 833 SW.printNumber("Version", XData.Vers()); |
528 SW.printBoolean("ExceptionData", XData.X()); | 834 SW.printBoolean("ExceptionData", XData.X()); |
529 SW.printBoolean("EpiloguePacked", XData.E()); | 835 SW.printBoolean("EpiloguePacked", XData.E()); |
530 SW.printBoolean("Fragment", XData.F()); | 836 if (!isAArch64) |
837 SW.printBoolean("Fragment", XData.F()); | |
531 SW.printNumber(XData.E() ? "EpilogueOffset" : "EpilogueScopes", | 838 SW.printNumber(XData.E() ? "EpilogueOffset" : "EpilogueScopes", |
532 XData.EpilogueCount()); | 839 XData.EpilogueCount()); |
533 SW.printNumber("ByteCodeLength", | 840 uint64_t ByteCodeLength = XData.CodeWords() * sizeof(uint32_t); |
534 static_cast<uint64_t>(XData.CodeWords() * sizeof(uint32_t))); | 841 SW.printNumber("ByteCodeLength", ByteCodeLength); |
842 | |
843 if ((int64_t)(Contents.size() - Offset - 4 * HeaderWords(XData) - | |
844 (XData.E() ? 0 : XData.EpilogueCount() * 4) - | |
845 (XData.X() ? 8 : 0)) < (int64_t)ByteCodeLength) | |
846 report_fatal_error("Malformed unwind data"); | |
535 | 847 |
536 if (XData.E()) { | 848 if (XData.E()) { |
537 ArrayRef<uint8_t> UC = XData.UnwindByteCode(); | 849 ArrayRef<uint8_t> UC = XData.UnwindByteCode(); |
538 if (!XData.F()) { | 850 if (isAArch64 || !XData.F()) { |
539 ListScope PS(SW, "Prologue"); | 851 ListScope PS(SW, "Prologue"); |
540 decodeOpcodes(UC, 0, /*Prologue=*/true); | 852 decodeOpcodes(UC, 0, /*Prologue=*/true); |
541 } | 853 } |
542 if (XData.EpilogueCount()) { | 854 if (XData.EpilogueCount()) { |
543 ListScope ES(SW, "Epilogue"); | 855 ListScope ES(SW, "Epilogue"); |
544 decodeOpcodes(UC, XData.EpilogueCount(), /*Prologue=*/false); | 856 decodeOpcodes(UC, XData.EpilogueCount(), /*Prologue=*/false); |
545 } | 857 } |
546 } else { | 858 } else { |
859 { | |
860 ListScope PS(SW, "Prologue"); | |
861 decodeOpcodes(XData.UnwindByteCode(), 0, /*Prologue=*/true); | |
862 } | |
547 ArrayRef<ulittle32_t> EpilogueScopes = XData.EpilogueScopes(); | 863 ArrayRef<ulittle32_t> EpilogueScopes = XData.EpilogueScopes(); |
548 ListScope ESS(SW, "EpilogueScopes"); | 864 ListScope ESS(SW, "EpilogueScopes"); |
549 for (const EpilogueScope ES : EpilogueScopes) { | 865 for (const EpilogueScope ES : EpilogueScopes) { |
550 DictScope ESES(SW, "EpilogueScope"); | 866 DictScope ESES(SW, "EpilogueScope"); |
551 SW.printNumber("StartOffset", ES.EpilogueStartOffset()); | 867 SW.printNumber("StartOffset", ES.EpilogueStartOffset()); |
552 SW.printNumber("Condition", ES.Condition()); | 868 if (!isAArch64) |
553 SW.printNumber("EpilogueStartIndex", ES.EpilogueStartIndex()); | 869 SW.printNumber("Condition", ES.Condition()); |
870 SW.printNumber("EpilogueStartIndex", | |
871 isAArch64 ? ES.EpilogueStartIndexAArch64() | |
872 : ES.EpilogueStartIndexARM()); | |
873 if (ES.ES & ~0xffc3ffff) | |
874 SW.printNumber("ReservedBits", (ES.ES >> 18) & 0xF); | |
554 | 875 |
555 ListScope Opcodes(SW, "Opcodes"); | 876 ListScope Opcodes(SW, "Opcodes"); |
556 decodeOpcodes(XData.UnwindByteCode(), ES.EpilogueStartIndex(), | 877 decodeOpcodes(XData.UnwindByteCode(), |
878 isAArch64 ? ES.EpilogueStartIndexAArch64() | |
879 : ES.EpilogueStartIndexARM(), | |
557 /*Prologue=*/false); | 880 /*Prologue=*/false); |
558 } | 881 } |
559 } | 882 } |
560 | 883 |
561 if (XData.X()) { | 884 if (XData.X()) { |
563 const uint32_t Parameter = XData.ExceptionHandlerParameter(); | 886 const uint32_t Parameter = XData.ExceptionHandlerParameter(); |
564 const size_t HandlerOffset = HeaderWords(XData) | 887 const size_t HandlerOffset = HeaderWords(XData) |
565 + (XData.E() ? 0 : XData.EpilogueCount()) | 888 + (XData.E() ? 0 : XData.EpilogueCount()) |
566 + XData.CodeWords(); | 889 + XData.CodeWords(); |
567 | 890 |
568 ErrorOr<SymbolRef> Symbol = | 891 ErrorOr<SymbolRef> Symbol = getRelocatedSymbol( |
569 getRelocatedSymbol(COFF, Section, HandlerOffset * sizeof(uint32_t)); | 892 COFF, Section, Offset + HandlerOffset * sizeof(uint32_t)); |
570 if (!Symbol) | 893 if (!Symbol) |
571 Symbol = getSymbol(COFF, Address, /*FunctionOnly=*/true); | 894 Symbol = getSymbol(COFF, Address, /*FunctionOnly=*/true); |
895 if (!Symbol) { | |
896 ListScope EHS(SW, "ExceptionHandler"); | |
897 SW.printString("Routine", "(null)"); | |
898 return true; | |
899 } | |
572 | 900 |
573 Expected<StringRef> Name = Symbol->getName(); | 901 Expected<StringRef> Name = Symbol->getName(); |
574 if (!Name) { | 902 if (!Name) { |
575 std::string Buf; | 903 std::string Buf; |
576 llvm::raw_string_ostream OS(Buf); | 904 llvm::raw_string_ostream OS(Buf); |
577 logAllUnhandledErrors(Name.takeError(), OS, ""); | 905 logAllUnhandledErrors(Name.takeError(), OS); |
578 OS.flush(); | 906 OS.flush(); |
579 report_fatal_error(Buf); | 907 report_fatal_error(Buf); |
580 } | 908 } |
581 | 909 |
582 ListScope EHS(SW, "ExceptionHandler"); | 910 ListScope EHS(SW, "ExceptionHandler"); |
611 if (Function) { | 939 if (Function) { |
612 Expected<StringRef> FunctionNameOrErr = Function->getName(); | 940 Expected<StringRef> FunctionNameOrErr = Function->getName(); |
613 if (!FunctionNameOrErr) { | 941 if (!FunctionNameOrErr) { |
614 std::string Buf; | 942 std::string Buf; |
615 llvm::raw_string_ostream OS(Buf); | 943 llvm::raw_string_ostream OS(Buf); |
616 logAllUnhandledErrors(FunctionNameOrErr.takeError(), OS, ""); | 944 logAllUnhandledErrors(FunctionNameOrErr.takeError(), OS); |
617 OS.flush(); | 945 OS.flush(); |
618 report_fatal_error(Buf); | 946 report_fatal_error(Buf); |
619 } | 947 } |
620 FunctionName = *FunctionNameOrErr; | 948 FunctionName = *FunctionNameOrErr; |
621 Expected<uint64_t> FunctionAddressOrErr = Function->getAddress(); | 949 Expected<uint64_t> FunctionAddressOrErr = Function->getAddress(); |
622 if (!FunctionAddressOrErr) { | 950 if (!FunctionAddressOrErr) { |
623 std::string Buf; | 951 std::string Buf; |
624 llvm::raw_string_ostream OS(Buf); | 952 llvm::raw_string_ostream OS(Buf); |
625 logAllUnhandledErrors(FunctionAddressOrErr.takeError(), OS, ""); | 953 logAllUnhandledErrors(FunctionAddressOrErr.takeError(), OS); |
626 OS.flush(); | 954 OS.flush(); |
627 report_fatal_error(Buf); | 955 report_fatal_error(Buf); |
628 } | 956 } |
629 FunctionAddress = *FunctionAddressOrErr; | 957 FunctionAddress = *FunctionAddressOrErr; |
630 } else { | 958 } else { |
631 const pe32_header *PEHeader; | 959 FunctionAddress = COFF.getImageBase() + RF.BeginAddress; |
632 if (COFF.getPE32Header(PEHeader)) | |
633 return false; | |
634 FunctionAddress = PEHeader->ImageBase + RF.BeginAddress; | |
635 } | 960 } |
636 | 961 |
637 SW.printString("Function", formatSymbol(FunctionName, FunctionAddress)); | 962 SW.printString("Function", formatSymbol(FunctionName, FunctionAddress)); |
638 | 963 |
639 if (XDataRecord) { | 964 if (XDataRecord) { |
640 Expected<StringRef> Name = XDataRecord->getName(); | 965 Expected<StringRef> Name = XDataRecord->getName(); |
641 if (!Name) { | 966 if (!Name) { |
642 std::string Buf; | 967 std::string Buf; |
643 llvm::raw_string_ostream OS(Buf); | 968 llvm::raw_string_ostream OS(Buf); |
644 logAllUnhandledErrors(Name.takeError(), OS, ""); | 969 logAllUnhandledErrors(Name.takeError(), OS); |
645 OS.flush(); | 970 OS.flush(); |
646 report_fatal_error(Buf); | 971 report_fatal_error(Buf); |
647 } | 972 } |
648 | 973 |
649 Expected<uint64_t> AddressOrErr = XDataRecord->getAddress(); | 974 Expected<uint64_t> AddressOrErr = XDataRecord->getAddress(); |
650 if (!AddressOrErr) { | 975 if (!AddressOrErr) { |
651 std::string Buf; | 976 std::string Buf; |
652 llvm::raw_string_ostream OS(Buf); | 977 llvm::raw_string_ostream OS(Buf); |
653 logAllUnhandledErrors(AddressOrErr.takeError(), OS, ""); | 978 logAllUnhandledErrors(AddressOrErr.takeError(), OS); |
654 OS.flush(); | 979 OS.flush(); |
655 report_fatal_error(Buf); | 980 report_fatal_error(Buf); |
656 } | 981 } |
657 uint64_t Address = *AddressOrErr; | 982 uint64_t Address = *AddressOrErr; |
658 | 983 |
664 consumeError(SIOrErr.takeError()); | 989 consumeError(SIOrErr.takeError()); |
665 return false; | 990 return false; |
666 } | 991 } |
667 section_iterator SI = *SIOrErr; | 992 section_iterator SI = *SIOrErr; |
668 | 993 |
669 return dumpXDataRecord(COFF, *SI, FunctionAddress, Address); | 994 // FIXME: Do we need to add an offset from the relocation? |
995 return dumpXDataRecord(COFF, *SI, FunctionAddress, | |
996 RF.ExceptionInformationRVA()); | |
670 } else { | 997 } else { |
671 const pe32_header *PEHeader; | 998 uint64_t Address = COFF.getImageBase() + RF.ExceptionInformationRVA(); |
672 if (COFF.getPE32Header(PEHeader)) | |
673 return false; | |
674 | |
675 uint64_t Address = PEHeader->ImageBase + RF.ExceptionInformationRVA(); | |
676 SW.printString("ExceptionRecord", formatSymbol("", Address)); | 999 SW.printString("ExceptionRecord", formatSymbol("", Address)); |
677 | 1000 |
678 ErrorOr<SectionRef> Section = | 1001 ErrorOr<SectionRef> Section = getSectionContaining(COFF, Address); |
679 getSectionContaining(COFF, RF.ExceptionInformationRVA()); | |
680 if (!Section) | 1002 if (!Section) |
681 return false; | 1003 return false; |
682 | 1004 |
683 return dumpXDataRecord(COFF, *Section, FunctionAddress, | 1005 return dumpXDataRecord(COFF, *Section, FunctionAddress, Address); |
684 RF.ExceptionInformationRVA()); | |
685 } | 1006 } |
686 } | 1007 } |
687 | 1008 |
688 bool Decoder::dumpPackedEntry(const object::COFFObjectFile &COFF, | 1009 bool Decoder::dumpPackedEntry(const object::COFFObjectFile &COFF, |
689 const SectionRef Section, uint64_t Offset, | 1010 const SectionRef Section, uint64_t Offset, |
701 if (Function) { | 1022 if (Function) { |
702 Expected<StringRef> FunctionNameOrErr = Function->getName(); | 1023 Expected<StringRef> FunctionNameOrErr = Function->getName(); |
703 if (!FunctionNameOrErr) { | 1024 if (!FunctionNameOrErr) { |
704 std::string Buf; | 1025 std::string Buf; |
705 llvm::raw_string_ostream OS(Buf); | 1026 llvm::raw_string_ostream OS(Buf); |
706 logAllUnhandledErrors(FunctionNameOrErr.takeError(), OS, ""); | 1027 logAllUnhandledErrors(FunctionNameOrErr.takeError(), OS); |
707 OS.flush(); | 1028 OS.flush(); |
708 report_fatal_error(Buf); | 1029 report_fatal_error(Buf); |
709 } | 1030 } |
710 FunctionName = *FunctionNameOrErr; | 1031 FunctionName = *FunctionNameOrErr; |
711 Expected<uint64_t> FunctionAddressOrErr = Function->getAddress(); | 1032 Expected<uint64_t> FunctionAddressOrErr = Function->getAddress(); |
712 if (!FunctionAddressOrErr) { | 1033 if (!FunctionAddressOrErr) { |
713 std::string Buf; | 1034 std::string Buf; |
714 llvm::raw_string_ostream OS(Buf); | 1035 llvm::raw_string_ostream OS(Buf); |
715 logAllUnhandledErrors(FunctionAddressOrErr.takeError(), OS, ""); | 1036 logAllUnhandledErrors(FunctionAddressOrErr.takeError(), OS); |
716 OS.flush(); | 1037 OS.flush(); |
717 report_fatal_error(Buf); | 1038 report_fatal_error(Buf); |
718 } | 1039 } |
719 FunctionAddress = *FunctionAddressOrErr; | 1040 FunctionAddress = *FunctionAddressOrErr; |
720 } else { | 1041 } else { |
723 return false; | 1044 return false; |
724 FunctionAddress = PEHeader->ImageBase + RF.BeginAddress; | 1045 FunctionAddress = PEHeader->ImageBase + RF.BeginAddress; |
725 } | 1046 } |
726 | 1047 |
727 SW.printString("Function", formatSymbol(FunctionName, FunctionAddress)); | 1048 SW.printString("Function", formatSymbol(FunctionName, FunctionAddress)); |
728 SW.printBoolean("Fragment", | 1049 if (!isAArch64) |
729 RF.Flag() == RuntimeFunctionFlag::RFF_PackedFragment); | 1050 SW.printBoolean("Fragment", |
1051 RF.Flag() == RuntimeFunctionFlag::RFF_PackedFragment); | |
730 SW.printNumber("FunctionLength", RF.FunctionLength()); | 1052 SW.printNumber("FunctionLength", RF.FunctionLength()); |
731 SW.startLine() << "ReturnType: " << RF.Ret() << '\n'; | 1053 SW.startLine() << "ReturnType: " << RF.Ret() << '\n'; |
732 SW.printBoolean("HomedParameters", RF.H()); | 1054 SW.printBoolean("HomedParameters", RF.H()); |
733 SW.startLine() << "SavedRegisters: "; | 1055 SW.startLine() << "SavedRegisters: "; |
734 printRegisters(SavedRegisterMask(RF)); | 1056 printRegisters(SavedRegisterMask(RF)); |
747 | 1069 |
748 const RuntimeFunction Entry(Data); | 1070 const RuntimeFunction Entry(Data); |
749 DictScope RFS(SW, "RuntimeFunction"); | 1071 DictScope RFS(SW, "RuntimeFunction"); |
750 if (Entry.Flag() == RuntimeFunctionFlag::RFF_Unpacked) | 1072 if (Entry.Flag() == RuntimeFunctionFlag::RFF_Unpacked) |
751 return dumpUnpackedEntry(COFF, Section, Offset, Index, Entry); | 1073 return dumpUnpackedEntry(COFF, Section, Offset, Index, Entry); |
1074 if (isAArch64) { | |
1075 SW.startLine() << "Packed unwind data not yet supported for ARM64\n"; | |
1076 return true; | |
1077 } | |
752 return dumpPackedEntry(COFF, Section, Offset, Index, Entry); | 1078 return dumpPackedEntry(COFF, Section, Offset, Index, Entry); |
753 } | 1079 } |
754 | 1080 |
755 void Decoder::dumpProcedureData(const COFFObjectFile &COFF, | 1081 void Decoder::dumpProcedureData(const COFFObjectFile &COFF, |
756 const SectionRef Section) { | 1082 const SectionRef Section) { |
766 for (unsigned EI = 0, EE = Contents.size() / PDataEntrySize; EI < EE; ++EI) | 1092 for (unsigned EI = 0, EE = Contents.size() / PDataEntrySize; EI < EE; ++EI) |
767 if (!dumpProcedureDataEntry(COFF, Section, EI, Contents)) | 1093 if (!dumpProcedureDataEntry(COFF, Section, EI, Contents)) |
768 break; | 1094 break; |
769 } | 1095 } |
770 | 1096 |
771 std::error_code Decoder::dumpProcedureData(const COFFObjectFile &COFF) { | 1097 Error Decoder::dumpProcedureData(const COFFObjectFile &COFF) { |
772 for (const auto &Section : COFF.sections()) { | 1098 for (const auto &Section : COFF.sections()) { |
773 StringRef SectionName; | 1099 Expected<StringRef> NameOrErr = |
774 if (std::error_code EC = | 1100 COFF.getSectionName(COFF.getCOFFSection(Section)); |
775 COFF.getSectionName(COFF.getCOFFSection(Section), SectionName)) | 1101 if (!NameOrErr) |
776 return EC; | 1102 return NameOrErr.takeError(); |
777 | 1103 |
778 if (SectionName.startswith(".pdata")) | 1104 if (NameOrErr->startswith(".pdata")) |
779 dumpProcedureData(COFF, Section); | 1105 dumpProcedureData(COFF, Section); |
780 } | 1106 } |
781 return std::error_code(); | 1107 return Error::success(); |
782 } | 1108 } |
783 } | 1109 } |
784 } | 1110 } |
785 } | 1111 } |