22
22
#include " private_typeinfo.h"
23
23
#include " unwind.h"
24
24
25
+ #if __has_include(<ptrauth.h>)
26
+ #include < ptrauth.h>
27
+ #endif
28
+
29
+ #include " libunwind.h"
30
+
25
31
// TODO: This is a temporary workaround for libc++abi to recognize that it's being
26
32
// built against LLVM's libunwind. LLVM's libunwind started reporting _LIBUNWIND_VERSION
27
33
// 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)
527
533
namespace
528
534
{
529
535
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
+
530
543
struct scan_results
531
544
{
532
545
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
536
549
void * adjustedPtr; // Used in cxa_exception.cpp
537
550
_Unwind_Reason_Code reason; // One of _URC_FATAL_PHASE1_ERROR,
538
551
// _URC_FATAL_PHASE2_ERROR,
@@ -541,7 +554,33 @@ struct scan_results
541
554
};
542
555
543
556
} // unnamed namespace
557
+ }
544
558
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" {
545
584
static
546
585
void
547
586
set_registers (_Unwind_Exception* unwind_exception, _Unwind_Context* context,
@@ -557,7 +596,22 @@ set_registers(_Unwind_Exception* unwind_exception, _Unwind_Context* context,
557
596
reinterpret_cast <uintptr_t >(unwind_exception));
558
597
_Unwind_SetGR (context, __builtin_eh_return_data_regno (1 ),
559
598
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 ,
605
+ ptrauth_string_discriminator (_LIBCXXABI_PTRAUTH_SCANRESULT_LANDINGPAD_DISC));
606
+ unw_word_t newIP = (unw_word_t )ptrauth_auth_and_resign (*(void **)&results.landingPad ,
607
+ _LIBCXXABI_PTRAUTH_KEY,
608
+ existingDiscriminator,
609
+ ptrauth_key_return_address,
610
+ stack_pointer);
611
+ _Unwind_SetIP (context, newIP);
612
+ #else
560
613
_Unwind_SetIP (context, results.landingPad );
614
+ #endif
561
615
}
562
616
563
617
/*
@@ -691,12 +745,12 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
691
745
// The call sites are ordered in increasing value of start
692
746
uintptr_t start = readEncodedPointer (&callSitePtr, callSiteEncoding);
693
747
uintptr_t length = readEncodedPointer (&callSitePtr, callSiteEncoding);
694
- uintptr_t landingPad = readEncodedPointer (&callSitePtr, callSiteEncoding);
748
+ landing_pad_t landingPad = readEncodedPointer (&callSitePtr, callSiteEncoding);
695
749
uintptr_t actionEntry = readULEB128 (&callSitePtr);
696
750
if ((start <= ipOffset) && (ipOffset < (start + length)))
697
751
#else // __USING_SJLJ_EXCEPTIONS__ || __WASM_EXCEPTIONS__
698
752
// ip is 1-based index into this table
699
- uintptr_t landingPad = readULEB128 (&callSitePtr);
753
+ landing_pad_t landingPad = readULEB128 (&callSitePtr);
700
754
uintptr_t actionEntry = readULEB128 (&callSitePtr);
701
755
if (--ip == 0 )
702
756
#endif // __USING_SJLJ_EXCEPTIONS__ || __WASM_EXCEPTIONS__
@@ -935,8 +989,7 @@ __gxx_personality_v0
935
989
results.ttypeIndex = exception_header->handlerSwitchValue ;
936
990
results.actionRecord = exception_header->actionRecord ;
937
991
results.languageSpecificData = exception_header->languageSpecificData ;
938
- results.landingPad =
939
- reinterpret_cast <uintptr_t >(exception_header->catchTemp );
992
+ set_landing_pad_as_ptr (results, exception_header->catchTemp );
940
993
results.adjustedPtr = exception_header->adjustedPtr ;
941
994
942
995
// Jump to the handler.
@@ -970,7 +1023,7 @@ __gxx_personality_v0
970
1023
exc->handlerSwitchValue = static_cast <int >(results.ttypeIndex );
971
1024
exc->actionRecord = results.actionRecord ;
972
1025
exc->languageSpecificData = results.languageSpecificData ;
973
- exc->catchTemp = reinterpret_cast < void *> (results. landingPad );
1026
+ exc->catchTemp = get_landing_pad_as_ptr (results);
974
1027
exc->adjustedPtr = results.adjustedPtr ;
975
1028
#ifdef __WASM_EXCEPTIONS__
976
1029
// Wasm only uses a single phase (_UA_SEARCH_PHASE), so save the
0 commit comments