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,19 @@ 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 , 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
560
610
_Unwind_SetIP (context, results.landingPad );
611
+ #endif
561
612
}
562
613
563
614
/*
@@ -691,12 +742,12 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
691
742
// The call sites are ordered in increasing value of start
692
743
uintptr_t start = readEncodedPointer (&callSitePtr, callSiteEncoding);
693
744
uintptr_t length = readEncodedPointer (&callSitePtr, callSiteEncoding);
694
- uintptr_t landingPad = readEncodedPointer (&callSitePtr, callSiteEncoding);
745
+ landing_pad_t landingPad = readEncodedPointer (&callSitePtr, callSiteEncoding);
695
746
uintptr_t actionEntry = readULEB128 (&callSitePtr);
696
747
if ((start <= ipOffset) && (ipOffset < (start + length)))
697
748
#else // __USING_SJLJ_EXCEPTIONS__ || __WASM_EXCEPTIONS__
698
749
// ip is 1-based index into this table
699
- uintptr_t landingPad = readULEB128 (&callSitePtr);
750
+ landing_pad_t landingPad = readULEB128 (&callSitePtr);
700
751
uintptr_t actionEntry = readULEB128 (&callSitePtr);
701
752
if (--ip == 0 )
702
753
#endif // __USING_SJLJ_EXCEPTIONS__ || __WASM_EXCEPTIONS__
@@ -935,8 +986,7 @@ __gxx_personality_v0
935
986
results.ttypeIndex = exception_header->handlerSwitchValue ;
936
987
results.actionRecord = exception_header->actionRecord ;
937
988
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 );
940
990
results.adjustedPtr = exception_header->adjustedPtr ;
941
991
942
992
// Jump to the handler.
@@ -970,7 +1020,7 @@ __gxx_personality_v0
970
1020
exc->handlerSwitchValue = static_cast <int >(results.ttypeIndex );
971
1021
exc->actionRecord = results.actionRecord ;
972
1022
exc->languageSpecificData = results.languageSpecificData ;
973
- exc->catchTemp = reinterpret_cast < void *> (results. landingPad );
1023
+ exc->catchTemp = get_landing_pad_as_ptr (results);
974
1024
exc->adjustedPtr = results.adjustedPtr ;
975
1025
#ifdef __WASM_EXCEPTIONS__
976
1026
// Wasm only uses a single phase (_UA_SEARCH_PHASE), so save the
0 commit comments