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 }