EricWF created this revision. EricWF added reviewers: mclow.lists, danalbert, jroelofs, compnerd. EricWF added a subscriber: cfe-commits.
In 32 bit builds on a 64 bit system `std::malloc` does not return correctly aligned memory. This leads to undefined behavior. This patch switches to using `posix_memalign` to allocate correctly aligned memory instead. https://reviews.llvm.org/D25417 Files: src/cxa_exception.cpp src/fallback_malloc.cpp test/test_exception_address_alignment.pass.cpp Index: test/test_exception_address_alignment.pass.cpp =================================================================== --- /dev/null +++ test/test_exception_address_alignment.pass.cpp @@ -0,0 +1,28 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Test that the address of the exception object is properly aligned to the +// largest supported alignment for the system. + +#include <cstdint> +#include <cassert> + +struct __attribute__((aligned)) AlignedType {}; +struct MinAligned { }; +static_assert(alignof(MinAligned) == 1 && sizeof(MinAligned) == 1, ""); + +int main() { + for (int i=0; i < 10; ++i) { + try { + throw MinAligned{}; + } catch (MinAligned const& ref) { + assert(reinterpret_cast<uintptr_t>(&ref) % alignof(AlignedType) == 0); + } + } +} Index: src/fallback_malloc.cpp =================================================================== --- src/fallback_malloc.cpp +++ src/fallback_malloc.cpp @@ -196,11 +196,13 @@ #pragma GCC visibility push(hidden) +struct __attribute__((aligned)) __aligned_type {}; + void * __malloc_with_fallback(size_t size) { - void *ptr = std::malloc(size); - if (NULL == ptr) // if malloc fails, fall back to emergency stash - ptr = fallback_malloc(size); - return ptr; + void* dest; + if (::posix_memalign(&dest, alignof(__aligned_type), size) == 0) + return dest; + return fallback_malloc(size); } void * __calloc_with_fallback(size_t count, size_t size) { Index: src/cxa_exception.cpp =================================================================== --- src/cxa_exception.cpp +++ src/cxa_exception.cpp @@ -65,12 +65,16 @@ return cxa_exception_from_thrown_object(unwind_exception + 1 ); } -static -inline -size_t -cxa_exception_size_from_exception_thrown_size(size_t size) -{ - return size + sizeof (__cxa_exception); +// Round s up to next multiple of a. +static inline +size_t aligned_allocation_size(size_t s, size_t a) { + return (s + a - 1) & ~(a - 1); +} + +static inline +size_t cxa_exception_size_from_exception_thrown_size(size_t size) { + return aligned_allocation_size(size + sizeof (__cxa_exception), + alignof(__cxa_exception)); } static void setExceptionClass(_Unwind_Exception* unwind_exception) {
Index: test/test_exception_address_alignment.pass.cpp =================================================================== --- /dev/null +++ test/test_exception_address_alignment.pass.cpp @@ -0,0 +1,28 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// Test that the address of the exception object is properly aligned to the +// largest supported alignment for the system. + +#include <cstdint> +#include <cassert> + +struct __attribute__((aligned)) AlignedType {}; +struct MinAligned { }; +static_assert(alignof(MinAligned) == 1 && sizeof(MinAligned) == 1, ""); + +int main() { + for (int i=0; i < 10; ++i) { + try { + throw MinAligned{}; + } catch (MinAligned const& ref) { + assert(reinterpret_cast<uintptr_t>(&ref) % alignof(AlignedType) == 0); + } + } +} Index: src/fallback_malloc.cpp =================================================================== --- src/fallback_malloc.cpp +++ src/fallback_malloc.cpp @@ -196,11 +196,13 @@ #pragma GCC visibility push(hidden) +struct __attribute__((aligned)) __aligned_type {}; + void * __malloc_with_fallback(size_t size) { - void *ptr = std::malloc(size); - if (NULL == ptr) // if malloc fails, fall back to emergency stash - ptr = fallback_malloc(size); - return ptr; + void* dest; + if (::posix_memalign(&dest, alignof(__aligned_type), size) == 0) + return dest; + return fallback_malloc(size); } void * __calloc_with_fallback(size_t count, size_t size) { Index: src/cxa_exception.cpp =================================================================== --- src/cxa_exception.cpp +++ src/cxa_exception.cpp @@ -65,12 +65,16 @@ return cxa_exception_from_thrown_object(unwind_exception + 1 ); } -static -inline -size_t -cxa_exception_size_from_exception_thrown_size(size_t size) -{ - return size + sizeof (__cxa_exception); +// Round s up to next multiple of a. +static inline +size_t aligned_allocation_size(size_t s, size_t a) { + return (s + a - 1) & ~(a - 1); +} + +static inline +size_t cxa_exception_size_from_exception_thrown_size(size_t size) { + return aligned_allocation_size(size + sizeof (__cxa_exception), + alignof(__cxa_exception)); } static void setExceptionClass(_Unwind_Exception* unwind_exception) {
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits