[libcxxabi] r319123 - Insert padding before the __cxa_exception header to ensure the thrown
Akira Hatanaka via cfe-commits
cfe-commits at lists.llvm.org
Mon Nov 27 16:36:29 PST 2017
Author: ahatanak
Date: Mon Nov 27 16:36:29 2017
New Revision: 319123
URL: http://llvm.org/viewvc/llvm-project?rev=319123&view=rev
Log:
Insert padding before the __cxa_exception header to ensure the thrown
object is sufficiently aligned.
r303175 annotated field unwindHeader of __cxa_exception with attribute
'aligned' to ensure the thrown object following the __cxa_exception
header was sufficiently aligned. This caused changes in the field
offsets of __cxa_exception relative to the start of the thrown object,
which was an ABI breaking change for some clients.
Instead of annotating field unwindHeader, this commit inserts extra
space before the header. This ensures the thrown object following the
header is sufficiently aligned without changing the field offsets, thus
avoiding any ABI breakages.
rdar://problem/25364625
rdar://problem/35556163
Modified:
libcxxabi/trunk/src/cxa_exception.cpp
libcxxabi/trunk/src/cxa_exception.hpp
Modified: libcxxabi/trunk/src/cxa_exception.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/src/cxa_exception.cpp?rev=319123&r1=319122&r2=319123&view=diff
==============================================================================
--- libcxxabi/trunk/src/cxa_exception.cpp (original)
+++ libcxxabi/trunk/src/cxa_exception.cpp Mon Nov 27 16:36:29 2017
@@ -137,6 +137,28 @@ static _LIBCXXABI_NORETURN void failed_t
std::__terminate(exception_header->terminateHandler);
}
+// Return the offset of the __cxa_exception header from the start of the
+// allocated buffer. If __cxa_exception's alignment is smaller than the maximum
+// useful alignment for the target machine, padding has to be inserted before
+// the header to ensure the thrown object that follows the header is
+// sufficiently aligned. This happens if _Unwind_exception isn't double-word
+// aligned (on Darwin, for example).
+static size_t get_cxa_exception_offset() {
+ struct S {
+ } __attribute__((aligned));
+
+ // Compute the maximum alignment for the target machine.
+ constexpr size_t alignment = std::alignment_of<S>::value;
+ constexpr size_t excp_size = sizeof(__cxa_exception);
+ constexpr size_t aligned_size =
+ (excp_size + alignment - 1) / alignment * alignment;
+ constexpr size_t offset = aligned_size - excp_size;
+ static_assert((offset == 0 ||
+ std::alignment_of<_Unwind_Exception>::value < alignment),
+ "offset is non-zero only if _Unwind_Exception isn't aligned");
+ return offset;
+}
+
extern "C" {
// Allocate a __cxa_exception object, and zero-fill it.
@@ -146,10 +168,16 @@ extern "C" {
// user's exception object.
void *__cxa_allocate_exception(size_t thrown_size) throw() {
size_t actual_size = cxa_exception_size_from_exception_thrown_size(thrown_size);
- __cxa_exception *exception_header =
- static_cast<__cxa_exception *>(__aligned_malloc_with_fallback(actual_size));
- if (NULL == exception_header)
+
+ // Allocate extra space before the __cxa_exception header to ensure the
+ // start of the thrown object is sufficiently aligned.
+ size_t header_offset = get_cxa_exception_offset();
+ char *raw_buffer =
+ (char *)__aligned_malloc_with_fallback(header_offset + actual_size);
+ if (NULL == raw_buffer)
std::terminate();
+ __cxa_exception *exception_header =
+ static_cast<__cxa_exception *>((void *)(raw_buffer + header_offset));
std::memset(exception_header, 0, actual_size);
return thrown_object_from_cxa_exception(exception_header);
}
@@ -157,7 +185,11 @@ void *__cxa_allocate_exception(size_t th
// Free a __cxa_exception object allocated with __cxa_allocate_exception.
void __cxa_free_exception(void *thrown_object) throw() {
- __aligned_free_with_fallback(cxa_exception_from_thrown_object(thrown_object));
+ // Compute the size of the padding before the header.
+ size_t header_offset = get_cxa_exception_offset();
+ char *raw_buffer =
+ ((char *)cxa_exception_from_thrown_object(thrown_object)) - header_offset;
+ __aligned_free_with_fallback((void *)raw_buffer);
}
Modified: libcxxabi/trunk/src/cxa_exception.hpp
URL: http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/src/cxa_exception.hpp?rev=319123&r1=319122&r2=319123&view=diff
==============================================================================
--- libcxxabi/trunk/src/cxa_exception.hpp (original)
+++ libcxxabi/trunk/src/cxa_exception.hpp Mon Nov 27 16:36:29 2017
@@ -60,22 +60,7 @@ struct _LIBCXXABI_HIDDEN __cxa_exception
// previously adding padded to 64-bit align unwindHeader.
size_t referenceCount;
#endif
-
- // This field is annotated with attribute aligned so that the exception
- // object following the field is sufficiently aligned and there is no
- // gap between the field and the exception object. r276215 made a change to
- // annotate _Unwind_Exception in unwind.h with __attribute__((aligned)), but
- // we cannot incorporate the fix on Darwin since it is an ABI-breaking
- // change, which is why we need the attribute on this field.
- //
- // For ARM EHABI, we do not align this field since _Unwind_Exception is an
- // alias of _Unwind_Control_Block, which is not annotated with
- // __attribute__((aligned).
-#if defined(_LIBCXXABI_ARM_EHABI)
_Unwind_Exception unwindHeader;
-#else
- _Unwind_Exception unwindHeader __attribute__((aligned));
-#endif
};
// http://sourcery.mentor.com/archives/cxx-abi-dev/msg01924.html
@@ -109,14 +94,7 @@ struct _LIBCXXABI_HIDDEN __cxa_dependent
#if !defined(__LP64__) && !defined(_LIBCXXABI_ARM_EHABI)
void* primaryException;
#endif
-
- // See the comment in __cxa_exception as to why this field has attribute
- // aligned.
-#if defined(_LIBCXXABI_ARM_EHABI)
_Unwind_Exception unwindHeader;
-#else
- _Unwind_Exception unwindHeader __attribute__((aligned));
-#endif
};
struct _LIBCXXABI_HIDDEN __cxa_eh_globals {
More information about the cfe-commits
mailing list