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-25 21:49:39+02:00
loge79b4e907a3ceed4984a252fb2bccab7f31ec383
tree18c9ee63ec96c1b0f600fbe0093c9aaca3c54ad3
parentdfabf1586fa2fcd9350e204fa138f44f952acbfd
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 @@
7373# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC
7474# elif defined(__aarch64__)
7575# define _LIBUNWIND_TARGET_AARCH64 1
76# define _LIBUNWIND_CONTEXT_SIZE 66
76#define _LIBUNWIND_CONTEXT_SIZE 67
7777# if defined(__SEH__)
7878# define _LIBUNWIND_CURSOR_SIZE 164
7979# else
80# define _LIBUNWIND_CURSOR_SIZE 78
80#define _LIBUNWIND_CURSOR_SIZE 79
8181# endif
8282# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64
8383# elif defined(__arm__)
......@@ -212,4 +212,13 @@
212212# define _LIBUNWIND_HIGHEST_DWARF_REGISTER 287
213213#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
215224#endif // ____LIBUNWIND_CONFIG_H__
lib/libunwind/include/libunwind.h+117-11
......@@ -43,6 +43,109 @@
4343 #define LIBUNWIND_AVAIL
4444#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
46149#if defined(_WIN32) && defined(__SEH__)
47150 #define LIBUNWIND_CURSOR_ALIGNMENT_ATTR __attribute__((__aligned__(16)))
48151#else
......@@ -88,17 +191,18 @@ typedef double unw_fpreg_t;
88191#endif
89192
90193struct unw_proc_info_t {
91 unw_word_t start_ip; /* start address of function */
92 unw_word_t end_ip; /* address after end of function */
93 unw_word_t lsda; /* address of language specific data area, */
94 /* or zero if not used */
95 unw_word_t handler; /* personality routine, or zero if not used */
96 unw_word_t gp; /* not used */
97 unw_word_t flags; /* not used */
98 uint32_t format; /* compact unwind encoding, or zero if none */
99 uint32_t unwind_info_size; /* size of DWARF unwind info, or zero if none */
100 unw_word_t unwind_info; /* address of DWARF unwind info, or zero */
101 unw_word_t extra; /* mach_header of mach-o image containing func */
194 unw_word_t __ptrauth_unwind_upi_startip start_ip; /* start address of function */
195 unw_word_t __ptrauth_unwind_upi_endip end_ip; /* address after end of function */
196 unw_word_t __ptrauth_unwind_upi_lsda lsda; /* address of language specific data area, */
197 /* or zero if not used */
198
199 unw_word_t __ptrauth_unwind_upi_handler_intptr handler;
200 unw_word_t gp; /* not used */
201 unw_word_t __ptrauth_unwind_upi_flags flags; /* not used */
202 uint32_t format; /* compact unwind encoding, or zero if none */
203 uint32_t unwind_info_size; /* size of DWARF unwind info, or zero if none */
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 */
102206};
103207typedef 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;
130234extern int unw_is_signal_frame(unw_cursor_t *) LIBUNWIND_AVAIL;
131235extern int unw_get_proc_name(unw_cursor_t *, char *, size_t, unw_word_t *) LIBUNWIND_AVAIL;
132236//extern int unw_get_save_loc(unw_cursor_t*, int, unw_save_loc_t*);
237extern const char *unw_strerror(int) LIBUNWIND_AVAIL;
133238
134239extern unw_addr_space_t unw_local_addr_space;
135240
......@@ -532,6 +637,7 @@ enum {
532637 UNW_AARCH64_X31 = 31,
533638 UNW_AARCH64_SP = 31,
534639 UNW_AARCH64_PC = 32,
640 UNW_AARCH64_VG = 46,
535641
536642 // reserved block
537643 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,
125125 uint32_t discriminator,
126126 _Unwind_VRS_DataRepresentation representation);
127127
128extern _Unwind_Reason_Code __gnu_unwind_frame(_Unwind_Exception *,
129 _Unwind_Context *);
130
128131#if defined(_LIBUNWIND_UNWIND_LEVEL1_EXTERNAL_LINKAGE)
129#define _LIBUNWIND_EXPORT_UNWIND_LEVEL1 extern
132#define _LIBUNWIND_EXPORT_UNWIND_LEVEL1 extern __inline__
130133#else
131134#define _LIBUNWIND_EXPORT_UNWIND_LEVEL1 static __inline__
132135#endif
lib/libunwind/src/AddressSpace.hpp+40-19
......@@ -129,22 +129,27 @@ struct UnwindInfoSections {
129129 defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) || \
130130 defined(_LIBUNWIND_USE_DL_ITERATE_PHDR)
131131 // No dso_base for SEH.
132 uintptr_t dso_base;
132 uintptr_t __ptrauth_unwind_uis_dso_base
133 dso_base = 0;
133134#endif
134135#if defined(_LIBUNWIND_USE_DL_ITERATE_PHDR)
135136 size_t text_segment_length;
136137#endif
137138#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
138 uintptr_t dwarf_section;
139 size_t dwarf_section_length;
139 uintptr_t __ptrauth_unwind_uis_dwarf_section
140 dwarf_section = 0;
141 size_t __ptrauth_unwind_uis_dwarf_section_length
142 dwarf_section_length = 0;
140143#endif
141144#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
142145 uintptr_t dwarf_index_section;
143146 size_t dwarf_index_section_length;
144147#endif
145148#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
146 uintptr_t compact_unwind_section;
147 size_t compact_unwind_section_length;
149 uintptr_t __ptrauth_unwind_uis_compact_unwind_section
150 compact_unwind_section = 0;
151 size_t __ptrauth_unwind_uis_compact_unwind_section_length
152 compact_unwind_section_length = 0;
148153#endif
149154#if defined(_LIBUNWIND_ARM_EHABI)
150155 uintptr_t arm_section;
......@@ -196,11 +201,16 @@ public:
196201 static int64_t getSLEB128(pint_t &addr, pint_t end);
197202
198203 pint_t getEncodedP(pint_t &addr, pint_t end, uint8_t encoding,
199 pint_t datarelBase = 0);
200 bool findFunctionName(pint_t addr, char *buf, size_t bufLen,
201 unw_word_t *offset);
202 bool findUnwindSections(pint_t targetAddr, UnwindInfoSections &info);
203 bool findOtherFDE(pint_t targetAddr, pint_t &fde);
204 pint_t datarelBase = 0, pint_t *resultAddr = nullptr);
205 template <typename R>
206 bool findFunctionName(typename R::link_hardened_reg_arg_t addr, char *buf,
207 size_t bufLen, unw_word_t *offset);
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
205215 static LocalAddressSpace sThisAddressSpace;
206216};
......@@ -269,7 +279,7 @@ inline int64_t LocalAddressSpace::getSLEB128(pint_t &addr, pint_t end) {
269279
270280inline LocalAddressSpace::pint_t
271281LocalAddressSpace::getEncodedP(pint_t &addr, pint_t end, uint8_t encoding,
272 pint_t datarelBase) {
282 pint_t datarelBase, pint_t *resultAddr) {
273283 pint_t startAddr = addr;
274284 const uint8_t *p = (uint8_t *)addr;
275285 pint_t result;
......@@ -353,8 +363,14 @@ LocalAddressSpace::getEncodedP(pint_t &addr, pint_t end, uint8_t encoding,
353363 break;
354364 }
355365
356 if (encoding & DW_EH_PE_indirect)
366 if (encoding & DW_EH_PE_indirect) {
367 if (resultAddr)
368 *resultAddr = result;
357369 result = getP(result);
370 } else {
371 if (resultAddr)
372 *resultAddr = startAddr;
373 }
358374
359375 return result;
360376}
......@@ -486,9 +502,9 @@ static int findUnwindSectionsByPhdr(struct dl_phdr_info *pinfo,
486502
487503#endif // defined(_LIBUNWIND_USE_DL_ITERATE_PHDR)
488504
489
490inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr,
491 UnwindInfoSections &info) {
505template <typename R>
506inline bool LocalAddressSpace::findUnwindSections(
507 typename R::link_hardened_reg_arg_t targetAddr, UnwindInfoSections &info) {
492508#ifdef __APPLE__
493509 dyld_unwind_sections dyldInfo;
494510 if (_dyld_find_unwind_sections((void *)targetAddr, &dyldInfo)) {
......@@ -658,16 +674,21 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr,
658674 return false;
659675}
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) {
662681 // TO DO: if OS has way to dynamically register FDEs, check that.
663682 (void)targetAddr;
664683 (void)fde;
665684 return false;
666685}
667686
668inline bool LocalAddressSpace::findFunctionName(pint_t addr, char *buf,
669 size_t bufLen,
670 unw_word_t *offset) {
687template <typename R>
688inline bool
689LocalAddressSpace::findFunctionName(typename R::link_hardened_reg_arg_t addr,
690 char *buf, size_t bufLen,
691 unw_word_t *offset) {
671692#if _LIBUNWIND_USE_DLADDR
672693 Dl_info dyldInfo;
673694 if (dladdr((void *)addr, &dyldInfo)) {
lib/libunwind/src/CompactUnwinder.hpp+16-5
......@@ -601,11 +601,17 @@ int CompactUnwinder_arm64<A>::stepWithCompactEncodingFrameless(
601601 savedRegisterLoc -= 8;
602602 }
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
604608 // subtract stack size off of sp
605609 registers.setSP(savedRegisterLoc);
606610
607 // set pc to be value in lr
608 registers.setIP(registers.getRegister(UNW_AARCH64_LR));
611 // Set pc to be value in lr. This needs to be performed after the new SP has
612 // been set, as the PC authentication schema entangles the SP of the new
613 // frame.
614 registers.setIP(linkRegister);
609615
610616 return UNW_STEP_SUCCESS;
611617}
......@@ -614,7 +620,7 @@ template <typename A>
614620int CompactUnwinder_arm64<A>::stepWithCompactEncodingFrame(
615621 compact_unwind_encoding_t encoding, uint64_t, A &addressSpace,
616622 Registers_arm64 &registers) {
617 uint64_t savedRegisterLoc = registers.getFP() - 8;
623 Registers_arm64::reg_t savedRegisterLoc = registers.getFP() - 8;
618624
619625 if (encoding & UNWIND_ARM64_FRAME_X19_X20_PAIR) {
620626 registers.setRegister(UNW_AARCH64_X19, addressSpace.get64(savedRegisterLoc));
......@@ -680,11 +686,16 @@ int CompactUnwinder_arm64<A>::stepWithCompactEncodingFrame(
680686 savedRegisterLoc -= 8;
681687 }
682688
683 uint64_t fp = registers.getFP();
689 Registers_arm64::reg_t fp = registers.getFP();
690
684691 // fp points to old fp
685692 registers.setFP(addressSpace.get64(fp));
686 // old sp is fp less saved fp and lr
693
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.
687697 registers.setSP(fp + 16);
698
688699 // pop return address into pc
689700 registers.setIP(addressSpace.get64(fp + 8));
690701
lib/libunwind/src/DwarfInstructions.hpp+24-13
......@@ -22,7 +22,6 @@
2222#include "dwarf2.h"
2323#include "libunwind_ext.h"
2424
25
2625namespace libunwind {
2726
2827
......@@ -34,8 +33,10 @@ public:
3433 typedef typename A::pint_t pint_t;
3534 typedef typename A::sint_t sint_t;
3635
37 static int stepWithDwarf(A &addressSpace, pint_t pc, pint_t fdeStart,
38 R &registers, bool &isSignalFrame, bool stage2);
36 static int stepWithDwarf(A &addressSpace,
37 typename R::link_hardened_reg_arg_t pc,
38 pint_t fdeStart, R &registers, bool &isSignalFrame,
39 bool stage2);
3940
4041private:
4142
......@@ -64,9 +65,10 @@ private:
6465
6566 static pint_t getCFA(A &addressSpace, const PrologInfo &prolog,
6667 const R &registers) {
67 if (prolog.cfaRegister != 0)
68 return (pint_t)((sint_t)registers.getRegister((int)prolog.cfaRegister) +
69 prolog.cfaRegisterOffset);
68 if (prolog.cfaRegister != 0) {
69 uintptr_t cfaRegister = registers.getRegister((int)prolog.cfaRegister);
70 return (pint_t)(cfaRegister + prolog.cfaRegisterOffset);
71 }
7072 if (prolog.cfaExpression != 0)
7173 return evaluateExpression((pint_t)prolog.cfaExpression, addressSpace,
7274 registers, 0);
......@@ -207,16 +209,16 @@ bool DwarfInstructions<A, R>::isReturnAddressSignedWithPC(A &addressSpace,
207209#endif
208210
209211template <typename A, typename R>
210int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
211 pint_t fdeStart, R &registers,
212 bool &isSignalFrame, bool stage2) {
212int DwarfInstructions<A, R>::stepWithDwarf(
213 A &addressSpace, typename R::link_hardened_reg_arg_t pc, pint_t fdeStart,
214 R &registers, bool &isSignalFrame, bool stage2) {
213215 FDE_Info fdeInfo;
214216 CIE_Info cieInfo;
215217 if (CFI_Parser<A>::decodeFDE(addressSpace, fdeStart, &fdeInfo,
216218 &cieInfo) == NULL) {
217219 PrologInfo prolog;
218 if (CFI_Parser<A>::parseFDEInstructions(addressSpace, fdeInfo, cieInfo, pc,
219 R::getArch(), &prolog)) {
220 if (CFI_Parser<A>::template parseFDEInstructions<R>(
221 addressSpace, fdeInfo, cieInfo, pc, R::getArch(), &prolog)) {
220222 // get pointer to cfa (architecture specific)
221223 pint_t cfa = getCFA(addressSpace, prolog, registers);
222224
......@@ -264,7 +266,7 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
264266 // by a CFI directive later on.
265267 newRegisters.setSP(cfa);
266268
267 pint_t returnAddress = 0;
269 typename R::reg_t returnAddress = 0;
268270 constexpr int lastReg = R::lastDwarfRegNum();
269271 static_assert(static_cast<int>(CFI_Parser<A>::kMaxRegisterNumber) >=
270272 lastReg,
......@@ -300,7 +302,16 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
300302
301303 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 //
304315 // If the target is aarch64 then the return address may have been signed
305316 // using the v8.3 pointer authentication extensions. The original
306317 // return address needs to be authenticated before the return address is
lib/libunwind/src/DwarfParser.hpp+60-22
......@@ -23,6 +23,10 @@
2323
2424#include "config.h"
2525
26#if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING)
27#include <ptrauth.h>
28#endif
29
2630namespace libunwind {
2731
2832/// CFI_Parser does basic parsing of a CFI (Call Frame Information) records.
......@@ -33,6 +37,7 @@ template <typename A>
3337class CFI_Parser {
3438public:
3539 typedef typename A::pint_t pint_t;
40 typedef pint_t __ptrauth_unwind_cie_info_personality personality_t;
3641
3742 /// Information encoded in a CIE (Common Information Entry)
3843 struct CIE_Info {
......@@ -43,7 +48,7 @@ public:
4348 uint8_t lsdaEncoding;
4449 uint8_t personalityEncoding;
4550 uint8_t personalityOffsetInCIE;
46 pint_t personality;
51 personality_t personality;
4752 uint32_t codeAlignFactor;
4853 int dataAlignFactor;
4954 bool isSignalFrame;
......@@ -155,14 +160,17 @@ public:
155160 }
156161 };
157162
158 static bool findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart,
159 size_t sectionLength, pint_t fdeHint, FDE_Info *fdeInfo,
160 CIE_Info *cieInfo);
163 template <typename R>
164 static bool findFDE(A &addressSpace, typename R::link_hardened_reg_arg_t pc,
165 pint_t ehSectionStart, size_t sectionLength,
166 pint_t fdeHint, FDE_Info *fdeInfo, CIE_Info *cieInfo);
161167 static const char *decodeFDE(A &addressSpace, pint_t fdeStart,
162168 FDE_Info *fdeInfo, CIE_Info *cieInfo,
163169 bool useCIEInfo = false);
170 template <typename R>
164171 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,
166174 int arch, PrologInfo *results);
167175
168176 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,
234242
235243/// Scan an eh_frame section to find an FDE for a pc
236244template <typename A>
237bool CFI_Parser<A>::findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart,
238 size_t sectionLength, pint_t fdeHint,
239 FDE_Info *fdeInfo, CIE_Info *cieInfo) {
245template <typename R>
246bool CFI_Parser<A>::findFDE(A &addressSpace,
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) {
240251 //fprintf(stderr, "findFDE(0x%llX)\n", (long long)pc);
241252 pint_t p = (fdeHint != 0) ? fdeHint : ehSectionStart;
242253 const pint_t ehSectionEnd = (sectionLength == SIZE_MAX)
......@@ -273,7 +284,7 @@ bool CFI_Parser<A>::findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart,
273284 pint_t pcRange = addressSpace.getEncodedP(
274285 p, nextCFI, cieInfo->pointerEncoding & 0x0F);
275286 // Test if pc is within the function this FDE covers.
276 if ((pcStart < pc) && (pc <= pcStart + pcRange)) {
287 if ((pcStart <= pc) && (pc < pcStart + pcRange)) {
277288 // parse rest of info
278289 fdeInfo->lsda = 0;
279290 // check for augmentation length
......@@ -369,6 +380,7 @@ const char *CFI_Parser<A>::parseCIE(A &addressSpace, pint_t cie,
369380 cieInfo->returnAddressRegister = (uint8_t)raReg;
370381 // parse augmentation data based on augmentation string
371382 const char *result = NULL;
383 pint_t resultAddr = 0;
372384 if (addressSpace.get8(strStart) == 'z') {
373385 // parse augmentation data length
374386 addressSpace.getULEB128(p, cieContentEnd);
......@@ -377,13 +389,41 @@ const char *CFI_Parser<A>::parseCIE(A &addressSpace, pint_t cie,
377389 case 'z':
378390 cieInfo->fdesHaveAugmentationData = true;
379391 break;
380 case 'P':
392 case 'P': {
381393 cieInfo->personalityEncoding = addressSpace.get8(p);
382394 ++p;
383395 cieInfo->personalityOffsetInCIE = (uint8_t)(p - cie);
384 cieInfo->personality = addressSpace
385 .getEncodedP(p, cieContentEnd, cieInfo->personalityEncoding);
396 pint_t personality = addressSpace.getEncodedP(
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));
386425 break;
426 }
387427 case 'L':
388428 cieInfo->lsdaEncoding = addressSpace.get8(p);
389429 ++p;
......@@ -417,10 +457,10 @@ const char *CFI_Parser<A>::parseCIE(A &addressSpace, pint_t cie,
417457
418458/// "run" the DWARF instructions and create the abstract PrologInfo for an FDE
419459template <typename A>
420bool CFI_Parser<A>::parseFDEInstructions(A &addressSpace,
421 const FDE_Info &fdeInfo,
422 const CIE_Info &cieInfo, pint_t upToPC,
423 int arch, PrologInfo *results) {
460template <typename R>
461bool CFI_Parser<A>::parseFDEInstructions(
462 A &addressSpace, const FDE_Info &fdeInfo, const CIE_Info &cieInfo,
463 typename R::link_hardened_reg_arg_t upToPC, int arch, PrologInfo *results) {
424464 // Alloca is used for the allocation of the rememberStack entries. It removes
425465 // the dependency on new/malloc but the below for loop can not be refactored
426466 // into functions. Entry could be saved during the processing of a CIE and
......@@ -808,12 +848,10 @@ bool CFI_Parser<A>::parseFDEInstructions(A &addressSpace,
808848 results->savedRegisters[UNW_AARCH64_RA_SIGN_STATE].value ^ 0x3;
809849 results->setRegisterValue(UNW_AARCH64_RA_SIGN_STATE, value,
810850 initialState);
811 // When calculating the value of the PC, it is assumed that the CFI
812 // instruction is placed before the signing instruction, however it is
813 // placed after. Because of this, we need to take into account the CFI
814 // instruction is one instruction call later than expected, and reduce
815 // the PC value by 4 bytes to compensate.
816 results->ptrAuthDiversifier = fdeInfo.pcStart + codeOffset - 0x4;
851 // When using Feat_PAuthLR, the PC value needs to be captured so that
852 // during unwinding, the correct PC value is used for re-authentication.
853 // It is assumed that the CFI is placed before the signing instruction.
854 results->ptrAuthDiversifier = fdeInfo.pcStart + codeOffset;
817855 _LIBUNWIND_TRACE_DWARF(
818856 "DW_CFA_AARCH64_negate_ra_state_with_pc(pc=0x%" PRIx64 ")\n",
819857 static_cast<uint64_t>(results->ptrAuthDiversifier));
lib/libunwind/src/EHHeaderParser.hpp+7-4
......@@ -37,8 +37,9 @@ public:
3737
3838 static bool decodeEHHdr(A &addressSpace, pint_t ehHdrStart, pint_t ehHdrEnd,
3939 EHHeaderInfo &ehHdrInfo);
40 static bool findFDE(A &addressSpace, pint_t pc, pint_t ehHdrStart,
41 uint32_t sectionLength,
40 template <typename R>
41 static bool findFDE(A &addressSpace, typename R::link_hardened_reg_arg_t pc,
42 pint_t ehHdrStart, uint32_t sectionLength,
4243 typename CFI_Parser<A>::FDE_Info *fdeInfo,
4344 typename CFI_Parser<A>::CIE_Info *cieInfo);
4445
......@@ -112,8 +113,10 @@ bool EHHeaderParser<A>::decodeTableEntry(
112113}
113114
114115template <typename A>
115bool EHHeaderParser<A>::findFDE(A &addressSpace, pint_t pc, pint_t ehHdrStart,
116 uint32_t sectionLength,
116template <typename R>
117bool EHHeaderParser<A>::findFDE(A &addressSpace,
118 typename R::link_hardened_reg_arg_t pc,
119 pint_t ehHdrStart, uint32_t sectionLength,
117120 typename CFI_Parser<A>::FDE_Info *fdeInfo,
118121 typename CFI_Parser<A>::CIE_Info *cieInfo) {
119122 pint_t ehHdrEnd = ehHdrStart + sectionLength;
lib/libunwind/src/Registers.hpp+226-22
......@@ -17,8 +17,13 @@
1717
1818#include "config.h"
1919#include "libunwind.h"
20#include "libunwind_ext.h"
2021#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
2227namespace libunwind {
2328
2429// For emulating 128-bit registers
......@@ -60,6 +65,10 @@ public:
6065 Registers_x86();
6166 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
6372 bool validRegister(int num) const;
6473 uint32_t getRegister(int num) const;
6574 void setRegister(int num, uint32_t value);
......@@ -278,6 +287,10 @@ public:
278287 Registers_x86_64();
279288 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
281294 bool validRegister(int num) const;
282295 uint64_t getRegister(int num) const;
283296 void setRegister(int num, uint64_t value);
......@@ -597,6 +610,10 @@ public:
597610 Registers_ppc();
598611 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
600617 bool validRegister(int num) const;
601618 uint32_t getRegister(int num) const;
602619 void setRegister(int num, uint32_t value);
......@@ -1169,6 +1186,10 @@ public:
11691186 Registers_ppc64();
11701187 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
11721193 bool validRegister(int num) const;
11731194 uint64_t getRegister(int num) const;
11741195 void setRegister(int num, uint64_t value);
......@@ -1814,7 +1835,9 @@ inline const char *Registers_ppc64::getRegisterName(int regNum) {
18141835/// Registers_arm64 holds the register state of a thread in a 64-bit arm
18151836/// process.
18161837class _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
18191842#if defined(_LIBUNWIND_USE_GCS)
18201843extern "C" void *__libunwind_shstk_get_jump_target() {
......@@ -1824,8 +1847,21 @@ extern "C" void *__libunwind_shstk_get_jump_target() {
18241847
18251848class _LIBUNWIND_HIDDEN Registers_arm64 {
18261849public:
1827 Registers_arm64();
1850 Registers_arm64() = default;
18281851 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
18301866 bool validRegister(int num) const;
18311867 uint64_t getRegister(int num) const;
......@@ -1837,7 +1873,14 @@ public:
18371873 v128 getVectorRegister(int num) const;
18381874 void setVectorRegister(int num, v128 value);
18391875 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
18411884 static constexpr int lastDwarfRegNum() {
18421885 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64;
18431886 }
......@@ -1845,27 +1888,104 @@ public:
18451888
18461889 uint64_t getSP() const { return _registers.__sp; }
18471890 void setSP(uint64_t value) { _registers.__sp = value; }
1848 uint64_t getIP() const { return _registers.__pc; }
1849 void setIP(uint64_t value) { _registers.__pc = value; }
1850 uint64_t getFP() const { return _registers.__fp; }
1851 void setFP(uint64_t value) { _registers.__fp = value; }
1891 uint64_t getIP() const {
1892 uint64_t value = _registers.__pc;
1893#if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING)
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
18531933private:
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
18541963 struct GPRs {
1855 uint64_t __x[29]; // x0-x28
1856 uint64_t __fp; // Frame pointer x29
1857 uint64_t __lr; // Link register x30
1858 uint64_t __sp; // Stack pointer x31
1859 uint64_t __pc; // Program counter
1860 uint64_t __ra_sign_state; // RA sign state register
1964 uint64_t __x[29] = {}; // x0-x28
1965 uint64_t __fp = 0; // Frame pointer x29
1966 uint64_t __lr = 0; // Link register x30
1967 uint64_t __sp = 0; // Stack pointer x31
1968 uint64_t __pc = 0; // Program counter
1969 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();
18611975 };
18621976
1863 GPRs _registers;
1864 double _vectorHalfRegisters[32];
1977 GPRs _registers = {};
18651978 // Currently only the lower double in 128-bit vectore registers
18661979 // is perserved during unwinding. We could define new register
18671980 // numbers (> 96) which mean whole vector registers, then this
18681981 // 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;
18691989};
18701990
18711991inline Registers_arm64::Registers_arm64(const void *registers) {
......@@ -1877,11 +1997,31 @@ inline Registers_arm64::Registers_arm64(const void *registers) {
18771997 memcpy(_vectorHalfRegisters,
18781998 static_cast<const uint8_t *>(registers) + sizeof(GPRs),
18791999 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
18802012}
18812013
1882inline Registers_arm64::Registers_arm64() {
1883 memset(&_registers, 0, sizeof(_registers));
1884 memset(&_vectorHalfRegisters, 0, sizeof(_vectorHalfRegisters));
2014inline Registers_arm64::Registers_arm64(const Registers_arm64 &other) {
2015 *this = other;
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;
18852025}
18862026
18872027inline bool Registers_arm64::validRegister(int regNum) const {
......@@ -1895,22 +2035,40 @@ inline bool Registers_arm64::validRegister(int regNum) const {
18952035 return false;
18962036 if (regNum == UNW_AARCH64_RA_SIGN_STATE)
18972037 return true;
2038 if (regNum == UNW_AARCH64_VG)
2039 return true;
18982040 if ((regNum > 32) && (regNum < 64))
18992041 return false;
19002042 return true;
19012043}
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
19032059inline uint64_t Registers_arm64::getRegister(int regNum) const {
19042060 if (regNum == UNW_REG_IP || regNum == UNW_AARCH64_PC)
1905 return _registers.__pc;
2061 return getIP();
19062062 if (regNum == UNW_REG_SP || regNum == UNW_AARCH64_SP)
19072063 return _registers.__sp;
19082064 if (regNum == UNW_AARCH64_RA_SIGN_STATE)
19092065 return _registers.__ra_sign_state;
19102066 if (regNum == UNW_AARCH64_FP)
1911 return _registers.__fp;
2067 return getFP();
19122068 if (regNum == UNW_AARCH64_LR)
19132069 return _registers.__lr;
2070 if (regNum == UNW_AARCH64_VG)
2071 return lazyGetVG();
19142072 if ((regNum >= 0) && (regNum < 29))
19152073 return _registers.__x[regNum];
19162074 _LIBUNWIND_ABORT("unsupported arm64 register");
......@@ -1918,15 +2076,17 @@ inline uint64_t Registers_arm64::getRegister(int regNum) const {
19182076
19192077inline void Registers_arm64::setRegister(int regNum, uint64_t value) {
19202078 if (regNum == UNW_REG_IP || regNum == UNW_AARCH64_PC)
1921 _registers.__pc = value;
2079 setIP(value);
19222080 else if (regNum == UNW_REG_SP || regNum == UNW_AARCH64_SP)
19232081 _registers.__sp = value;
19242082 else if (regNum == UNW_AARCH64_RA_SIGN_STATE)
19252083 _registers.__ra_sign_state = value;
19262084 else if (regNum == UNW_AARCH64_FP)
1927 _registers.__fp = value;
2085 setFP(value);
19282086 else if (regNum == UNW_AARCH64_LR)
19292087 _registers.__lr = value;
2088 else if (regNum == UNW_AARCH64_VG)
2089 _misc_registers.__vg = value;
19302090 else if ((regNum >= 0) && (regNum < 29))
19312091 _registers.__x[regNum] = value;
19322092 else
......@@ -2116,6 +2276,10 @@ public:
21162276 Registers_arm();
21172277 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
21192283 bool validRegister(int num) const;
21202284 uint32_t getRegister(int num) const;
21212285 void setRegister(int num, uint32_t value);
......@@ -2621,6 +2785,10 @@ public:
26212785 Registers_or1k();
26222786 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
26242792 bool validRegister(int num) const;
26252793 uint32_t getRegister(int num) const;
26262794 void setRegister(int num, uint32_t value);
......@@ -2820,6 +2988,10 @@ public:
28202988 Registers_mips_o32();
28212989 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
28232995 bool validRegister(int num) const;
28242996 uint32_t getRegister(int num) const;
28252997 void setRegister(int num, uint32_t value);
......@@ -3155,6 +3327,10 @@ public:
31553327 Registers_mips_newabi();
31563328 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
31583334 bool validRegister(int num) const;
31593335 uint64_t getRegister(int num) const;
31603336 void setRegister(int num, uint64_t value);
......@@ -3458,6 +3634,10 @@ public:
34583634 Registers_sparc();
34593635 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
34613641 bool validRegister(int num) const;
34623642 uint32_t getRegister(int num) const;
34633643 void setRegister(int num, uint32_t value);
......@@ -3644,6 +3824,10 @@ public:
36443824 Registers_sparc64() = default;
36453825 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
36473831 bool validRegister(int num) const;
36483832 uint64_t getRegister(int num) const;
36493833 void setRegister(int num, uint64_t value);
......@@ -3829,6 +4013,10 @@ public:
38294013 Registers_hexagon();
38304014 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
38324020 bool validRegister(int num) const;
38334021 uint32_t getRegister(int num) const;
38344022 void setRegister(int num, uint32_t value);
......@@ -4044,6 +4232,10 @@ public:
40444232 Registers_riscv();
40454233 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
40474239 bool validRegister(int num) const;
40484240 reg_t getRegister(int num) const;
40494241 void setRegister(int num, reg_t value);
......@@ -4341,6 +4533,10 @@ public:
43414533 Registers_ve();
43424534 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
43444540 bool validRegister(int num) const;
43454541 uint64_t getRegister(int num) const;
43464542 void setRegister(int num, uint64_t value);
......@@ -4784,6 +4980,10 @@ public:
47844980 Registers_s390x();
47854981 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
47874987 bool validRegister(int num) const;
47884988 uint64_t getRegister(int num) const;
47894989 void setRegister(int num, uint64_t value);
......@@ -5072,6 +5272,10 @@ public:
50725272 Registers_loongarch();
50735273 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
50755279 bool validRegister(int num) const;
50765280 uint64_t getRegister(int num) const;
50775281 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,
163163 // If we were called by __libunwind_seh_personality(), indicate that
164164 // a handler was found; otherwise, initiate phase 2 by unwinding.
165165 if (ours && ms_exc->NumberParameters > 1)
166 return 4 /* ExceptionExecuteHandler in mingw */;
166 return static_cast<EXCEPTION_DISPOSITION>(4);
167167 // This should never happen in phase 2.
168168 if (IS_UNWINDING(ms_exc->ExceptionFlags))
169169 _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,
182182 // a handler was found; otherwise, it's time to initiate a collided
183183 // unwind to the target.
184184 if (ours && !IS_UNWINDING(ms_exc->ExceptionFlags) && ms_exc->NumberParameters > 1)
185 return 4 /* ExceptionExecuteHandler in mingw */;
185 return static_cast<EXCEPTION_DISPOSITION>(4);
186186 // This should never happen in phase 1.
187187 if (!IS_UNWINDING(ms_exc->ExceptionFlags))
188188 _LIBUNWIND_ABORT("Personality installed context during phase 1!");
......@@ -259,13 +259,12 @@ __libunwind_seh_personality(int version, _Unwind_Action state,
259259 (void *)disp_ctx->LanguageHandler, (void *)&ms_exc,
260260 (void *)disp_ctx->EstablisherFrame,
261261 (void *)disp_ctx->ContextRecord, (void *)disp_ctx);
262 EXCEPTION_DISPOSITION ms_act = disp_ctx->LanguageHandler(&ms_exc,
263 (PVOID)disp_ctx->EstablisherFrame,
264 disp_ctx->ContextRecord,
265 disp_ctx);
262 int ms_act = static_cast<int>(
263 disp_ctx->LanguageHandler(&ms_exc, (PVOID)disp_ctx->EstablisherFrame,
264 disp_ctx->ContextRecord, disp_ctx));
266265 _LIBUNWIND_TRACE_UNWINDING("__libunwind_seh_personality() LanguageHandler "
267266 "returned %d",
268 (int)ms_act);
267 ms_act);
269268 switch (ms_act) {
270269 case ExceptionContinueExecution: return _URC_END_OF_STACK;
271270 case ExceptionContinueSearch: return _URC_CONTINUE_UNWIND;
lib/libunwind/src/Unwind-wasm.c+7-7
......@@ -37,13 +37,13 @@ struct _Unwind_LandingPadContext {
3737// function
3838thread_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.
4141/// 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 other
43/// hand, WebAssembly stack unwinding process is performed by a VM, and the
44/// personality function cannot be called from there. So the compiler inserts
45/// a call to this function in landing pads in the user code, which in turn
46/// calls the personality function.
42/// calls the personality function for each frame it lands. On the other hand,
43/// WebAssembly stack unwinding process is performed by a VM, and the
44/// personality function cannot be called from there. So the compiler inserts a
45/// call to this function in landing pads in the user code, which in turn calls
46/// the personality function.
4747_Unwind_Reason_Code _Unwind_CallPersonality(void *exception_ptr) {
4848 struct _Unwind_Exception *exception_object =
4949 (struct _Unwind_Exception *)exception_ptr;
......@@ -92,7 +92,7 @@ _LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index,
9292
9393/// Called by personality handler to get instruction pointer.
9494_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 we
95 // The result will be used as a 1-based index after decrementing 1, so we
9696 // increment 2 here
9797 uintptr_t result =
9898 ((struct _Unwind_LandingPadContext *)context)->lpad_index + 2;
lib/libunwind/src/UnwindCursor.hpp+167-49
......@@ -41,7 +41,8 @@
4141#define _LIBUNWIND_CHECK_LINUX_SIGRETURN 1
4242#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))
4546#include <OS.h>
4647#include <signal.h>
4748#define _LIBUNWIND_CHECK_HAIKU_SIGRETURN 1
......@@ -120,7 +121,9 @@ class _LIBUNWIND_HIDDEN DwarfFDECache {
120121 typedef typename A::pint_t pint_t;
121122public:
122123 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
124127 static void add(pint_t mh, pint_t ip_start, pint_t ip_end, pint_t fde);
125128 static void removeAllIn(pint_t mh);
126129 static void iterateCacheEntries(void (*func)(unw_word_t ip_start,
......@@ -173,7 +176,9 @@ bool DwarfFDECache<A>::_registeredForDyldUnloads = false;
173176#endif
174177
175178template <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) {
177182 pint_t result = 0;
178183 _LIBUNWIND_LOG_IF_FALSE(_lock.lock_shared());
179184 for (entry *p = _buffer; p < _bufferUsed; ++p) {
......@@ -471,7 +476,9 @@ public:
471476 virtual void getInfo(unw_proc_info_t *) {
472477 _LIBUNWIND_ABORT("getInfo not implemented");
473478 }
474 virtual void jumpto() { _LIBUNWIND_ABORT("jumpto not implemented"); }
479 _LIBUNWIND_TRACE_NO_INLINE virtual void jumpto() {
480 _LIBUNWIND_ABORT("jumpto not implemented");
481 }
475482 virtual bool isSignalFrame() {
476483 _LIBUNWIND_ABORT("isSignalFrame not implemented");
477484 }
......@@ -488,6 +495,12 @@ public:
488495 virtual void saveVFPAsX() { _LIBUNWIND_ABORT("saveVFPAsX not implemented"); }
489496#endif
490497
498#ifdef _LIBUNWIND_TRACE_RET_INJECT
499 virtual void setWalkedFrames(unsigned) {
500 _LIBUNWIND_ABORT("setWalkedFrames not implemented");
501 }
502#endif
503
491504#ifdef _AIX
492505 virtual uintptr_t getDataRelBase() {
493506 _LIBUNWIND_ABORT("getDataRelBase not implemented");
......@@ -964,7 +977,8 @@ public:
964977 virtual void setFloatReg(int, unw_fpreg_t);
965978 virtual int step(bool stage2 = false);
966979 virtual void getInfo(unw_proc_info_t *);
967 virtual void jumpto();
980 _LIBUNWIND_TRACE_NO_INLINE
981 virtual void jumpto();
968982 virtual bool isSignalFrame();
969983 virtual bool getFunctionName(char *buf, size_t len, unw_word_t *off);
970984 virtual void setInfoBasedOnIPRegister(bool isReturnAddress = false);
......@@ -973,6 +987,10 @@ public:
973987 virtual void saveVFPAsX();
974988#endif
975989
990#ifdef _LIBUNWIND_TRACE_RET_INJECT
991 virtual void setWalkedFrames(unsigned);
992#endif
993
976994#ifdef _AIX
977995 virtual uintptr_t getDataRelBase();
978996#endif
......@@ -1045,19 +1063,28 @@ private:
10451063#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
10461064 bool getInfoFromFdeCie(const typename CFI_Parser<A>::FDE_Info &fdeInfo,
10471065 const typename CFI_Parser<A>::CIE_Info &cieInfo,
1048 pint_t pc, uintptr_t dso_base);
1049 bool getInfoFromDwarfSection(pint_t pc, const UnwindInfoSections &sects,
1050 uint32_t fdeSectionOffsetHint=0);
1066 typename R::link_hardened_reg_arg_t pc,
1067 uintptr_t dso_base);
1068 bool getInfoFromDwarfSection(typename R::link_hardened_reg_arg_t pc,
1069 const UnwindInfoSections &sects,
1070 uint32_t fdeSectionOffsetHint = 0);
10511071 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
10521079 return DwarfInstructions<A, R>::stepWithDwarf(
1053 _addressSpace, (pint_t)this->getReg(UNW_REG_IP),
1054 (pint_t)_info.unwind_info, _registers, _isSignalFrame, stage2);
1080 _addressSpace, pc, (pint_t)_info.unwind_info, _registers,
1081 _isSignalFrame, stage2);
10551082 }
10561083#endif
10571084
10581085#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
1059 bool getInfoFromCompactEncodingSection(pint_t pc,
1060 const UnwindInfoSections &sects);
1086 bool getInfoFromCompactEncodingSection(typename R::link_hardened_reg_arg_t pc,
1087 const UnwindInfoSections &sects);
10611088 int stepWithCompactEncoding(bool stage2 = false) {
10621089#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
10631090 if ( compactSaysUseDwarf() )
......@@ -1344,9 +1371,12 @@ private:
13441371 bool _unwindInfoMissing;
13451372 bool _isSignalFrame;
13461373#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) || \
1347 defined(_LIBUNWIND_TARGET_HAIKU)
1374 defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN)
13481375 bool _isSigReturn = false;
13491376#endif
1377#ifdef _LIBUNWIND_TRACE_RET_INJECT
1378 uint32_t _walkedFrames;
1379#endif
13501380};
13511381
13521382
......@@ -1358,13 +1388,13 @@ UnwindCursor<A, R>::UnwindCursor(unw_context_t *context, A &as)
13581388 "UnwindCursor<> does not fit in unw_cursor_t");
13591389 static_assert((alignof(UnwindCursor<A, R>) <= alignof(unw_cursor_t)),
13601390 "UnwindCursor<> requires more alignment than unw_cursor_t");
1361 memset(&_info, 0, sizeof(_info));
1391 memset(static_cast<void *>(&_info), 0, sizeof(_info));
13621392}
13631393
13641394template <typename A, typename R>
13651395UnwindCursor<A, R>::UnwindCursor(A &as, void *)
13661396 : _addressSpace(as), _unwindInfoMissing(false), _isSignalFrame(false) {
1367 memset(&_info, 0, sizeof(_info));
1397 memset(static_cast<void *>(&_info), 0, sizeof(_info));
13681398 // FIXME
13691399 // fill in _registers from thread arg
13701400}
......@@ -1401,7 +1431,46 @@ void UnwindCursor<A, R>::setFloatReg(int regNum, unw_fpreg_t value) {
14011431}
14021432
14031433template <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
14041472 _registers.jumpto();
1473#endif
14051474}
14061475
14071476#ifdef __arm__
......@@ -1410,6 +1479,13 @@ template <typename A, typename R> void UnwindCursor<A, R>::saveVFPAsX() {
14101479}
14111480#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
14131489#ifdef _AIX
14141490template <typename A, typename R>
14151491uintptr_t UnwindCursor<A, R>::getDataRelBase() {
......@@ -1658,11 +1734,11 @@ bool UnwindCursor<A, R>::getInfoFromEHABISection(
16581734template <typename A, typename R>
16591735bool UnwindCursor<A, R>::getInfoFromFdeCie(
16601736 const typename CFI_Parser<A>::FDE_Info &fdeInfo,
1661 const typename CFI_Parser<A>::CIE_Info &cieInfo, pint_t pc,
1662 uintptr_t dso_base) {
1737 const typename CFI_Parser<A>::CIE_Info &cieInfo,
1738 typename R::link_hardened_reg_arg_t pc, uintptr_t dso_base) {
16631739 typename CFI_Parser<A>::PrologInfo prolog;
1664 if (CFI_Parser<A>::parseFDEInstructions(_addressSpace, fdeInfo, cieInfo, pc,
1665 R::getArch(), &prolog)) {
1740 if (CFI_Parser<A>::template parseFDEInstructions<R>(
1741 _addressSpace, fdeInfo, cieInfo, pc, R::getArch(), &prolog)) {
16661742 // Save off parsed FDE info
16671743 _info.start_ip = fdeInfo.pcStart;
16681744 _info.end_ip = fdeInfo.pcEnd;
......@@ -1682,43 +1758,42 @@ bool UnwindCursor<A, R>::getInfoFromFdeCie(
16821758}
16831759
16841760template <typename A, typename R>
1685bool UnwindCursor<A, R>::getInfoFromDwarfSection(pint_t pc,
1686 const UnwindInfoSections &sects,
1687 uint32_t fdeSectionOffsetHint) {
1761bool UnwindCursor<A, R>::getInfoFromDwarfSection(
1762 typename R::link_hardened_reg_arg_t pc, const UnwindInfoSections &sects,
1763 uint32_t fdeSectionOffsetHint) {
16881764 typename CFI_Parser<A>::FDE_Info fdeInfo;
16891765 typename CFI_Parser<A>::CIE_Info cieInfo;
16901766 bool foundFDE = false;
16911767 bool foundInCache = false;
16921768 // If compact encoding table gave offset into dwarf section, go directly there
16931769 if (fdeSectionOffsetHint != 0) {
1694 foundFDE = CFI_Parser<A>::findFDE(_addressSpace, pc, sects.dwarf_section,
1695 sects.dwarf_section_length,
1696 sects.dwarf_section + fdeSectionOffsetHint,
1697 &fdeInfo, &cieInfo);
1770 foundFDE = CFI_Parser<A>::template findFDE<R>(
1771 _addressSpace, pc, sects.dwarf_section, sects.dwarf_section_length,
1772 sects.dwarf_section + fdeSectionOffsetHint, &fdeInfo, &cieInfo);
16981773 }
16991774#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
17001775 if (!foundFDE && (sects.dwarf_index_section != 0)) {
1701 foundFDE = EHHeaderParser<A>::findFDE(
1776 foundFDE = EHHeaderParser<A>::template findFDE<R>(
17021777 _addressSpace, pc, sects.dwarf_index_section,
17031778 (uint32_t)sects.dwarf_index_section_length, &fdeInfo, &cieInfo);
17041779 }
17051780#endif
17061781 if (!foundFDE) {
17071782 // 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);
17091785 if (cachedFDE != 0) {
1710 foundFDE =
1711 CFI_Parser<A>::findFDE(_addressSpace, pc, sects.dwarf_section,
1712 sects.dwarf_section_length,
1713 cachedFDE, &fdeInfo, &cieInfo);
1786 foundFDE = CFI_Parser<A>::template findFDE<R>(
1787 _addressSpace, pc, sects.dwarf_section, sects.dwarf_section_length,
1788 cachedFDE, &fdeInfo, &cieInfo);
17141789 foundInCache = foundFDE;
17151790 }
17161791 }
17171792 if (!foundFDE) {
17181793 // Still not found, do full scan of __eh_frame section.
1719 foundFDE = CFI_Parser<A>::findFDE(_addressSpace, pc, sects.dwarf_section,
1720 sects.dwarf_section_length, 0,
1721 &fdeInfo, &cieInfo);
1794 foundFDE = CFI_Parser<A>::template findFDE<R>(
1795 _addressSpace, pc, sects.dwarf_section, sects.dwarf_section_length, 0,
1796 &fdeInfo, &cieInfo);
17221797 }
17231798 if (foundFDE) {
17241799 if (getInfoFromFdeCie(fdeInfo, cieInfo, pc, sects.dso_base)) {
......@@ -1742,8 +1817,8 @@ bool UnwindCursor<A, R>::getInfoFromDwarfSection(pint_t pc,
17421817
17431818#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
17441819template <typename A, typename R>
1745bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection(pint_t pc,
1746 const UnwindInfoSections &sects) {
1820bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection(
1821 typename R::link_hardened_reg_arg_t pc, const UnwindInfoSections &sects) {
17471822 const bool log = false;
17481823 if (log)
17491824 fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX, mh=0x%llX)\n",
......@@ -1974,6 +2049,16 @@ bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection(pint_t pc,
19742049 personalityIndex * sizeof(uint32_t));
19752050 pint_t personalityPointer = sects.dso_base + (pint_t)personalityDelta;
19762051 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
19772062 if (log)
19782063 fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX), "
19792064 "personalityDelta=0x%08X, personality=0x%08llX\n",
......@@ -1987,7 +2072,11 @@ bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection(pint_t pc,
19872072 _info.start_ip = funcStart;
19882073 _info.end_ip = funcEnd;
19892074 _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));
19912080 _info.gp = 0;
19922081 _info.flags = 0;
19932082 _info.format = encoding;
......@@ -2640,11 +2729,19 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
26402729 _isSigReturn = false;
26412730#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
26442734#if defined(_LIBUNWIND_ARM_EHABI)
26452735 // Remove the thumb bit so the IP represents the actual instruction address.
26462736 // 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;
26482745#endif
26492746
26502747 // Exit early if at the top of the stack.
......@@ -2679,7 +2776,7 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
26792776
26802777 // Ask address space object to find unwind sections for this pc.
26812778 UnwindInfoSections sects;
2682 if (_addressSpace.findUnwindSections(pc, sects)) {
2779 if (_addressSpace.template findUnwindSections<R>(pc, sects)) {
26832780#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
26842781 // If there is a compact unwind encoding table, look there first.
26852782 if (sects.compact_unwind_section != 0) {
......@@ -2735,8 +2832,8 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
27352832#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
27362833 // There is no static unwind info for this pc. Look to see if an FDE was
27372834 // dynamically registered for it.
2738 pint_t cachedFDE = DwarfFDECache<A>::findFDE(DwarfFDECache<A>::kSearchAll,
2739 pc);
2835 pint_t cachedFDE =
2836 DwarfFDECache<A>::template findFDE<R>(DwarfFDECache<A>::kSearchAll, pc);
27402837 if (cachedFDE != 0) {
27412838 typename CFI_Parser<A>::FDE_Info fdeInfo;
27422839 typename CFI_Parser<A>::CIE_Info cieInfo;
......@@ -2748,7 +2845,7 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
27482845 // Lastly, ask AddressSpace object about platform specific ways to locate
27492846 // other FDEs.
27502847 pint_t fde;
2751 if (_addressSpace.findOtherFDE(pc, fde)) {
2848 if (_addressSpace.template findOtherFDE<R>(pc, fde)) {
27522849 typename CFI_Parser<A>::FDE_Info fdeInfo;
27532850 typename CFI_Parser<A>::CIE_Info cieInfo;
27542851 if (!CFI_Parser<A>::decodeFDE(_addressSpace, fde, &fdeInfo, &cieInfo)) {
......@@ -2772,6 +2869,21 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
27722869
27732870#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && \
27742871 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
27752887template <typename A, typename R>
27762888bool UnwindCursor<A, R>::setInfoForSigReturn(Registers_arm64 &) {
27772889 // Look for the sigreturn trampoline. The trampoline's body is two
......@@ -2796,7 +2908,7 @@ bool UnwindCursor<A, R>::setInfoForSigReturn(Registers_arm64 &) {
27962908 return false;
27972909 auto *instructions = reinterpret_cast<const uint32_t *>(pc);
27982910 // 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)
28002912 return false;
28012913
28022914 _info = {};
......@@ -3188,16 +3300,22 @@ template <typename A, typename R> int UnwindCursor<A, R>::step(bool stage2) {
31883300template <typename A, typename R>
31893301void UnwindCursor<A, R>::getInfo(unw_proc_info_t *info) {
31903302 if (_unwindInfoMissing)
3191 memset(info, 0, sizeof(*info));
3303 memset(static_cast<void *>(info), 0, sizeof(*info));
31923304 else
31933305 *info = _info;
31943306}
31953307
31963308template <typename A, typename R>
31973309bool UnwindCursor<A, R>::getFunctionName(char *buf, size_t bufLen,
3198 unw_word_t *offset) {
3199 return _addressSpace.findFunctionName((pint_t)this->getReg(UNW_REG_IP),
3200 buf, bufLen, offset);
3310 unw_word_t *offset) {
3311#if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING)
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);
32013319}
32023320
32033321#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN)
lib/libunwind/src/UnwindLevel1.c+46-17
......@@ -48,16 +48,15 @@
4848// avoided when invoking the `jumpto()` function. To do this, we use inline
4949// assemblies to "goto" the `jumpto()` for these architectures.
5050#if !defined(_LIBUNWIND_USE_CET) && !defined(_LIBUNWIND_USE_GCS)
51#define __unw_phase2_resume(cursor, fn) \
51#define __unw_phase2_resume(cursor, payload) \
5252 do { \
53 (void)fn; \
54 __unw_resume((cursor)); \
53 __unw_resume_with_frames_walked((cursor), (payload)); \
5554 } while (0)
5655#elif defined(_LIBUNWIND_TARGET_I386)
5756#define __shstk_step_size (4)
58#define __unw_phase2_resume(cursor, fn) \
57#define __unw_phase2_resume(cursor, payload) \
5958 do { \
60 _LIBUNWIND_POP_SHSTK_SSP((fn)); \
59 _LIBUNWIND_POP_SHSTK_SSP((payload)); \
6160 void *shstkRegContext = __libunwind_shstk_get_registers((cursor)); \
6261 void *shstkJumpAddress = __libunwind_shstk_get_jump_target(); \
6362 __asm__ volatile("push %%edi\n\t" \
......@@ -67,9 +66,9 @@
6766 } while (0)
6867#elif defined(_LIBUNWIND_TARGET_X86_64)
6968#define __shstk_step_size (8)
70#define __unw_phase2_resume(cursor, fn) \
69#define __unw_phase2_resume(cursor, payload) \
7170 do { \
72 _LIBUNWIND_POP_SHSTK_SSP((fn)); \
71 _LIBUNWIND_POP_SHSTK_SSP((payload)); \
7372 void *shstkRegContext = __libunwind_shstk_get_registers((cursor)); \
7473 void *shstkJumpAddress = __libunwind_shstk_get_jump_target(); \
7574 __asm__ volatile("jmpq *%%rdx\n\t" ::"D"(shstkRegContext), \
......@@ -77,19 +76,37 @@
7776 } while (0)
7877#elif defined(_LIBUNWIND_TARGET_AARCH64)
7978#define __shstk_step_size (8)
80#define __unw_phase2_resume(cursor, fn) \
79#define __unw_phase2_resume(cursor, payload) \
8180 do { \
82 _LIBUNWIND_POP_SHSTK_SSP((fn)); \
81 _LIBUNWIND_POP_SHSTK_SSP((payload)); \
8382 void *shstkRegContext = __libunwind_shstk_get_registers((cursor)); \
8483 void *shstkJumpAddress = __libunwind_shstk_get_jump_target(); \
8584 __asm__ volatile("mov x0, %0\n\t" \
85 "mov x1, #0\n\t" \
8686 "br %1\n\t" \
8787 : \
8888 : "r"(shstkRegContext), "r"(shstkJumpAddress) \
89 : "x0"); \
89 : "x0", "x1"); \
9090 } while (0)
9191#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
93110static _Unwind_Reason_Code
94111unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) {
95112 __unw_init_local(cursor, uc);
......@@ -147,8 +164,7 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except
147164 // If there is a personality routine, ask it if it will want to stop at
148165 // this frame.
149166 if (frameInfo.handler != 0) {
150 _Unwind_Personality_Fn p =
151 (_Unwind_Personality_Fn)(uintptr_t)(frameInfo.handler);
167 _Unwind_Personality_Fn p = get_handler_function(&frameInfo);
152168 _LIBUNWIND_TRACE_UNWINDING(
153169 "unwind_phase1(ex_obj=%p): calling personality function %p",
154170 (void *)exception_object, (void *)(uintptr_t)p);
......@@ -184,11 +200,12 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except
184200 }
185201 return _URC_NO_REASON;
186202}
187extern int __unw_step_stage2(unw_cursor_t *);
188203
189204#if defined(_LIBUNWIND_USE_GCS)
190205// Enable the GCS target feature to permit gcspop instructions to be used.
191206__attribute__((target("+gcs")))
207#else
208_LIBUNWIND_TRACE_NO_INLINE
192209#endif
193210static _Unwind_Reason_Code
194211unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor,
......@@ -276,8 +293,7 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor,
276293 ++framesWalked;
277294 // If there is a personality routine, tell it we are unwinding.
278295 if (frameInfo.handler != 0) {
279 _Unwind_Personality_Fn p =
280 (_Unwind_Personality_Fn)(uintptr_t)(frameInfo.handler);
296 _Unwind_Personality_Fn p = get_handler_function(&frameInfo);
281297 _Unwind_Action action = _UA_CLEANUP_PHASE;
282298 if (sp == exception_object->private_2) {
283299 // 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,
334350#if defined(_LIBUNWIND_USE_GCS)
335351// Enable the GCS target feature to permit gcspop instructions to be used.
336352__attribute__((target("+gcs")))
353#else
354_LIBUNWIND_TRACE_NO_INLINE
337355#endif
338356static _Unwind_Reason_Code
339357unwind_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,
394412 ++framesWalked;
395413 // If there is a personality routine, tell it we are unwinding.
396414 if (frameInfo.handler != 0) {
397 _Unwind_Personality_Fn p =
398 (_Unwind_Personality_Fn)(intptr_t)(frameInfo.handler);
415 _Unwind_Personality_Fn p = get_handler_function(&frameInfo);
399416 _LIBUNWIND_TRACE_UNWINDING(
400417 "unwind_phase2_forced(ex_obj=%p): calling personality function %p",
401418 (void *)exception_object, (void *)(uintptr_t)p);
......@@ -597,6 +614,18 @@ _LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) {
597614 unw_cursor_t *cursor = (unw_cursor_t *)context;
598615 unw_word_t result;
599616 __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
600629 _LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => 0x%" PRIxPTR,
601630 (void *)context, result);
602631 return (uintptr_t)result;
lib/libunwind/src/UnwindRegistersRestore.S+46-5
......@@ -6,6 +6,8 @@
66//
77//===----------------------------------------------------------------------===//
88
9#if !defined(__wasm__)
10
911#include "assembly.h"
1012
1113#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 @@
1618
1719#if defined(_AIX)
1820 .toc
21#elif defined(__aarch64__) && defined(__ELF__) && defined(_LIBUNWIND_EXECUTE_ONLY_CODE)
22 .section .text,"axy",@progbits,unique,0
1923#else
2024 .text
2125#endif
2226
23#if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__wasm__)
27#if !defined(__USING_SJLJ_EXCEPTIONS__)
2428
2529#if defined(__i386__)
30.att_syntax
31
2632DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_x86_jumpto)
2733#
2834# extern "C" void __libunwind_Registers_x86_jumpto(Registers_x86 *);
......@@ -67,6 +73,7 @@ DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_x86_jumpto)
6773 # skip gs
6874
6975#elif defined(__x86_64__) && !defined(__arm64ec__)
76.att_syntax
7077
7178DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_x86_64_jumpto)
7279#
......@@ -629,18 +636,35 @@ Lnovec:
629636
630637#elif defined(__aarch64__)
631638
639#ifndef __has_feature
640#define __has_feature(__feature) 0
641#endif
642
632643#if defined(__ARM_FEATURE_GCS_DEFAULT)
633644.arch_extension gcs
634645#endif
635646
636647//
637// extern "C" void __libunwind_Registers_arm64_jumpto(Registers_arm64 *);
648// extern "C" void __libunwind_Registers_arm64_jumpto(Registers_arm64 *, unsigned);
638649//
639650// On entry:
640651// thread_state pointer is in x0
652// walked_frames counter is in x1
641653//
642654 .p2align 2
643655DEFINE_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
644668 // skip restore of x0,x1 for now
645669 ldp x2, x3, [x0, #0x010]
646670 ldp x4, x5, [x0, #0x020]
......@@ -657,7 +681,7 @@ DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_arm64_jumpto)
657681 ldp x24,x25, [x0, #0x0C0]
658682 ldp x26,x27, [x0, #0x0D0]
659683 ldp x28,x29, [x0, #0x0E0]
660 ldr x30, [x0, #0x100] // restore pc into lr
684
661685#if defined(__ARM_FP) && __ARM_FP != 0
662686 ldp d0, d1, [x0, #0x110]
663687 ldp d2, d3, [x0, #0x120]
......@@ -681,7 +705,18 @@ DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_arm64_jumpto)
681705 // context struct, because it is allocated on the stack, and an exception
682706 // could clobber the de-allocated portion of the stack after sp has been
683707 // 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
685720 ldp x0, x1, [x0, #0x000] // restore x0,x1
686721 mov sp,x16 // restore sp
687722#if defined(__ARM_FEATURE_GCS_DEFAULT)
......@@ -694,7 +729,12 @@ DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_arm64_jumpto)
694729 gcspushm x30
695730Lnogcs:
696731#endif
732
733#if __has_feature(ptrauth_calls)
734 retab
735#else
697736 ret x30 // jump to pc
737#endif
698738
699739#elif defined(__arm__) && !defined(__APPLE__)
700740
......@@ -1253,7 +1293,8 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind19Registers_loongarch6jumptoEv)
12531293
12541294#endif
12551295
1256#endif /* !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__wasm__) */
1296#endif /* !defined(__USING_SJLJ_EXCEPTIONS__) */
12571297
12581298NO_EXEC_STACK_DIRECTIVE
12591299
1300#endif /* !defined(__wasm__) */
lib/libunwind/src/UnwindRegistersSave.S+86-2
......@@ -6,6 +6,8 @@
66//
77//===----------------------------------------------------------------------===//
88
9#if !defined(__wasm__)
10
911#include "assembly.h"
1012
1113#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 @@
1618
1719#if defined(_AIX)
1820 .toc
21#elif defined(__aarch64__) && defined(__ELF__) && defined(_LIBUNWIND_EXECUTE_ONLY_CODE)
22 .section .text,"axy",@progbits,unique,0
1923#else
2024 .text
2125#endif
2226
23#if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__wasm__)
27#if !defined(__USING_SJLJ_EXCEPTIONS__)
2428
2529#if defined(__i386__)
30.att_syntax
2631
2732#
2833# extern int __unw_getcontext(unw_context_t* thread_state)
......@@ -107,6 +112,7 @@ DEFINE_LIBUNWIND_FUNCTION("#__unw_getcontext")
107112 .text
108113
109114#elif defined(__x86_64__)
115.att_syntax
110116
111117#
112118# extern int __unw_getcontext(unw_context_t* thread_state)
......@@ -759,6 +765,10 @@ LnoR2Fix:
759765
760766#elif defined(__aarch64__)
761767
768#ifndef __has_feature
769#define __has_feature(__feature) 0
770#endif
771
762772//
763773// extern int __unw_getcontext(unw_context_t* thread_state)
764774//
......@@ -767,6 +777,11 @@ LnoR2Fix:
767777//
768778 .p2align 2
769779DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
780
781#if __has_feature(ptrauth_calls)
782 pacibsp
783#endif
784
770785 stp x0, x1, [x0, #0x000]
771786 stp x2, x3, [x0, #0x010]
772787 stp x4, x5, [x0, #0x020]
......@@ -807,7 +822,74 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
807822 str d31, [x0, #0x208]
808823#endif
809824 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
810891 ret
892#endif
811893
812894#elif defined(__arm__) && !defined(__APPLE__)
813895
......@@ -1232,6 +1314,8 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
12321314 WEAK_ALIAS(__unw_getcontext, unw_getcontext)
12331315#endif
12341316
1235#endif /* !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__wasm__) */
1317#endif /* !defined(__USING_SJLJ_EXCEPTIONS__) */
12361318
12371319NO_EXEC_STACK_DIRECTIVE
1320
1321#endif /* !defined(__wasm__) */
lib/libunwind/src/assembly.h+5-1
......@@ -15,7 +15,7 @@
1515#ifndef UNWIND_ASSEMBLY_H
1616#define UNWIND_ASSEMBLY_H
1717
18#if defined(__linux__) && defined(__CET__)
18#if defined(__CET__)
1919#include <cet.h>
2020#define _LIBUNWIND_CET_ENDBR _CET_ENDBR
2121#else
......@@ -132,6 +132,10 @@
132132
133133#if defined(__APPLE__)
134134
135#if defined(__aarch64__) || defined(__arm64__) || defined(__arm64e__)
136#define _LIBUNWIND_TRACE_RET_INJECT 1
137#endif
138
135139#define SYMBOL_IS_FUNC(name)
136140#define HIDDEN_SYMBOL(name) .private_extern name
137141#if defined(_LIBUNWIND_HIDE_SYMBOLS)
lib/libunwind/src/config.h+9
......@@ -28,6 +28,9 @@
2828 #define _LIBUNWIND_SUPPORT_COMPACT_UNWIND 1
2929 #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1
3030 #endif
31 #if defined(__aarch64__) || defined(__arm64__) || defined(__arm64e__)
32 #define _LIBUNWIND_TRACE_RET_INJECT 1
33 #endif
3134#elif defined(_WIN32)
3235 #ifdef __SEH__
3336 #define _LIBUNWIND_SUPPORT_SEH_UNWIND 1
......@@ -61,6 +64,12 @@
6164 #endif
6265#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
6473#if defined(_LIBUNWIND_HIDE_SYMBOLS)
6574 // The CMake file passes -fvisibility=hidden to control ELF/Mach-O visibility.
6675 #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,
3131 _Unwind_Personality_Fn);
3232#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
3486// Pointer encodings documented at:
3587// 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(
206258 return continueUnwind(exceptionObject, context);
207259
208260 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);
210263 uintptr_t pcOffset = pc - funcStart;
211264
212265 // Parse LSDA header.
......@@ -225,11 +278,14 @@ COMPILER_RT_ABI _Unwind_Reason_Code __gcc_personality_v0(
225278 const uint8_t *callSiteTableEnd = callSiteTableStart + callSiteTableLength;
226279 const uint8_t *p = callSiteTableStart;
227280 while (p < callSiteTableEnd) {
228 uintptr_t start = readEncodedPointer(&p, callSiteEncoding);
229 size_t length = readEncodedPointer(&p, callSiteEncoding);
230 size_t landingPad = readEncodedPointer(&p, callSiteEncoding);
281 uintptr_t __ptrauth_gcc_personality_start start =
282 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);
231287 readULEB128(&p); // action value not used for C code
232 if (landingPad == 0)
288 if (landingPadOffset == 0)
233289 continue; // no landing pad for this entry
234290 if ((start <= pcOffset) && (pcOffset < (start + length))) {
235291 // Found landing pad for the PC.
......@@ -239,7 +295,24 @@ COMPILER_RT_ABI _Unwind_Reason_Code __gcc_personality_v0(
239295 _Unwind_SetGR(context, __builtin_eh_return_data_regno(0),
240296 (uintptr_t)exceptionObject);
241297 _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
243316 return _URC_INSTALL_CONTEXT;
244317 }
245318 }
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,
118118 typedef LocalAddressSpace::pint_t pint_t;
119119 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
120120 if (co->validReg(regNum)) {
121 co->setReg(regNum, (pint_t)value);
122121 // special case altering IP to re-find info (being called by personality
123122 // function)
124123 if (regNum == UNW_REG_IP) {
125124 unw_proc_info_t info;
126125 // First, get the FDE for the old location and then update it.
127126 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
129170 // If the original call expects stack adjustment, perform this now.
130171 // Normal frame unwinding would have included the offset already in the
131172 // CFA computation.
......@@ -133,7 +174,11 @@ _LIBUNWIND_HIDDEN int __unw_set_reg(unw_cursor_t *cursor, unw_regnum_t regNum,
133174 // this should actually be - info.gp. LLVM doesn't currently support
134175 // any such platforms and Clang doesn't export a macro for them.
135176 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);
137182 }
138183 return UNW_ESUCCESS;
139184 }
......@@ -205,7 +250,27 @@ _LIBUNWIND_HIDDEN int __unw_get_proc_info(unw_cursor_t *cursor,
205250}
206251_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).
209274_LIBUNWIND_HIDDEN int __unw_resume(unw_cursor_t *cursor) {
210275 _LIBUNWIND_TRACE_API("__unw_resume(cursor=%p)", static_cast<void *>(cursor));
211276#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) {
347412}
348413
349414#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
350450#endif // !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__wasm__)
351451
352452#ifdef __APPLE__
lib/libunwind/src/libunwind_ext.h+7-1
......@@ -26,11 +26,16 @@ extern "C" {
2626extern int __unw_getcontext(unw_context_t *);
2727extern int __unw_init_local(unw_cursor_t *, unw_context_t *);
2828extern int __unw_step(unw_cursor_t *);
29extern int __unw_step_stage2(unw_cursor_t *);
2930extern int __unw_get_reg(unw_cursor_t *, unw_regnum_t, unw_word_t *);
3031extern int __unw_get_fpreg(unw_cursor_t *, unw_regnum_t, unw_fpreg_t *);
3132extern int __unw_set_reg(unw_cursor_t *, unw_regnum_t, unw_word_t);
3233extern 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
3540#ifdef __arm__
3641/* 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 *);
4247extern int __unw_is_fpreg(unw_cursor_t *, unw_regnum_t);
4348extern int __unw_is_signal_frame(unw_cursor_t *);
4449extern int __unw_get_proc_name(unw_cursor_t *, char *, size_t, unw_word_t *);
50extern const char *__unw_strerror(int);
4551
4652#if defined(_AIX)
4753extern uintptr_t __unw_get_data_rel_base(unw_cursor_t *);
lib/libunwind/src/shadow_stack_unwind.h+2-2
......@@ -12,8 +12,8 @@
1212
1313#include "libunwind.h"
1414
15// Currently, CET is implemented on Linux x86 platforms.
16#if defined(_LIBUNWIND_TARGET_LINUX) && defined(__CET__) && defined(__SHSTK__)
15// Currently, CET is implemented on some ELF x86 platforms.
16#if defined(__CET__) && defined(__SHSTK__)
1717#define _LIBUNWIND_USE_CET 1
1818#endif
1919