diff options
author | emaste <emaste@FreeBSD.org> | 2016-07-25 14:16:28 +0000 |
---|---|---|
committer | emaste <emaste@FreeBSD.org> | 2016-07-25 14:16:28 +0000 |
commit | eafa662f76d570477b7d79bbb4280c64591774dd (patch) | |
tree | 48ebc23778a9b5f7147abf31b89cfae986741029 /contrib/libcxxrt | |
parent | 545d990a81b5df5354712165e83217404a6eb3c2 (diff) | |
download | FreeBSD-src-eafa662f76d570477b7d79bbb4280c64591774dd.zip FreeBSD-src-eafa662f76d570477b7d79bbb4280c64591774dd.tar.gz |
MFC r303157: 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.
Approved by: re (gjb)
Sponsored by: The FreeBSD Foundation
Diffstat (limited to 'contrib/libcxxrt')
-rw-r--r-- | contrib/libcxxrt/exception.cc | 30 |
1 files changed, 24 insertions, 6 deletions
diff --git a/contrib/libcxxrt/exception.cc b/contrib/libcxxrt/exception.cc index 84fc92d..dbc9c62 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); } /** |