Skip to content
Merged
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
e7f03a8
[runtimes][PAC] Harden unwinding when possible (#138571)
ojhunt Aug 6, 2025
61b763a
Updating to include some fixes I lost in the last update
ojhunt Aug 6, 2025
6e696ad
Build fix due to not testing the build after apply review feedback \o/
ojhunt Aug 6, 2025
27d43af
work around a bug where clang reports a template function as unused
ojhunt Aug 6, 2025
8dc3194
And another one
ojhunt Aug 6, 2025
d3ba2f8
Add all the required reg_t and link_reg_t decls, and unify location
ojhunt Aug 6, 2025
c1ec8d6
This erroneous error is annoying
ojhunt Aug 6, 2025
7a78b25
Remove header include that is unnecessary but apparently works in som…
ojhunt Aug 7, 2025
a5cd944
Update for feature check changes
ojhunt Sep 2, 2025
c2c0190
yet more cleaning up
ojhunt Sep 4, 2025
3e59382
cleanup compiler-rt formatting
ojhunt Sep 4, 2025
ef03071
update libcxxabi formatting
ojhunt Sep 4, 2025
5b832be
Just make this a release mode failure
ojhunt Sep 27, 2025
49a0111
Address comments
ojhunt Sep 28, 2025
fc1375a
Sigh, actually make sure it builds, also address warnings
ojhunt Sep 28, 2025
782cbdb
Updating for feedback
ojhunt Sep 30, 2025
34555e7
whoops, wrong test
ojhunt Sep 30, 2025
d70e802
You would not believe how long it took to find this
ojhunt Oct 3, 2025
7192221
Addressing some feedback
ojhunt Oct 7, 2025
0d482fa
cleaning up the [ab]use of unions
ojhunt Oct 8, 2025
8d7e526
Addressing myriad feedback
ojhunt Oct 8, 2025
0f2679a
Fixing remaining issues
ojhunt Oct 8, 2025
74de39b
formatting corrections
ojhunt Oct 15, 2025
a9d9113
A somewhat gross 'lets see if this is the bot issue' change
ojhunt Oct 17, 2025
3c5a776
Ooooh, this might be it -- also it remains absurd that this isn't an …
ojhunt Oct 17, 2025
865181e
Let's stop doing this in the fragile field by field way
ojhunt Oct 18, 2025
5e03a33
Fix the build because I am clever
ojhunt Oct 18, 2025
1839bb4
Remove union, improve comments.
ojhunt Oct 20, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 75 additions & 6 deletions compiler-rt/lib/builtins/gcc_personality_v0.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,54 @@ EXCEPTION_DISPOSITION _GCC_specific_handler(PEXCEPTION_RECORD, void *, PCONTEXT,
_Unwind_Personality_Fn);
#endif

#if __has_feature(ptrauth_calls)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed previously, let's use the new macro LIBUNWIND_PTRAUTH_CALLS_AND_RETURNS defined as follows everywhere instead of __has_include(<ptrauth.h>), __has_feature(ptrauth_calls), __has_feature(ptrauth_returns), __has_extension(ptrauth_qualifier), etc:

#if __has_feature(ptrauth_calls) && __has_feature(ptrauth_returns)
#define LIBUNWIND_PTRAUTH_CALLS_AND_RETURNS
#elif __has_feature(ptrauth_calls) || __has_feature(ptrauth_returns)
#error "Either both or none of ptrauth_calls and ptrauth_returns is allowed to be enabled"
#endif

See proposed fix in commit 644405b in my branch https://github.com/kovdan01/llvm-project/commits/pointer-authenticated-unwinding-2025-09-22-with-fixes/.

I think this should be done in scope of this PR.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This also breaks compilation with GCC 13.3:

#if __has_feature(ptrauth_calls)
#endif

Output:

$ gcc test.c -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-linux-gnu/13/lto-wrapper
OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa
OFFLOAD_TARGET_DEFAULT=1
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 13.3.0-6ubuntu2~24.04' --with-bugurl=file:///usr/share/doc/gcc-13/README.Bugs --enable-languages=c,ada,c++,go,d,fortran,objc,obj-c++,m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-13 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/libexec --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-libstdcxx-backtrace --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --enable-cet --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-13-fG75Ri/gcc-13-13.3.0/debian/tmp-nvptx/usr,amdgcn-amdhsa=/build/gcc-13-fG75Ri/gcc-13-13.3.0/debian/tmp-gcn/usr --enable-offload-defaulted --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-serialization=2
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 13.3.0 (Ubuntu 13.3.0-6ubuntu2~24.04) 
COLLECT_GCC_OPTIONS='-v' '-mtune=generic' '-march=x86-64' '-dumpdir' 'a-'
 /usr/libexec/gcc/x86_64-linux-gnu/13/cc1 -quiet -v -imultiarch x86_64-linux-gnu test.c -quiet -dumpdir a- -dumpbase test.c -dumpbase-ext .c -mtune=generic -march=x86-64 -version -fasynchronous-unwind-tables -fstack-protector-strong -Wformat -Wformat-security -fstack-clash-protection -fcf-protection -o /tmp/ccc8jUuR.s
GNU C17 (Ubuntu 13.3.0-6ubuntu2~24.04) version 13.3.0 (x86_64-linux-gnu)
        compiled by GNU C version 13.3.0, GMP version 6.3.0, MPFR version 4.2.1, MPC version 1.3.1, isl version isl-0.26-GMP

GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/13/include-fixed/x86_64-linux-gnu"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/13/include-fixed"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/13/../../../../x86_64-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
 /usr/lib/gcc/x86_64-linux-gnu/13/include                                                                                                         
 /usr/local/include
 /usr/include/x86_64-linux-gnu
 /usr/include
End of search list.
Compiler executable checksum: 38987c28e967c64056a6454abdef726e                                                                                    
test.c:1:18: error: missing binary operator before token "("
    1 | #if __has_feature(ptrauth_calls)
      |                  ^

As seen on compilerexplorer: https://godbolt.org/z/WW95ad5rP

#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

Expand Down Expand Up @@ -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.
Expand All @@ -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.
Expand All @@ -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;
}
}
Expand Down
41 changes: 41 additions & 0 deletions libcxxabi/include/__cxxabi_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,47 @@
#define _LIBCXXABI_DTOR_FUNC
#endif

#if __has_include(<ptrauth.h>)
# include <ptrauth.h>
#endif

#if __has_feature(ptrauth_calls)

// ptrauth_string_discriminator("__cxa_exception::actionRecord") == 0xFC91
# define __ptrauth_cxxabi_action_record __ptrauth(ptrauth_key_process_dependent_data, 1, 0xFC91)

// ptrauth_string_discriminator("__cxa_exception::languageSpecificData") == 0xE8EE
# define __ptrauth_cxxabi_lsd __ptrauth(ptrauth_key_process_dependent_data, 1, 0xE8EE)

// ptrauth_string_discriminator("__cxa_exception::catchTemp") == 0xFA58
# define __ptrauth_cxxabi_catch_temp_disc 0xFA58
# define __ptrauth_cxxabi_catch_temp_key ptrauth_key_process_dependent_data
# define __ptrauth_cxxabi_catch_temp __ptrauth(__ptrauth_cxxabi_catch_temp_key, 1, __ptrauth_cxxabi_catch_temp_disc)

// ptrauth_string_discriminator("__cxa_exception::adjustedPtr") == 0x99E4
# define __ptrauth_cxxabi_adjusted_ptr __ptrauth(ptrauth_key_process_dependent_data, 1, 0x99E4)

// ptrauth_string_discriminator("__cxa_exception::unexpectedHandler") == 0x99A9
# define __ptrauth_cxxabi_unexpected_handler __ptrauth(ptrauth_key_function_pointer, 1, 0x99A9)

// ptrauth_string_discriminator("__cxa_exception::terminateHandler") == 0x0886)
# define __ptrauth_cxxabi_terminate_handler __ptrauth(ptrauth_key_function_pointer, 1, 0x886)

// ptrauth_string_discriminator("__cxa_exception::exceptionDestructor") == 0xC088
# define __ptrauth_cxxabi_exception_destructor __ptrauth(ptrauth_key_function_pointer, 1, 0xC088)

#else

# define __ptrauth_cxxabi_action_record
# define __ptrauth_cxxabi_lsd
# define __ptrauth_cxxabi_catch_temp
# define __ptrauth_cxxabi_adjusted_ptr
# define __ptrauth_cxxabi_unexpected_handler
# define __ptrauth_cxxabi_terminate_handler
# define __ptrauth_cxxabi_exception_destructor

#endif

#if __cplusplus < 201103L
# define _LIBCXXABI_NOEXCEPT throw()
#else
Expand Down
4 changes: 3 additions & 1 deletion libcxxabi/src/cxa_exception.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
30 changes: 16 additions & 14 deletions libcxxabi/src/cxa_exception.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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)
Expand All @@ -79,16 +79,18 @@ 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.
void* primaryException;
#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;

Expand All @@ -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)
Expand Down
Loading
Loading