From ff20d64b1d48a358adb11543683d700fa8f19976 Mon Sep 17 00:00:00 2001 From: Yedidya Feldblum Date: Sun, 19 Jan 2025 21:44:48 -0800 Subject: [PATCH] fix __cxa_exception alignment under libstdc++ with gcc Summary: Fixes: https://github.com/facebook/folly/issues/2359. In the debugger, I observed calls to `__cxa_allocate_exception` with size `n` calling `malloc` with size `128 + n`. I compared 128 with `sizeof(__cxa_refcounted_exception)` in our replica, which was only 120. So there must have been some difference between the replica and the original. But there was no difference between the fields in `__cxa_refcounted_exception` or in `__cxa_exception`; so the only remaining place to look was in `_Unwind_Exception`. We do not have a replica of `_Unwind_Exception` since `unwind.h` is always available, but it might be from either libgcc or from libunwind, so the difference must have been between these two. * The type `_Unwind_Exception` is marked in libgcc as being fully aligned: https://github.com/gcc-mirror/gcc/blob/releases/gcc-14.2.0/libgcc/unwind-generic.h#L106. * Likewise in llvm-unwind: https://github.com/llvm/llvm-project/blob/llvmorg-19.1.7/libunwind/include/unwind_itanium.h#L41. * It is used without explicit alignment in libstdc++ authoritative `__cxa_exception`: https://github.com/gcc-mirror/gcc/blob/releases/gcc-14.2.0/libstdc%2B%2B-v3/libsupc%2B%2B/unwind-cxx.h#L97. * The type may not be marked as being fully aligned in upstream libunwind: https://github.com/libunwind/libunwind/blob/v1.8.1/include/unwind.h#L80. * In our replica of `__cxa_exception`, we must mark the field as being fully aligned in case the replica uses a definition of the type which is not marked as being fully aligned. Differential Revision: D68391229 --- folly/lang/Exception.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/folly/lang/Exception.cpp b/folly/lang/Exception.cpp index b750df1fac0..11ed8956532 100644 --- a/folly/lang/Exception.cpp +++ b/folly/lang/Exception.cpp @@ -96,6 +96,17 @@ typedef unsigned _Unwind_Ptr __attribute__((__mode__(__pointer__))); namespace __cxxabiv1 { +// libsupc++ itanium-abi __cxa_exception assumes that _Unwind_Exception is +// maximally-aligned, and indeed libgcc itanium-abi _Unwind_Exception is so; +// but libunwind itanium-abi _Unwind_Exception is not maximally-aligned +#ifdef __ARM_EABI_UNWINDER__ +// https://github.com/gcc-mirror/gcc/blob/releases/gcc-14.2.0/gcc/ginclude/unwind-arm-common.h#L119 +static constexpr size_t __folly_unwind_exception_align = 8; +#else +// https://github.com/gcc-mirror/gcc/blob/releases/gcc-14.2.0/libgcc/unwind-generic.h#L106 +static constexpr size_t __folly_unwind_exception_align = alignof(max_align_t); +#endif + static constexpr uint64_t __gxx_primary_exception_class = 0x474E5543432B2B00; // GNCUC++\0 static constexpr uint64_t __gxx_dependent_exception_class = @@ -118,7 +129,7 @@ struct __cxa_exception { _Unwind_Ptr catchTemp; void* adjustedPtr; #endif - _Unwind_Exception unwindHeader; + alignas(__folly_unwind_exception_align) _Unwind_Exception unwindHeader; }; struct __cxa_refcounted_exception {