aboutsummaryrefslogtreecommitdiff
path: root/libcxxabi/src
diff options
context:
space:
mode:
Diffstat (limited to 'libcxxabi/src')
-rw-r--r--libcxxabi/src/cxa_exception.cpp4
-rw-r--r--libcxxabi/src/cxa_exception.h30
-rw-r--r--libcxxabi/src/cxa_personality.cpp129
3 files changed, 139 insertions, 24 deletions
diff --git a/libcxxabi/src/cxa_exception.cpp b/libcxxabi/src/cxa_exception.cpp
index 92901a8..73ba21c 100644
--- a/libcxxabi/src/cxa_exception.cpp
+++ b/libcxxabi/src/cxa_exception.cpp
@@ -192,7 +192,9 @@ void *__cxa_allocate_exception(size_t thrown_size) throw() {
std::terminate();
__cxa_exception *exception_header =
static_cast<__cxa_exception *>((void *)(raw_buffer + header_offset));
- ::memset(exception_header, 0, actual_size);
+ // We warn on memset to a non-trivially castable type. We might want to
+ // change that diagnostic to not fire on a trivially obvious zero fill.
+ ::memset(static_cast<void*>(exception_header), 0, actual_size);
return thrown_object_from_cxa_exception(exception_header);
}
diff --git a/libcxxabi/src/cxa_exception.h b/libcxxabi/src/cxa_exception.h
index aba08f2..fa4c4dc 100644
--- a/libcxxabi/src/cxa_exception.h
+++ b/libcxxabi/src/cxa_exception.h
@@ -47,10 +47,10 @@ struct _LIBCXXABI_HIDDEN __cxa_exception {
// In Wasm, a destructor returns its argument
void *(_LIBCXXABI_DTOR_FUNC *exceptionDestructor)(void *);
#else
- void (_LIBCXXABI_DTOR_FUNC *exceptionDestructor)(void *);
+ void (_LIBCXXABI_DTOR_FUNC *__ptrauth_cxxabi_exception_destructor exceptionDestructor)(void *);
#endif
- std::unexpected_handler unexpectedHandler;
- std::terminate_handler terminateHandler;
+ std::unexpected_handler __ptrauth_cxxabi_unexpected_handler unexpectedHandler;
+ std::terminate_handler __ptrauth_cxxabi_terminate_handler terminateHandler;
__cxa_exception *nextException;
@@ -61,10 +61,10 @@ struct _LIBCXXABI_HIDDEN __cxa_exception {
int propagationCount;
#else
int handlerSwitchValue;
- const unsigned char *actionRecord;
- const unsigned char *languageSpecificData;
- void *catchTemp;
- void *adjustedPtr;
+ const unsigned char *__ptrauth_cxxabi_action_record actionRecord;
+ const unsigned char *__ptrauth_cxxabi_lsd languageSpecificData;
+ void *__ptrauth_cxxabi_catch_temp catchTemp;
+ void *__ptrauth_cxxabi_adjusted_ptr adjustedPtr;
#endif
#if !defined(__LP64__) && !defined(_WIN64) && !defined(_LIBCXXABI_ARM_EHABI)
@@ -79,6 +79,8 @@ struct _LIBCXXABI_HIDDEN __cxa_exception {
// http://sourcery.mentor.com/archives/cxx-abi-dev/msg01924.html
// The layout of this structure MUST match the layout of __cxa_exception, with
// primaryException instead of referenceCount.
+// The pointer authentication schemas specified here must also match those of
+// the corresponding members in __cxa_exception.
struct _LIBCXXABI_HIDDEN __cxa_dependent_exception {
#if defined(__LP64__) || defined(_WIN64) || defined(_LIBCXXABI_ARM_EHABI)
void* reserve; // padding.
@@ -86,9 +88,9 @@ struct _LIBCXXABI_HIDDEN __cxa_dependent_exception {
#endif
std::type_info *exceptionType;
- void (_LIBCXXABI_DTOR_FUNC *exceptionDestructor)(void *);
- std::unexpected_handler unexpectedHandler;
- std::terminate_handler terminateHandler;
+ void (_LIBCXXABI_DTOR_FUNC *__ptrauth_cxxabi_exception_destructor exceptionDestructor)(void *);
+ std::unexpected_handler __ptrauth_cxxabi_unexpected_handler unexpectedHandler;
+ std::terminate_handler __ptrauth_cxxabi_terminate_handler terminateHandler;
__cxa_exception *nextException;
@@ -99,10 +101,10 @@ struct _LIBCXXABI_HIDDEN __cxa_dependent_exception {
int propagationCount;
#else
int handlerSwitchValue;
- const unsigned char *actionRecord;
- const unsigned char *languageSpecificData;
- void * catchTemp;
- void *adjustedPtr;
+ const unsigned char *__ptrauth_cxxabi_action_record actionRecord;
+ const unsigned char *__ptrauth_cxxabi_lsd languageSpecificData;
+ void *__ptrauth_cxxabi_catch_temp catchTemp;
+ void *__ptrauth_cxxabi_adjusted_ptr adjustedPtr;
#endif
#if !defined(__LP64__) && !defined(_WIN64) && !defined(_LIBCXXABI_ARM_EHABI)
diff --git a/libcxxabi/src/cxa_personality.cpp b/libcxxabi/src/cxa_personality.cpp
index 5f6e75c..b7eb0f2 100644
--- a/libcxxabi/src/cxa_personality.cpp
+++ b/libcxxabi/src/cxa_personality.cpp
@@ -20,7 +20,47 @@
#include "cxa_exception.h"
#include "cxa_handlers.h"
#include "private_typeinfo.h"
-#include "unwind.h"
+
+#if __has_feature(ptrauth_calls)
+
+// CXXABI depends on defintions in libunwind as pointer auth couples the
+// definitions
+# include "libunwind.h"
+
+// The actual value of the discriminators listed below is not important.
+// The derivation of the constants is only being included for the purpose
+// of maintaining a record of how they were originally produced.
+
+// ptrauth_string_discriminator("scan_results::languageSpecificData") == 0xE50D)
+# define __ptrauth_scan_results_lsd __ptrauth(ptrauth_key_process_dependent_code, 1, 0xE50D)
+
+// ptrauth_string_discriminator("scan_results::actionRecord") == 0x9823
+# define __ptrauth_scan_results_action_record __ptrauth(ptrauth_key_process_dependent_code, 1, 0x9823)
+
+// scan result is broken up as we have a manual re-sign that requires each component
+# define __ptrauth_scan_results_landingpad_key ptrauth_key_process_dependent_code
+// ptrauth_string_discriminator("scan_results::landingPad") == 0xD27C
+# define __ptrauth_scan_results_landingpad_disc 0xD27C
+# define __ptrauth_scan_results_landingpad \
+ __ptrauth(__ptrauth_scan_results_landingpad_key, 1, __ptrauth_scan_results_landingpad_disc)
+
+// `__ptrauth_restricted_intptr` is a feature of apple clang that predates
+// support for direct application of `__ptrauth` to integer types. This
+// guard is necessary to support compilation with those compiler.
+# if __has_extension(ptrauth_restricted_intptr_qualifier)
+# define __ptrauth_scan_results_landingpad_intptr \
+ __ptrauth_restricted_intptr(__ptrauth_scan_results_landingpad_key, 1, __ptrauth_scan_results_landingpad_disc)
+# else
+# define __ptrauth_scan_results_landingpad_intptr \
+ __ptrauth(__ptrauth_scan_results_landingpad_key, 1, __ptrauth_scan_results_landingpad_disc)
+# endif
+
+#else
+# define __ptrauth_scan_results_lsd
+# define __ptrauth_scan_results_action_record
+# define __ptrauth_scan_results_landingpad
+# define __ptrauth_scan_results_landingpad_intptr
+#endif
// TODO: This is a temporary workaround for libc++abi to recognize that it's being
// built against LLVM's libunwind. LLVM's libunwind started reporting _LIBUNWIND_VERSION
@@ -527,12 +567,17 @@ get_thrown_object_ptr(_Unwind_Exception* unwind_exception)
namespace
{
+typedef const uint8_t *__ptrauth_scan_results_lsd lsd_ptr_t;
+typedef const uint8_t *__ptrauth_scan_results_action_record action_ptr_t;
+typedef uintptr_t __ptrauth_scan_results_landingpad_intptr landing_pad_t;
+typedef void *__ptrauth_scan_results_landingpad landing_pad_ptr_t;
+
struct scan_results
{
int64_t ttypeIndex; // > 0 catch handler, < 0 exception spec handler, == 0 a cleanup
- const uint8_t* actionRecord; // Currently unused. Retained to ease future maintenance.
- const uint8_t* languageSpecificData; // Needed only for __cxa_call_unexpected
- uintptr_t landingPad; // null -> nothing found, else something found
+ action_ptr_t actionRecord; // Currently unused. Retained to ease future maintenance.
+ lsd_ptr_t languageSpecificData; // Needed only for __cxa_call_unexpected
+ landing_pad_t landingPad; // null -> nothing found, else something found
void* adjustedPtr; // Used in cxa_exception.cpp
_Unwind_Reason_Code reason; // One of _URC_FATAL_PHASE1_ERROR,
// _URC_FATAL_PHASE2_ERROR,
@@ -557,7 +602,23 @@ set_registers(_Unwind_Exception* unwind_exception, _Unwind_Context* context,
reinterpret_cast<uintptr_t>(unwind_exception));
_Unwind_SetGR(context, __builtin_eh_return_data_regno(1),
static_cast<uintptr_t>(results.ttypeIndex));
+#if __has_feature(ptrauth_calls)
+ auto stackPointer = _Unwind_GetGR(context, UNW_REG_SP);
+ // We manually re-sign the IP as the __ptrauth qualifiers cannot
+ // express the required relationship with the destination address
+ const auto existingDiscriminator =
+ ptrauth_blend_discriminator(&results.landingPad,
+ __ptrauth_scan_results_landingpad_disc);
+ unw_word_t newIP /* opaque __ptrauth(ptrauth_key_return_address, stackPointer, 0) */ =
+ (unw_word_t)ptrauth_auth_and_resign(*(void* const*)&results.landingPad,
+ __ptrauth_scan_results_landingpad_key,
+ existingDiscriminator,
+ ptrauth_key_return_address,
+ stackPointer);
+ _Unwind_SetIP(context, newIP);
+#else
_Unwind_SetIP(context, results.landingPad);
+#endif
}
/*
@@ -691,12 +752,12 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
// The call sites are ordered in increasing value of start
uintptr_t start = readEncodedPointer(&callSitePtr, callSiteEncoding);
uintptr_t length = readEncodedPointer(&callSitePtr, callSiteEncoding);
- uintptr_t landingPad = readEncodedPointer(&callSitePtr, callSiteEncoding);
+ landing_pad_t landingPad = readEncodedPointer(&callSitePtr, callSiteEncoding);
uintptr_t actionEntry = readULEB128(&callSitePtr);
if ((start <= ipOffset) && (ipOffset < (start + length)))
#else // __USING_SJLJ_EXCEPTIONS__ || __WASM_EXCEPTIONS__
// ip is 1-based index into this table
- uintptr_t landingPad = readULEB128(&callSitePtr);
+ landing_pad_t landingPad = readULEB128(&callSitePtr);
uintptr_t actionEntry = readULEB128(&callSitePtr);
if (--ip == 0)
#endif // __USING_SJLJ_EXCEPTIONS__ || __WASM_EXCEPTIONS__
@@ -903,6 +964,57 @@ _UA_CLEANUP_PHASE
*/
#if !defined(_LIBCXXABI_ARM_EHABI)
+
+// We use these helper functions to work around the behavior of casting between
+// integers (even those that are authenticated) and authenticated pointers.
+// Because the schemas being used are address discriminated we cannot use a
+// trivial value union to coerce the types so instead we perform the re-signing
+// manually.
+using __cxa_catch_temp_type = decltype(__cxa_exception::catchTemp);
+static inline void set_landing_pad(scan_results& results,
+ const __cxa_catch_temp_type& source) {
+#if __has_feature(ptrauth_calls)
+ const uintptr_t sourceDiscriminator =
+ ptrauth_blend_discriminator(&source, __ptrauth_cxxabi_catch_temp_disc);
+ const uintptr_t targetDiscriminator =
+ ptrauth_blend_discriminator(&results.landingPad,
+ __ptrauth_scan_results_landingpad_disc);
+ uintptr_t reauthenticatedLandingPad =
+ (uintptr_t)ptrauth_auth_and_resign(*reinterpret_cast<void* const*>(&source),
+ __ptrauth_cxxabi_catch_temp_key,
+ sourceDiscriminator,
+ __ptrauth_scan_results_landingpad_key,
+ targetDiscriminator);
+ memmove(reinterpret_cast<void *>(&results.landingPad),
+ reinterpret_cast<void *>(&reauthenticatedLandingPad),
+ sizeof(reauthenticatedLandingPad));
+#else
+ results.landingPad = reinterpret_cast<landing_pad_t>(source);
+#endif
+}
+
+static inline void get_landing_pad(__cxa_catch_temp_type &dest,
+ const scan_results &results) {
+#if __has_feature(ptrauth_calls)
+ const uintptr_t sourceDiscriminator =
+ ptrauth_blend_discriminator(&results.landingPad,
+ __ptrauth_scan_results_landingpad_disc);
+ const uintptr_t targetDiscriminator =
+ ptrauth_blend_discriminator(&dest, __ptrauth_cxxabi_catch_temp_disc);
+ uintptr_t reauthenticatedPointer =
+ (uintptr_t)ptrauth_auth_and_resign(*reinterpret_cast<void* const*>(&results.landingPad),
+ __ptrauth_scan_results_landingpad_key,
+ sourceDiscriminator,
+ __ptrauth_cxxabi_catch_temp_key,
+ targetDiscriminator);
+ memmove(reinterpret_cast<void *>(&dest),
+ reinterpret_cast<void *>(&reauthenticatedPointer),
+ sizeof(reauthenticatedPointer));
+#else
+ dest = reinterpret_cast<__cxa_catch_temp_type>(results.landingPad);
+#endif
+}
+
#ifdef __WASM_EXCEPTIONS__
_Unwind_Reason_Code __gxx_personality_wasm0
#elif defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)
@@ -935,8 +1047,7 @@ __gxx_personality_v0
results.ttypeIndex = exception_header->handlerSwitchValue;
results.actionRecord = exception_header->actionRecord;
results.languageSpecificData = exception_header->languageSpecificData;
- results.landingPad =
- reinterpret_cast<uintptr_t>(exception_header->catchTemp);
+ set_landing_pad(results, exception_header->catchTemp);
results.adjustedPtr = exception_header->adjustedPtr;
// Jump to the handler.
@@ -970,7 +1081,7 @@ __gxx_personality_v0
exc->handlerSwitchValue = static_cast<int>(results.ttypeIndex);
exc->actionRecord = results.actionRecord;
exc->languageSpecificData = results.languageSpecificData;
- exc->catchTemp = reinterpret_cast<void*>(results.landingPad);
+ get_landing_pad(exc->catchTemp, results);
exc->adjustedPtr = results.adjustedPtr;
#ifdef __WASM_EXCEPTIONS__
// Wasm only uses a single phase (_UA_SEARCH_PHASE), so save the