diff --git a/libcxx/include/typeinfo b/libcxx/include/typeinfo index dafc7b89248ec..56974a43b361d 100644 --- a/libcxx/include/typeinfo +++ b/libcxx/include/typeinfo @@ -276,7 +276,19 @@ struct __type_info_implementations { __impl; }; -class _LIBCPP_EXPORTED_FROM_ABI type_info { +# if defined(__arm64__) && __has_cpp_attribute(clang::ptrauth_vtable_pointer) +# if __has_feature(ptrauth_type_info_discriminated_vtable_pointer) +# define _LIBCPP_TYPE_INFO_VTABLE_POINTER_AUTH \ + [[clang::ptrauth_vtable_pointer(process_independent, address_discrimination, type_discrimination)]] +# else +# define _LIBCPP_TYPE_INFO_VTABLE_POINTER_AUTH \ + [[clang::ptrauth_vtable_pointer(process_independent, no_address_discrimination, no_extra_discrimination)]] +# endif +# else +# define _LIBCPP_TYPE_INFO_VTABLE_POINTER_AUTH +# endif + +class _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_TYPE_INFO_VTABLE_POINTER_AUTH type_info { type_info& operator=(const type_info&); type_info(const type_info&); diff --git a/libcxx/src/include/overridable_function.h b/libcxx/src/include/overridable_function.h index 7b0fba10f47d4..fca66ea6daf7a 100644 --- a/libcxx/src/include/overridable_function.h +++ b/libcxx/src/include/overridable_function.h @@ -13,6 +13,10 @@ #include <__config> #include +#if defined(__arm64e__) && __has_feature(ptrauth_calls) +# include +#endif + #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif @@ -81,6 +85,14 @@ _LIBCPP_HIDE_FROM_ABI bool __is_function_overridden(_Ret (*__fptr)(_Args...)) no uintptr_t __end = reinterpret_cast(&__lcxx_override_end); uintptr_t __ptr = reinterpret_cast(__fptr); +#if defined(__arm64e__) && __has_feature(ptrauth_calls) + // We must pass a void* to ptrauth_strip since it only accepts a pointer type. Also, in particular, + // we must NOT pass a function pointer, otherwise we will strip the function pointer, and then attempt + // to authenticate and re-sign it when casting it to a uintptr_t again, which will fail because we just + // stripped the function pointer. See rdar://122927845. + __ptr = reinterpret_cast(ptrauth_strip(reinterpret_cast(__ptr), ptrauth_key_function_pointer)); +#endif + // Finally, the function was overridden if it falls outside of the section's bounds. return __ptr < __start || __ptr > __end; } diff --git a/libcxxabi/src/private_typeinfo.cpp b/libcxxabi/src/private_typeinfo.cpp index 5c68f3e994cd9..9e58501a55934 100644 --- a/libcxxabi/src/private_typeinfo.cpp +++ b/libcxxabi/src/private_typeinfo.cpp @@ -51,6 +51,21 @@ #include #endif +#if __has_feature(ptrauth_calls) +#include +#endif + + +template +static inline +T * +get_vtable(T *vtable) { +#if __has_feature(ptrauth_calls) + vtable = ptrauth_strip(vtable, ptrauth_key_cxx_vtable_pointer); +#endif + return vtable; +} + static inline bool is_equal(const std::type_info* x, const std::type_info* y, bool use_strcmp) @@ -103,6 +118,7 @@ void dyn_cast_get_derived_info(derived_object_info* info, const void* static_ptr info->dynamic_type = *(reinterpret_cast(ptr_to_ti_proxy)); #else void **vtable = *static_cast(static_ptr); + vtable = get_vtable(vtable); info->offset_to_derived = reinterpret_cast(vtable[-2]); info->dynamic_ptr = static_cast(static_ptr) + info->offset_to_derived; info->dynamic_type = static_cast(vtable[-1]); @@ -561,6 +577,7 @@ __base_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info, offset_to_base = __offset_flags >> __offset_shift; if (is_virtual) { const char* vtable = *static_cast(adjustedPtr); + vtable = get_vtable(vtable); offset_to_base = update_offset_to_base(vtable, offset_to_base); } } else if (!is_virtual) { @@ -1501,6 +1518,7 @@ __base_class_type_info::search_above_dst(__dynamic_cast_info* info, if (__offset_flags & __virtual_mask) { const char* vtable = *static_cast(current_ptr); + vtable = get_vtable(vtable); offset_to_base = update_offset_to_base(vtable, offset_to_base); } __base_type->search_above_dst(info, dst_ptr, @@ -1521,6 +1539,7 @@ __base_class_type_info::search_below_dst(__dynamic_cast_info* info, if (__offset_flags & __virtual_mask) { const char* vtable = *static_cast(current_ptr); + vtable = get_vtable(vtable); offset_to_base = update_offset_to_base(vtable, offset_to_base); } __base_type->search_below_dst(info,