authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-01-17 05:24:24+01:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-04-22 15:31:56+02:00
log20f08ad09c515099b316e3624e0986cdcb8d2b93
tree6ca62bc7a1870443f4f9df285411ebe7261debe9
parent78591e1d988b8983d811d573fbbf6de5a93baa07
signaturebadge-check Signed by SSH key SHA256:7B/LJ7bpR1eX8aCXSr4mtd5M45VMPKcx9zY8e95b5QM

libunwind: update to LLVM 22


21 files changed, 1069 insertions(+), 200 deletions(-)

lib/libunwind/include/__libunwind_config.h+11-2
...@@ -73,11 +73,11 @@...@@ -73,11 +73,11 @@
73# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC73# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC
74# elif defined(__aarch64__)74# elif defined(__aarch64__)
75# define _LIBUNWIND_TARGET_AARCH64 175# define _LIBUNWIND_TARGET_AARCH64 1
76# define _LIBUNWIND_CONTEXT_SIZE 6676#define _LIBUNWIND_CONTEXT_SIZE 67
77# if defined(__SEH__)77# if defined(__SEH__)
78# define _LIBUNWIND_CURSOR_SIZE 16478# define _LIBUNWIND_CURSOR_SIZE 164
79# else79# else
80# define _LIBUNWIND_CURSOR_SIZE 7880#define _LIBUNWIND_CURSOR_SIZE 79
81# endif81# endif
82# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM6482# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64
83# elif defined(__arm__)83# elif defined(__arm__)
...@@ -212,4 +212,13 @@...@@ -212,4 +212,13 @@
212# define _LIBUNWIND_HIGHEST_DWARF_REGISTER 287212# define _LIBUNWIND_HIGHEST_DWARF_REGISTER 287
213#endif // _LIBUNWIND_IS_NATIVE_ONLY213#endif // _LIBUNWIND_IS_NATIVE_ONLY
214214
215#if defined(__has_feature)
216# if __has_feature(ptrauth_calls) && __has_feature(ptrauth_returns)
217# define _LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING 1
218# elif __has_feature(ptrauth_calls) != __has_feature(ptrauth_returns)
219# error "Either both or none of ptrauth_calls and ptrauth_returns "\
220 "is allowed to be enabled"
221# endif
222#endif
223
215#endif // ____LIBUNWIND_CONFIG_H__224#endif // ____LIBUNWIND_CONFIG_H__
lib/libunwind/include/libunwind.h+117-11
...@@ -43,6 +43,109 @@...@@ -43,6 +43,109 @@
43 #define LIBUNWIND_AVAIL43 #define LIBUNWIND_AVAIL
44#endif44#endif
4545
46#if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING)
47
48 #include <ptrauth.h>
49
50 // `__ptrauth_restricted_intptr` is a feature of apple clang that predates
51 // support for direct application of `__ptrauth` to integer types. This
52 // guard is necessary to support compilation with those compiler.
53 #if __has_extension(ptrauth_restricted_intptr_qualifier)
54 #define __unwind_ptrauth_restricted_intptr(...) \
55 __ptrauth_restricted_intptr(__VA_ARGS__)
56 #else
57 #define __unwind_ptrauth_restricted_intptr(...) \
58 __ptrauth(__VA_ARGS__)
59 #endif
60
61 // ptrauth_string_discriminator("unw_proc_info_t::handler") == 0x7405
62 #define __ptrauth_unwind_upi_handler_disc 0x7405
63
64 #define __ptrauth_unwind_upi_handler \
65 __ptrauth(ptrauth_key_function_pointer, 1, __ptrauth_unwind_upi_handler_disc)
66
67 #define __ptrauth_unwind_upi_handler_intptr \
68 __unwind_ptrauth_restricted_intptr(ptrauth_key_function_pointer, 1,\
69 __ptrauth_unwind_upi_handler_disc)
70
71 // ptrauth_string_discriminator("unw_proc_info_t::start_ip") == 0xCA2C
72 #define __ptrauth_unwind_upi_startip \
73 __unwind_ptrauth_restricted_intptr(ptrauth_key_process_independent_code, 1, 0xCA2C)
74
75 // ptrauth_string_discriminator("unw_proc_info_t::end_ip") == 0xE183
76 #define __ptrauth_unwind_upi_endip \
77 __unwind_ptrauth_restricted_intptr(ptrauth_key_process_independent_code, 1, 0xE183)
78
79 // ptrauth_string_discriminator("unw_proc_info_t::lsda") == 0x83DE
80 #define __ptrauth_unwind_upi_lsda \
81 __unwind_ptrauth_restricted_intptr(ptrauth_key_process_dependent_data, 1, 0x83DE)
82
83 // ptrauth_string_discriminator("unw_proc_info_t::flags") == 0x79A1
84 #define __ptrauth_unwind_upi_flags \
85 __unwind_ptrauth_restricted_intptr(ptrauth_key_process_dependent_data, 1, 0x79A1)
86
87 // ptrauth_string_discriminator("unw_proc_info_t::unwind_info") == 0xC20C
88 #define __ptrauth_unwind_upi_info \
89 __unwind_ptrauth_restricted_intptr(ptrauth_key_process_dependent_data, 1, 0xC20C)
90
91 // ptrauth_string_discriminator("unw_proc_info_t::extra") == 0x03DF
92 #define __ptrauth_unwind_upi_extra \
93 __unwind_ptrauth_restricted_intptr(ptrauth_key_process_dependent_data, 1, 0x03DF)
94
95 // ptrauth_string_discriminator("Registers_arm64::link_reg_t") == 0x8301
96 #define __ptrauth_unwind_registers_arm64_link_reg \
97 __unwind_ptrauth_restricted_intptr(ptrauth_key_process_dependent_code, 1, 0x8301)
98
99 // ptrauth_string_discriminator("UnwindInfoSections::dso_base") == 0x4FF5
100 #define __ptrauth_unwind_uis_dso_base \
101 __unwind_ptrauth_restricted_intptr(ptrauth_key_process_dependent_data, 1, 0x4FF5)
102
103 // ptrauth_string_discriminator("UnwindInfoSections::dwarf_section") == 0x4974
104 #define __ptrauth_unwind_uis_dwarf_section \
105 __unwind_ptrauth_restricted_intptr(ptrauth_key_process_dependent_data, 1, 0x4974)
106
107 // ptrauth_string_discriminator("UnwindInfoSections::dwarf_section_length") == 0x2A9A
108 #define __ptrauth_unwind_uis_dwarf_section_length \
109 __unwind_ptrauth_restricted_intptr(ptrauth_key_process_dependent_data, 1, 0x2A9A)
110
111 // ptrauth_string_discriminator("UnwindInfoSections::compact_unwind_section") == 0xA27B
112 #define __ptrauth_unwind_uis_compact_unwind_section \
113 __unwind_ptrauth_restricted_intptr(ptrauth_key_process_dependent_data, 1, 0xA27B)
114
115 // ptrauth_string_discriminator("UnwindInfoSections::compact_unwind_section_length") == 0x5D0A
116 #define __ptrauth_unwind_uis_compact_unwind_section_length \
117 __unwind_ptrauth_restricted_intptr(ptrauth_key_process_dependent_data, 1, 0x5D0A)
118
119 // ptrauth_string_discriminator("CIE_Info::personality") == 0x6A40
120 #define __ptrauth_unwind_cie_info_personality_disc 0x6A40
121 #define __ptrauth_unwind_cie_info_personality \
122 __unwind_ptrauth_restricted_intptr(ptrauth_key_function_pointer, 1, \
123 __ptrauth_unwind_cie_info_personality_disc)
124
125 // ptrauth_string_discriminator("personality") == 0x7EAD)
126 #define __ptrauth_unwind_pauthtest_personality_disc 0x7EAD
127
128#else
129
130 #define __unwind_ptrauth_restricted_intptr(...)
131 #define __ptrauth_unwind_upi_handler
132 #define __ptrauth_unwind_upi_handler_intptr
133 #define __ptrauth_unwind_upi_startip
134 #define __ptrauth_unwind_upi_endip
135 #define __ptrauth_unwind_upi_lsda
136 #define __ptrauth_unwind_upi_flags
137 #define __ptrauth_unwind_upi_info
138 #define __ptrauth_unwind_upi_extra
139 #define __ptrauth_unwind_registers_arm64_link_reg
140 #define __ptrauth_unwind_uis_dso_base
141 #define __ptrauth_unwind_uis_dwarf_section
142 #define __ptrauth_unwind_uis_dwarf_section_length
143 #define __ptrauth_unwind_uis_compact_unwind_section
144 #define __ptrauth_unwind_uis_compact_unwind_section_length
145 #define __ptrauth_unwind_cie_info_personality
146
147#endif
148
46#if defined(_WIN32) && defined(__SEH__)149#if defined(_WIN32) && defined(__SEH__)
47 #define LIBUNWIND_CURSOR_ALIGNMENT_ATTR __attribute__((__aligned__(16)))150 #define LIBUNWIND_CURSOR_ALIGNMENT_ATTR __attribute__((__aligned__(16)))
48#else151#else
...@@ -88,17 +191,18 @@ typedef double unw_fpreg_t;...@@ -88,17 +191,18 @@ typedef double unw_fpreg_t;
88#endif191#endif
89192
90struct unw_proc_info_t {193struct unw_proc_info_t {
91 unw_word_t start_ip; /* start address of function */194 unw_word_t __ptrauth_unwind_upi_startip start_ip; /* start address of function */
92 unw_word_t end_ip; /* address after end of function */195 unw_word_t __ptrauth_unwind_upi_endip end_ip; /* address after end of function */
93 unw_word_t lsda; /* address of language specific data area, */196 unw_word_t __ptrauth_unwind_upi_lsda lsda; /* address of language specific data area, */
94 /* or zero if not used */197 /* or zero if not used */
95 unw_word_t handler; /* personality routine, or zero if not used */198
96 unw_word_t gp; /* not used */199 unw_word_t __ptrauth_unwind_upi_handler_intptr handler;
97 unw_word_t flags; /* not used */200 unw_word_t gp; /* not used */
98 uint32_t format; /* compact unwind encoding, or zero if none */201 unw_word_t __ptrauth_unwind_upi_flags flags; /* not used */
99 uint32_t unwind_info_size; /* size of DWARF unwind info, or zero if none */202 uint32_t format; /* compact unwind encoding, or zero if none */
100 unw_word_t unwind_info; /* address of DWARF unwind info, or zero */203 uint32_t unwind_info_size; /* size of DWARF unwind info, or zero if none */
101 unw_word_t extra; /* mach_header of mach-o image containing func */204 unw_word_t __ptrauth_unwind_upi_info unwind_info; /* address of DWARF unwind info, or zero */
205 unw_word_t __ptrauth_unwind_upi_extra extra; /* mach_header of mach-o image containing func */
102};206};
103typedef struct unw_proc_info_t unw_proc_info_t;207typedef struct unw_proc_info_t unw_proc_info_t;
104208
...@@ -130,6 +234,7 @@ extern int unw_is_fpreg(unw_cursor_t *, unw_regnum_t) LIBUNWIND_AVAIL;...@@ -130,6 +234,7 @@ extern int unw_is_fpreg(unw_cursor_t *, unw_regnum_t) LIBUNWIND_AVAIL;
130extern int unw_is_signal_frame(unw_cursor_t *) LIBUNWIND_AVAIL;234extern int unw_is_signal_frame(unw_cursor_t *) LIBUNWIND_AVAIL;
131extern int unw_get_proc_name(unw_cursor_t *, char *, size_t, unw_word_t *) LIBUNWIND_AVAIL;235extern int unw_get_proc_name(unw_cursor_t *, char *, size_t, unw_word_t *) LIBUNWIND_AVAIL;
132//extern int unw_get_save_loc(unw_cursor_t*, int, unw_save_loc_t*);236//extern int unw_get_save_loc(unw_cursor_t*, int, unw_save_loc_t*);
237extern const char *unw_strerror(int) LIBUNWIND_AVAIL;
133238
134extern unw_addr_space_t unw_local_addr_space;239extern unw_addr_space_t unw_local_addr_space;
135240
...@@ -532,6 +637,7 @@ enum {...@@ -532,6 +637,7 @@ enum {
532 UNW_AARCH64_X31 = 31,637 UNW_AARCH64_X31 = 31,
533 UNW_AARCH64_SP = 31,638 UNW_AARCH64_SP = 31,
534 UNW_AARCH64_PC = 32,639 UNW_AARCH64_PC = 32,
640 UNW_AARCH64_VG = 46,
535641
536 // reserved block642 // reserved block
537 UNW_AARCH64_RA_SIGN_STATE = 34,643 UNW_AARCH64_RA_SIGN_STATE = 34,
lib/libunwind/include/unwind_arm_ehabi.h+4-1
...@@ -125,8 +125,11 @@ _Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass,...@@ -125,8 +125,11 @@ _Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass,
125 uint32_t discriminator,125 uint32_t discriminator,
126 _Unwind_VRS_DataRepresentation representation);126 _Unwind_VRS_DataRepresentation representation);
127127
128extern _Unwind_Reason_Code __gnu_unwind_frame(_Unwind_Exception *,
129 _Unwind_Context *);
130
128#if defined(_LIBUNWIND_UNWIND_LEVEL1_EXTERNAL_LINKAGE)131#if defined(_LIBUNWIND_UNWIND_LEVEL1_EXTERNAL_LINKAGE)
129#define _LIBUNWIND_EXPORT_UNWIND_LEVEL1 extern132#define _LIBUNWIND_EXPORT_UNWIND_LEVEL1 extern __inline__
130#else133#else
131#define _LIBUNWIND_EXPORT_UNWIND_LEVEL1 static __inline__134#define _LIBUNWIND_EXPORT_UNWIND_LEVEL1 static __inline__
132#endif135#endif
lib/libunwind/src/AddressSpace.hpp+40-19
...@@ -129,22 +129,27 @@ struct UnwindInfoSections {...@@ -129,22 +129,27 @@ struct UnwindInfoSections {
129 defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) || \129 defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) || \
130 defined(_LIBUNWIND_USE_DL_ITERATE_PHDR)130 defined(_LIBUNWIND_USE_DL_ITERATE_PHDR)
131 // No dso_base for SEH.131 // No dso_base for SEH.
132 uintptr_t dso_base;132 uintptr_t __ptrauth_unwind_uis_dso_base
133 dso_base = 0;
133#endif134#endif
134#if defined(_LIBUNWIND_USE_DL_ITERATE_PHDR)135#if defined(_LIBUNWIND_USE_DL_ITERATE_PHDR)
135 size_t text_segment_length;136 size_t text_segment_length;
136#endif137#endif
137#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)138#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
138 uintptr_t dwarf_section;139 uintptr_t __ptrauth_unwind_uis_dwarf_section
139 size_t dwarf_section_length;140 dwarf_section = 0;
141 size_t __ptrauth_unwind_uis_dwarf_section_length
142 dwarf_section_length = 0;
140#endif143#endif
141#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)144#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
142 uintptr_t dwarf_index_section;145 uintptr_t dwarf_index_section;
143 size_t dwarf_index_section_length;146 size_t dwarf_index_section_length;
144#endif147#endif
145#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)148#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
146 uintptr_t compact_unwind_section;149 uintptr_t __ptrauth_unwind_uis_compact_unwind_section
147 size_t compact_unwind_section_length;150 compact_unwind_section = 0;
151 size_t __ptrauth_unwind_uis_compact_unwind_section_length
152 compact_unwind_section_length = 0;
148#endif153#endif
149#if defined(_LIBUNWIND_ARM_EHABI)154#if defined(_LIBUNWIND_ARM_EHABI)
150 uintptr_t arm_section;155 uintptr_t arm_section;
...@@ -196,11 +201,16 @@ public:...@@ -196,11 +201,16 @@ public:
196 static int64_t getSLEB128(pint_t &addr, pint_t end);201 static int64_t getSLEB128(pint_t &addr, pint_t end);
197202
198 pint_t getEncodedP(pint_t &addr, pint_t end, uint8_t encoding,203 pint_t getEncodedP(pint_t &addr, pint_t end, uint8_t encoding,
199 pint_t datarelBase = 0);204 pint_t datarelBase = 0, pint_t *resultAddr = nullptr);
200 bool findFunctionName(pint_t addr, char *buf, size_t bufLen,205 template <typename R>
201 unw_word_t *offset);206 bool findFunctionName(typename R::link_hardened_reg_arg_t addr, char *buf,
202 bool findUnwindSections(pint_t targetAddr, UnwindInfoSections &info);207 size_t bufLen, unw_word_t *offset);
203 bool findOtherFDE(pint_t targetAddr, pint_t &fde);208 template <typename R>
209 bool findUnwindSections(typename R::link_hardened_reg_arg_t targetAddr,
210 UnwindInfoSections &info);
211 template <typename R>
212 bool findOtherFDE(typename R::link_hardened_reg_arg_t targetAddr,
213 pint_t &fde);
204214
205 static LocalAddressSpace sThisAddressSpace;215 static LocalAddressSpace sThisAddressSpace;
206};216};
...@@ -269,7 +279,7 @@ inline int64_t LocalAddressSpace::getSLEB128(pint_t &addr, pint_t end) {...@@ -269,7 +279,7 @@ inline int64_t LocalAddressSpace::getSLEB128(pint_t &addr, pint_t end) {
269279
270inline LocalAddressSpace::pint_t280inline LocalAddressSpace::pint_t
271LocalAddressSpace::getEncodedP(pint_t &addr, pint_t end, uint8_t encoding,281LocalAddressSpace::getEncodedP(pint_t &addr, pint_t end, uint8_t encoding,
272 pint_t datarelBase) {282 pint_t datarelBase, pint_t *resultAddr) {
273 pint_t startAddr = addr;283 pint_t startAddr = addr;
274 const uint8_t *p = (uint8_t *)addr;284 const uint8_t *p = (uint8_t *)addr;
275 pint_t result;285 pint_t result;
...@@ -353,8 +363,14 @@ LocalAddressSpace::getEncodedP(pint_t &addr, pint_t end, uint8_t encoding,...@@ -353,8 +363,14 @@ LocalAddressSpace::getEncodedP(pint_t &addr, pint_t end, uint8_t encoding,
353 break;363 break;
354 }364 }
355365
356 if (encoding & DW_EH_PE_indirect)366 if (encoding & DW_EH_PE_indirect) {
367 if (resultAddr)
368 *resultAddr = result;
357 result = getP(result);369 result = getP(result);
370 } else {
371 if (resultAddr)
372 *resultAddr = startAddr;
373 }
358374
359 return result;375 return result;
360}376}
...@@ -486,9 +502,9 @@ static int findUnwindSectionsByPhdr(struct dl_phdr_info *pinfo,...@@ -486,9 +502,9 @@ static int findUnwindSectionsByPhdr(struct dl_phdr_info *pinfo,
486502
487#endif // defined(_LIBUNWIND_USE_DL_ITERATE_PHDR)503#endif // defined(_LIBUNWIND_USE_DL_ITERATE_PHDR)
488504
489505template <typename R>
490inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr,506inline bool LocalAddressSpace::findUnwindSections(
491 UnwindInfoSections &info) {507 typename R::link_hardened_reg_arg_t targetAddr, UnwindInfoSections &info) {
492#ifdef __APPLE__508#ifdef __APPLE__
493 dyld_unwind_sections dyldInfo;509 dyld_unwind_sections dyldInfo;
494 if (_dyld_find_unwind_sections((void *)targetAddr, &dyldInfo)) {510 if (_dyld_find_unwind_sections((void *)targetAddr, &dyldInfo)) {
...@@ -658,16 +674,21 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr,...@@ -658,16 +674,21 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr,
658 return false;674 return false;
659}675}
660676
661inline bool LocalAddressSpace::findOtherFDE(pint_t targetAddr, pint_t &fde) {677template <typename R>
678inline bool
679LocalAddressSpace::findOtherFDE(typename R::link_hardened_reg_arg_t targetAddr,
680 pint_t &fde) {
662 // TO DO: if OS has way to dynamically register FDEs, check that.681 // TO DO: if OS has way to dynamically register FDEs, check that.
663 (void)targetAddr;682 (void)targetAddr;
664 (void)fde;683 (void)fde;
665 return false;684 return false;
666}685}
667686
668inline bool LocalAddressSpace::findFunctionName(pint_t addr, char *buf,687template <typename R>
669 size_t bufLen,688inline bool
670 unw_word_t *offset) {689LocalAddressSpace::findFunctionName(typename R::link_hardened_reg_arg_t addr,
690 char *buf, size_t bufLen,
691 unw_word_t *offset) {
671#if _LIBUNWIND_USE_DLADDR692#if _LIBUNWIND_USE_DLADDR
672 Dl_info dyldInfo;693 Dl_info dyldInfo;
673 if (dladdr((void *)addr, &dyldInfo)) {694 if (dladdr((void *)addr, &dyldInfo)) {
lib/libunwind/src/CompactUnwinder.hpp+16-5
...@@ -601,11 +601,17 @@ int CompactUnwinder_arm64<A>::stepWithCompactEncodingFrameless(...@@ -601,11 +601,17 @@ int CompactUnwinder_arm64<A>::stepWithCompactEncodingFrameless(
601 savedRegisterLoc -= 8;601 savedRegisterLoc -= 8;
602 }602 }
603603
604 // We load the link register prior to setting the new SP as the authentication
605 // schema for LR entangles the SP of the old frame into the diversifier.
606 Registers_arm64::reg_t linkRegister = registers.getRegister(UNW_AARCH64_LR);
607
604 // subtract stack size off of sp608 // subtract stack size off of sp
605 registers.setSP(savedRegisterLoc);609 registers.setSP(savedRegisterLoc);
606610
607 // set pc to be value in lr611 // Set pc to be value in lr. This needs to be performed after the new SP has
608 registers.setIP(registers.getRegister(UNW_AARCH64_LR));612 // been set, as the PC authentication schema entangles the SP of the new
613 // frame.
614 registers.setIP(linkRegister);
609615
610 return UNW_STEP_SUCCESS;616 return UNW_STEP_SUCCESS;
611}617}
...@@ -614,7 +620,7 @@ template <typename A>...@@ -614,7 +620,7 @@ template <typename A>
614int CompactUnwinder_arm64<A>::stepWithCompactEncodingFrame(620int CompactUnwinder_arm64<A>::stepWithCompactEncodingFrame(
615 compact_unwind_encoding_t encoding, uint64_t, A &addressSpace,621 compact_unwind_encoding_t encoding, uint64_t, A &addressSpace,
616 Registers_arm64 &registers) {622 Registers_arm64 &registers) {
617 uint64_t savedRegisterLoc = registers.getFP() - 8;623 Registers_arm64::reg_t savedRegisterLoc = registers.getFP() - 8;
618624
619 if (encoding & UNWIND_ARM64_FRAME_X19_X20_PAIR) {625 if (encoding & UNWIND_ARM64_FRAME_X19_X20_PAIR) {
620 registers.setRegister(UNW_AARCH64_X19, addressSpace.get64(savedRegisterLoc));626 registers.setRegister(UNW_AARCH64_X19, addressSpace.get64(savedRegisterLoc));
...@@ -680,11 +686,16 @@ int CompactUnwinder_arm64<A>::stepWithCompactEncodingFrame(...@@ -680,11 +686,16 @@ int CompactUnwinder_arm64<A>::stepWithCompactEncodingFrame(
680 savedRegisterLoc -= 8;686 savedRegisterLoc -= 8;
681 }687 }
682688
683 uint64_t fp = registers.getFP();689 Registers_arm64::reg_t fp = registers.getFP();
690
684 // fp points to old fp691 // fp points to old fp
685 registers.setFP(addressSpace.get64(fp));692 registers.setFP(addressSpace.get64(fp));
686 // old sp is fp less saved fp and lr693
694 // Old sp is fp less saved fp and lr. We need to set this prior to setting
695 // the lr as the pointer authentication schema for the lr incorporates the
696 // sp as part of the diversifier.
687 registers.setSP(fp + 16);697 registers.setSP(fp + 16);
698
688 // pop return address into pc699 // pop return address into pc
689 registers.setIP(addressSpace.get64(fp + 8));700 registers.setIP(addressSpace.get64(fp + 8));
690701
lib/libunwind/src/DwarfInstructions.hpp+24-13
...@@ -22,7 +22,6 @@...@@ -22,7 +22,6 @@
22#include "dwarf2.h"22#include "dwarf2.h"
23#include "libunwind_ext.h"23#include "libunwind_ext.h"
2424
25
26namespace libunwind {25namespace libunwind {
2726
2827
...@@ -34,8 +33,10 @@ public:...@@ -34,8 +33,10 @@ public:
34 typedef typename A::pint_t pint_t;33 typedef typename A::pint_t pint_t;
35 typedef typename A::sint_t sint_t;34 typedef typename A::sint_t sint_t;
3635
37 static int stepWithDwarf(A &addressSpace, pint_t pc, pint_t fdeStart,36 static int stepWithDwarf(A &addressSpace,
38 R &registers, bool &isSignalFrame, bool stage2);37 typename R::link_hardened_reg_arg_t pc,
38 pint_t fdeStart, R &registers, bool &isSignalFrame,
39 bool stage2);
3940
40private:41private:
4142
...@@ -64,9 +65,10 @@ private:...@@ -64,9 +65,10 @@ private:
6465
65 static pint_t getCFA(A &addressSpace, const PrologInfo &prolog,66 static pint_t getCFA(A &addressSpace, const PrologInfo &prolog,
66 const R &registers) {67 const R &registers) {
67 if (prolog.cfaRegister != 0)68 if (prolog.cfaRegister != 0) {
68 return (pint_t)((sint_t)registers.getRegister((int)prolog.cfaRegister) +69 uintptr_t cfaRegister = registers.getRegister((int)prolog.cfaRegister);
69 prolog.cfaRegisterOffset);70 return (pint_t)(cfaRegister + prolog.cfaRegisterOffset);
71 }
70 if (prolog.cfaExpression != 0)72 if (prolog.cfaExpression != 0)
71 return evaluateExpression((pint_t)prolog.cfaExpression, addressSpace,73 return evaluateExpression((pint_t)prolog.cfaExpression, addressSpace,
72 registers, 0);74 registers, 0);
...@@ -207,16 +209,16 @@ bool DwarfInstructions<A, R>::isReturnAddressSignedWithPC(A &addressSpace,...@@ -207,16 +209,16 @@ bool DwarfInstructions<A, R>::isReturnAddressSignedWithPC(A &addressSpace,
207#endif209#endif
208210
209template <typename A, typename R>211template <typename A, typename R>
210int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,212int DwarfInstructions<A, R>::stepWithDwarf(
211 pint_t fdeStart, R &registers,213 A &addressSpace, typename R::link_hardened_reg_arg_t pc, pint_t fdeStart,
212 bool &isSignalFrame, bool stage2) {214 R &registers, bool &isSignalFrame, bool stage2) {
213 FDE_Info fdeInfo;215 FDE_Info fdeInfo;
214 CIE_Info cieInfo;216 CIE_Info cieInfo;
215 if (CFI_Parser<A>::decodeFDE(addressSpace, fdeStart, &fdeInfo,217 if (CFI_Parser<A>::decodeFDE(addressSpace, fdeStart, &fdeInfo,
216 &cieInfo) == NULL) {218 &cieInfo) == NULL) {
217 PrologInfo prolog;219 PrologInfo prolog;
218 if (CFI_Parser<A>::parseFDEInstructions(addressSpace, fdeInfo, cieInfo, pc,220 if (CFI_Parser<A>::template parseFDEInstructions<R>(
219 R::getArch(), &prolog)) {221 addressSpace, fdeInfo, cieInfo, pc, R::getArch(), &prolog)) {
220 // get pointer to cfa (architecture specific)222 // get pointer to cfa (architecture specific)
221 pint_t cfa = getCFA(addressSpace, prolog, registers);223 pint_t cfa = getCFA(addressSpace, prolog, registers);
222224
...@@ -264,7 +266,7 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,...@@ -264,7 +266,7 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
264 // by a CFI directive later on.266 // by a CFI directive later on.
265 newRegisters.setSP(cfa);267 newRegisters.setSP(cfa);
266268
267 pint_t returnAddress = 0;269 typename R::reg_t returnAddress = 0;
268 constexpr int lastReg = R::lastDwarfRegNum();270 constexpr int lastReg = R::lastDwarfRegNum();
269 static_assert(static_cast<int>(CFI_Parser<A>::kMaxRegisterNumber) >=271 static_assert(static_cast<int>(CFI_Parser<A>::kMaxRegisterNumber) >=
270 lastReg,272 lastReg,
...@@ -300,7 +302,16 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,...@@ -300,7 +302,16 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
300302
301 isSignalFrame = cieInfo.isSignalFrame;303 isSignalFrame = cieInfo.isSignalFrame;
302304
303#if defined(_LIBUNWIND_TARGET_AARCH64)305#if defined(_LIBUNWIND_TARGET_AARCH64) && \
306 !defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING)
307 // There are two ways of return address signing: pac-ret (enabled via
308 // -mbranch-protection=pac-ret) and ptrauth-returns (enabled as part of
309 // Apple's arm64e or experimental pauthtest ABI on Linux). The code
310 // below handles signed RA for pac-ret, while ptrauth-returns uses
311 // different logic.
312 // TODO: unify logic for both cases, see
313 // https://github.com/llvm/llvm-project/issues/160110
314 //
304 // If the target is aarch64 then the return address may have been signed315 // If the target is aarch64 then the return address may have been signed
305 // using the v8.3 pointer authentication extensions. The original316 // using the v8.3 pointer authentication extensions. The original
306 // return address needs to be authenticated before the return address is317 // return address needs to be authenticated before the return address is
lib/libunwind/src/DwarfParser.hpp+60-22
...@@ -23,6 +23,10 @@...@@ -23,6 +23,10 @@
2323
24#include "config.h"24#include "config.h"
2525
26#if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING)
27#include <ptrauth.h>
28#endif
29
26namespace libunwind {30namespace libunwind {
2731
28/// CFI_Parser does basic parsing of a CFI (Call Frame Information) records.32/// CFI_Parser does basic parsing of a CFI (Call Frame Information) records.
...@@ -33,6 +37,7 @@ template <typename A>...@@ -33,6 +37,7 @@ template <typename A>
33class CFI_Parser {37class CFI_Parser {
34public:38public:
35 typedef typename A::pint_t pint_t;39 typedef typename A::pint_t pint_t;
40 typedef pint_t __ptrauth_unwind_cie_info_personality personality_t;
3641
37 /// Information encoded in a CIE (Common Information Entry)42 /// Information encoded in a CIE (Common Information Entry)
38 struct CIE_Info {43 struct CIE_Info {
...@@ -43,7 +48,7 @@ public:...@@ -43,7 +48,7 @@ public:
43 uint8_t lsdaEncoding;48 uint8_t lsdaEncoding;
44 uint8_t personalityEncoding;49 uint8_t personalityEncoding;
45 uint8_t personalityOffsetInCIE;50 uint8_t personalityOffsetInCIE;
46 pint_t personality;51 personality_t personality;
47 uint32_t codeAlignFactor;52 uint32_t codeAlignFactor;
48 int dataAlignFactor;53 int dataAlignFactor;
49 bool isSignalFrame;54 bool isSignalFrame;
...@@ -155,14 +160,17 @@ public:...@@ -155,14 +160,17 @@ public:
155 }160 }
156 };161 };
157162
158 static bool findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart,163 template <typename R>
159 size_t sectionLength, pint_t fdeHint, FDE_Info *fdeInfo,164 static bool findFDE(A &addressSpace, typename R::link_hardened_reg_arg_t pc,
160 CIE_Info *cieInfo);165 pint_t ehSectionStart, size_t sectionLength,
166 pint_t fdeHint, FDE_Info *fdeInfo, CIE_Info *cieInfo);
161 static const char *decodeFDE(A &addressSpace, pint_t fdeStart,167 static const char *decodeFDE(A &addressSpace, pint_t fdeStart,
162 FDE_Info *fdeInfo, CIE_Info *cieInfo,168 FDE_Info *fdeInfo, CIE_Info *cieInfo,
163 bool useCIEInfo = false);169 bool useCIEInfo = false);
170 template <typename R>
164 static bool parseFDEInstructions(A &addressSpace, const FDE_Info &fdeInfo,171 static bool parseFDEInstructions(A &addressSpace, const FDE_Info &fdeInfo,
165 const CIE_Info &cieInfo, pint_t upToPC,172 const CIE_Info &cieInfo,
173 typename R::link_hardened_reg_arg_t upToPC,
166 int arch, PrologInfo *results);174 int arch, PrologInfo *results);
167175
168 static const char *parseCIE(A &addressSpace, pint_t cie, CIE_Info *cieInfo);176 static const char *parseCIE(A &addressSpace, pint_t cie, CIE_Info *cieInfo);
...@@ -234,9 +242,12 @@ const char *CFI_Parser<A>::decodeFDE(A &addressSpace, pint_t fdeStart,...@@ -234,9 +242,12 @@ const char *CFI_Parser<A>::decodeFDE(A &addressSpace, pint_t fdeStart,
234242
235/// Scan an eh_frame section to find an FDE for a pc243/// Scan an eh_frame section to find an FDE for a pc
236template <typename A>244template <typename A>
237bool CFI_Parser<A>::findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart,245template <typename R>
238 size_t sectionLength, pint_t fdeHint,246bool CFI_Parser<A>::findFDE(A &addressSpace,
239 FDE_Info *fdeInfo, CIE_Info *cieInfo) {247 typename R::link_hardened_reg_arg_t pc,
248 pint_t ehSectionStart, size_t sectionLength,
249 pint_t fdeHint, FDE_Info *fdeInfo,
250 CIE_Info *cieInfo) {
240 //fprintf(stderr, "findFDE(0x%llX)\n", (long long)pc);251 //fprintf(stderr, "findFDE(0x%llX)\n", (long long)pc);
241 pint_t p = (fdeHint != 0) ? fdeHint : ehSectionStart;252 pint_t p = (fdeHint != 0) ? fdeHint : ehSectionStart;
242 const pint_t ehSectionEnd = (sectionLength == SIZE_MAX)253 const pint_t ehSectionEnd = (sectionLength == SIZE_MAX)
...@@ -273,7 +284,7 @@ bool CFI_Parser<A>::findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart,...@@ -273,7 +284,7 @@ bool CFI_Parser<A>::findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart,
273 pint_t pcRange = addressSpace.getEncodedP(284 pint_t pcRange = addressSpace.getEncodedP(
274 p, nextCFI, cieInfo->pointerEncoding & 0x0F);285 p, nextCFI, cieInfo->pointerEncoding & 0x0F);
275 // Test if pc is within the function this FDE covers.286 // Test if pc is within the function this FDE covers.
276 if ((pcStart < pc) && (pc <= pcStart + pcRange)) {287 if ((pcStart <= pc) && (pc < pcStart + pcRange)) {
277 // parse rest of info288 // parse rest of info
278 fdeInfo->lsda = 0;289 fdeInfo->lsda = 0;
279 // check for augmentation length290 // check for augmentation length
...@@ -369,6 +380,7 @@ const char *CFI_Parser<A>::parseCIE(A &addressSpace, pint_t cie,...@@ -369,6 +380,7 @@ const char *CFI_Parser<A>::parseCIE(A &addressSpace, pint_t cie,
369 cieInfo->returnAddressRegister = (uint8_t)raReg;380 cieInfo->returnAddressRegister = (uint8_t)raReg;
370 // parse augmentation data based on augmentation string381 // parse augmentation data based on augmentation string
371 const char *result = NULL;382 const char *result = NULL;
383 pint_t resultAddr = 0;
372 if (addressSpace.get8(strStart) == 'z') {384 if (addressSpace.get8(strStart) == 'z') {
373 // parse augmentation data length385 // parse augmentation data length
374 addressSpace.getULEB128(p, cieContentEnd);386 addressSpace.getULEB128(p, cieContentEnd);
...@@ -377,13 +389,41 @@ const char *CFI_Parser<A>::parseCIE(A &addressSpace, pint_t cie,...@@ -377,13 +389,41 @@ const char *CFI_Parser<A>::parseCIE(A &addressSpace, pint_t cie,
377 case 'z':389 case 'z':
378 cieInfo->fdesHaveAugmentationData = true;390 cieInfo->fdesHaveAugmentationData = true;
379 break;391 break;
380 case 'P':392 case 'P': {
381 cieInfo->personalityEncoding = addressSpace.get8(p);393 cieInfo->personalityEncoding = addressSpace.get8(p);
382 ++p;394 ++p;
383 cieInfo->personalityOffsetInCIE = (uint8_t)(p - cie);395 cieInfo->personalityOffsetInCIE = (uint8_t)(p - cie);
384 cieInfo->personality = addressSpace396 pint_t personality = addressSpace.getEncodedP(
385 .getEncodedP(p, cieContentEnd, cieInfo->personalityEncoding);397 p, cieContentEnd, cieInfo->personalityEncoding,
398 /*datarelBase=*/0, &resultAddr);
399#if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING)
400 if (personality) {
401 // The GOT for the personality function was signed address
402 // authenticated. Manually re-sign with the CIE_Info::personality
403 // schema. If we could guarantee the encoding of the personality we
404 // could avoid this by simply giving resultAddr the correct ptrauth
405 // schema and performing an assignment.
406#if defined(__arm64e__)
407 const auto oldDiscriminator = resultAddr;
408#else
409 const auto oldDiscriminator = ptrauth_blend_discriminator(
410 (void *)resultAddr, __ptrauth_unwind_pauthtest_personality_disc);
411#endif
412 const auto discriminator = ptrauth_blend_discriminator(
413 &cieInfo->personality,
414 __ptrauth_unwind_cie_info_personality_disc);
415 void *signedPtr = ptrauth_auth_and_resign(
416 (void *)personality, ptrauth_key_function_pointer,
417 oldDiscriminator, ptrauth_key_function_pointer, discriminator);
418 personality = (pint_t)signedPtr;
419 }
420#endif
421 // We use memmove to set the CIE personality as we have already
422 // re-signed the pointer to the correct schema.
423 memmove((void *)&cieInfo->personality, (void *)&personality,
424 sizeof(personality));
386 break;425 break;
426 }
387 case 'L':427 case 'L':
388 cieInfo->lsdaEncoding = addressSpace.get8(p);428 cieInfo->lsdaEncoding = addressSpace.get8(p);
389 ++p;429 ++p;
...@@ -417,10 +457,10 @@ const char *CFI_Parser<A>::parseCIE(A &addressSpace, pint_t cie,...@@ -417,10 +457,10 @@ const char *CFI_Parser<A>::parseCIE(A &addressSpace, pint_t cie,
417457
418/// "run" the DWARF instructions and create the abstract PrologInfo for an FDE458/// "run" the DWARF instructions and create the abstract PrologInfo for an FDE
419template <typename A>459template <typename A>
420bool CFI_Parser<A>::parseFDEInstructions(A &addressSpace,460template <typename R>
421 const FDE_Info &fdeInfo,461bool CFI_Parser<A>::parseFDEInstructions(
422 const CIE_Info &cieInfo, pint_t upToPC,462 A &addressSpace, const FDE_Info &fdeInfo, const CIE_Info &cieInfo,
423 int arch, PrologInfo *results) {463 typename R::link_hardened_reg_arg_t upToPC, int arch, PrologInfo *results) {
424 // Alloca is used for the allocation of the rememberStack entries. It removes464 // Alloca is used for the allocation of the rememberStack entries. It removes
425 // the dependency on new/malloc but the below for loop can not be refactored465 // the dependency on new/malloc but the below for loop can not be refactored
426 // into functions. Entry could be saved during the processing of a CIE and466 // into functions. Entry could be saved during the processing of a CIE and
...@@ -808,12 +848,10 @@ bool CFI_Parser<A>::parseFDEInstructions(A &addressSpace,...@@ -808,12 +848,10 @@ bool CFI_Parser<A>::parseFDEInstructions(A &addressSpace,
808 results->savedRegisters[UNW_AARCH64_RA_SIGN_STATE].value ^ 0x3;848 results->savedRegisters[UNW_AARCH64_RA_SIGN_STATE].value ^ 0x3;
809 results->setRegisterValue(UNW_AARCH64_RA_SIGN_STATE, value,849 results->setRegisterValue(UNW_AARCH64_RA_SIGN_STATE, value,
810 initialState);850 initialState);
811 // When calculating the value of the PC, it is assumed that the CFI851 // When using Feat_PAuthLR, the PC value needs to be captured so that
812 // instruction is placed before the signing instruction, however it is852 // during unwinding, the correct PC value is used for re-authentication.
813 // placed after. Because of this, we need to take into account the CFI853 // It is assumed that the CFI is placed before the signing instruction.
814 // instruction is one instruction call later than expected, and reduce854 results->ptrAuthDiversifier = fdeInfo.pcStart + codeOffset;
815 // the PC value by 4 bytes to compensate.
816 results->ptrAuthDiversifier = fdeInfo.pcStart + codeOffset - 0x4;
817 _LIBUNWIND_TRACE_DWARF(855 _LIBUNWIND_TRACE_DWARF(
818 "DW_CFA_AARCH64_negate_ra_state_with_pc(pc=0x%" PRIx64 ")\n",856 "DW_CFA_AARCH64_negate_ra_state_with_pc(pc=0x%" PRIx64 ")\n",
819 static_cast<uint64_t>(results->ptrAuthDiversifier));857 static_cast<uint64_t>(results->ptrAuthDiversifier));
lib/libunwind/src/EHHeaderParser.hpp+7-4
...@@ -37,8 +37,9 @@ public:...@@ -37,8 +37,9 @@ public:
3737
38 static bool decodeEHHdr(A &addressSpace, pint_t ehHdrStart, pint_t ehHdrEnd,38 static bool decodeEHHdr(A &addressSpace, pint_t ehHdrStart, pint_t ehHdrEnd,
39 EHHeaderInfo &ehHdrInfo);39 EHHeaderInfo &ehHdrInfo);
40 static bool findFDE(A &addressSpace, pint_t pc, pint_t ehHdrStart,40 template <typename R>
41 uint32_t sectionLength,41 static bool findFDE(A &addressSpace, typename R::link_hardened_reg_arg_t pc,
42 pint_t ehHdrStart, uint32_t sectionLength,
42 typename CFI_Parser<A>::FDE_Info *fdeInfo,43 typename CFI_Parser<A>::FDE_Info *fdeInfo,
43 typename CFI_Parser<A>::CIE_Info *cieInfo);44 typename CFI_Parser<A>::CIE_Info *cieInfo);
4445
...@@ -112,8 +113,10 @@ bool EHHeaderParser<A>::decodeTableEntry(...@@ -112,8 +113,10 @@ bool EHHeaderParser<A>::decodeTableEntry(
112}113}
113114
114template <typename A>115template <typename A>
115bool EHHeaderParser<A>::findFDE(A &addressSpace, pint_t pc, pint_t ehHdrStart,116template <typename R>
116 uint32_t sectionLength,117bool EHHeaderParser<A>::findFDE(A &addressSpace,
118 typename R::link_hardened_reg_arg_t pc,
119 pint_t ehHdrStart, uint32_t sectionLength,
117 typename CFI_Parser<A>::FDE_Info *fdeInfo,120 typename CFI_Parser<A>::FDE_Info *fdeInfo,
118 typename CFI_Parser<A>::CIE_Info *cieInfo) {121 typename CFI_Parser<A>::CIE_Info *cieInfo) {
119 pint_t ehHdrEnd = ehHdrStart + sectionLength;122 pint_t ehHdrEnd = ehHdrStart + sectionLength;
lib/libunwind/src/Registers.hpp+226-22
...@@ -17,8 +17,13 @@...@@ -17,8 +17,13 @@
1717
18#include "config.h"18#include "config.h"
19#include "libunwind.h"19#include "libunwind.h"
20#include "libunwind_ext.h"
20#include "shadow_stack_unwind.h"21#include "shadow_stack_unwind.h"
2122
23#if defined(_LIBUNWIND_HAVE_GETAUXVAL) || defined(_LIBUNWIND_HAVE_ELF_AUX_INFO)
24#include <sys/auxv.h>
25#endif
26
22namespace libunwind {27namespace libunwind {
2328
24// For emulating 128-bit registers29// For emulating 128-bit registers
...@@ -60,6 +65,10 @@ public:...@@ -60,6 +65,10 @@ public:
60 Registers_x86();65 Registers_x86();
61 Registers_x86(const void *registers);66 Registers_x86(const void *registers);
6267
68 typedef uint32_t reg_t;
69 typedef uint32_t link_reg_t;
70 typedef const link_reg_t &link_hardened_reg_arg_t;
71
63 bool validRegister(int num) const;72 bool validRegister(int num) const;
64 uint32_t getRegister(int num) const;73 uint32_t getRegister(int num) const;
65 void setRegister(int num, uint32_t value);74 void setRegister(int num, uint32_t value);
...@@ -278,6 +287,10 @@ public:...@@ -278,6 +287,10 @@ public:
278 Registers_x86_64();287 Registers_x86_64();
279 Registers_x86_64(const void *registers);288 Registers_x86_64(const void *registers);
280289
290 typedef uint64_t reg_t;
291 typedef uint64_t link_reg_t;
292 typedef const link_reg_t &link_hardened_reg_arg_t;
293
281 bool validRegister(int num) const;294 bool validRegister(int num) const;
282 uint64_t getRegister(int num) const;295 uint64_t getRegister(int num) const;
283 void setRegister(int num, uint64_t value);296 void setRegister(int num, uint64_t value);
...@@ -597,6 +610,10 @@ public:...@@ -597,6 +610,10 @@ public:
597 Registers_ppc();610 Registers_ppc();
598 Registers_ppc(const void *registers);611 Registers_ppc(const void *registers);
599612
613 typedef uint32_t reg_t;
614 typedef uint32_t link_reg_t;
615 typedef const link_reg_t &link_hardened_reg_arg_t;
616
600 bool validRegister(int num) const;617 bool validRegister(int num) const;
601 uint32_t getRegister(int num) const;618 uint32_t getRegister(int num) const;
602 void setRegister(int num, uint32_t value);619 void setRegister(int num, uint32_t value);
...@@ -1169,6 +1186,10 @@ public:...@@ -1169,6 +1186,10 @@ public:
1169 Registers_ppc64();1186 Registers_ppc64();
1170 Registers_ppc64(const void *registers);1187 Registers_ppc64(const void *registers);
11711188
1189 typedef uint64_t reg_t;
1190 typedef uint64_t link_reg_t;
1191 typedef const link_reg_t &link_hardened_reg_arg_t;
1192
1172 bool validRegister(int num) const;1193 bool validRegister(int num) const;
1173 uint64_t getRegister(int num) const;1194 uint64_t getRegister(int num) const;
1174 void setRegister(int num, uint64_t value);1195 void setRegister(int num, uint64_t value);
...@@ -1814,7 +1835,9 @@ inline const char *Registers_ppc64::getRegisterName(int regNum) {...@@ -1814,7 +1835,9 @@ inline const char *Registers_ppc64::getRegisterName(int regNum) {
1814/// Registers_arm64 holds the register state of a thread in a 64-bit arm1835/// Registers_arm64 holds the register state of a thread in a 64-bit arm
1815/// process.1836/// process.
1816class _LIBUNWIND_HIDDEN Registers_arm64;1837class _LIBUNWIND_HIDDEN Registers_arm64;
1817extern "C" void __libunwind_Registers_arm64_jumpto(Registers_arm64 *);1838extern "C" int64_t __libunwind_Registers_arm64_za_disable();
1839extern "C" void __libunwind_Registers_arm64_jumpto(Registers_arm64 *,
1840 unsigned walkedFrames);
18181841
1819#if defined(_LIBUNWIND_USE_GCS)1842#if defined(_LIBUNWIND_USE_GCS)
1820extern "C" void *__libunwind_shstk_get_jump_target() {1843extern "C" void *__libunwind_shstk_get_jump_target() {
...@@ -1824,8 +1847,21 @@ extern "C" void *__libunwind_shstk_get_jump_target() {...@@ -1824,8 +1847,21 @@ extern "C" void *__libunwind_shstk_get_jump_target() {
18241847
1825class _LIBUNWIND_HIDDEN Registers_arm64 {1848class _LIBUNWIND_HIDDEN Registers_arm64 {
1826public:1849public:
1827 Registers_arm64();1850 Registers_arm64() = default;
1828 Registers_arm64(const void *registers);1851 Registers_arm64(const void *registers);
1852 Registers_arm64(const Registers_arm64 &);
1853 Registers_arm64 &operator=(const Registers_arm64 &);
1854
1855 typedef uint64_t reg_t;
1856 typedef uint64_t __ptrauth_unwind_registers_arm64_link_reg link_reg_t;
1857
1858 // Use `link_hardened_reg_arg_t` to pass values of `link_reg_t` type as
1859 // function arguments. We need to use a const l-value reference to keep
1860 // signature of `__ptrauth`-qualified values of `link_reg_t` type on AArch64
1861 // PAuth-enabled ABI intact. Passing the raw pointer by value would cause
1862 // authentication on the caller side and make the pointer prone to
1863 // substitution if spilled to the stack in the callee.
1864 typedef const link_reg_t &link_hardened_reg_arg_t;
18291865
1830 bool validRegister(int num) const;1866 bool validRegister(int num) const;
1831 uint64_t getRegister(int num) const;1867 uint64_t getRegister(int num) const;
...@@ -1837,7 +1873,14 @@ public:...@@ -1837,7 +1873,14 @@ public:
1837 v128 getVectorRegister(int num) const;1873 v128 getVectorRegister(int num) const;
1838 void setVectorRegister(int num, v128 value);1874 void setVectorRegister(int num, v128 value);
1839 static const char *getRegisterName(int num);1875 static const char *getRegisterName(int num);
1840 void jumpto() { __libunwind_Registers_arm64_jumpto(this); }1876 void jumpto(unsigned walkedFrames = 0) {
1877 zaDisable();
1878 __libunwind_Registers_arm64_jumpto(this, walkedFrames);
1879 }
1880#ifdef _LIBUNWIND_TRACE_RET_INJECT
1881 _LIBUNWIND_TRACE_NO_INLINE
1882 void returnto(unsigned walkedFrames) { jumpto(walkedFrames); }
1883#endif
1841 static constexpr int lastDwarfRegNum() {1884 static constexpr int lastDwarfRegNum() {
1842 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64;1885 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64;
1843 }1886 }
...@@ -1845,27 +1888,104 @@ public:...@@ -1845,27 +1888,104 @@ public:
18451888
1846 uint64_t getSP() const { return _registers.__sp; }1889 uint64_t getSP() const { return _registers.__sp; }
1847 void setSP(uint64_t value) { _registers.__sp = value; }1890 void setSP(uint64_t value) { _registers.__sp = value; }
1848 uint64_t getIP() const { return _registers.__pc; }1891 uint64_t getIP() const {
1849 void setIP(uint64_t value) { _registers.__pc = value; }1892 uint64_t value = _registers.__pc;
1850 uint64_t getFP() const { return _registers.__fp; }1893#if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING)
1851 void setFP(uint64_t value) { _registers.__fp = value; }1894 // Note the value of the PC was signed to its address in the register state
1895 // but everyone else expects it to be sign by the SP, so convert on return.
1896 value = (uint64_t)ptrauth_auth_and_resign((void *)_registers.__pc,
1897 ptrauth_key_return_address,
1898 &_registers.__pc,
1899 ptrauth_key_return_address,
1900 getSP());
1901#endif
1902 return value;
1903 }
1904 void setIP(uint64_t value) {
1905#if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING)
1906 // Note the value which was set should have been signed with the SP.
1907 // We then resign with the slot we are being stored in to so that both SP
1908 // and LR can't be spoofed at the same time.
1909 value = (uint64_t)ptrauth_auth_and_resign((void *)value,
1910 ptrauth_key_return_address,
1911 getSP(),
1912 ptrauth_key_return_address,
1913 &_registers.__pc);
1914#endif
1915 _registers.__pc = value;
1916 }
1917 uint64_t getFP() const { return _registers.__fp; }
1918 void setFP(uint64_t value) { _registers.__fp = value; }
1919
1920#if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING)
1921 void
1922 loadAndAuthenticateLinkRegister(reg_t inplaceAuthedLinkRegister,
1923 link_reg_t *referenceAuthedLinkRegister) {
1924 // If we are in an arm64/arm64e frame, then the PC should have been signed
1925 // with the SP
1926 *referenceAuthedLinkRegister =
1927 (uint64_t)ptrauth_auth_data((void *)inplaceAuthedLinkRegister,
1928 ptrauth_key_return_address,
1929 _registers.__sp);
1930 }
1931#endif
18521932
1853private:1933private:
1934 uint64_t lazyGetVG() const;
1935
1936 void zaDisable() const {
1937 if (!_misc_registers.__has_sme)
1938 return;
1939 if (__libunwind_Registers_arm64_za_disable() != 0)
1940 _LIBUNWIND_ABORT("SME ZA disable failed");
1941 }
1942
1943#if defined(_LIBUNWIND_HAVE_GETAUXVAL)
1944 static bool checkHasSME() {
1945 constexpr int hwcap2_sme = (1 << 23);
1946 unsigned long hwcap2 = getauxval(AT_HWCAP2);
1947 return (hwcap2 & hwcap2_sme) != 0;
1948 }
1949#elif defined(_LIBUNWIND_HAVE_ELF_AUX_INFO)
1950 static bool checkHasSME() {
1951 constexpr int hwcap2_sme = (1 << 23);
1952 unsigned long hwcap2 = 0;
1953 elf_aux_info(AT_HWCAP2, &hwcap2, sizeof(hwcap2));
1954 return (hwcap2 & hwcap2_sme) != 0;
1955 }
1956#else
1957 static bool checkHasSME() {
1958 // TODO: Support other platforms.
1959 return false;
1960 }
1961#endif
1962
1854 struct GPRs {1963 struct GPRs {
1855 uint64_t __x[29]; // x0-x281964 uint64_t __x[29] = {}; // x0-x28
1856 uint64_t __fp; // Frame pointer x291965 uint64_t __fp = 0; // Frame pointer x29
1857 uint64_t __lr; // Link register x301966 uint64_t __lr = 0; // Link register x30
1858 uint64_t __sp; // Stack pointer x311967 uint64_t __sp = 0; // Stack pointer x31
1859 uint64_t __pc; // Program counter1968 uint64_t __pc = 0; // Program counter
1860 uint64_t __ra_sign_state; // RA sign state register1969 uint64_t __ra_sign_state = 0; // RA sign state register
1970 };
1971
1972 struct Misc {
1973 mutable uint32_t __vg = 0; // Vector Granule
1974 bool __has_sme = checkHasSME();
1861 };1975 };
18621976
1863 GPRs _registers;1977 GPRs _registers = {};
1864 double _vectorHalfRegisters[32];
1865 // Currently only the lower double in 128-bit vectore registers1978 // Currently only the lower double in 128-bit vectore registers
1866 // is perserved during unwinding. We could define new register1979 // is perserved during unwinding. We could define new register
1867 // numbers (> 96) which mean whole vector registers, then this1980 // numbers (> 96) which mean whole vector registers, then this
1868 // struct would need to change to contain whole vector registers.1981 // struct would need to change to contain whole vector registers.
1982 double _vectorHalfRegisters[32] = {};
1983
1984 // Miscellaneous/virtual registers. These are stored below the GPRs and FPRs
1985 // as they do not correspond to physical registers, so do not need to be
1986 // saved/restored in UnwindRegistersRestore.S and UnwindRegistersSave.S, and
1987 // we don't want to modify the existing offsets for GPRs and FPRs.
1988 Misc _misc_registers;
1869};1989};
18701990
1871inline Registers_arm64::Registers_arm64(const void *registers) {1991inline Registers_arm64::Registers_arm64(const void *registers) {
...@@ -1877,11 +1997,31 @@ inline Registers_arm64::Registers_arm64(const void *registers) {...@@ -1877,11 +1997,31 @@ inline Registers_arm64::Registers_arm64(const void *registers) {
1877 memcpy(_vectorHalfRegisters,1997 memcpy(_vectorHalfRegisters,
1878 static_cast<const uint8_t *>(registers) + sizeof(GPRs),1998 static_cast<const uint8_t *>(registers) + sizeof(GPRs),
1879 sizeof(_vectorHalfRegisters));1999 sizeof(_vectorHalfRegisters));
2000 _misc_registers.__vg = 0;
2001
2002#if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING)
2003 // We have to do some pointer authentication fixups after this copy,
2004 // and as part of that we need to load the source pc without
2005 // authenticating so that we maintain the signature for the resigning
2006 // performed by setIP.
2007 uint64_t pcRegister = 0;
2008 memmove(&pcRegister, ((uint8_t *)&_registers) + offsetof(GPRs, __pc),
2009 sizeof(pcRegister));
2010 setIP(pcRegister);
2011#endif
1880}2012}
18812013
1882inline Registers_arm64::Registers_arm64() {2014inline Registers_arm64::Registers_arm64(const Registers_arm64 &other) {
1883 memset(&_registers, 0, sizeof(_registers));2015 *this = other;
1884 memset(&_vectorHalfRegisters, 0, sizeof(_vectorHalfRegisters));2016}
2017
2018inline Registers_arm64 &
2019Registers_arm64::operator=(const Registers_arm64 &other) {
2020 memmove(static_cast<void *>(this), &other, sizeof(*this));
2021 // We perform this step to ensure that we correctly authenticate and re-sign
2022 // the pc after the bitwise copy.
2023 setIP(other.getIP());
2024 return *this;
1885}2025}
18862026
1887inline bool Registers_arm64::validRegister(int regNum) const {2027inline bool Registers_arm64::validRegister(int regNum) const {
...@@ -1895,22 +2035,40 @@ inline bool Registers_arm64::validRegister(int regNum) const {...@@ -1895,22 +2035,40 @@ inline bool Registers_arm64::validRegister(int regNum) const {
1895 return false;2035 return false;
1896 if (regNum == UNW_AARCH64_RA_SIGN_STATE)2036 if (regNum == UNW_AARCH64_RA_SIGN_STATE)
1897 return true;2037 return true;
2038 if (regNum == UNW_AARCH64_VG)
2039 return true;
1898 if ((regNum > 32) && (regNum < 64))2040 if ((regNum > 32) && (regNum < 64))
1899 return false;2041 return false;
1900 return true;2042 return true;
1901}2043}
19022044
2045inline uint64_t Registers_arm64::lazyGetVG() const {
2046 if (!_misc_registers.__vg) {
2047#if defined(__aarch64__)
2048 register uint64_t vg asm("x0");
2049 asm(".inst 0x04e0e3e0" // CNTD x0
2050 : "=r"(vg));
2051 _misc_registers.__vg = vg;
2052#else
2053 _LIBUNWIND_ABORT("arm64 VG undefined");
2054#endif
2055 }
2056 return _misc_registers.__vg;
2057}
2058
1903inline uint64_t Registers_arm64::getRegister(int regNum) const {2059inline uint64_t Registers_arm64::getRegister(int regNum) const {
1904 if (regNum == UNW_REG_IP || regNum == UNW_AARCH64_PC)2060 if (regNum == UNW_REG_IP || regNum == UNW_AARCH64_PC)
1905 return _registers.__pc;2061 return getIP();
1906 if (regNum == UNW_REG_SP || regNum == UNW_AARCH64_SP)2062 if (regNum == UNW_REG_SP || regNum == UNW_AARCH64_SP)
1907 return _registers.__sp;2063 return _registers.__sp;
1908 if (regNum == UNW_AARCH64_RA_SIGN_STATE)2064 if (regNum == UNW_AARCH64_RA_SIGN_STATE)
1909 return _registers.__ra_sign_state;2065 return _registers.__ra_sign_state;
1910 if (regNum == UNW_AARCH64_FP)2066 if (regNum == UNW_AARCH64_FP)
1911 return _registers.__fp;2067 return getFP();
1912 if (regNum == UNW_AARCH64_LR)2068 if (regNum == UNW_AARCH64_LR)
1913 return _registers.__lr;2069 return _registers.__lr;
2070 if (regNum == UNW_AARCH64_VG)
2071 return lazyGetVG();
1914 if ((regNum >= 0) && (regNum < 29))2072 if ((regNum >= 0) && (regNum < 29))
1915 return _registers.__x[regNum];2073 return _registers.__x[regNum];
1916 _LIBUNWIND_ABORT("unsupported arm64 register");2074 _LIBUNWIND_ABORT("unsupported arm64 register");
...@@ -1918,15 +2076,17 @@ inline uint64_t Registers_arm64::getRegister(int regNum) const {...@@ -1918,15 +2076,17 @@ inline uint64_t Registers_arm64::getRegister(int regNum) const {
19182076
1919inline void Registers_arm64::setRegister(int regNum, uint64_t value) {2077inline void Registers_arm64::setRegister(int regNum, uint64_t value) {
1920 if (regNum == UNW_REG_IP || regNum == UNW_AARCH64_PC)2078 if (regNum == UNW_REG_IP || regNum == UNW_AARCH64_PC)
1921 _registers.__pc = value;2079 setIP(value);
1922 else if (regNum == UNW_REG_SP || regNum == UNW_AARCH64_SP)2080 else if (regNum == UNW_REG_SP || regNum == UNW_AARCH64_SP)
1923 _registers.__sp = value;2081 _registers.__sp = value;
1924 else if (regNum == UNW_AARCH64_RA_SIGN_STATE)2082 else if (regNum == UNW_AARCH64_RA_SIGN_STATE)
1925 _registers.__ra_sign_state = value;2083 _registers.__ra_sign_state = value;
1926 else if (regNum == UNW_AARCH64_FP)2084 else if (regNum == UNW_AARCH64_FP)
1927 _registers.__fp = value;2085 setFP(value);
1928 else if (regNum == UNW_AARCH64_LR)2086 else if (regNum == UNW_AARCH64_LR)
1929 _registers.__lr = value;2087 _registers.__lr = value;
2088 else if (regNum == UNW_AARCH64_VG)
2089 _misc_registers.__vg = value;
1930 else if ((regNum >= 0) && (regNum < 29))2090 else if ((regNum >= 0) && (regNum < 29))
1931 _registers.__x[regNum] = value;2091 _registers.__x[regNum] = value;
1932 else2092 else
...@@ -2116,6 +2276,10 @@ public:...@@ -2116,6 +2276,10 @@ public:
2116 Registers_arm();2276 Registers_arm();
2117 Registers_arm(const void *registers);2277 Registers_arm(const void *registers);
21182278
2279 typedef uint32_t reg_t;
2280 typedef uint32_t link_reg_t;
2281 typedef const link_reg_t &link_hardened_reg_arg_t;
2282
2119 bool validRegister(int num) const;2283 bool validRegister(int num) const;
2120 uint32_t getRegister(int num) const;2284 uint32_t getRegister(int num) const;
2121 void setRegister(int num, uint32_t value);2285 void setRegister(int num, uint32_t value);
...@@ -2621,6 +2785,10 @@ public:...@@ -2621,6 +2785,10 @@ public:
2621 Registers_or1k();2785 Registers_or1k();
2622 Registers_or1k(const void *registers);2786 Registers_or1k(const void *registers);
26232787
2788 typedef uint32_t reg_t;
2789 typedef uint32_t link_reg_t;
2790 typedef const link_reg_t &link_hardened_reg_arg_t;
2791
2624 bool validRegister(int num) const;2792 bool validRegister(int num) const;
2625 uint32_t getRegister(int num) const;2793 uint32_t getRegister(int num) const;
2626 void setRegister(int num, uint32_t value);2794 void setRegister(int num, uint32_t value);
...@@ -2820,6 +2988,10 @@ public:...@@ -2820,6 +2988,10 @@ public:
2820 Registers_mips_o32();2988 Registers_mips_o32();
2821 Registers_mips_o32(const void *registers);2989 Registers_mips_o32(const void *registers);
28222990
2991 typedef uint32_t reg_t;
2992 typedef uint32_t link_reg_t;
2993 typedef const link_reg_t &link_hardened_reg_arg_t;
2994
2823 bool validRegister(int num) const;2995 bool validRegister(int num) const;
2824 uint32_t getRegister(int num) const;2996 uint32_t getRegister(int num) const;
2825 void setRegister(int num, uint32_t value);2997 void setRegister(int num, uint32_t value);
...@@ -3155,6 +3327,10 @@ public:...@@ -3155,6 +3327,10 @@ public:
3155 Registers_mips_newabi();3327 Registers_mips_newabi();
3156 Registers_mips_newabi(const void *registers);3328 Registers_mips_newabi(const void *registers);
31573329
3330 typedef uint64_t reg_t;
3331 typedef uint64_t link_reg_t;
3332 typedef const link_reg_t &link_hardened_reg_arg_t;
3333
3158 bool validRegister(int num) const;3334 bool validRegister(int num) const;
3159 uint64_t getRegister(int num) const;3335 uint64_t getRegister(int num) const;
3160 void setRegister(int num, uint64_t value);3336 void setRegister(int num, uint64_t value);
...@@ -3458,6 +3634,10 @@ public:...@@ -3458,6 +3634,10 @@ public:
3458 Registers_sparc();3634 Registers_sparc();
3459 Registers_sparc(const void *registers);3635 Registers_sparc(const void *registers);
34603636
3637 typedef uint32_t reg_t;
3638 typedef uint32_t link_reg_t;
3639 typedef const link_reg_t &link_hardened_reg_arg_t;
3640
3461 bool validRegister(int num) const;3641 bool validRegister(int num) const;
3462 uint32_t getRegister(int num) const;3642 uint32_t getRegister(int num) const;
3463 void setRegister(int num, uint32_t value);3643 void setRegister(int num, uint32_t value);
...@@ -3644,6 +3824,10 @@ public:...@@ -3644,6 +3824,10 @@ public:
3644 Registers_sparc64() = default;3824 Registers_sparc64() = default;
3645 Registers_sparc64(const void *registers);3825 Registers_sparc64(const void *registers);
36463826
3827 typedef uint64_t reg_t;
3828 typedef uint64_t link_reg_t;
3829 typedef const link_reg_t &link_hardened_reg_arg_t;
3830
3647 bool validRegister(int num) const;3831 bool validRegister(int num) const;
3648 uint64_t getRegister(int num) const;3832 uint64_t getRegister(int num) const;
3649 void setRegister(int num, uint64_t value);3833 void setRegister(int num, uint64_t value);
...@@ -3829,6 +4013,10 @@ public:...@@ -3829,6 +4013,10 @@ public:
3829 Registers_hexagon();4013 Registers_hexagon();
3830 Registers_hexagon(const void *registers);4014 Registers_hexagon(const void *registers);
38314015
4016 typedef uint32_t reg_t;
4017 typedef uint32_t link_reg_t;
4018 typedef const link_reg_t &link_hardened_reg_arg_t;
4019
3832 bool validRegister(int num) const;4020 bool validRegister(int num) const;
3833 uint32_t getRegister(int num) const;4021 uint32_t getRegister(int num) const;
3834 void setRegister(int num, uint32_t value);4022 void setRegister(int num, uint32_t value);
...@@ -4044,6 +4232,10 @@ public:...@@ -4044,6 +4232,10 @@ public:
4044 Registers_riscv();4232 Registers_riscv();
4045 Registers_riscv(const void *registers);4233 Registers_riscv(const void *registers);
40464234
4235 typedef ::libunwind::reg_t reg_t;
4236 typedef ::libunwind::reg_t link_reg_t;
4237 typedef const link_reg_t &link_hardened_reg_arg_t;
4238
4047 bool validRegister(int num) const;4239 bool validRegister(int num) const;
4048 reg_t getRegister(int num) const;4240 reg_t getRegister(int num) const;
4049 void setRegister(int num, reg_t value);4241 void setRegister(int num, reg_t value);
...@@ -4341,6 +4533,10 @@ public:...@@ -4341,6 +4533,10 @@ public:
4341 Registers_ve();4533 Registers_ve();
4342 Registers_ve(const void *registers);4534 Registers_ve(const void *registers);
43434535
4536 typedef uint64_t reg_t;
4537 typedef uint64_t link_reg_t;
4538 typedef const link_reg_t &link_hardened_reg_arg_t;
4539
4344 bool validRegister(int num) const;4540 bool validRegister(int num) const;
4345 uint64_t getRegister(int num) const;4541 uint64_t getRegister(int num) const;
4346 void setRegister(int num, uint64_t value);4542 void setRegister(int num, uint64_t value);
...@@ -4784,6 +4980,10 @@ public:...@@ -4784,6 +4980,10 @@ public:
4784 Registers_s390x();4980 Registers_s390x();
4785 Registers_s390x(const void *registers);4981 Registers_s390x(const void *registers);
47864982
4983 typedef uint64_t reg_t;
4984 typedef uint64_t link_reg_t;
4985 typedef const link_reg_t &link_hardened_reg_arg_t;
4986
4787 bool validRegister(int num) const;4987 bool validRegister(int num) const;
4788 uint64_t getRegister(int num) const;4988 uint64_t getRegister(int num) const;
4789 void setRegister(int num, uint64_t value);4989 void setRegister(int num, uint64_t value);
...@@ -5072,6 +5272,10 @@ public:...@@ -5072,6 +5272,10 @@ public:
5072 Registers_loongarch();5272 Registers_loongarch();
5073 Registers_loongarch(const void *registers);5273 Registers_loongarch(const void *registers);
50745274
5275 typedef uint64_t reg_t;
5276 typedef uint64_t link_reg_t;
5277 typedef const link_reg_t &link_hardened_reg_arg_t;
5278
5075 bool validRegister(int num) const;5279 bool validRegister(int num) const;
5076 uint64_t getRegister(int num) const;5280 uint64_t getRegister(int num) const;
5077 void setRegister(int num, uint64_t value);5281 void setRegister(int num, uint64_t value);
lib/libunwind/src/Unwind-seh.cpp+6-7
...@@ -163,7 +163,7 @@ _GCC_specific_handler(PEXCEPTION_RECORD ms_exc, PVOID frame, PCONTEXT ms_ctx,...@@ -163,7 +163,7 @@ _GCC_specific_handler(PEXCEPTION_RECORD ms_exc, PVOID frame, PCONTEXT ms_ctx,
163 // If we were called by __libunwind_seh_personality(), indicate that163 // If we were called by __libunwind_seh_personality(), indicate that
164 // a handler was found; otherwise, initiate phase 2 by unwinding.164 // a handler was found; otherwise, initiate phase 2 by unwinding.
165 if (ours && ms_exc->NumberParameters > 1)165 if (ours && ms_exc->NumberParameters > 1)
166 return 4 /* ExceptionExecuteHandler in mingw */;166 return static_cast<EXCEPTION_DISPOSITION>(4);
167 // This should never happen in phase 2.167 // This should never happen in phase 2.
168 if (IS_UNWINDING(ms_exc->ExceptionFlags))168 if (IS_UNWINDING(ms_exc->ExceptionFlags))
169 _LIBUNWIND_ABORT("Personality indicated exception handler in phase 2!");169 _LIBUNWIND_ABORT("Personality indicated exception handler in phase 2!");
...@@ -182,7 +182,7 @@ _GCC_specific_handler(PEXCEPTION_RECORD ms_exc, PVOID frame, PCONTEXT ms_ctx,...@@ -182,7 +182,7 @@ _GCC_specific_handler(PEXCEPTION_RECORD ms_exc, PVOID frame, PCONTEXT ms_ctx,
182 // a handler was found; otherwise, it's time to initiate a collided182 // a handler was found; otherwise, it's time to initiate a collided
183 // unwind to the target.183 // unwind to the target.
184 if (ours && !IS_UNWINDING(ms_exc->ExceptionFlags) && ms_exc->NumberParameters > 1)184 if (ours && !IS_UNWINDING(ms_exc->ExceptionFlags) && ms_exc->NumberParameters > 1)
185 return 4 /* ExceptionExecuteHandler in mingw */;185 return static_cast<EXCEPTION_DISPOSITION>(4);
186 // This should never happen in phase 1.186 // This should never happen in phase 1.
187 if (!IS_UNWINDING(ms_exc->ExceptionFlags))187 if (!IS_UNWINDING(ms_exc->ExceptionFlags))
188 _LIBUNWIND_ABORT("Personality installed context during phase 1!");188 _LIBUNWIND_ABORT("Personality installed context during phase 1!");
...@@ -259,13 +259,12 @@ __libunwind_seh_personality(int version, _Unwind_Action state,...@@ -259,13 +259,12 @@ __libunwind_seh_personality(int version, _Unwind_Action state,
259 (void *)disp_ctx->LanguageHandler, (void *)&ms_exc,259 (void *)disp_ctx->LanguageHandler, (void *)&ms_exc,
260 (void *)disp_ctx->EstablisherFrame,260 (void *)disp_ctx->EstablisherFrame,
261 (void *)disp_ctx->ContextRecord, (void *)disp_ctx);261 (void *)disp_ctx->ContextRecord, (void *)disp_ctx);
262 EXCEPTION_DISPOSITION ms_act = disp_ctx->LanguageHandler(&ms_exc,262 int ms_act = static_cast<int>(
263 (PVOID)disp_ctx->EstablisherFrame,263 disp_ctx->LanguageHandler(&ms_exc, (PVOID)disp_ctx->EstablisherFrame,
264 disp_ctx->ContextRecord,264 disp_ctx->ContextRecord, disp_ctx));
265 disp_ctx);
266 _LIBUNWIND_TRACE_UNWINDING("__libunwind_seh_personality() LanguageHandler "265 _LIBUNWIND_TRACE_UNWINDING("__libunwind_seh_personality() LanguageHandler "
267 "returned %d",266 "returned %d",
268 (int)ms_act);267 ms_act);
269 switch (ms_act) {268 switch (ms_act) {
270 case ExceptionContinueExecution: return _URC_END_OF_STACK;269 case ExceptionContinueExecution: return _URC_END_OF_STACK;
271 case ExceptionContinueSearch: return _URC_CONTINUE_UNWIND;270 case ExceptionContinueSearch: return _URC_CONTINUE_UNWIND;
lib/libunwind/src/Unwind-wasm.c+7-7
...@@ -37,13 +37,13 @@ struct _Unwind_LandingPadContext {...@@ -37,13 +37,13 @@ struct _Unwind_LandingPadContext {
37// function37// function
38thread_local struct _Unwind_LandingPadContext __wasm_lpad_context;38thread_local struct _Unwind_LandingPadContext __wasm_lpad_context;
3939
40/// Calls to this function is in landing pads in compiler-generated user code.40/// Calls to this function are in landing pads in compiler-generated user code.
41/// In other EH schemes, stack unwinding is done by libunwind library, which41/// In other EH schemes, stack unwinding is done by libunwind library, which
42/// calls the personality function for each each frame it lands. On the other42/// calls the personality function for each frame it lands. On the other hand,
43/// hand, WebAssembly stack unwinding process is performed by a VM, and the43/// WebAssembly stack unwinding process is performed by a VM, and the
44/// personality function cannot be called from there. So the compiler inserts44/// personality function cannot be called from there. So the compiler inserts a
45/// a call to this function in landing pads in the user code, which in turn45/// call to this function in landing pads in the user code, which in turn calls
46/// calls the personality function.46/// the personality function.
47_Unwind_Reason_Code _Unwind_CallPersonality(void *exception_ptr) {47_Unwind_Reason_Code _Unwind_CallPersonality(void *exception_ptr) {
48 struct _Unwind_Exception *exception_object =48 struct _Unwind_Exception *exception_object =
49 (struct _Unwind_Exception *)exception_ptr;49 (struct _Unwind_Exception *)exception_ptr;
...@@ -92,7 +92,7 @@ _LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index,...@@ -92,7 +92,7 @@ _LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index,
9292
93/// Called by personality handler to get instruction pointer.93/// Called by personality handler to get instruction pointer.
94_LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) {94_LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) {
95 // The result will be used as an 1-based index after decrementing 1, so we95 // The result will be used as a 1-based index after decrementing 1, so we
96 // increment 2 here96 // increment 2 here
97 uintptr_t result =97 uintptr_t result =
98 ((struct _Unwind_LandingPadContext *)context)->lpad_index + 2;98 ((struct _Unwind_LandingPadContext *)context)->lpad_index + 2;
lib/libunwind/src/UnwindCursor.hpp+167-49
...@@ -41,7 +41,8 @@...@@ -41,7 +41,8 @@
41#define _LIBUNWIND_CHECK_LINUX_SIGRETURN 141#define _LIBUNWIND_CHECK_LINUX_SIGRETURN 1
42#endif42#endif
4343
44#if defined(_LIBUNWIND_TARGET_HAIKU) && defined(_LIBUNWIND_TARGET_X86_64)44#if defined(_LIBUNWIND_TARGET_HAIKU) && \
45 (defined(_LIBUNWIND_TARGET_I386) || defined(_LIBUNWIND_TARGET_X86_64))
45#include <OS.h>46#include <OS.h>
46#include <signal.h>47#include <signal.h>
47#define _LIBUNWIND_CHECK_HAIKU_SIGRETURN 148#define _LIBUNWIND_CHECK_HAIKU_SIGRETURN 1
...@@ -120,7 +121,9 @@ class _LIBUNWIND_HIDDEN DwarfFDECache {...@@ -120,7 +121,9 @@ class _LIBUNWIND_HIDDEN DwarfFDECache {
120 typedef typename A::pint_t pint_t;121 typedef typename A::pint_t pint_t;
121public:122public:
122 static constexpr pint_t kSearchAll = static_cast<pint_t>(-1);123 static constexpr pint_t kSearchAll = static_cast<pint_t>(-1);
123 static pint_t findFDE(pint_t mh, pint_t pc);124 template <typename R>
125 static pint_t findFDE(pint_t mh, typename R::link_hardened_reg_arg_t pc);
126
124 static void add(pint_t mh, pint_t ip_start, pint_t ip_end, pint_t fde);127 static void add(pint_t mh, pint_t ip_start, pint_t ip_end, pint_t fde);
125 static void removeAllIn(pint_t mh);128 static void removeAllIn(pint_t mh);
126 static void iterateCacheEntries(void (*func)(unw_word_t ip_start,129 static void iterateCacheEntries(void (*func)(unw_word_t ip_start,
...@@ -173,7 +176,9 @@ bool DwarfFDECache<A>::_registeredForDyldUnloads = false;...@@ -173,7 +176,9 @@ bool DwarfFDECache<A>::_registeredForDyldUnloads = false;
173#endif176#endif
174177
175template <typename A>178template <typename A>
176typename A::pint_t DwarfFDECache<A>::findFDE(pint_t mh, pint_t pc) {179template <typename R>
180typename DwarfFDECache<A>::pint_t
181DwarfFDECache<A>::findFDE(pint_t mh, typename R::link_hardened_reg_arg_t pc) {
177 pint_t result = 0;182 pint_t result = 0;
178 _LIBUNWIND_LOG_IF_FALSE(_lock.lock_shared());183 _LIBUNWIND_LOG_IF_FALSE(_lock.lock_shared());
179 for (entry *p = _buffer; p < _bufferUsed; ++p) {184 for (entry *p = _buffer; p < _bufferUsed; ++p) {
...@@ -471,7 +476,9 @@ public:...@@ -471,7 +476,9 @@ public:
471 virtual void getInfo(unw_proc_info_t *) {476 virtual void getInfo(unw_proc_info_t *) {
472 _LIBUNWIND_ABORT("getInfo not implemented");477 _LIBUNWIND_ABORT("getInfo not implemented");
473 }478 }
474 virtual void jumpto() { _LIBUNWIND_ABORT("jumpto not implemented"); }479 _LIBUNWIND_TRACE_NO_INLINE virtual void jumpto() {
480 _LIBUNWIND_ABORT("jumpto not implemented");
481 }
475 virtual bool isSignalFrame() {482 virtual bool isSignalFrame() {
476 _LIBUNWIND_ABORT("isSignalFrame not implemented");483 _LIBUNWIND_ABORT("isSignalFrame not implemented");
477 }484 }
...@@ -488,6 +495,12 @@ public:...@@ -488,6 +495,12 @@ public:
488 virtual void saveVFPAsX() { _LIBUNWIND_ABORT("saveVFPAsX not implemented"); }495 virtual void saveVFPAsX() { _LIBUNWIND_ABORT("saveVFPAsX not implemented"); }
489#endif496#endif
490497
498#ifdef _LIBUNWIND_TRACE_RET_INJECT
499 virtual void setWalkedFrames(unsigned) {
500 _LIBUNWIND_ABORT("setWalkedFrames not implemented");
501 }
502#endif
503
491#ifdef _AIX504#ifdef _AIX
492 virtual uintptr_t getDataRelBase() {505 virtual uintptr_t getDataRelBase() {
493 _LIBUNWIND_ABORT("getDataRelBase not implemented");506 _LIBUNWIND_ABORT("getDataRelBase not implemented");
...@@ -964,7 +977,8 @@ public:...@@ -964,7 +977,8 @@ public:
964 virtual void setFloatReg(int, unw_fpreg_t);977 virtual void setFloatReg(int, unw_fpreg_t);
965 virtual int step(bool stage2 = false);978 virtual int step(bool stage2 = false);
966 virtual void getInfo(unw_proc_info_t *);979 virtual void getInfo(unw_proc_info_t *);
967 virtual void jumpto();980 _LIBUNWIND_TRACE_NO_INLINE
981 virtual void jumpto();
968 virtual bool isSignalFrame();982 virtual bool isSignalFrame();
969 virtual bool getFunctionName(char *buf, size_t len, unw_word_t *off);983 virtual bool getFunctionName(char *buf, size_t len, unw_word_t *off);
970 virtual void setInfoBasedOnIPRegister(bool isReturnAddress = false);984 virtual void setInfoBasedOnIPRegister(bool isReturnAddress = false);
...@@ -973,6 +987,10 @@ public:...@@ -973,6 +987,10 @@ public:
973 virtual void saveVFPAsX();987 virtual void saveVFPAsX();
974#endif988#endif
975989
990#ifdef _LIBUNWIND_TRACE_RET_INJECT
991 virtual void setWalkedFrames(unsigned);
992#endif
993
976#ifdef _AIX994#ifdef _AIX
977 virtual uintptr_t getDataRelBase();995 virtual uintptr_t getDataRelBase();
978#endif996#endif
...@@ -1045,19 +1063,28 @@ private:...@@ -1045,19 +1063,28 @@ private:
1045#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)1063#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1046 bool getInfoFromFdeCie(const typename CFI_Parser<A>::FDE_Info &fdeInfo,1064 bool getInfoFromFdeCie(const typename CFI_Parser<A>::FDE_Info &fdeInfo,
1047 const typename CFI_Parser<A>::CIE_Info &cieInfo,1065 const typename CFI_Parser<A>::CIE_Info &cieInfo,
1048 pint_t pc, uintptr_t dso_base);1066 typename R::link_hardened_reg_arg_t pc,
1049 bool getInfoFromDwarfSection(pint_t pc, const UnwindInfoSections &sects,1067 uintptr_t dso_base);
1050 uint32_t fdeSectionOffsetHint=0);1068 bool getInfoFromDwarfSection(typename R::link_hardened_reg_arg_t pc,
1069 const UnwindInfoSections &sects,
1070 uint32_t fdeSectionOffsetHint = 0);
1051 int stepWithDwarfFDE(bool stage2) {1071 int stepWithDwarfFDE(bool stage2) {
1072#if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING)
1073 typename R::reg_t rawPC = this->getReg(UNW_REG_IP);
1074 typename R::link_reg_t pc;
1075 _registers.loadAndAuthenticateLinkRegister(rawPC, &pc);
1076#else
1077 typename R::link_reg_t pc = this->getReg(UNW_REG_IP);
1078#endif
1052 return DwarfInstructions<A, R>::stepWithDwarf(1079 return DwarfInstructions<A, R>::stepWithDwarf(
1053 _addressSpace, (pint_t)this->getReg(UNW_REG_IP),1080 _addressSpace, pc, (pint_t)_info.unwind_info, _registers,
1054 (pint_t)_info.unwind_info, _registers, _isSignalFrame, stage2);1081 _isSignalFrame, stage2);
1055 }1082 }
1056#endif1083#endif
10571084
1058#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)1085#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
1059 bool getInfoFromCompactEncodingSection(pint_t pc,1086 bool getInfoFromCompactEncodingSection(typename R::link_hardened_reg_arg_t pc,
1060 const UnwindInfoSections &sects);1087 const UnwindInfoSections &sects);
1061 int stepWithCompactEncoding(bool stage2 = false) {1088 int stepWithCompactEncoding(bool stage2 = false) {
1062#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)1089#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1063 if ( compactSaysUseDwarf() )1090 if ( compactSaysUseDwarf() )
...@@ -1344,9 +1371,12 @@ private:...@@ -1344,9 +1371,12 @@ private:
1344 bool _unwindInfoMissing;1371 bool _unwindInfoMissing;
1345 bool _isSignalFrame;1372 bool _isSignalFrame;
1346#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) || \1373#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) || \
1347 defined(_LIBUNWIND_TARGET_HAIKU)1374 defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN)
1348 bool _isSigReturn = false;1375 bool _isSigReturn = false;
1349#endif1376#endif
1377#ifdef _LIBUNWIND_TRACE_RET_INJECT
1378 uint32_t _walkedFrames;
1379#endif
1350};1380};
13511381
13521382
...@@ -1358,13 +1388,13 @@ UnwindCursor<A, R>::UnwindCursor(unw_context_t *context, A &as)...@@ -1358,13 +1388,13 @@ UnwindCursor<A, R>::UnwindCursor(unw_context_t *context, A &as)
1358 "UnwindCursor<> does not fit in unw_cursor_t");1388 "UnwindCursor<> does not fit in unw_cursor_t");
1359 static_assert((alignof(UnwindCursor<A, R>) <= alignof(unw_cursor_t)),1389 static_assert((alignof(UnwindCursor<A, R>) <= alignof(unw_cursor_t)),
1360 "UnwindCursor<> requires more alignment than unw_cursor_t");1390 "UnwindCursor<> requires more alignment than unw_cursor_t");
1361 memset(&_info, 0, sizeof(_info));1391 memset(static_cast<void *>(&_info), 0, sizeof(_info));
1362}1392}
13631393
1364template <typename A, typename R>1394template <typename A, typename R>
1365UnwindCursor<A, R>::UnwindCursor(A &as, void *)1395UnwindCursor<A, R>::UnwindCursor(A &as, void *)
1366 : _addressSpace(as), _unwindInfoMissing(false), _isSignalFrame(false) {1396 : _addressSpace(as), _unwindInfoMissing(false), _isSignalFrame(false) {
1367 memset(&_info, 0, sizeof(_info));1397 memset(static_cast<void *>(&_info), 0, sizeof(_info));
1368 // FIXME1398 // FIXME
1369 // fill in _registers from thread arg1399 // fill in _registers from thread arg
1370}1400}
...@@ -1401,7 +1431,46 @@ void UnwindCursor<A, R>::setFloatReg(int regNum, unw_fpreg_t value) {...@@ -1401,7 +1431,46 @@ void UnwindCursor<A, R>::setFloatReg(int regNum, unw_fpreg_t value) {
1401}1431}
14021432
1403template <typename A, typename R> void UnwindCursor<A, R>::jumpto() {1433template <typename A, typename R> void UnwindCursor<A, R>::jumpto() {
1434#ifdef _LIBUNWIND_TRACE_RET_INJECT
1435 /*
1436
1437 The value of `_walkedFrames` is computed in `unwind_phase2` and represents the
1438 number of frames walked starting `unwind_phase2` to get to the landing pad.
1439
1440 ```
1441 // uc is initialized by __unw_getcontext in the parent frame.
1442 // The first stack frame walked is unwind_phase2.
1443 unsigned framesWalked = 1;
1444 ```
1445
1446 To that, we need to add the number of function calls in libunwind between
1447 `unwind_phase2` & `__libunwind_Registers_arm64_jumpto` which performs the long
1448 jump, to rebalance the execution flow.
1449
1450 ```
1451 frame #0: libunwind.1.dylib`__libunwind_Registers_arm64_jumpto at UnwindRegistersRestore.S:646
1452 frame #1: libunwind.1.dylib`libunwind::Registers_arm64::returnto at Registers.hpp:2291:3
1453 frame #2: libunwind.1.dylib`libunwind::UnwindCursor<libunwind::LocalAddressSpace, libunwind::Registers_arm64>::jumpto at UnwindCursor.hpp:1474:14
1454 frame #3: libunwind.1.dylib`__unw_resume at libunwind.cpp:375:7
1455 frame #4: libunwind.1.dylib`__unw_resume_with_frames_walked at libunwind.cpp:363:10
1456 frame #5: libunwind.1.dylib`unwind_phase2 at UnwindLevel1.c:328:9
1457 frame #6: libunwind.1.dylib`_Unwind_RaiseException at UnwindLevel1.c:480:10
1458 frame #7: libc++abi.dylib`__cxa_throw at cxa_exception.cpp:295:5
1459 ...
1460 ```
1461
1462 If we look at the backtrace from `__libunwind_Registers_arm64_jumpto`, we see
1463 there are 5 frames on the stack to reach `unwind_phase2`. However, only 4 of
1464 them will never return, since `__libunwind_Registers_arm64_jumpto` returns
1465 back to the landing pad, so we need to subtract 1 to the number of
1466 `_EXTRA_LIBUNWIND_FRAMES_WALKED`.
1467 */
1468
1469 static constexpr size_t _EXTRA_LIBUNWIND_FRAMES_WALKED = 5 - 1;
1470 _registers.returnto(_walkedFrames + _EXTRA_LIBUNWIND_FRAMES_WALKED);
1471#else
1404 _registers.jumpto();1472 _registers.jumpto();
1473#endif
1405}1474}
14061475
1407#ifdef __arm__1476#ifdef __arm__
...@@ -1410,6 +1479,13 @@ template <typename A, typename R> void UnwindCursor<A, R>::saveVFPAsX() {...@@ -1410,6 +1479,13 @@ template <typename A, typename R> void UnwindCursor<A, R>::saveVFPAsX() {
1410}1479}
1411#endif1480#endif
14121481
1482#ifdef _LIBUNWIND_TRACE_RET_INJECT
1483template <typename A, typename R>
1484void UnwindCursor<A, R>::setWalkedFrames(unsigned walkedFrames) {
1485 _walkedFrames = walkedFrames;
1486}
1487#endif
1488
1413#ifdef _AIX1489#ifdef _AIX
1414template <typename A, typename R>1490template <typename A, typename R>
1415uintptr_t UnwindCursor<A, R>::getDataRelBase() {1491uintptr_t UnwindCursor<A, R>::getDataRelBase() {
...@@ -1658,11 +1734,11 @@ bool UnwindCursor<A, R>::getInfoFromEHABISection(...@@ -1658,11 +1734,11 @@ bool UnwindCursor<A, R>::getInfoFromEHABISection(
1658template <typename A, typename R>1734template <typename A, typename R>
1659bool UnwindCursor<A, R>::getInfoFromFdeCie(1735bool UnwindCursor<A, R>::getInfoFromFdeCie(
1660 const typename CFI_Parser<A>::FDE_Info &fdeInfo,1736 const typename CFI_Parser<A>::FDE_Info &fdeInfo,
1661 const typename CFI_Parser<A>::CIE_Info &cieInfo, pint_t pc,1737 const typename CFI_Parser<A>::CIE_Info &cieInfo,
1662 uintptr_t dso_base) {1738 typename R::link_hardened_reg_arg_t pc, uintptr_t dso_base) {
1663 typename CFI_Parser<A>::PrologInfo prolog;1739 typename CFI_Parser<A>::PrologInfo prolog;
1664 if (CFI_Parser<A>::parseFDEInstructions(_addressSpace, fdeInfo, cieInfo, pc,1740 if (CFI_Parser<A>::template parseFDEInstructions<R>(
1665 R::getArch(), &prolog)) {1741 _addressSpace, fdeInfo, cieInfo, pc, R::getArch(), &prolog)) {
1666 // Save off parsed FDE info1742 // Save off parsed FDE info
1667 _info.start_ip = fdeInfo.pcStart;1743 _info.start_ip = fdeInfo.pcStart;
1668 _info.end_ip = fdeInfo.pcEnd;1744 _info.end_ip = fdeInfo.pcEnd;
...@@ -1682,43 +1758,42 @@ bool UnwindCursor<A, R>::getInfoFromFdeCie(...@@ -1682,43 +1758,42 @@ bool UnwindCursor<A, R>::getInfoFromFdeCie(
1682}1758}
16831759
1684template <typename A, typename R>1760template <typename A, typename R>
1685bool UnwindCursor<A, R>::getInfoFromDwarfSection(pint_t pc,1761bool UnwindCursor<A, R>::getInfoFromDwarfSection(
1686 const UnwindInfoSections &sects,1762 typename R::link_hardened_reg_arg_t pc, const UnwindInfoSections &sects,
1687 uint32_t fdeSectionOffsetHint) {1763 uint32_t fdeSectionOffsetHint) {
1688 typename CFI_Parser<A>::FDE_Info fdeInfo;1764 typename CFI_Parser<A>::FDE_Info fdeInfo;
1689 typename CFI_Parser<A>::CIE_Info cieInfo;1765 typename CFI_Parser<A>::CIE_Info cieInfo;
1690 bool foundFDE = false;1766 bool foundFDE = false;
1691 bool foundInCache = false;1767 bool foundInCache = false;
1692 // If compact encoding table gave offset into dwarf section, go directly there1768 // If compact encoding table gave offset into dwarf section, go directly there
1693 if (fdeSectionOffsetHint != 0) {1769 if (fdeSectionOffsetHint != 0) {
1694 foundFDE = CFI_Parser<A>::findFDE(_addressSpace, pc, sects.dwarf_section,1770 foundFDE = CFI_Parser<A>::template findFDE<R>(
1695 sects.dwarf_section_length,1771 _addressSpace, pc, sects.dwarf_section, sects.dwarf_section_length,
1696 sects.dwarf_section + fdeSectionOffsetHint,1772 sects.dwarf_section + fdeSectionOffsetHint, &fdeInfo, &cieInfo);
1697 &fdeInfo, &cieInfo);
1698 }1773 }
1699#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)1774#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
1700 if (!foundFDE && (sects.dwarf_index_section != 0)) {1775 if (!foundFDE && (sects.dwarf_index_section != 0)) {
1701 foundFDE = EHHeaderParser<A>::findFDE(1776 foundFDE = EHHeaderParser<A>::template findFDE<R>(
1702 _addressSpace, pc, sects.dwarf_index_section,1777 _addressSpace, pc, sects.dwarf_index_section,
1703 (uint32_t)sects.dwarf_index_section_length, &fdeInfo, &cieInfo);1778 (uint32_t)sects.dwarf_index_section_length, &fdeInfo, &cieInfo);
1704 }1779 }
1705#endif1780#endif
1706 if (!foundFDE) {1781 if (!foundFDE) {
1707 // otherwise, search cache of previously found FDEs.1782 // otherwise, search cache of previously found FDEs.
1708 pint_t cachedFDE = DwarfFDECache<A>::findFDE(sects.dso_base, pc);1783 pint_t cachedFDE =
1784 DwarfFDECache<A>::template findFDE<R>(sects.dso_base, pc);
1709 if (cachedFDE != 0) {1785 if (cachedFDE != 0) {
1710 foundFDE =1786 foundFDE = CFI_Parser<A>::template findFDE<R>(
1711 CFI_Parser<A>::findFDE(_addressSpace, pc, sects.dwarf_section,1787 _addressSpace, pc, sects.dwarf_section, sects.dwarf_section_length,
1712 sects.dwarf_section_length,1788 cachedFDE, &fdeInfo, &cieInfo);
1713 cachedFDE, &fdeInfo, &cieInfo);
1714 foundInCache = foundFDE;1789 foundInCache = foundFDE;
1715 }1790 }
1716 }1791 }
1717 if (!foundFDE) {1792 if (!foundFDE) {
1718 // Still not found, do full scan of __eh_frame section.1793 // Still not found, do full scan of __eh_frame section.
1719 foundFDE = CFI_Parser<A>::findFDE(_addressSpace, pc, sects.dwarf_section,1794 foundFDE = CFI_Parser<A>::template findFDE<R>(
1720 sects.dwarf_section_length, 0,1795 _addressSpace, pc, sects.dwarf_section, sects.dwarf_section_length, 0,
1721 &fdeInfo, &cieInfo);1796 &fdeInfo, &cieInfo);
1722 }1797 }
1723 if (foundFDE) {1798 if (foundFDE) {
1724 if (getInfoFromFdeCie(fdeInfo, cieInfo, pc, sects.dso_base)) {1799 if (getInfoFromFdeCie(fdeInfo, cieInfo, pc, sects.dso_base)) {
...@@ -1742,8 +1817,8 @@ bool UnwindCursor<A, R>::getInfoFromDwarfSection(pint_t pc,...@@ -1742,8 +1817,8 @@ bool UnwindCursor<A, R>::getInfoFromDwarfSection(pint_t pc,
17421817
1743#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)1818#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
1744template <typename A, typename R>1819template <typename A, typename R>
1745bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection(pint_t pc,1820bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection(
1746 const UnwindInfoSections &sects) {1821 typename R::link_hardened_reg_arg_t pc, const UnwindInfoSections &sects) {
1747 const bool log = false;1822 const bool log = false;
1748 if (log)1823 if (log)
1749 fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX, mh=0x%llX)\n",1824 fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX, mh=0x%llX)\n",
...@@ -1974,6 +2049,16 @@ bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection(pint_t pc,...@@ -1974,6 +2049,16 @@ bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection(pint_t pc,
1974 personalityIndex * sizeof(uint32_t));2049 personalityIndex * sizeof(uint32_t));
1975 pint_t personalityPointer = sects.dso_base + (pint_t)personalityDelta;2050 pint_t personalityPointer = sects.dso_base + (pint_t)personalityDelta;
1976 personality = _addressSpace.getP(personalityPointer);2051 personality = _addressSpace.getP(personalityPointer);
2052#if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING)
2053 // The GOT for the personality function was signed address authenticated.
2054 // Resign it as a regular function pointer.
2055 const auto discriminator = ptrauth_blend_discriminator(
2056 &_info.handler, __ptrauth_unwind_upi_handler_disc);
2057 void *signedPtr = ptrauth_auth_and_resign(
2058 (void *)personality, ptrauth_key_function_pointer, personalityPointer,
2059 ptrauth_key_function_pointer, discriminator);
2060 personality = (__typeof(personality))signedPtr;
2061#endif
1977 if (log)2062 if (log)
1978 fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX), "2063 fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX), "
1979 "personalityDelta=0x%08X, personality=0x%08llX\n",2064 "personalityDelta=0x%08X, personality=0x%08llX\n",
...@@ -1987,7 +2072,11 @@ bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection(pint_t pc,...@@ -1987,7 +2072,11 @@ bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection(pint_t pc,
1987 _info.start_ip = funcStart;2072 _info.start_ip = funcStart;
1988 _info.end_ip = funcEnd;2073 _info.end_ip = funcEnd;
1989 _info.lsda = lsda;2074 _info.lsda = lsda;
1990 _info.handler = personality;2075 // We use memmove to copy the personality function as we have already manually
2076 // re-signed the pointer, and assigning directly will attempt to incorrectly
2077 // sign the already signed value.
2078 memmove(reinterpret_cast<void *>(&_info.handler),
2079 reinterpret_cast<void *>(&personality), sizeof(personality));
1991 _info.gp = 0;2080 _info.gp = 0;
1992 _info.flags = 0;2081 _info.flags = 0;
1993 _info.format = encoding;2082 _info.format = encoding;
...@@ -2640,11 +2729,19 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {...@@ -2640,11 +2729,19 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
2640 _isSigReturn = false;2729 _isSigReturn = false;
2641#endif2730#endif
26422731
2643 pint_t pc = static_cast<pint_t>(this->getReg(UNW_REG_IP));2732 typename R::reg_t rawPC = this->getReg(UNW_REG_IP);
2733
2644#if defined(_LIBUNWIND_ARM_EHABI)2734#if defined(_LIBUNWIND_ARM_EHABI)
2645 // Remove the thumb bit so the IP represents the actual instruction address.2735 // Remove the thumb bit so the IP represents the actual instruction address.
2646 // This matches the behaviour of _Unwind_GetIP on arm.2736 // This matches the behaviour of _Unwind_GetIP on arm.
2647 pc &= (pint_t)~0x1;2737 rawPC &= (pint_t)~0x1;
2738#endif
2739
2740 typename R::link_reg_t pc;
2741#if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING)
2742 _registers.loadAndAuthenticateLinkRegister(rawPC, &pc);
2743#else
2744 pc = rawPC;
2648#endif2745#endif
26492746
2650 // Exit early if at the top of the stack.2747 // Exit early if at the top of the stack.
...@@ -2679,7 +2776,7 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {...@@ -2679,7 +2776,7 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
26792776
2680 // Ask address space object to find unwind sections for this pc.2777 // Ask address space object to find unwind sections for this pc.
2681 UnwindInfoSections sects;2778 UnwindInfoSections sects;
2682 if (_addressSpace.findUnwindSections(pc, sects)) {2779 if (_addressSpace.template findUnwindSections<R>(pc, sects)) {
2683#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)2780#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
2684 // If there is a compact unwind encoding table, look there first.2781 // If there is a compact unwind encoding table, look there first.
2685 if (sects.compact_unwind_section != 0) {2782 if (sects.compact_unwind_section != 0) {
...@@ -2735,8 +2832,8 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {...@@ -2735,8 +2832,8 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
2735#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)2832#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
2736 // There is no static unwind info for this pc. Look to see if an FDE was2833 // There is no static unwind info for this pc. Look to see if an FDE was
2737 // dynamically registered for it.2834 // dynamically registered for it.
2738 pint_t cachedFDE = DwarfFDECache<A>::findFDE(DwarfFDECache<A>::kSearchAll,2835 pint_t cachedFDE =
2739 pc);2836 DwarfFDECache<A>::template findFDE<R>(DwarfFDECache<A>::kSearchAll, pc);
2740 if (cachedFDE != 0) {2837 if (cachedFDE != 0) {
2741 typename CFI_Parser<A>::FDE_Info fdeInfo;2838 typename CFI_Parser<A>::FDE_Info fdeInfo;
2742 typename CFI_Parser<A>::CIE_Info cieInfo;2839 typename CFI_Parser<A>::CIE_Info cieInfo;
...@@ -2748,7 +2845,7 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {...@@ -2748,7 +2845,7 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
2748 // Lastly, ask AddressSpace object about platform specific ways to locate2845 // Lastly, ask AddressSpace object about platform specific ways to locate
2749 // other FDEs.2846 // other FDEs.
2750 pint_t fde;2847 pint_t fde;
2751 if (_addressSpace.findOtherFDE(pc, fde)) {2848 if (_addressSpace.template findOtherFDE<R>(pc, fde)) {
2752 typename CFI_Parser<A>::FDE_Info fdeInfo;2849 typename CFI_Parser<A>::FDE_Info fdeInfo;
2753 typename CFI_Parser<A>::CIE_Info cieInfo;2850 typename CFI_Parser<A>::CIE_Info cieInfo;
2754 if (!CFI_Parser<A>::decodeFDE(_addressSpace, fde, &fdeInfo, &cieInfo)) {2851 if (!CFI_Parser<A>::decodeFDE(_addressSpace, fde, &fdeInfo, &cieInfo)) {
...@@ -2772,6 +2869,21 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {...@@ -2772,6 +2869,21 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
27722869
2773#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && \2870#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && \
2774 defined(_LIBUNWIND_TARGET_AARCH64)2871 defined(_LIBUNWIND_TARGET_AARCH64)
2872
2873/*
2874 * The linux sigreturn restorer stub will always have the form:
2875 *
2876 * d2801168 movz x8, #0x8b
2877 * d4000001 svc #0x0
2878 */
2879#if defined(__AARCH64EB__)
2880#define MOVZ_X8_8B 0x681180d2
2881#define SVC_0 0x010000d4
2882#else
2883#define MOVZ_X8_8B 0xd2801168
2884#define SVC_0 0xd4000001
2885#endif
2886
2775template <typename A, typename R>2887template <typename A, typename R>
2776bool UnwindCursor<A, R>::setInfoForSigReturn(Registers_arm64 &) {2888bool UnwindCursor<A, R>::setInfoForSigReturn(Registers_arm64 &) {
2777 // Look for the sigreturn trampoline. The trampoline's body is two2889 // Look for the sigreturn trampoline. The trampoline's body is two
...@@ -2796,7 +2908,7 @@ bool UnwindCursor<A, R>::setInfoForSigReturn(Registers_arm64 &) {...@@ -2796,7 +2908,7 @@ bool UnwindCursor<A, R>::setInfoForSigReturn(Registers_arm64 &) {
2796 return false;2908 return false;
2797 auto *instructions = reinterpret_cast<const uint32_t *>(pc);2909 auto *instructions = reinterpret_cast<const uint32_t *>(pc);
2798 // Look for instructions: mov x8, #0x8b; svc #0x02910 // Look for instructions: mov x8, #0x8b; svc #0x0
2799 if (instructions[0] != 0xd2801168 || instructions[1] != 0xd4000001)2911 if (instructions[0] != MOVZ_X8_8B || instructions[1] != SVC_0)
2800 return false;2912 return false;
28012913
2802 _info = {};2914 _info = {};
...@@ -3188,16 +3300,22 @@ template <typename A, typename R> int UnwindCursor<A, R>::step(bool stage2) {...@@ -3188,16 +3300,22 @@ template <typename A, typename R> int UnwindCursor<A, R>::step(bool stage2) {
3188template <typename A, typename R>3300template <typename A, typename R>
3189void UnwindCursor<A, R>::getInfo(unw_proc_info_t *info) {3301void UnwindCursor<A, R>::getInfo(unw_proc_info_t *info) {
3190 if (_unwindInfoMissing)3302 if (_unwindInfoMissing)
3191 memset(info, 0, sizeof(*info));3303 memset(static_cast<void *>(info), 0, sizeof(*info));
3192 else3304 else
3193 *info = _info;3305 *info = _info;
3194}3306}
31953307
3196template <typename A, typename R>3308template <typename A, typename R>
3197bool UnwindCursor<A, R>::getFunctionName(char *buf, size_t bufLen,3309bool UnwindCursor<A, R>::getFunctionName(char *buf, size_t bufLen,
3198 unw_word_t *offset) {3310 unw_word_t *offset) {
3199 return _addressSpace.findFunctionName((pint_t)this->getReg(UNW_REG_IP),3311#if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING)
3200 buf, bufLen, offset);3312 typename R::reg_t rawPC = this->getReg(UNW_REG_IP);
3313 typename R::link_reg_t pc;
3314 _registers.loadAndAuthenticateLinkRegister(rawPC, &pc);
3315#else
3316 typename R::link_reg_t pc = this->getReg(UNW_REG_IP);
3317#endif
3318 return _addressSpace.template findFunctionName<R>(pc, buf, bufLen, offset);
3201}3319}
32023320
3203#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN)3321#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN)
lib/libunwind/src/UnwindLevel1.c+46-17
...@@ -48,16 +48,15 @@...@@ -48,16 +48,15 @@
48// avoided when invoking the `jumpto()` function. To do this, we use inline48// avoided when invoking the `jumpto()` function. To do this, we use inline
49// assemblies to "goto" the `jumpto()` for these architectures.49// assemblies to "goto" the `jumpto()` for these architectures.
50#if !defined(_LIBUNWIND_USE_CET) && !defined(_LIBUNWIND_USE_GCS)50#if !defined(_LIBUNWIND_USE_CET) && !defined(_LIBUNWIND_USE_GCS)
51#define __unw_phase2_resume(cursor, fn) \51#define __unw_phase2_resume(cursor, payload) \
52 do { \52 do { \
53 (void)fn; \53 __unw_resume_with_frames_walked((cursor), (payload)); \
54 __unw_resume((cursor)); \
55 } while (0)54 } while (0)
56#elif defined(_LIBUNWIND_TARGET_I386)55#elif defined(_LIBUNWIND_TARGET_I386)
57#define __shstk_step_size (4)56#define __shstk_step_size (4)
58#define __unw_phase2_resume(cursor, fn) \57#define __unw_phase2_resume(cursor, payload) \
59 do { \58 do { \
60 _LIBUNWIND_POP_SHSTK_SSP((fn)); \59 _LIBUNWIND_POP_SHSTK_SSP((payload)); \
61 void *shstkRegContext = __libunwind_shstk_get_registers((cursor)); \60 void *shstkRegContext = __libunwind_shstk_get_registers((cursor)); \
62 void *shstkJumpAddress = __libunwind_shstk_get_jump_target(); \61 void *shstkJumpAddress = __libunwind_shstk_get_jump_target(); \
63 __asm__ volatile("push %%edi\n\t" \62 __asm__ volatile("push %%edi\n\t" \
...@@ -67,9 +66,9 @@...@@ -67,9 +66,9 @@
67 } while (0)66 } while (0)
68#elif defined(_LIBUNWIND_TARGET_X86_64)67#elif defined(_LIBUNWIND_TARGET_X86_64)
69#define __shstk_step_size (8)68#define __shstk_step_size (8)
70#define __unw_phase2_resume(cursor, fn) \69#define __unw_phase2_resume(cursor, payload) \
71 do { \70 do { \
72 _LIBUNWIND_POP_SHSTK_SSP((fn)); \71 _LIBUNWIND_POP_SHSTK_SSP((payload)); \
73 void *shstkRegContext = __libunwind_shstk_get_registers((cursor)); \72 void *shstkRegContext = __libunwind_shstk_get_registers((cursor)); \
74 void *shstkJumpAddress = __libunwind_shstk_get_jump_target(); \73 void *shstkJumpAddress = __libunwind_shstk_get_jump_target(); \
75 __asm__ volatile("jmpq *%%rdx\n\t" ::"D"(shstkRegContext), \74 __asm__ volatile("jmpq *%%rdx\n\t" ::"D"(shstkRegContext), \
...@@ -77,19 +76,37 @@...@@ -77,19 +76,37 @@
77 } while (0)76 } while (0)
78#elif defined(_LIBUNWIND_TARGET_AARCH64)77#elif defined(_LIBUNWIND_TARGET_AARCH64)
79#define __shstk_step_size (8)78#define __shstk_step_size (8)
80#define __unw_phase2_resume(cursor, fn) \79#define __unw_phase2_resume(cursor, payload) \
81 do { \80 do { \
82 _LIBUNWIND_POP_SHSTK_SSP((fn)); \81 _LIBUNWIND_POP_SHSTK_SSP((payload)); \
83 void *shstkRegContext = __libunwind_shstk_get_registers((cursor)); \82 void *shstkRegContext = __libunwind_shstk_get_registers((cursor)); \
84 void *shstkJumpAddress = __libunwind_shstk_get_jump_target(); \83 void *shstkJumpAddress = __libunwind_shstk_get_jump_target(); \
85 __asm__ volatile("mov x0, %0\n\t" \84 __asm__ volatile("mov x0, %0\n\t" \
85 "mov x1, #0\n\t" \
86 "br %1\n\t" \86 "br %1\n\t" \
87 : \87 : \
88 : "r"(shstkRegContext), "r"(shstkJumpAddress) \88 : "r"(shstkRegContext), "r"(shstkJumpAddress) \
89 : "x0"); \89 : "x0", "x1"); \
90 } while (0)90 } while (0)
91#endif91#endif
9292
93// We need this helper function as the semantics of casting between integers and
94// function pointers mean that we end up with a function pointer without the
95// correct signature. Instead we assign to an integer with a matching schema,
96// and then memmove the result into a variable of the correct type. This memmove
97// is possible as `_Unwind_Personality_Fn` is a standard function pointer, and
98// as such is not address diversified.
99static _Unwind_Personality_Fn get_handler_function(unw_proc_info_t *frameInfo) {
100 uintptr_t __unwind_ptrauth_restricted_intptr(ptrauth_key_function_pointer,
101 0,
102 ptrauth_function_pointer_type_discriminator(_Unwind_Personality_Fn))
103 reauthenticatedIntegerHandler = frameInfo->handler;
104 _Unwind_Personality_Fn handler;
105 memmove(&handler, (void *)&reauthenticatedIntegerHandler,
106 sizeof(_Unwind_Personality_Fn));
107 return handler;
108}
109
93static _Unwind_Reason_Code110static _Unwind_Reason_Code
94unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) {111unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) {
95 __unw_init_local(cursor, uc);112 __unw_init_local(cursor, uc);
...@@ -147,8 +164,7 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except...@@ -147,8 +164,7 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except
147 // If there is a personality routine, ask it if it will want to stop at164 // If there is a personality routine, ask it if it will want to stop at
148 // this frame.165 // this frame.
149 if (frameInfo.handler != 0) {166 if (frameInfo.handler != 0) {
150 _Unwind_Personality_Fn p =167 _Unwind_Personality_Fn p = get_handler_function(&frameInfo);
151 (_Unwind_Personality_Fn)(uintptr_t)(frameInfo.handler);
152 _LIBUNWIND_TRACE_UNWINDING(168 _LIBUNWIND_TRACE_UNWINDING(
153 "unwind_phase1(ex_obj=%p): calling personality function %p",169 "unwind_phase1(ex_obj=%p): calling personality function %p",
154 (void *)exception_object, (void *)(uintptr_t)p);170 (void *)exception_object, (void *)(uintptr_t)p);
...@@ -184,11 +200,12 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except...@@ -184,11 +200,12 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except
184 }200 }
185 return _URC_NO_REASON;201 return _URC_NO_REASON;
186}202}
187extern int __unw_step_stage2(unw_cursor_t *);
188203
189#if defined(_LIBUNWIND_USE_GCS)204#if defined(_LIBUNWIND_USE_GCS)
190// Enable the GCS target feature to permit gcspop instructions to be used.205// Enable the GCS target feature to permit gcspop instructions to be used.
191__attribute__((target("+gcs")))206__attribute__((target("+gcs")))
207#else
208_LIBUNWIND_TRACE_NO_INLINE
192#endif209#endif
193static _Unwind_Reason_Code210static _Unwind_Reason_Code
194unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor,211unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor,
...@@ -276,8 +293,7 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor,...@@ -276,8 +293,7 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor,
276 ++framesWalked;293 ++framesWalked;
277 // If there is a personality routine, tell it we are unwinding.294 // If there is a personality routine, tell it we are unwinding.
278 if (frameInfo.handler != 0) {295 if (frameInfo.handler != 0) {
279 _Unwind_Personality_Fn p =296 _Unwind_Personality_Fn p = get_handler_function(&frameInfo);
280 (_Unwind_Personality_Fn)(uintptr_t)(frameInfo.handler);
281 _Unwind_Action action = _UA_CLEANUP_PHASE;297 _Unwind_Action action = _UA_CLEANUP_PHASE;
282 if (sp == exception_object->private_2) {298 if (sp == exception_object->private_2) {
283 // Tell personality this was the frame it marked in phase 1.299 // Tell personality this was the frame it marked in phase 1.
...@@ -334,6 +350,8 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor,...@@ -334,6 +350,8 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor,
334#if defined(_LIBUNWIND_USE_GCS)350#if defined(_LIBUNWIND_USE_GCS)
335// Enable the GCS target feature to permit gcspop instructions to be used.351// Enable the GCS target feature to permit gcspop instructions to be used.
336__attribute__((target("+gcs")))352__attribute__((target("+gcs")))
353#else
354_LIBUNWIND_TRACE_NO_INLINE
337#endif355#endif
338static _Unwind_Reason_Code356static _Unwind_Reason_Code
339unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor,357unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor,
...@@ -394,8 +412,7 @@ unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor,...@@ -394,8 +412,7 @@ unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor,
394 ++framesWalked;412 ++framesWalked;
395 // If there is a personality routine, tell it we are unwinding.413 // If there is a personality routine, tell it we are unwinding.
396 if (frameInfo.handler != 0) {414 if (frameInfo.handler != 0) {
397 _Unwind_Personality_Fn p =415 _Unwind_Personality_Fn p = get_handler_function(&frameInfo);
398 (_Unwind_Personality_Fn)(intptr_t)(frameInfo.handler);
399 _LIBUNWIND_TRACE_UNWINDING(416 _LIBUNWIND_TRACE_UNWINDING(
400 "unwind_phase2_forced(ex_obj=%p): calling personality function %p",417 "unwind_phase2_forced(ex_obj=%p): calling personality function %p",
401 (void *)exception_object, (void *)(uintptr_t)p);418 (void *)exception_object, (void *)(uintptr_t)p);
...@@ -597,6 +614,18 @@ _LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) {...@@ -597,6 +614,18 @@ _LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) {
597 unw_cursor_t *cursor = (unw_cursor_t *)context;614 unw_cursor_t *cursor = (unw_cursor_t *)context;
598 unw_word_t result;615 unw_word_t result;
599 __unw_get_reg(cursor, UNW_REG_IP, &result);616 __unw_get_reg(cursor, UNW_REG_IP, &result);
617
618#if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING)
619 // If we are in an arm64e frame, then the PC should have been signed with the
620 // sp
621 {
622 unw_word_t sp;
623 __unw_get_reg(cursor, UNW_REG_SP, &sp);
624 result = (unw_word_t)ptrauth_auth_data((void *)result,
625 ptrauth_key_return_address, sp);
626 }
627#endif
628
600 _LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => 0x%" PRIxPTR,629 _LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => 0x%" PRIxPTR,
601 (void *)context, result);630 (void *)context, result);
602 return (uintptr_t)result;631 return (uintptr_t)result;
lib/libunwind/src/UnwindRegistersRestore.S+46-5
...@@ -6,6 +6,8 @@...@@ -6,6 +6,8 @@
6//6//
7//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
88
9#if !defined(__wasm__)
10
9#include "assembly.h"11#include "assembly.h"
1012
11#define FROM_0_TO_15 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,1513#define FROM_0_TO_15 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
...@@ -16,13 +18,17 @@...@@ -16,13 +18,17 @@
1618
17#if defined(_AIX)19#if defined(_AIX)
18 .toc20 .toc
21#elif defined(__aarch64__) && defined(__ELF__) && defined(_LIBUNWIND_EXECUTE_ONLY_CODE)
22 .section .text,"axy",@progbits,unique,0
19#else23#else
20 .text24 .text
21#endif25#endif
2226
23#if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__wasm__)27#if !defined(__USING_SJLJ_EXCEPTIONS__)
2428
25#if defined(__i386__)29#if defined(__i386__)
30.att_syntax
31
26DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_x86_jumpto)32DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_x86_jumpto)
27#33#
28# extern "C" void __libunwind_Registers_x86_jumpto(Registers_x86 *);34# extern "C" void __libunwind_Registers_x86_jumpto(Registers_x86 *);
...@@ -67,6 +73,7 @@ DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_x86_jumpto)...@@ -67,6 +73,7 @@ DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_x86_jumpto)
67 # skip gs73 # skip gs
6874
69#elif defined(__x86_64__) && !defined(__arm64ec__)75#elif defined(__x86_64__) && !defined(__arm64ec__)
76.att_syntax
7077
71DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_x86_64_jumpto)78DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_x86_64_jumpto)
72#79#
...@@ -629,18 +636,35 @@ Lnovec:...@@ -629,18 +636,35 @@ Lnovec:
629636
630#elif defined(__aarch64__)637#elif defined(__aarch64__)
631638
639#ifndef __has_feature
640#define __has_feature(__feature) 0
641#endif
642
632#if defined(__ARM_FEATURE_GCS_DEFAULT)643#if defined(__ARM_FEATURE_GCS_DEFAULT)
633.arch_extension gcs644.arch_extension gcs
634#endif645#endif
635646
636//647//
637// extern "C" void __libunwind_Registers_arm64_jumpto(Registers_arm64 *);648// extern "C" void __libunwind_Registers_arm64_jumpto(Registers_arm64 *, unsigned);
638//649//
639// On entry:650// On entry:
640// thread_state pointer is in x0651// thread_state pointer is in x0
652// walked_frames counter is in x1
641//653//
642 .p2align 2654 .p2align 2
643DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_arm64_jumpto)655DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_arm64_jumpto)
656
657 #if defined(_LIBUNWIND_TRACE_RET_INJECT)
658 cbz w1, 1f
659 0:
660 subs w1, w1, #1
661 adr x16, #8
662 ret x16
663
664 b.ne 0b
665 1:
666 #endif
667
644 // skip restore of x0,x1 for now668 // skip restore of x0,x1 for now
645 ldp x2, x3, [x0, #0x010]669 ldp x2, x3, [x0, #0x010]
646 ldp x4, x5, [x0, #0x020]670 ldp x4, x5, [x0, #0x020]
...@@ -657,7 +681,7 @@ DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_arm64_jumpto)...@@ -657,7 +681,7 @@ DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_arm64_jumpto)
657 ldp x24,x25, [x0, #0x0C0]681 ldp x24,x25, [x0, #0x0C0]
658 ldp x26,x27, [x0, #0x0D0]682 ldp x26,x27, [x0, #0x0D0]
659 ldp x28,x29, [x0, #0x0E0]683 ldp x28,x29, [x0, #0x0E0]
660 ldr x30, [x0, #0x100] // restore pc into lr684
661#if defined(__ARM_FP) && __ARM_FP != 0685#if defined(__ARM_FP) && __ARM_FP != 0
662 ldp d0, d1, [x0, #0x110]686 ldp d0, d1, [x0, #0x110]
663 ldp d2, d3, [x0, #0x120]687 ldp d2, d3, [x0, #0x120]
...@@ -681,7 +705,18 @@ DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_arm64_jumpto)...@@ -681,7 +705,18 @@ DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_arm64_jumpto)
681 // context struct, because it is allocated on the stack, and an exception705 // context struct, because it is allocated on the stack, and an exception
682 // could clobber the de-allocated portion of the stack after sp has been706 // could clobber the de-allocated portion of the stack after sp has been
683 // restored.707 // restored.
684 ldr x16, [x0, #0x0F8]708
709 ldr x16, [x0, #0x0F8] // load sp into scratch
710 ldr lr, [x0, #0x100] // restore pc into lr
711
712#if __has_feature(ptrauth_calls)
713 // The LR is signed with its address inside the register state. Time
714 // to resign to be a regular ROP protected signed pointer
715 add x1, x0, #0x100
716 autib lr, x1
717 pacib lr, x16 // signed the scratch register for sp
718#endif
719
685 ldp x0, x1, [x0, #0x000] // restore x0,x1720 ldp x0, x1, [x0, #0x000] // restore x0,x1
686 mov sp,x16 // restore sp721 mov sp,x16 // restore sp
687#if defined(__ARM_FEATURE_GCS_DEFAULT)722#if defined(__ARM_FEATURE_GCS_DEFAULT)
...@@ -694,7 +729,12 @@ DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_arm64_jumpto)...@@ -694,7 +729,12 @@ DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_arm64_jumpto)
694 gcspushm x30729 gcspushm x30
695Lnogcs:730Lnogcs:
696#endif731#endif
732
733#if __has_feature(ptrauth_calls)
734 retab
735#else
697 ret x30 // jump to pc736 ret x30 // jump to pc
737#endif
698738
699#elif defined(__arm__) && !defined(__APPLE__)739#elif defined(__arm__) && !defined(__APPLE__)
700740
...@@ -1253,7 +1293,8 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind19Registers_loongarch6jumptoEv)...@@ -1253,7 +1293,8 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind19Registers_loongarch6jumptoEv)
12531293
1254#endif1294#endif
12551295
1256#endif /* !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__wasm__) */1296#endif /* !defined(__USING_SJLJ_EXCEPTIONS__) */
12571297
1258NO_EXEC_STACK_DIRECTIVE1298NO_EXEC_STACK_DIRECTIVE
12591299
1300#endif /* !defined(__wasm__) */
lib/libunwind/src/UnwindRegistersSave.S+86-2
...@@ -6,6 +6,8 @@...@@ -6,6 +6,8 @@
6//6//
7//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
88
9#if !defined(__wasm__)
10
9#include "assembly.h"11#include "assembly.h"
1012
11#define FROM_0_TO_15 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,1513#define FROM_0_TO_15 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
...@@ -16,13 +18,16 @@...@@ -16,13 +18,16 @@
1618
17#if defined(_AIX)19#if defined(_AIX)
18 .toc20 .toc
21#elif defined(__aarch64__) && defined(__ELF__) && defined(_LIBUNWIND_EXECUTE_ONLY_CODE)
22 .section .text,"axy",@progbits,unique,0
19#else23#else
20 .text24 .text
21#endif25#endif
2226
23#if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__wasm__)27#if !defined(__USING_SJLJ_EXCEPTIONS__)
2428
25#if defined(__i386__)29#if defined(__i386__)
30.att_syntax
2631
27#32#
28# extern int __unw_getcontext(unw_context_t* thread_state)33# extern int __unw_getcontext(unw_context_t* thread_state)
...@@ -107,6 +112,7 @@ DEFINE_LIBUNWIND_FUNCTION("#__unw_getcontext")...@@ -107,6 +112,7 @@ DEFINE_LIBUNWIND_FUNCTION("#__unw_getcontext")
107 .text112 .text
108113
109#elif defined(__x86_64__)114#elif defined(__x86_64__)
115.att_syntax
110116
111#117#
112# extern int __unw_getcontext(unw_context_t* thread_state)118# extern int __unw_getcontext(unw_context_t* thread_state)
...@@ -759,6 +765,10 @@ LnoR2Fix:...@@ -759,6 +765,10 @@ LnoR2Fix:
759765
760#elif defined(__aarch64__)766#elif defined(__aarch64__)
761767
768#ifndef __has_feature
769#define __has_feature(__feature) 0
770#endif
771
762//772//
763// extern int __unw_getcontext(unw_context_t* thread_state)773// extern int __unw_getcontext(unw_context_t* thread_state)
764//774//
...@@ -767,6 +777,11 @@ LnoR2Fix:...@@ -767,6 +777,11 @@ LnoR2Fix:
767//777//
768 .p2align 2778 .p2align 2
769DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)779DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
780
781#if __has_feature(ptrauth_calls)
782 pacibsp
783#endif
784
770 stp x0, x1, [x0, #0x000]785 stp x0, x1, [x0, #0x000]
771 stp x2, x3, [x0, #0x010]786 stp x2, x3, [x0, #0x010]
772 stp x4, x5, [x0, #0x020]787 stp x4, x5, [x0, #0x020]
...@@ -807,7 +822,74 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)...@@ -807,7 +822,74 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
807 str d31, [x0, #0x208]822 str d31, [x0, #0x208]
808#endif823#endif
809 mov x0, #0 // return UNW_ESUCCESS824 mov x0, #0 // return UNW_ESUCCESS
825
826#if __has_feature(ptrauth_calls)
827 retab
828#else
829 ret
830#endif
831
832//
833// extern "C" int64_t __libunwind_Registers_arm64_za_disable()
834//
835// This function implements the requirements of the __arm_za_disable ABI
836// routine, except that it will not abort; it will return a non-zero value
837// to signify the routine failed.
838//
839// Note: This function uses SME instructions. It must only be called if SME
840// has been confirmed to be available.
841//
842// On return:
843//
844// A status is placed in x0. A zero value indicates success; any non-zero
845// value indicates failure.
846//
847 .p2align 2
848DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_arm64_za_disable)
849 .variant_pcs __libunwind_Registers_arm64_za_disable
850#if __has_feature(ptrauth_calls)
851 pacibsp
852#endif
853 // If TPIDR2_EL0 is null, the subroutine just disables ZA.
854 .inst 0xd53bd0b0 // mrs x16, TPIDR2_EL0
855 cbz x16, 1f
856
857 // If any of the reserved bytes in the first 16 bytes of the TPIDR2 block are
858 // nonzero, return a non-zero value (libunwind will then abort).
859 ldrh w0, [x16, #10]
860 cbnz w0, 2f
861 ldr w0, [x16, #12]
862 cbnz w0, 2f
863
864 // If num_za_save_slices is zero, the subroutine just disables ZA.
865 ldrh w0, [x16, #8]
866 cbz x0, 1f
867
868 // If za_save_buffer is NULL, the subroutine just disables ZA.
869 ldr x16, [x16]
870 cbz x16, 1f
871
872 // Store ZA to za_save_buffer.
873 mov x15, xzr
8740:
875 .inst 0xe1206200 // str za[w15,0], [x16]
876 .inst 0x04305830 // addsvl x16, x16, #1
877 add x15, x15, #1
878 cmp x0, x15
879 b.ne 0b
8801:
881 // * Set TPIDR2_EL0 to null.
882 .inst 0xd51bd0bf // msr TPIDR2_EL0, xzr
883 // * Set PSTATE.ZA to 0.
884 .inst 0xd503447f // smstop za
885 // * Return zero (success)
886 mov x0, xzr
8872:
888#if __has_feature(ptrauth_calls)
889 retab
890#else
810 ret891 ret
892#endif
811893
812#elif defined(__arm__) && !defined(__APPLE__)894#elif defined(__arm__) && !defined(__APPLE__)
813895
...@@ -1232,6 +1314,8 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)...@@ -1232,6 +1314,8 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
1232 WEAK_ALIAS(__unw_getcontext, unw_getcontext)1314 WEAK_ALIAS(__unw_getcontext, unw_getcontext)
1233#endif1315#endif
12341316
1235#endif /* !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__wasm__) */1317#endif /* !defined(__USING_SJLJ_EXCEPTIONS__) */
12361318
1237NO_EXEC_STACK_DIRECTIVE1319NO_EXEC_STACK_DIRECTIVE
1320
1321#endif /* !defined(__wasm__) */
lib/libunwind/src/assembly.h+5-1
...@@ -15,7 +15,7 @@...@@ -15,7 +15,7 @@
15#ifndef UNWIND_ASSEMBLY_H15#ifndef UNWIND_ASSEMBLY_H
16#define UNWIND_ASSEMBLY_H16#define UNWIND_ASSEMBLY_H
1717
18#if defined(__linux__) && defined(__CET__)18#if defined(__CET__)
19#include <cet.h>19#include <cet.h>
20#define _LIBUNWIND_CET_ENDBR _CET_ENDBR20#define _LIBUNWIND_CET_ENDBR _CET_ENDBR
21#else21#else
...@@ -132,6 +132,10 @@...@@ -132,6 +132,10 @@
132132
133#if defined(__APPLE__)133#if defined(__APPLE__)
134134
135#if defined(__aarch64__) || defined(__arm64__) || defined(__arm64e__)
136#define _LIBUNWIND_TRACE_RET_INJECT 1
137#endif
138
135#define SYMBOL_IS_FUNC(name)139#define SYMBOL_IS_FUNC(name)
136#define HIDDEN_SYMBOL(name) .private_extern name140#define HIDDEN_SYMBOL(name) .private_extern name
137#if defined(_LIBUNWIND_HIDE_SYMBOLS)141#if defined(_LIBUNWIND_HIDE_SYMBOLS)
lib/libunwind/src/config.h+9
...@@ -28,6 +28,9 @@...@@ -28,6 +28,9 @@
28 #define _LIBUNWIND_SUPPORT_COMPACT_UNWIND 128 #define _LIBUNWIND_SUPPORT_COMPACT_UNWIND 1
29 #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 129 #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1
30 #endif30 #endif
31 #if defined(__aarch64__) || defined(__arm64__) || defined(__arm64e__)
32 #define _LIBUNWIND_TRACE_RET_INJECT 1
33 #endif
31#elif defined(_WIN32)34#elif defined(_WIN32)
32 #ifdef __SEH__35 #ifdef __SEH__
33 #define _LIBUNWIND_SUPPORT_SEH_UNWIND 136 #define _LIBUNWIND_SUPPORT_SEH_UNWIND 1
...@@ -61,6 +64,12 @@...@@ -61,6 +64,12 @@
61 #endif64 #endif
62#endif65#endif
6366
67#ifdef _LIBUNWIND_TRACE_RET_INJECT
68#define _LIBUNWIND_TRACE_NO_INLINE __attribute__((noinline, disable_tail_calls))
69#else
70#define _LIBUNWIND_TRACE_NO_INLINE
71#endif
72
64#if defined(_LIBUNWIND_HIDE_SYMBOLS)73#if defined(_LIBUNWIND_HIDE_SYMBOLS)
65 // The CMake file passes -fvisibility=hidden to control ELF/Mach-O visibility.74 // The CMake file passes -fvisibility=hidden to control ELF/Mach-O visibility.
66 #define _LIBUNWIND_EXPORT75 #define _LIBUNWIND_EXPORT
lib/libunwind/src/gcc_personality_v0.c+79-6
...@@ -31,6 +31,58 @@ EXCEPTION_DISPOSITION _GCC_specific_handler(PEXCEPTION_RECORD, void *, PCONTEXT,...@@ -31,6 +31,58 @@ EXCEPTION_DISPOSITION _GCC_specific_handler(PEXCEPTION_RECORD, void *, PCONTEXT,
31 _Unwind_Personality_Fn);31 _Unwind_Personality_Fn);
32#endif32#endif
3333
34#ifndef __has_feature
35#define __has_feature(__feature) 0
36#endif
37
38#if __has_feature(ptrauth_calls)
39#include <ptrauth.h>
40
41// `__ptrauth_restricted_intptr` is a feature of apple clang that predates
42// support for direct application of `__ptrauth` to integer types. This
43// guard is necessary to support compilation with those compiler.
44#if __has_feature(ptrauth_restricted_intptr_qualifier)
45#define __ptrauth_gcc_personality_intptr(key, addressDiscriminated, \
46 discriminator) \
47 __ptrauth_restricted_intptr(key, addressDiscriminated, discriminator)
48#else
49#define __ptrauth_gcc_personality_intptr(key, addressDiscriminated, \
50 discriminator) \
51 __ptrauth(key, addressDiscriminated, discriminator)
52#endif
53#else
54#define __ptrauth_gcc_personality_intptr(...)
55#endif
56
57#define __ptrauth_gcc_personality_func_key ptrauth_key_function_pointer
58
59// ptrauth_string_discriminator("__gcc_personality_v0'funcStart") == 0xDFEB
60#define __ptrauth_gcc_personality_func_start \
61 __ptrauth_gcc_personality_intptr(__ptrauth_gcc_personality_func_key, 1, \
62 0xDFEB)
63
64// ptrauth_string_discriminator("__gcc_personality_v0'start") == 0x52DC
65#define __ptrauth_gcc_personality_start \
66 __ptrauth_gcc_personality_intptr(__ptrauth_gcc_personality_func_key, 1, \
67 0x52DC)
68
69// ptrauth_string_discriminator("__gcc_personality_v0'length") == 0xFFF7
70#define __ptrauth_gcc_personality_length \
71 __ptrauth_gcc_personality_intptr(__ptrauth_gcc_personality_func_key, 1, \
72 0xFFF7)
73
74// ptrauth_string_discriminator("__gcc_personality_v0'landingPadOffset") ==
75// 0x6498
76#define __ptrauth_gcc_personality_lpoffset \
77 __ptrauth_gcc_personality_intptr(__ptrauth_gcc_personality_func_key, 1, \
78 0x6498)
79
80// ptrauth_string_discriminator("__gcc_personality_v0'landingPad") == 0xA134
81#define __ptrauth_gcc_personality_lpad_disc 0xA134
82#define __ptrauth_gcc_personality_lpad \
83 __ptrauth_gcc_personality_intptr(__ptrauth_gcc_personality_func_key, 1, \
84 __ptrauth_gcc_personality_lpad_disc)
85
34// Pointer encodings documented at:86// Pointer encodings documented at:
35// http://refspecs.freestandards.org/LSB_1.3.0/gLSB/gLSB/ehframehdr.html87// http://refspecs.freestandards.org/LSB_1.3.0/gLSB/gLSB/ehframehdr.html
3688
...@@ -206,7 +258,8 @@ COMPILER_RT_ABI _Unwind_Reason_Code __gcc_personality_v0(...@@ -206,7 +258,8 @@ COMPILER_RT_ABI _Unwind_Reason_Code __gcc_personality_v0(
206 return continueUnwind(exceptionObject, context);258 return continueUnwind(exceptionObject, context);
207259
208 uintptr_t pc = (uintptr_t)_Unwind_GetIP(context) - 1;260 uintptr_t pc = (uintptr_t)_Unwind_GetIP(context) - 1;
209 uintptr_t funcStart = (uintptr_t)_Unwind_GetRegionStart(context);261 uintptr_t __ptrauth_gcc_personality_func_start funcStart =
262 (uintptr_t)_Unwind_GetRegionStart(context);
210 uintptr_t pcOffset = pc - funcStart;263 uintptr_t pcOffset = pc - funcStart;
211264
212 // Parse LSDA header.265 // Parse LSDA header.
...@@ -225,11 +278,14 @@ COMPILER_RT_ABI _Unwind_Reason_Code __gcc_personality_v0(...@@ -225,11 +278,14 @@ COMPILER_RT_ABI _Unwind_Reason_Code __gcc_personality_v0(
225 const uint8_t *callSiteTableEnd = callSiteTableStart + callSiteTableLength;278 const uint8_t *callSiteTableEnd = callSiteTableStart + callSiteTableLength;
226 const uint8_t *p = callSiteTableStart;279 const uint8_t *p = callSiteTableStart;
227 while (p < callSiteTableEnd) {280 while (p < callSiteTableEnd) {
228 uintptr_t start = readEncodedPointer(&p, callSiteEncoding);281 uintptr_t __ptrauth_gcc_personality_start start =
229 size_t length = readEncodedPointer(&p, callSiteEncoding);282 readEncodedPointer(&p, callSiteEncoding);
230 size_t landingPad = readEncodedPointer(&p, callSiteEncoding);283 size_t __ptrauth_gcc_personality_length length =
284 readEncodedPointer(&p, callSiteEncoding);
285 size_t __ptrauth_gcc_personality_lpoffset landingPadOffset =
286 readEncodedPointer(&p, callSiteEncoding);
231 readULEB128(&p); // action value not used for C code287 readULEB128(&p); // action value not used for C code
232 if (landingPad == 0)288 if (landingPadOffset == 0)
233 continue; // no landing pad for this entry289 continue; // no landing pad for this entry
234 if ((start <= pcOffset) && (pcOffset < (start + length))) {290 if ((start <= pcOffset) && (pcOffset < (start + length))) {
235 // Found landing pad for the PC.291 // Found landing pad for the PC.
...@@ -239,7 +295,24 @@ COMPILER_RT_ABI _Unwind_Reason_Code __gcc_personality_v0(...@@ -239,7 +295,24 @@ COMPILER_RT_ABI _Unwind_Reason_Code __gcc_personality_v0(
239 _Unwind_SetGR(context, __builtin_eh_return_data_regno(0),295 _Unwind_SetGR(context, __builtin_eh_return_data_regno(0),
240 (uintptr_t)exceptionObject);296 (uintptr_t)exceptionObject);
241 _Unwind_SetGR(context, __builtin_eh_return_data_regno(1), 0);297 _Unwind_SetGR(context, __builtin_eh_return_data_regno(1), 0);
242 _Unwind_SetIP(context, (funcStart + landingPad));298 size_t __ptrauth_gcc_personality_lpad landingPad =
299 funcStart + landingPadOffset;
300#if __has_feature(ptrauth_calls)
301 uintptr_t stackPointer = _Unwind_GetGR(context, -2);
302 const uintptr_t existingDiscriminator = ptrauth_blend_discriminator(
303 &landingPad, __ptrauth_gcc_personality_lpad_disc);
304 // newIP is authenticated as if it were qualified with a pseudo qualifier
305 // along the lines of:
306 // __ptrauth(ptrauth_key_return_address, <stackPointer>, 0)
307 // where the stack pointer is used in place of the strict storage
308 // address.
309 uintptr_t newIP = (uintptr_t)ptrauth_auth_and_resign(
310 *(void **)&landingPad, __ptrauth_gcc_personality_func_key,
311 existingDiscriminator, ptrauth_key_return_address, stackPointer);
312 _Unwind_SetIP(context, newIP);
313#else
314 _Unwind_SetIP(context, landingPad);
315#endif
243 return _URC_INSTALL_CONTEXT;316 return _URC_INSTALL_CONTEXT;
244 }317 }
245 }318 }
lib/libunwind/src/libunwind.cpp+104-4
...@@ -118,14 +118,55 @@ _LIBUNWIND_HIDDEN int __unw_set_reg(unw_cursor_t *cursor, unw_regnum_t regNum,...@@ -118,14 +118,55 @@ _LIBUNWIND_HIDDEN int __unw_set_reg(unw_cursor_t *cursor, unw_regnum_t regNum,
118 typedef LocalAddressSpace::pint_t pint_t;118 typedef LocalAddressSpace::pint_t pint_t;
119 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;119 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
120 if (co->validReg(regNum)) {120 if (co->validReg(regNum)) {
121 co->setReg(regNum, (pint_t)value);
122 // special case altering IP to re-find info (being called by personality121 // special case altering IP to re-find info (being called by personality
123 // function)122 // function)
124 if (regNum == UNW_REG_IP) {123 if (regNum == UNW_REG_IP) {
125 unw_proc_info_t info;124 unw_proc_info_t info;
126 // First, get the FDE for the old location and then update it.125 // First, get the FDE for the old location and then update it.
127 co->getInfo(&info);126 co->getInfo(&info);
128 co->setInfoBasedOnIPRegister(false);127
128 pint_t sp = (pint_t)co->getReg(UNW_REG_SP);
129
130#if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING)
131 {
132 // It is only valid to set the IP within the current function. This is
133 // important for ptrauth, otherwise the IP cannot be correctly signed.
134 // The current signature of `value` is via the schema:
135 // __ptrauth(ptrauth_key_return_address, <<sp>>, 0)
136 // For this to be generally usable we manually re-sign it to the
137 // directly supported schema:
138 // __ptrauth(ptrauth_key_return_address, 1, 0)
139 unw_word_t
140 __unwind_ptrauth_restricted_intptr(ptrauth_key_return_address, 1,
141 0) authenticated_value;
142 unw_word_t opaque_value = (uint64_t)ptrauth_auth_and_resign(
143 (void *)value, ptrauth_key_return_address, sp,
144 ptrauth_key_return_address, &authenticated_value);
145 memmove(reinterpret_cast<void *>(&authenticated_value),
146 reinterpret_cast<void *>(&opaque_value),
147 sizeof(authenticated_value));
148 if (authenticated_value < info.start_ip ||
149 authenticated_value > info.end_ip)
150 _LIBUNWIND_ABORT("PC vs frame info mismatch");
151
152 // PC should have been signed with the sp, so we verify that
153 // roundtripping does not fail. The `ptrauth_auth_and_resign` is
154 // guaranteed to trap on authentication failure even without FPAC
155 // feature.
156 pint_t pc = (pint_t)co->getReg(UNW_REG_IP);
157 if (ptrauth_auth_and_resign((void *)pc, ptrauth_key_return_address, sp,
158 ptrauth_key_return_address,
159 sp) != (void *)pc) {
160 _LIBUNWIND_LOG(
161 "Bad unwind with PAuth-enabled ABI (0x%zX, 0x%zX)->0x%zX\n", pc,
162 sp,
163 (pint_t)ptrauth_auth_data((void *)pc, ptrauth_key_return_address,
164 sp));
165 _LIBUNWIND_ABORT("Bad unwind with PAuth-enabled ABI");
166 }
167 }
168#endif
169
129 // If the original call expects stack adjustment, perform this now.170 // If the original call expects stack adjustment, perform this now.
130 // Normal frame unwinding would have included the offset already in the171 // Normal frame unwinding would have included the offset already in the
131 // CFA computation.172 // CFA computation.
...@@ -133,7 +174,11 @@ _LIBUNWIND_HIDDEN int __unw_set_reg(unw_cursor_t *cursor, unw_regnum_t regNum,...@@ -133,7 +174,11 @@ _LIBUNWIND_HIDDEN int __unw_set_reg(unw_cursor_t *cursor, unw_regnum_t regNum,
133 // this should actually be - info.gp. LLVM doesn't currently support174 // this should actually be - info.gp. LLVM doesn't currently support
134 // any such platforms and Clang doesn't export a macro for them.175 // any such platforms and Clang doesn't export a macro for them.
135 if (info.gp)176 if (info.gp)
136 co->setReg(UNW_REG_SP, co->getReg(UNW_REG_SP) + info.gp);177 co->setReg(UNW_REG_SP, sp + info.gp);
178 co->setReg(UNW_REG_IP, value);
179 co->setInfoBasedOnIPRegister(false);
180 } else {
181 co->setReg(regNum, (pint_t)value);
137 }182 }
138 return UNW_ESUCCESS;183 return UNW_ESUCCESS;
139 }184 }
...@@ -205,7 +250,27 @@ _LIBUNWIND_HIDDEN int __unw_get_proc_info(unw_cursor_t *cursor,...@@ -205,7 +250,27 @@ _LIBUNWIND_HIDDEN int __unw_get_proc_info(unw_cursor_t *cursor,
205}250}
206_LIBUNWIND_WEAK_ALIAS(__unw_get_proc_info, unw_get_proc_info)251_LIBUNWIND_WEAK_ALIAS(__unw_get_proc_info, unw_get_proc_info)
207252
208/// Resume execution at cursor position (aka longjump).253/// Rebalance the execution flow by injecting the right amount of `ret`
254/// instruction relatively to the amount of `walkedFrames` then resume execution
255/// at cursor position (aka longjump).
256_LIBUNWIND_HIDDEN int __unw_resume_with_frames_walked(unw_cursor_t *cursor,
257 unsigned walkedFrames) {
258 _LIBUNWIND_TRACE_API("__unw_resume(cursor=%p, walkedFrames=%u)",
259 static_cast<void *>(cursor), walkedFrames);
260#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
261 // Inform the ASan runtime that now might be a good time to clean stuff up.
262 __asan_handle_no_return();
263#endif
264#ifdef _LIBUNWIND_TRACE_RET_INJECT
265 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
266 co->setWalkedFrames(walkedFrames);
267#endif
268 return __unw_resume(cursor);
269}
270_LIBUNWIND_WEAK_ALIAS(__unw_resume_with_frames_walked,
271 unw_resume_with_frames_walked)
272
273/// Legacy function. Resume execution at cursor position (aka longjump).
209_LIBUNWIND_HIDDEN int __unw_resume(unw_cursor_t *cursor) {274_LIBUNWIND_HIDDEN int __unw_resume(unw_cursor_t *cursor) {
210 _LIBUNWIND_TRACE_API("__unw_resume(cursor=%p)", static_cast<void *>(cursor));275 _LIBUNWIND_TRACE_API("__unw_resume(cursor=%p)", static_cast<void *>(cursor));
211#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)276#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
...@@ -347,6 +412,41 @@ void __unw_remove_dynamic_eh_frame_section(unw_word_t eh_frame_start) {...@@ -347,6 +412,41 @@ void __unw_remove_dynamic_eh_frame_section(unw_word_t eh_frame_start) {
347}412}
348413
349#endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)414#endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
415
416/// Maps the UNW_* error code to a textual representation
417_LIBUNWIND_HIDDEN const char *__unw_strerror(int error_code) {
418 switch (error_code) {
419 case UNW_ESUCCESS:
420 return "no error";
421 case UNW_EUNSPEC:
422 return "unspecified (general) error";
423 case UNW_ENOMEM:
424 return "out of memory";
425 case UNW_EBADREG:
426 return "bad register number";
427 case UNW_EREADONLYREG:
428 return "attempt to write read-only register";
429 case UNW_ESTOPUNWIND:
430 return "stop unwinding";
431 case UNW_EINVALIDIP:
432 return "invalid IP";
433 case UNW_EBADFRAME:
434 return "bad frame";
435 case UNW_EINVAL:
436 return "unsupported operation or bad value";
437 case UNW_EBADVERSION:
438 return "unwind info has unsupported version";
439 case UNW_ENOINFO:
440 return "no unwind info found";
441#if defined(_LIBUNWIND_TARGET_AARCH64) && !defined(_LIBUNWIND_IS_NATIVE_ONLY)
442 case UNW_ECROSSRASIGNING:
443 return "cross unwind with return address signing";
444#endif
445 }
446 return "invalid error code";
447}
448_LIBUNWIND_WEAK_ALIAS(__unw_strerror, unw_strerror)
449
350#endif // !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__wasm__)450#endif // !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__wasm__)
351451
352#ifdef __APPLE__452#ifdef __APPLE__
lib/libunwind/src/libunwind_ext.h+7-1
...@@ -26,11 +26,16 @@ extern "C" {...@@ -26,11 +26,16 @@ extern "C" {
26extern int __unw_getcontext(unw_context_t *);26extern int __unw_getcontext(unw_context_t *);
27extern int __unw_init_local(unw_cursor_t *, unw_context_t *);27extern int __unw_init_local(unw_cursor_t *, unw_context_t *);
28extern int __unw_step(unw_cursor_t *);28extern int __unw_step(unw_cursor_t *);
29extern int __unw_step_stage2(unw_cursor_t *);
29extern int __unw_get_reg(unw_cursor_t *, unw_regnum_t, unw_word_t *);30extern int __unw_get_reg(unw_cursor_t *, unw_regnum_t, unw_word_t *);
30extern int __unw_get_fpreg(unw_cursor_t *, unw_regnum_t, unw_fpreg_t *);31extern int __unw_get_fpreg(unw_cursor_t *, unw_regnum_t, unw_fpreg_t *);
31extern int __unw_set_reg(unw_cursor_t *, unw_regnum_t, unw_word_t);32extern int __unw_set_reg(unw_cursor_t *, unw_regnum_t, unw_word_t);
32extern int __unw_set_fpreg(unw_cursor_t *, unw_regnum_t, unw_fpreg_t);33extern int __unw_set_fpreg(unw_cursor_t *, unw_regnum_t, unw_fpreg_t);
33extern int __unw_resume(unw_cursor_t *);34_LIBUNWIND_TRACE_NO_INLINE
35 extern int __unw_resume_with_frames_walked(unw_cursor_t *, unsigned);
36// `__unw_resume` is a legacy function. Use `__unw_resume_with_frames_walked` instead.
37_LIBUNWIND_TRACE_NO_INLINE
38 extern int __unw_resume(unw_cursor_t *);
3439
35#ifdef __arm__40#ifdef __arm__
36/* Save VFP registers in FSTMX format (instead of FSTMD). */41/* Save VFP registers in FSTMX format (instead of FSTMD). */
...@@ -42,6 +47,7 @@ extern int __unw_get_proc_info(unw_cursor_t *, unw_proc_info_t *);...@@ -42,6 +47,7 @@ extern int __unw_get_proc_info(unw_cursor_t *, unw_proc_info_t *);
42extern int __unw_is_fpreg(unw_cursor_t *, unw_regnum_t);47extern int __unw_is_fpreg(unw_cursor_t *, unw_regnum_t);
43extern int __unw_is_signal_frame(unw_cursor_t *);48extern int __unw_is_signal_frame(unw_cursor_t *);
44extern int __unw_get_proc_name(unw_cursor_t *, char *, size_t, unw_word_t *);49extern int __unw_get_proc_name(unw_cursor_t *, char *, size_t, unw_word_t *);
50extern const char *__unw_strerror(int);
4551
46#if defined(_AIX)52#if defined(_AIX)
47extern uintptr_t __unw_get_data_rel_base(unw_cursor_t *);53extern uintptr_t __unw_get_data_rel_base(unw_cursor_t *);
lib/libunwind/src/shadow_stack_unwind.h+2-2
...@@ -12,8 +12,8 @@...@@ -12,8 +12,8 @@
1212
13#include "libunwind.h"13#include "libunwind.h"
1414
15// Currently, CET is implemented on Linux x86 platforms.15// Currently, CET is implemented on some ELF x86 platforms.
16#if defined(_LIBUNWIND_TARGET_LINUX) && defined(__CET__) && defined(__SHSTK__)16#if defined(__CET__) && defined(__SHSTK__)
17#define _LIBUNWIND_USE_CET 117#define _LIBUNWIND_USE_CET 1
18#endif18#endif
1919