2222#include " private_typeinfo.h"
2323#include " unwind.h"
2424
25+ #if __has_include(<ptrauth.h>)
26+ # include < ptrauth.h>
27+ #endif
28+
29+ #include " libunwind.h"
30+
2531// TODO: This is a temporary workaround for libc++abi to recognize that it's being
2632// built against LLVM's libunwind. LLVM's libunwind started reporting _LIBUNWIND_VERSION
2733// in LLVM 15 -- we can remove this workaround after shipping LLVM 17. Once we remove
@@ -527,12 +533,19 @@ get_thrown_object_ptr(_Unwind_Exception* unwind_exception)
527533namespace
528534{
529535
536+ #define _LIBCXXABI_PTRAUTH_KEY ptrauth_key_process_dependent_code
537+ typedef const uint8_t * _LIBCXXABI_PTRAUTH_PDD (" scan_results::languageSpecificData" ) lsd_ptr_t;
538+ typedef const uint8_t * _LIBCXXABI_PTRAUTH_PDD (" scan_results::actionRecord" ) action_ptr_t;
539+ #define _LIBCXXABI_PTRAUTH_SCANRESULT_LANDINGPAD_DISC " scan_results::landingPad"
540+ typedef uintptr_t _LIBCXXABI_PTRAUTH_RI_PDD (_LIBCXXABI_PTRAUTH_SCANRESULT_LANDINGPAD_DISC) landing_pad_t;
541+ typedef void * _LIBCXXABI_PTRAUTH_PDD (_LIBCXXABI_PTRAUTH_SCANRESULT_LANDINGPAD_DISC) landing_pad_ptr_t;
542+
530543struct scan_results
531544{
532545 int64_t ttypeIndex; // > 0 catch handler, < 0 exception spec handler, == 0 a cleanup
533- const uint8_t * actionRecord; // Currently unused. Retained to ease future maintenance.
534- const uint8_t * languageSpecificData; // Needed only for __cxa_call_unexpected
535- uintptr_t landingPad; // null -> nothing found, else something found
546+ action_ptr_t actionRecord; // Currently unused. Retained to ease future maintenance.
547+ lsd_ptr_t languageSpecificData; // Needed only for __cxa_call_unexpected
548+ landing_pad_t landingPad; // null -> nothing found, else something found
536549 void * adjustedPtr; // Used in cxa_exception.cpp
537550 _Unwind_Reason_Code reason; // One of _URC_FATAL_PHASE1_ERROR,
538551 // _URC_FATAL_PHASE2_ERROR,
@@ -541,7 +554,33 @@ struct scan_results
541554};
542555
543556} // unnamed namespace
557+ }
544558
559+ namespace {
560+ // The logical model for casting authenticated function pointers makes
561+ // it impossible to directly cast them without breaking the authentication,
562+ // as a result we need this pair of helpers.
563+ template <typename PtrType>
564+ void set_landing_pad_as_ptr (scan_results& results, const PtrType& out) {
565+ union {
566+ landing_pad_t * as_landing_pad;
567+ landing_pad_ptr_t * as_pointer;
568+ } u;
569+ u.as_landing_pad = &results.landingPad ;
570+ *u.as_pointer = out;
571+ }
572+
573+ static const landing_pad_ptr_t & get_landing_pad_as_ptr (const scan_results& results) {
574+ union {
575+ const landing_pad_t * as_landing_pad;
576+ const landing_pad_ptr_t * as_pointer;
577+ } u;
578+ u.as_landing_pad = &results.landingPad ;
579+ return *u.as_pointer ;
580+ }
581+ } // unnamed namespace
582+
583+ extern " C" {
545584static
546585void
547586set_registers (_Unwind_Exception* unwind_exception, _Unwind_Context* context,
@@ -557,7 +596,19 @@ set_registers(_Unwind_Exception* unwind_exception, _Unwind_Context* context,
557596 reinterpret_cast <uintptr_t >(unwind_exception));
558597 _Unwind_SetGR (context, __builtin_eh_return_data_regno (1 ),
559598 static_cast <uintptr_t >(results.ttypeIndex ));
599+ #if defined(__APPLE__) && __has_feature(ptrauth_qualifier)
600+ auto stack_pointer = _Unwind_GetGR (context, UNW_REG_SP);
601+ // We manually re-sign the IP as the __ptrauth qualifiers cannot
602+ // express the required relationship with the destination address
603+ const auto existingDiscriminator = ptrauth_blend_discriminator (
604+ &results.landingPad , ptrauth_string_discriminator (_LIBCXXABI_PTRAUTH_SCANRESULT_LANDINGPAD_DISC));
605+ unw_word_t newIP =
606+ (unw_word_t )ptrauth_auth_and_resign (*(void **)&results.landingPad , _LIBCXXABI_PTRAUTH_KEY, existingDiscriminator,
607+ ptrauth_key_return_address, stack_pointer);
608+ _Unwind_SetIP (context, newIP);
609+ #else
560610 _Unwind_SetIP (context, results.landingPad );
611+ #endif
561612}
562613
563614/*
@@ -691,12 +742,12 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
691742 // The call sites are ordered in increasing value of start
692743 uintptr_t start = readEncodedPointer (&callSitePtr, callSiteEncoding);
693744 uintptr_t length = readEncodedPointer (&callSitePtr, callSiteEncoding);
694- uintptr_t landingPad = readEncodedPointer (&callSitePtr, callSiteEncoding);
745+ landing_pad_t landingPad = readEncodedPointer (&callSitePtr, callSiteEncoding);
695746 uintptr_t actionEntry = readULEB128 (&callSitePtr);
696747 if ((start <= ipOffset) && (ipOffset < (start + length)))
697748#else // __USING_SJLJ_EXCEPTIONS__ || __WASM_EXCEPTIONS__
698749 // ip is 1-based index into this table
699- uintptr_t landingPad = readULEB128 (&callSitePtr);
750+ landing_pad_t landingPad = readULEB128 (&callSitePtr);
700751 uintptr_t actionEntry = readULEB128 (&callSitePtr);
701752 if (--ip == 0 )
702753#endif // __USING_SJLJ_EXCEPTIONS__ || __WASM_EXCEPTIONS__
@@ -935,8 +986,7 @@ __gxx_personality_v0
935986 results.ttypeIndex = exception_header->handlerSwitchValue ;
936987 results.actionRecord = exception_header->actionRecord ;
937988 results.languageSpecificData = exception_header->languageSpecificData ;
938- results.landingPad =
939- reinterpret_cast <uintptr_t >(exception_header->catchTemp );
989+ set_landing_pad_as_ptr (results, exception_header->catchTemp );
940990 results.adjustedPtr = exception_header->adjustedPtr ;
941991
942992 // Jump to the handler.
@@ -970,7 +1020,7 @@ __gxx_personality_v0
9701020 exc->handlerSwitchValue = static_cast <int >(results.ttypeIndex );
9711021 exc->actionRecord = results.actionRecord ;
9721022 exc->languageSpecificData = results.languageSpecificData ;
973- exc->catchTemp = reinterpret_cast < void *> (results. landingPad );
1023+ exc->catchTemp = get_landing_pad_as_ptr (results);
9741024 exc->adjustedPtr = results.adjustedPtr ;
9751025#ifdef __WASM_EXCEPTIONS__
9761026 // Wasm only uses a single phase (_UA_SEARCH_PHASE), so save the
0 commit comments