aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEd Maste <emaste@FreeBSD.org>2016-07-21 18:20:35 +0000
committerEd Maste <emaste@FreeBSD.org>2016-07-21 18:20:35 +0000
commit3c4fd2463bb29f65ef1404011fcb31e508cdf2e2 (patch)
tree1c5faa7b67e52a2c3ed81e721e29949fcb5aa7bb
parentbb04182c902075e81578400e81e2cb1c05f6bbcd (diff)
downloadsrc-3c4fd2463bb29f65ef1404011fcb31e508cdf2e2.tar.gz
src-3c4fd2463bb29f65ef1404011fcb31e508cdf2e2.zip
libcxxrt: add padding in __cxa_allocate_* to fix alignment
The addition of the referenceCount to __cxa_allocate_exception put the unwindHeader at offset 0x58 in __cxa_exception, but it requires 16-byte alignment. In order to avoid changing the current __cxa_exception ABI (and thus breaking its consumers), add explicit padding in the allocation routines (and account for it when freeing). This is intended as a lower-risk change for FreeBSD 11. A "more correct" fix should be prepared for upstream and -CURRENT. Reviewed by: dim MFC after: 3 days Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D7271
Notes
Notes: svn path=/head/; revision=303157
-rw-r--r--contrib/libcxxrt/exception.cc30
1 files changed, 24 insertions, 6 deletions
diff --git a/contrib/libcxxrt/exception.cc b/contrib/libcxxrt/exception.cc
index 84fc92dd6818..dbc9c628f0b8 100644
--- a/contrib/libcxxrt/exception.cc
+++ b/contrib/libcxxrt/exception.cc
@@ -572,6 +572,19 @@ static void free_exception(char *e)
}
}
+#ifdef __LP64__
+/**
+ * There's an ABI bug in __cxa_exception: unwindHeader requires 16-byte
+ * alignment but it was broken by the addition of the referenceCount.
+ * The unwindHeader is at offset 0x58 in __cxa_exception. In order to keep
+ * compatibility with consumers of the broken __cxa_exception, explicitly add
+ * padding on allocation (and account for it on free).
+ */
+static const int exception_alignment_padding = 8;
+#else
+static const int exception_alignment_padding = 0;
+#endif
+
/**
* Allocates an exception structure. Returns a pointer to the space that can
* be used to store an object of thrown_size bytes. This function will use an
@@ -580,16 +593,19 @@ static void free_exception(char *e)
*/
extern "C" void *__cxa_allocate_exception(size_t thrown_size)
{
- size_t size = thrown_size + sizeof(__cxa_exception);
+ size_t size = exception_alignment_padding + sizeof(__cxa_exception) +
+ thrown_size;
char *buffer = alloc_or_die(size);
- return buffer+sizeof(__cxa_exception);
+ return buffer + exception_alignment_padding + sizeof(__cxa_exception);
}
extern "C" void *__cxa_allocate_dependent_exception(void)
{
- size_t size = sizeof(__cxa_dependent_exception);
+ size_t size = exception_alignment_padding +
+ sizeof(__cxa_dependent_exception);
char *buffer = alloc_or_die(size);
- return buffer+sizeof(__cxa_dependent_exception);
+ return buffer + exception_alignment_padding +
+ sizeof(__cxa_dependent_exception);
}
/**
@@ -617,7 +633,8 @@ extern "C" void __cxa_free_exception(void *thrown_exception)
}
}
- free_exception(reinterpret_cast<char*>(ex));
+ free_exception(reinterpret_cast<char*>(ex) -
+ exception_alignment_padding);
}
static void releaseException(__cxa_exception *exception)
@@ -644,7 +661,8 @@ void __cxa_free_dependent_exception(void *thrown_exception)
{
releaseException(realExceptionFromException(reinterpret_cast<__cxa_exception*>(ex)));
}
- free_exception(reinterpret_cast<char*>(ex));
+ free_exception(reinterpret_cast<char*>(ex) -
+ exception_alignment_padding);
}
/**