| author | |
| committer | |
| log | 55fa349ad946aaa4e2ff5a5dc2a3f0d6bce64282 |
| tree | fbd8365132d929851ec418d048a90aaafd1d575e |
| parent | b5f8fb85e64022ed1ee59ff70753577839ad41b6 |
| signature |
Import LLVM's D32450/D116857 patch to enable unwinding support on
SPARCv9 systems.9 files changed, 367 insertions(+), 10 deletions(-)
lib/libunwind/include/__libunwind_config.h+7| ... | ... | @@ -23,6 +23,7 @@ |
| 23 | 23 | #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_OR1K 32 |
| 24 | 24 | #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS 65 |
| 25 | 25 | #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC 31 |
| 26 | #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC64 31 | |
| 26 | 27 | #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_HEXAGON 34 |
| 27 | 28 | #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_RISCV 64 |
| 28 | 29 | #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_VE 143 |
| ... | ... | @@ -125,6 +126,11 @@ |
| 125 | 126 | # error "Unsupported MIPS ABI and/or environment" |
| 126 | 127 | # endif |
| 127 | 128 | # define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS |
| 129 | # elif defined(__sparc__) && defined(__arch64__) | |
| 130 | # define _LIBUNWIND_TARGET_SPARC64 1 | |
| 131 | # define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC64 | |
| 132 | # define _LIBUNWIND_CONTEXT_SIZE 33 | |
| 133 | # define _LIBUNWIND_CURSOR_SIZE 45 | |
| 128 | 134 | # elif defined(__sparc__) |
| 129 | 135 | #define _LIBUNWIND_TARGET_SPARC 1 |
| 130 | 136 | #define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC |
| ... | ... | @@ -165,6 +171,7 @@ |
| 165 | 171 | # define _LIBUNWIND_TARGET_MIPS_O32 1 |
| 166 | 172 | # define _LIBUNWIND_TARGET_MIPS_NEWABI 1 |
| 167 | 173 | # define _LIBUNWIND_TARGET_SPARC 1 |
| 174 | # define _LIBUNWIND_TARGET_SPARC64 1 | |
| 168 | 175 | # define _LIBUNWIND_TARGET_HEXAGON 1 |
| 169 | 176 | # define _LIBUNWIND_TARGET_RISCV 1 |
| 170 | 177 | # define _LIBUNWIND_TARGET_VE 1 |
lib/libunwind/src/DwarfInstructions.hpp+21-1| ... | ... | @@ -67,7 +67,7 @@ private: |
| 67 | 67 | return (pint_t)((sint_t)registers.getRegister((int)prolog.cfaRegister) + |
| 68 | 68 | prolog.cfaRegisterOffset); |
| 69 | 69 | if (prolog.cfaExpression != 0) |
| 70 | return evaluateExpression((pint_t)prolog.cfaExpression, addressSpace, | |
| 70 | return evaluateExpression((pint_t)prolog.cfaExpression, addressSpace, | |
| 71 | 71 | registers, 0); |
| 72 | 72 | assert(0 && "getCFA(): unknown location"); |
| 73 | 73 | __builtin_unreachable(); |
| ... | ... | @@ -75,6 +75,14 @@ private: |
| 75 | 75 | }; |
| 76 | 76 | |
| 77 | 77 | |
| 78 | template <typename R> | |
| 79 | auto getSparcWCookie(const R &r, int) -> decltype(r.getWCookie()) { | |
| 80 | return r.getWCookie(); | |
| 81 | } | |
| 82 | template <typename R> uint64_t getSparcWCookie(const R &, long) { | |
| 83 | return 0; | |
| 84 | } | |
| 85 | ||
| 78 | 86 | template <typename A, typename R> |
| 79 | 87 | typename A::pint_t DwarfInstructions<A, R>::getSavedRegister( |
| 80 | 88 | A &addressSpace, const R &registers, pint_t cfa, |
| ... | ... | @@ -83,6 +91,10 @@ typename A::pint_t DwarfInstructions<A, R>::getSavedRegister( |
| 83 | 91 | case CFI_Parser<A>::kRegisterInCFA: |
| 84 | 92 | return (pint_t)addressSpace.getRegister(cfa + (pint_t)savedReg.value); |
| 85 | 93 | |
| 94 | case CFI_Parser<A>::kRegisterInCFADecrypt: // sparc64 specific | |
| 95 | return addressSpace.getP(cfa + (pint_t)savedReg.value) ^ | |
| 96 | getSparcWCookie(registers, 0); | |
| 97 | ||
| 86 | 98 | case CFI_Parser<A>::kRegisterAtExpression: |
| 87 | 99 | return (pint_t)addressSpace.getRegister(evaluateExpression( |
| 88 | 100 | (pint_t)savedReg.value, addressSpace, registers, cfa)); |
| ... | ... | @@ -121,6 +133,7 @@ double DwarfInstructions<A, R>::getSavedFloatRegister( |
| 121 | 133 | case CFI_Parser<A>::kRegisterUndefined: |
| 122 | 134 | case CFI_Parser<A>::kRegisterOffsetFromCFA: |
| 123 | 135 | case CFI_Parser<A>::kRegisterInRegister: |
| 136 | case CFI_Parser<A>::kRegisterInCFADecrypt: | |
| 124 | 137 | // FIX ME |
| 125 | 138 | break; |
| 126 | 139 | } |
| ... | ... | @@ -145,6 +158,7 @@ v128 DwarfInstructions<A, R>::getSavedVectorRegister( |
| 145 | 158 | case CFI_Parser<A>::kRegisterUndefined: |
| 146 | 159 | case CFI_Parser<A>::kRegisterOffsetFromCFA: |
| 147 | 160 | case CFI_Parser<A>::kRegisterInRegister: |
| 161 | case CFI_Parser<A>::kRegisterInCFADecrypt: | |
| 148 | 162 | // FIX ME |
| 149 | 163 | break; |
| 150 | 164 | } |
| ... | ... | @@ -249,6 +263,12 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc, |
| 249 | 263 | } |
| 250 | 264 | #endif |
| 251 | 265 | |
| 266 | #if defined(_LIBUNWIND_TARGET_SPARC64) | |
| 267 | // Skip call site instruction and delay slot | |
| 268 | if (R::getArch() == REGISTERS_SPARC64) | |
| 269 | returnAddress += 8; | |
| 270 | #endif | |
| 271 | ||
| 252 | 272 | #if defined(_LIBUNWIND_TARGET_PPC64) |
| 253 | 273 | #define PPC64_ELFV1_R2_LOAD_INST_ENCODING 0xe8410028u // ld r2,40(r1) |
| 254 | 274 | #define PPC64_ELFV1_R2_OFFSET 40 |
lib/libunwind/src/DwarfParser.hpp+24-1| ... | ... | @@ -71,6 +71,7 @@ public: |
| 71 | 71 | kRegisterUnused, |
| 72 | 72 | kRegisterUndefined, |
| 73 | 73 | kRegisterInCFA, |
| 74 | kRegisterInCFADecrypt, // sparc64 specific | |
| 74 | 75 | kRegisterOffsetFromCFA, |
| 75 | 76 | kRegisterInRegister, |
| 76 | 77 | kRegisterAtExpression, |
| ... | ... | @@ -723,7 +724,8 @@ bool CFI_Parser<A>::parseFDEInstructions(A &addressSpace, |
| 723 | 724 | "DW_CFA_GNU_negative_offset_extended(%" PRId64 ")\n", offset); |
| 724 | 725 | break; |
| 725 | 726 | |
| 726 | #if defined(_LIBUNWIND_TARGET_AARCH64) || defined(_LIBUNWIND_TARGET_SPARC) | |
| 727 | #if defined(_LIBUNWIND_TARGET_AARCH64) || defined(_LIBUNWIND_TARGET_SPARC) || \ | |
| 728 | defined(_LIBUNWIND_TARGET_SPARC64) | |
| 727 | 729 | // The same constant is used to represent different instructions on |
| 728 | 730 | // AArch64 (negate_ra_state) and SPARC (window_save). |
| 729 | 731 | static_assert(DW_CFA_AARCH64_negate_ra_state == DW_CFA_GNU_window_save, |
| ... | ... | @@ -757,8 +759,29 @@ bool CFI_Parser<A>::parseFDEInstructions(A &addressSpace, |
| 757 | 759 | } |
| 758 | 760 | break; |
| 759 | 761 | #endif |
| 762 | ||
| 763 | #if defined(_LIBUNWIND_TARGET_SPARC64) | |
| 764 | // case DW_CFA_GNU_window_save: | |
| 765 | case REGISTERS_SPARC64: | |
| 766 | // Don't save %o0-%o7 on sparc64. | |
| 767 | // https://reviews.llvm.org/D32450#736405 | |
| 768 | ||
| 769 | for (reg = UNW_SPARC_L0; reg <= UNW_SPARC_I7; reg++) { | |
| 770 | if (reg == UNW_SPARC_I7) | |
| 771 | results->setRegister( | |
| 772 | reg, kRegisterInCFADecrypt, | |
| 773 | ((int64_t)reg - UNW_SPARC_L0) * sizeof(pint_t), initialState); | |
| 774 | else | |
| 775 | results->setRegister( | |
| 776 | reg, kRegisterInCFA, | |
| 777 | ((int64_t)reg - UNW_SPARC_L0) * sizeof(pint_t), initialState); | |
| 778 | } | |
| 779 | _LIBUNWIND_TRACE_DWARF("DW_CFA_GNU_window_save\n"); | |
| 780 | break; | |
| 781 | #endif | |
| 760 | 782 | } |
| 761 | 783 | break; |
| 784 | ||
| 762 | 785 | #else |
| 763 | 786 | (void)arch; |
| 764 | 787 | #endif |
lib/libunwind/src/Registers.hpp+187| ... | ... | @@ -34,6 +34,7 @@ enum { |
| 34 | 34 | REGISTERS_MIPS_O32, |
| 35 | 35 | REGISTERS_MIPS_NEWABI, |
| 36 | 36 | REGISTERS_SPARC, |
| 37 | REGISTERS_SPARC64, | |
| 37 | 38 | REGISTERS_HEXAGON, |
| 38 | 39 | REGISTERS_RISCV, |
| 39 | 40 | REGISTERS_VE, |
| ... | ... | @@ -3546,6 +3547,192 @@ inline const char *Registers_sparc::getRegisterName(int regNum) { |
| 3546 | 3547 | } |
| 3547 | 3548 | #endif // _LIBUNWIND_TARGET_SPARC |
| 3548 | 3549 | |
| 3550 | ||
| 3551 | #if defined(_LIBUNWIND_TARGET_SPARC64) | |
| 3552 | /// Registers_sparc64 holds the register state of a thread in a 64-bit | |
| 3553 | /// sparc process. | |
| 3554 | class _LIBUNWIND_HIDDEN Registers_sparc64 { | |
| 3555 | public: | |
| 3556 | Registers_sparc64() = default; | |
| 3557 | Registers_sparc64(const void *registers); | |
| 3558 | ||
| 3559 | bool validRegister(int num) const; | |
| 3560 | uint64_t getRegister(int num) const; | |
| 3561 | void setRegister(int num, uint64_t value); | |
| 3562 | bool validFloatRegister(int num) const; | |
| 3563 | double getFloatRegister(int num) const; | |
| 3564 | void setFloatRegister(int num, double value); | |
| 3565 | bool validVectorRegister(int num) const; | |
| 3566 | v128 getVectorRegister(int num) const; | |
| 3567 | void setVectorRegister(int num, v128 value); | |
| 3568 | const char *getRegisterName(int num); | |
| 3569 | void jumpto(); | |
| 3570 | static int lastDwarfRegNum() { | |
| 3571 | return _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC64; | |
| 3572 | } | |
| 3573 | static int getArch() { return REGISTERS_SPARC64; } | |
| 3574 | ||
| 3575 | uint64_t getSP() const { return _registers.__regs[UNW_SPARC_O6] + 2047; } | |
| 3576 | void setSP(uint64_t value) { _registers.__regs[UNW_SPARC_O6] = value - 2047; } | |
| 3577 | uint64_t getIP() const { return _registers.__regs[UNW_SPARC_O7]; } | |
| 3578 | void setIP(uint64_t value) { _registers.__regs[UNW_SPARC_O7] = value; } | |
| 3579 | uint64_t getWCookie() const { return _wcookie; } | |
| 3580 | ||
| 3581 | private: | |
| 3582 | struct sparc64_thread_state_t { | |
| 3583 | uint64_t __regs[32]; | |
| 3584 | }; | |
| 3585 | ||
| 3586 | sparc64_thread_state_t _registers{}; | |
| 3587 | uint64_t _wcookie = 0; | |
| 3588 | }; | |
| 3589 | ||
| 3590 | inline Registers_sparc64::Registers_sparc64(const void *registers) { | |
| 3591 | static_assert((check_fit<Registers_sparc64, unw_context_t>::does_fit), | |
| 3592 | "sparc64 registers do not fit into unw_context_t"); | |
| 3593 | memcpy(&_registers, registers, sizeof(_registers)); | |
| 3594 | memcpy(&_wcookie, | |
| 3595 | static_cast<const uint8_t *>(registers) + sizeof(_registers), | |
| 3596 | sizeof(_wcookie)); | |
| 3597 | } | |
| 3598 | ||
| 3599 | inline bool Registers_sparc64::validRegister(int regNum) const { | |
| 3600 | if (regNum == UNW_REG_IP) | |
| 3601 | return true; | |
| 3602 | if (regNum == UNW_REG_SP) | |
| 3603 | return true; | |
| 3604 | if (regNum < 0) | |
| 3605 | return false; | |
| 3606 | if (regNum <= UNW_SPARC_I7) | |
| 3607 | return true; | |
| 3608 | return false; | |
| 3609 | } | |
| 3610 | ||
| 3611 | inline uint64_t Registers_sparc64::getRegister(int regNum) const { | |
| 3612 | if (regNum >= UNW_SPARC_G0 && regNum <= UNW_SPARC_I7) | |
| 3613 | return _registers.__regs[regNum]; | |
| 3614 | ||
| 3615 | switch (regNum) { | |
| 3616 | case UNW_REG_IP: | |
| 3617 | return _registers.__regs[UNW_SPARC_O7]; | |
| 3618 | case UNW_REG_SP: | |
| 3619 | return _registers.__regs[UNW_SPARC_O6] + 2047; | |
| 3620 | } | |
| 3621 | _LIBUNWIND_ABORT("unsupported sparc64 register"); | |
| 3622 | } | |
| 3623 | ||
| 3624 | inline void Registers_sparc64::setRegister(int regNum, uint64_t value) { | |
| 3625 | if (regNum >= UNW_SPARC_G0 && regNum <= UNW_SPARC_I7) { | |
| 3626 | _registers.__regs[regNum] = value; | |
| 3627 | return; | |
| 3628 | } | |
| 3629 | ||
| 3630 | switch (regNum) { | |
| 3631 | case UNW_REG_IP: | |
| 3632 | _registers.__regs[UNW_SPARC_O7] = value; | |
| 3633 | return; | |
| 3634 | case UNW_REG_SP: | |
| 3635 | _registers.__regs[UNW_SPARC_O6] = value - 2047; | |
| 3636 | return; | |
| 3637 | } | |
| 3638 | _LIBUNWIND_ABORT("unsupported sparc64 register"); | |
| 3639 | } | |
| 3640 | ||
| 3641 | inline bool Registers_sparc64::validFloatRegister(int) const { return false; } | |
| 3642 | ||
| 3643 | inline double Registers_sparc64::getFloatRegister(int) const { | |
| 3644 | _LIBUNWIND_ABORT("no sparc64 float registers"); | |
| 3645 | } | |
| 3646 | ||
| 3647 | inline void Registers_sparc64::setFloatRegister(int, double) { | |
| 3648 | _LIBUNWIND_ABORT("no sparc64 float registers"); | |
| 3649 | } | |
| 3650 | ||
| 3651 | inline bool Registers_sparc64::validVectorRegister(int) const { return false; } | |
| 3652 | ||
| 3653 | inline v128 Registers_sparc64::getVectorRegister(int) const { | |
| 3654 | _LIBUNWIND_ABORT("no sparc64 vector registers"); | |
| 3655 | } | |
| 3656 | ||
| 3657 | inline void Registers_sparc64::setVectorRegister(int, v128) { | |
| 3658 | _LIBUNWIND_ABORT("no sparc64 vector registers"); | |
| 3659 | } | |
| 3660 | ||
| 3661 | inline const char *Registers_sparc64::getRegisterName(int regNum) { | |
| 3662 | switch (regNum) { | |
| 3663 | case UNW_REG_IP: | |
| 3664 | return "pc"; | |
| 3665 | case UNW_SPARC_G0: | |
| 3666 | return "g0"; | |
| 3667 | case UNW_SPARC_G1: | |
| 3668 | return "g1"; | |
| 3669 | case UNW_SPARC_G2: | |
| 3670 | return "g2"; | |
| 3671 | case UNW_SPARC_G3: | |
| 3672 | return "g3"; | |
| 3673 | case UNW_SPARC_G4: | |
| 3674 | return "g4"; | |
| 3675 | case UNW_SPARC_G5: | |
| 3676 | return "g5"; | |
| 3677 | case UNW_SPARC_G6: | |
| 3678 | return "g6"; | |
| 3679 | case UNW_SPARC_G7: | |
| 3680 | return "g7"; | |
| 3681 | case UNW_SPARC_O0: | |
| 3682 | return "o0"; | |
| 3683 | case UNW_SPARC_O1: | |
| 3684 | return "o1"; | |
| 3685 | case UNW_SPARC_O2: | |
| 3686 | return "o2"; | |
| 3687 | case UNW_SPARC_O3: | |
| 3688 | return "o3"; | |
| 3689 | case UNW_SPARC_O4: | |
| 3690 | return "o4"; | |
| 3691 | case UNW_SPARC_O5: | |
| 3692 | return "o5"; | |
| 3693 | case UNW_REG_SP: | |
| 3694 | case UNW_SPARC_O6: | |
| 3695 | return "o6"; | |
| 3696 | case UNW_SPARC_O7: | |
| 3697 | return "o7"; | |
| 3698 | case UNW_SPARC_L0: | |
| 3699 | return "l0"; | |
| 3700 | case UNW_SPARC_L1: | |
| 3701 | return "l1"; | |
| 3702 | case UNW_SPARC_L2: | |
| 3703 | return "l2"; | |
| 3704 | case UNW_SPARC_L3: | |
| 3705 | return "l3"; | |
| 3706 | case UNW_SPARC_L4: | |
| 3707 | return "l4"; | |
| 3708 | case UNW_SPARC_L5: | |
| 3709 | return "l5"; | |
| 3710 | case UNW_SPARC_L6: | |
| 3711 | return "l6"; | |
| 3712 | case UNW_SPARC_L7: | |
| 3713 | return "l7"; | |
| 3714 | case UNW_SPARC_I0: | |
| 3715 | return "i0"; | |
| 3716 | case UNW_SPARC_I1: | |
| 3717 | return "i1"; | |
| 3718 | case UNW_SPARC_I2: | |
| 3719 | return "i2"; | |
| 3720 | case UNW_SPARC_I3: | |
| 3721 | return "i3"; | |
| 3722 | case UNW_SPARC_I4: | |
| 3723 | return "i4"; | |
| 3724 | case UNW_SPARC_I5: | |
| 3725 | return "i5"; | |
| 3726 | case UNW_SPARC_I6: | |
| 3727 | return "i6"; | |
| 3728 | case UNW_SPARC_I7: | |
| 3729 | return "i7"; | |
| 3730 | default: | |
| 3731 | return "unknown register"; | |
| 3732 | } | |
| 3733 | } | |
| 3734 | #endif // _LIBUNWIND_TARGET_SPARC64 | |
| 3735 | ||
| 3549 | 3736 | #if defined(_LIBUNWIND_TARGET_HEXAGON) |
| 3550 | 3737 | /// Registers_hexagon holds the register state of a thread in a Hexagon QDSP6 |
| 3551 | 3738 | /// process. |
lib/libunwind/src/UnwindCursor.hpp+16| ... | ... | @@ -1020,6 +1020,10 @@ private: |
| 1020 | 1020 | int stepWithCompactEncoding(Registers_sparc &) { return UNW_EINVAL; } |
| 1021 | 1021 | #endif |
| 1022 | 1022 | |
| 1023 | #if defined(_LIBUNWIND_TARGET_SPARC64) | |
| 1024 | int stepWithCompactEncoding(Registers_sparc64 &) { return UNW_EINVAL; } | |
| 1025 | #endif | |
| 1026 | ||
| 1023 | 1027 | #if defined (_LIBUNWIND_TARGET_RISCV) |
| 1024 | 1028 | int stepWithCompactEncoding(Registers_riscv &) { |
| 1025 | 1029 | return UNW_EINVAL; |
| ... | ... | @@ -1092,6 +1096,12 @@ private: |
| 1092 | 1096 | bool compactSaysUseDwarf(Registers_sparc &, uint32_t *) const { return true; } |
| 1093 | 1097 | #endif |
| 1094 | 1098 | |
| 1099 | #if defined(_LIBUNWIND_TARGET_SPARC64) | |
| 1100 | bool compactSaysUseDwarf(Registers_sparc64 &, uint32_t *) const { | |
| 1101 | return true; | |
| 1102 | } | |
| 1103 | #endif | |
| 1104 | ||
| 1095 | 1105 | #if defined (_LIBUNWIND_TARGET_RISCV) |
| 1096 | 1106 | bool compactSaysUseDwarf(Registers_riscv &, uint32_t *) const { |
| 1097 | 1107 | return true; |
| ... | ... | @@ -1170,6 +1180,12 @@ private: |
| 1170 | 1180 | compact_unwind_encoding_t dwarfEncoding(Registers_sparc &) const { return 0; } |
| 1171 | 1181 | #endif |
| 1172 | 1182 | |
| 1183 | #if defined(_LIBUNWIND_TARGET_SPARC64) | |
| 1184 | compact_unwind_encoding_t dwarfEncoding(Registers_sparc64 &) const { | |
| 1185 | return 0; | |
| 1186 | } | |
| 1187 | #endif | |
| 1188 | ||
| 1173 | 1189 | #if defined (_LIBUNWIND_TARGET_RISCV) |
| 1174 | 1190 | compact_unwind_encoding_t dwarfEncoding(Registers_riscv &) const { |
| 1175 | 1191 | return 0; |
lib/libunwind/src/UnwindRegistersRestore.S+47| ... | ... | @@ -1050,6 +1050,53 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind21Registers_mips_newabi6jumptoEv) |
| 1050 | 1050 | ld $4, (8 * 4)($4) |
| 1051 | 1051 | .set pop |
| 1052 | 1052 | |
| 1053 | #elif defined(__sparc__) && defined(__arch64__) | |
| 1054 | ||
| 1055 | DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind17Registers_sparc646jumptoEv) | |
| 1056 | // | |
| 1057 | // void libunwind::Registers_sparc64::jumpto() | |
| 1058 | // | |
| 1059 | // On entry: | |
| 1060 | // thread_state pointer is in %o0 | |
| 1061 | // | |
| 1062 | .register %g2, #scratch | |
| 1063 | .register %g3, #scratch | |
| 1064 | .register %g6, #scratch | |
| 1065 | .register %g7, #scratch | |
| 1066 | flushw | |
| 1067 | ldx [%o0 + 0x08], %g1 | |
| 1068 | ldx [%o0 + 0x10], %g2 | |
| 1069 | ldx [%o0 + 0x18], %g3 | |
| 1070 | ldx [%o0 + 0x20], %g4 | |
| 1071 | ldx [%o0 + 0x28], %g5 | |
| 1072 | ldx [%o0 + 0x30], %g6 | |
| 1073 | ldx [%o0 + 0x38], %g7 | |
| 1074 | ldx [%o0 + 0x48], %o1 | |
| 1075 | ldx [%o0 + 0x50], %o2 | |
| 1076 | ldx [%o0 + 0x58], %o3 | |
| 1077 | ldx [%o0 + 0x60], %o4 | |
| 1078 | ldx [%o0 + 0x68], %o5 | |
| 1079 | ldx [%o0 + 0x70], %o6 | |
| 1080 | ldx [%o0 + 0x78], %o7 | |
| 1081 | ldx [%o0 + 0x80], %l0 | |
| 1082 | ldx [%o0 + 0x88], %l1 | |
| 1083 | ldx [%o0 + 0x90], %l2 | |
| 1084 | ldx [%o0 + 0x98], %l3 | |
| 1085 | ldx [%o0 + 0xa0], %l4 | |
| 1086 | ldx [%o0 + 0xa8], %l5 | |
| 1087 | ldx [%o0 + 0xb0], %l6 | |
| 1088 | ldx [%o0 + 0xb8], %l7 | |
| 1089 | ldx [%o0 + 0xc0], %i0 | |
| 1090 | ldx [%o0 + 0xc8], %i1 | |
| 1091 | ldx [%o0 + 0xd0], %i2 | |
| 1092 | ldx [%o0 + 0xd8], %i3 | |
| 1093 | ldx [%o0 + 0xe0], %i4 | |
| 1094 | ldx [%o0 + 0xe8], %i5 | |
| 1095 | ldx [%o0 + 0xf0], %i6 | |
| 1096 | ldx [%o0 + 0xf8], %i7 | |
| 1097 | jmp %o7 | |
| 1098 | ldx [%o0 + 0x40], %o0 | |
| 1099 | ||
| 1053 | 1100 | #elif defined(__sparc__) |
| 1054 | 1101 | |
| 1055 | 1102 | // |
lib/libunwind/src/UnwindRegistersSave.S+59-1| ... | ... | @@ -766,7 +766,7 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) |
| 766 | 766 | @ |
| 767 | 767 | @ On entry: |
| 768 | 768 | @ thread_state pointer is in r0 |
| 769 | @ | |
| 769 | @ | |
| 770 | 770 | @ Per EHABI #4.7 this only saves the core integer registers. |
| 771 | 771 | @ EHABI #7.4.5 notes that in general all VRS registers should be restored |
| 772 | 772 | @ however this is very hard to do for VFP registers because it is unknown |
| ... | ... | @@ -996,6 +996,64 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) |
| 996 | 996 | |
| 997 | 997 | jumpr r31 |
| 998 | 998 | |
| 999 | #elif defined(__sparc__) && defined(__arch64__) | |
| 1000 | ||
| 1001 | # | |
| 1002 | # extern int __unw_getcontext(unw_context_t* thread_state) | |
| 1003 | # | |
| 1004 | # On entry: | |
| 1005 | # thread_state pointer is in %o0 | |
| 1006 | # | |
| 1007 | DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) | |
| 1008 | .register %g2, #scratch | |
| 1009 | .register %g3, #scratch | |
| 1010 | .register %g6, #scratch | |
| 1011 | .register %g7, #scratch | |
| 1012 | stx %g1, [%o0 + 0x08] | |
| 1013 | stx %g2, [%o0 + 0x10] | |
| 1014 | stx %g3, [%o0 + 0x18] | |
| 1015 | stx %g4, [%o0 + 0x20] | |
| 1016 | stx %g5, [%o0 + 0x28] | |
| 1017 | stx %g6, [%o0 + 0x30] | |
| 1018 | stx %g7, [%o0 + 0x38] | |
| 1019 | stx %o0, [%o0 + 0x40] | |
| 1020 | stx %o1, [%o0 + 0x48] | |
| 1021 | stx %o2, [%o0 + 0x50] | |
| 1022 | stx %o3, [%o0 + 0x58] | |
| 1023 | stx %o4, [%o0 + 0x60] | |
| 1024 | stx %o5, [%o0 + 0x68] | |
| 1025 | stx %o6, [%o0 + 0x70] | |
| 1026 | stx %o7, [%o0 + 0x78] | |
| 1027 | stx %l0, [%o0 + 0x80] | |
| 1028 | stx %l1, [%o0 + 0x88] | |
| 1029 | stx %l2, [%o0 + 0x90] | |
| 1030 | stx %l3, [%o0 + 0x98] | |
| 1031 | stx %l4, [%o0 + 0xa0] | |
| 1032 | stx %l5, [%o0 + 0xa8] | |
| 1033 | stx %l6, [%o0 + 0xb0] | |
| 1034 | stx %l7, [%o0 + 0xb8] | |
| 1035 | stx %i0, [%o0 + 0xc0] | |
| 1036 | stx %i1, [%o0 + 0xc8] | |
| 1037 | stx %i2, [%o0 + 0xd0] | |
| 1038 | stx %i3, [%o0 + 0xd8] | |
| 1039 | stx %i4, [%o0 + 0xe0] | |
| 1040 | stx %i5, [%o0 + 0xe8] | |
| 1041 | stx %i6, [%o0 + 0xf0] | |
| 1042 | stx %i7, [%o0 + 0xf8] | |
| 1043 | ||
| 1044 | # save StackGhost cookie | |
| 1045 | mov %i7, %g4 | |
| 1046 | save %sp, -176, %sp | |
| 1047 | # register window flush necessary even without StackGhost | |
| 1048 | flushw | |
| 1049 | restore | |
| 1050 | ldx [%sp + 2047 + 0x78], %g5 | |
| 1051 | xor %g4, %g5, %g4 | |
| 1052 | stx %g4, [%o0 + 0x100] | |
| 1053 | retl | |
| 1054 | # return UNW_ESUCCESS | |
| 1055 | clr %o0 | |
| 1056 | ||
| 999 | 1057 | #elif defined(__sparc__) |
| 1000 | 1058 | |
| 1001 | 1059 | # |
lib/libunwind/src/config.h+4-7| ... | ... | @@ -109,13 +109,10 @@ |
| 109 | 109 | #define _LIBUNWIND_SUPPORT_FRAME_APIS |
| 110 | 110 | #endif |
| 111 | 111 | |
| 112 | #if defined(__i386__) || defined(__x86_64__) || \ | |
| 113 | defined(__ppc__) || defined(__ppc64__) || defined(__powerpc64__) || \ | |
| 114 | (!defined(__APPLE__) && defined(__arm__)) || \ | |
| 115 | defined(__aarch64__) || \ | |
| 116 | defined(__mips__) || \ | |
| 117 | defined(__riscv) || \ | |
| 118 | defined(__hexagon__) | |
| 112 | #if defined(__i386__) || defined(__x86_64__) || defined(__powerpc__) || \ | |
| 113 | (!defined(__APPLE__) && defined(__arm__)) || defined(__aarch64__) || \ | |
| 114 | defined(__mips__) || defined(__riscv) || defined(__hexagon__) || \ | |
| 115 | defined(__sparc__) | |
| 119 | 116 | #if !defined(_LIBUNWIND_BUILD_SJLJ_APIS) |
| 120 | 117 | #define _LIBUNWIND_BUILD_ZERO_COST_APIS |
| 121 | 118 | #endif |
lib/libunwind/src/libunwind.cpp+2| ... | ... | @@ -69,6 +69,8 @@ _LIBUNWIND_HIDDEN int __unw_init_local(unw_cursor_t *cursor, |
| 69 | 69 | # define REGISTER_KIND Registers_mips_newabi |
| 70 | 70 | #elif defined(__mips__) |
| 71 | 71 | # warning The MIPS architecture is not supported with this ABI and environment! |
| 72 | #elif defined(__sparc__) && defined(__arch64__) | |
| 73 | # define REGISTER_KIND Registers_sparc64 | |
| 72 | 74 | #elif defined(__sparc__) |
| 73 | 75 | # define REGISTER_KIND Registers_sparc |
| 74 | 76 | #elif defined(__riscv) |