diff options
Diffstat (limited to 'compiler-rt')
-rw-r--r-- | compiler-rt/lib/builtins/gcc_personality_v0.c | 81 |
1 files changed, 75 insertions, 6 deletions
diff --git a/compiler-rt/lib/builtins/gcc_personality_v0.c b/compiler-rt/lib/builtins/gcc_personality_v0.c index ef63a5f..3ed17fa 100644 --- a/compiler-rt/lib/builtins/gcc_personality_v0.c +++ b/compiler-rt/lib/builtins/gcc_personality_v0.c @@ -30,6 +30,54 @@ EXCEPTION_DISPOSITION _GCC_specific_handler(PEXCEPTION_RECORD, void *, PCONTEXT, _Unwind_Personality_Fn); #endif +#if __has_feature(ptrauth_calls) +#include <ptrauth.h> + +// `__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_feature(ptrauth_restricted_intptr_qualifier) +#define __ptrauth_gcc_personality_intptr(key, addressDiscriminated, \ + discriminator) \ + __ptrauth_restricted_intptr(key, addressDiscriminated, discriminator) +#else +#define __ptrauth_gcc_personality_intptr(key, addressDiscriminated, \ + discriminator) \ + __ptrauth(key, addressDiscriminated, discriminator) +#endif +#else +#define __ptrauth_gcc_personality_intptr(...) +#endif + +#define __ptrauth_gcc_personality_func_key ptrauth_key_function_pointer + +// ptrauth_string_discriminator("__gcc_personality_v0'funcStart") == 0xDFEB +#define __ptrauth_gcc_personality_func_start \ + __ptrauth_gcc_personality_intptr(__ptrauth_gcc_personality_func_key, 1, \ + 0xDFEB) + +// ptrauth_string_discriminator("__gcc_personality_v0'start") == 0x52DC +#define __ptrauth_gcc_personality_start \ + __ptrauth_gcc_personality_intptr(__ptrauth_gcc_personality_func_key, 1, \ + 0x52DC) + +// ptrauth_string_discriminator("__gcc_personality_v0'length") == 0xFFF7 +#define __ptrauth_gcc_personality_length \ + __ptrauth_gcc_personality_intptr(__ptrauth_gcc_personality_func_key, 1, \ + 0xFFF7) + +// ptrauth_string_discriminator("__gcc_personality_v0'landingPadOffset") == +// 0x6498 +#define __ptrauth_gcc_personality_lpoffset \ + __ptrauth_gcc_personality_intptr(__ptrauth_gcc_personality_func_key, 1, \ + 0x6498) + +// ptrauth_string_discriminator("__gcc_personality_v0'landingPad") == 0xA134 +#define __ptrauth_gcc_personality_lpad_disc 0xA134 +#define __ptrauth_gcc_personality_lpad \ + __ptrauth_gcc_personality_intptr(__ptrauth_gcc_personality_func_key, 1, \ + __ptrauth_gcc_personality_lpad_disc) + // Pointer encodings documented at: // http://refspecs.freestandards.org/LSB_1.3.0/gLSB/gLSB/ehframehdr.html @@ -205,7 +253,8 @@ COMPILER_RT_ABI _Unwind_Reason_Code __gcc_personality_v0( return continueUnwind(exceptionObject, context); uintptr_t pc = (uintptr_t)_Unwind_GetIP(context) - 1; - uintptr_t funcStart = (uintptr_t)_Unwind_GetRegionStart(context); + uintptr_t __ptrauth_gcc_personality_func_start funcStart = + (uintptr_t)_Unwind_GetRegionStart(context); uintptr_t pcOffset = pc - funcStart; // Parse LSDA header. @@ -224,11 +273,14 @@ COMPILER_RT_ABI _Unwind_Reason_Code __gcc_personality_v0( const uint8_t *callSiteTableEnd = callSiteTableStart + callSiteTableLength; const uint8_t *p = callSiteTableStart; while (p < callSiteTableEnd) { - uintptr_t start = readEncodedPointer(&p, callSiteEncoding); - size_t length = readEncodedPointer(&p, callSiteEncoding); - size_t landingPad = readEncodedPointer(&p, callSiteEncoding); + uintptr_t __ptrauth_gcc_personality_start start = + readEncodedPointer(&p, callSiteEncoding); + size_t __ptrauth_gcc_personality_length length = + readEncodedPointer(&p, callSiteEncoding); + size_t __ptrauth_gcc_personality_lpoffset landingPadOffset = + readEncodedPointer(&p, callSiteEncoding); readULEB128(&p); // action value not used for C code - if (landingPad == 0) + if (landingPadOffset == 0) continue; // no landing pad for this entry if ((start <= pcOffset) && (pcOffset < (start + length))) { // Found landing pad for the PC. @@ -238,7 +290,24 @@ COMPILER_RT_ABI _Unwind_Reason_Code __gcc_personality_v0( _Unwind_SetGR(context, __builtin_eh_return_data_regno(0), (uintptr_t)exceptionObject); _Unwind_SetGR(context, __builtin_eh_return_data_regno(1), 0); - _Unwind_SetIP(context, (funcStart + landingPad)); + size_t __ptrauth_gcc_personality_lpad landingPad = + funcStart + landingPadOffset; +#if __has_feature(ptrauth_calls) + uintptr_t stackPointer = _Unwind_GetGR(context, -2); + const uintptr_t existingDiscriminator = ptrauth_blend_discriminator( + &landingPad, __ptrauth_gcc_personality_lpad_disc); + // newIP is authenticated as if it were qualified with a pseudo qualifier + // along the lines of: + // __ptrauth(ptrauth_key_return_address, <stackPointer>, 0) + // where the stack pointer is used in place of the strict storage + // address. + uintptr_t newIP = (uintptr_t)ptrauth_auth_and_resign( + *(void **)&landingPad, __ptrauth_gcc_personality_func_key, + existingDiscriminator, ptrauth_key_return_address, stackPointer); + _Unwind_SetIP(context, newIP); +#else + _Unwind_SetIP(context, landingPad); +#endif return _URC_INSTALL_CONTEXT; } } |