diff --git a/clang/docs/PointerAuthentication.rst b/clang/docs/PointerAuthentication.rst index 7e65f4b1b4915..4c92948afae76 100644 --- a/clang/docs/PointerAuthentication.rst +++ b/clang/docs/PointerAuthentication.rst @@ -752,6 +752,40 @@ type. Implementations are not required to make all bits of the result equally significant; in particular, some implementations are known to not leave meaningful data in the low bits. +``ptrauth_nop_cast`` +^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: c + + ptrauth_nop_cast(__type, __value) + +Cast a pointer to the given type without changing any signature. + +This operation can be used to convert a value from one type to another without +attempting to re-sign the value. This makes it possible to view a signed value +of one type as another type signed with the same schema. This can be used to +convert implicit schemas to explicit schemas, to convert to or from opaque +types, or simply to change the effective underlying type of a signed value. + +The `__type` must be a pointer sized value compatible with the `__ptrauth` +qualifier. The authentication schema must not include address diversity. + +The result is a bitwise identical value with the type passed as the `__type` +argument. + +``ptrauth_function_pointer_type_discriminator`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: c + + ptrauth_function_pointer_type_discriminator(__type) + +Compute the constant discriminator used by Clang to sign pointers with the +given C function pointer type. + +A call to this function is an integer constant expression. + + Standard ``__ptrauth`` qualifiers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Headers/ptrauth.h b/clang/lib/Headers/ptrauth.h index ad28f06f0930c..ca9ac5a55ea7d 100644 --- a/clang/lib/Headers/ptrauth.h +++ b/clang/lib/Headers/ptrauth.h @@ -199,6 +199,25 @@ typedef __UINTPTR_TYPE__ ptrauth_generic_signature_t; ptrauth_auth_and_resign(__value, __old_key, __old_data, \ ptrauth_key_function_pointer, 0) +/* Cast a value to the given type without changing any signature. + + The type must be a pointer sized type compatible with the __ptrauth + qualifier. + The value must be an expression with a non-address diversified pointer + authentication schema, and will be converted to an rvalue prior to the cast. + The result has type given by the first argument. + + The result has an identical bit-pattern to the input pointer. */ +#define ptrauth_nop_cast(__type, __value) \ + ({ \ + union { \ + typeof(*(__value)) *__fptr; \ + typeof(__type) __opaque; \ + } __storage; \ + __storage.__fptr = (__value); \ + __storage.__opaque; \ + }) + /* Authenticate a data pointer. The value must be an expression of non-function pointer type. @@ -275,6 +294,32 @@ typedef __UINTPTR_TYPE__ ptrauth_generic_signature_t; #define ptrauth_sign_generic_data(__value, __data) \ __builtin_ptrauth_sign_generic_data(__value, __data) +/* Define some standard __ptrauth qualifiers used in the ABI. */ +#define __ptrauth_function_pointer(__typekey) \ + __ptrauth(ptrauth_key_function_pointer, 0, __typekey) +#define __ptrauth_return_address __ptrauth(ptrauth_key_return_address, 1, 0) +#define __ptrauth_block_invocation_pointer \ + __ptrauth(ptrauth_key_function_pointer, 1, 0) +#define __ptrauth_block_copy_helper \ + __ptrauth(ptrauth_key_function_pointer, 1, 0) +#define __ptrauth_block_destroy_helper \ + __ptrauth(ptrauth_key_function_pointer, 1, 0) +#define __ptrauth_block_byref_copy_helper \ + __ptrauth(ptrauth_key_function_pointer, 1, 0) +#define __ptrauth_block_byref_destroy_helper \ + __ptrauth(ptrauth_key_function_pointer, 1, 0) +#if __has_feature(ptrauth_signed_block_descriptors) +#define __ptrauth_block_descriptor_pointer \ + __ptrauth(ptrauth_key_block_descriptor_pointer, 1, 0xC0BB) +#else +#define __ptrauth_block_descriptor_pointer +#endif + +#define __ptrauth_cxx_vtable_pointer \ + __ptrauth(ptrauth_key_cxx_vtable_pointer, 0, 0) +#define __ptrauth_cxx_vtt_vtable_pointer \ + __ptrauth(ptrauth_key_cxx_vtable_pointer, 0, 0) + /* C++ vtable pointer signing class attribute */ #define ptrauth_cxx_vtable_pointer(key, address_discrimination, \ extra_discrimination...) \ @@ -383,6 +428,7 @@ typedef __UINTPTR_TYPE__ ptrauth_generic_signature_t; ((ptrauth_extra_data_t)0); \ }) +#define ptrauth_nop_cast(__type, __value) (__type)(__value) #define ptrauth_type_discriminator(__type) ((ptrauth_extra_data_t)0) #define ptrauth_function_pointer_type_discriminator(__type) \ ((ptrauth_extra_data_t)0) @@ -398,9 +444,23 @@ typedef __UINTPTR_TYPE__ ptrauth_generic_signature_t; #define ptrauth_cxx_vtable_pointer(key, address_discrimination, \ extra_discrimination...) +#define __ptrauth_function_pointer(__typekey) +#define __ptrauth_return_address +#define __ptrauth_block_invocation_pointer +#define __ptrauth_block_copy_helper +#define __ptrauth_block_destroy_helper +#define __ptrauth_block_byref_copy_helper +#define __ptrauth_block_byref_destroy_helper +#define __ptrauth_block_descriptor_pointer +#define __ptrauth_objc_method_list_imp +#define __ptrauth_objc_method_list_pointer #define __ptrauth_objc_isa_pointer #define __ptrauth_objc_isa_uintptr #define __ptrauth_objc_super_pointer +#define __ptrauth_cxx_vtable_pointer +#define __ptrauth_cxx_vtt_vtable_pointer +#define __ptrauth_objc_sel +#define __ptrauth_objc_class_ro #endif /* __has_feature(ptrauth_intrinsics) || defined(__PTRAUTH__) */