From 76969eaf3d386df61f4891d439a50b9c471a31e6 Mon Sep 17 00:00:00 2001 From: Kostya Kortchinsky Date: Tue, 12 Jun 2018 14:42:40 +0000 Subject: [scudo] Add C++17 aligned new/delete operators support Summary: This CL adds support for aligned new/delete operators (C++17). Currently we do not support alignment inconsistency detection on deallocation, as this requires a header change, but the APIs are introduced and are functional. Add a smoke test for the aligned version of the operators. Reviewers: alekseyshl Reviewed By: alekseyshl Subscribers: delcypher, #sanitizers, llvm-commits Differential Revision: https://reviews.llvm.org/D48031 llvm-svn: 334505 --- compiler-rt/lib/scudo/scudo_allocator.cpp | 30 ++++---- compiler-rt/lib/scudo/scudo_allocator.h | 6 +- compiler-rt/lib/scudo/scudo_malloc.cpp | 6 +- compiler-rt/lib/scudo/scudo_new_delete.cpp | 107 +++++++++++++++++++---------- 4 files changed, 87 insertions(+), 62 deletions(-) (limited to 'compiler-rt/lib/scudo') diff --git a/compiler-rt/lib/scudo/scudo_allocator.cpp b/compiler-rt/lib/scudo/scudo_allocator.cpp index b497c5a9d5a..fba4b5ac07d 100644 --- a/compiler-rt/lib/scudo/scudo_allocator.cpp +++ b/compiler-rt/lib/scudo/scudo_allocator.cpp @@ -480,7 +480,8 @@ struct ScudoAllocator { // Deallocates a Chunk, which means either adding it to the quarantine or // directly returning it to the backend if criteria are met. - void deallocate(void *Ptr, uptr DeleteSize, AllocType Type) { + void deallocate(void *Ptr, uptr DeleteSize, uptr DeleteAlignment, + AllocType Type) { // For a deallocation, we only ensure minimal initialization, meaning thread // local data will be left uninitialized for now (when using ELF TLS). The // fallback cache will be used instead. This is a workaround for a situation @@ -513,6 +514,7 @@ struct ScudoAllocator { dieWithMessage("invalid sized delete when deallocating address %p\n", Ptr); } + (void)DeleteAlignment; // TODO(kostyak): verify that the alignment matches. quarantineOrDeallocateChunk(Ptr, &Header, Size); } @@ -627,23 +629,23 @@ void ScudoTSD::commitBack() { Instance.commitBack(this); } -void *scudoMalloc(uptr Size, AllocType Type) { - return SetErrnoOnNull(Instance.allocate(Size, MinAlignment, Type)); -} - -void scudoFree(void *Ptr, AllocType Type) { - Instance.deallocate(Ptr, 0, Type); +void *scudoAllocate(uptr Size, uptr Alignment, AllocType Type) { + if (Alignment && UNLIKELY(!IsPowerOfTwo(Alignment))) { + errno = EINVAL; + return Instance.handleBadRequest(); + } + return SetErrnoOnNull(Instance.allocate(Size, Alignment, Type)); } -void scudoSizedFree(void *Ptr, uptr Size, AllocType Type) { - Instance.deallocate(Ptr, Size, Type); +void scudoDeallocate(void *Ptr, uptr Size, uptr Alignment, AllocType Type) { + Instance.deallocate(Ptr, Size, Alignment, Type); } void *scudoRealloc(void *Ptr, uptr Size) { if (!Ptr) return SetErrnoOnNull(Instance.allocate(Size, MinAlignment, FromMalloc)); if (Size == 0) { - Instance.deallocate(Ptr, 0, FromMalloc); + Instance.deallocate(Ptr, 0, 0, FromMalloc); return nullptr; } return SetErrnoOnNull(Instance.reallocate(Ptr, Size)); @@ -669,14 +671,6 @@ void *scudoPvalloc(uptr Size) { return SetErrnoOnNull(Instance.allocate(Size, PageSize, FromMemalign)); } -void *scudoMemalign(uptr Alignment, uptr Size) { - if (UNLIKELY(!IsPowerOfTwo(Alignment))) { - errno = EINVAL; - return Instance.handleBadRequest(); - } - return SetErrnoOnNull(Instance.allocate(Size, Alignment, FromMemalign)); -} - int scudoPosixMemalign(void **MemPtr, uptr Alignment, uptr Size) { if (UNLIKELY(!CheckPosixMemalignAlignment(Alignment))) { Instance.handleBadRequest(); diff --git a/compiler-rt/lib/scudo/scudo_allocator.h b/compiler-rt/lib/scudo/scudo_allocator.h index c29edea4692..f3234fbc95e 100644 --- a/compiler-rt/lib/scudo/scudo_allocator.h +++ b/compiler-rt/lib/scudo/scudo_allocator.h @@ -115,12 +115,10 @@ typedef ScudoCombinedAllocator. namespace std { struct nothrow_t {}; +enum class align_val_t: size_t {}; } // namespace std // TODO(alekseys): throw std::bad_alloc instead of dying on OOM. +#define OPERATOR_NEW_BODY_ALIGN(Type, Align, NoThrow) \ + void *Ptr = scudoAllocate(size, static_cast(Align), Type); \ + if (!NoThrow && UNLIKELY(!Ptr)) DieOnFailure::OnOOM(); \ + return Ptr; +#define OPERATOR_NEW_BODY(Type, NoThrow) \ + OPERATOR_NEW_BODY_ALIGN(Type, 0, NoThrow) + +CXX_OPERATOR_ATTRIBUTE +void *operator new(size_t size) +{ OPERATOR_NEW_BODY(FromNew, /*NoThrow=*/false); } +CXX_OPERATOR_ATTRIBUTE +void *operator new[](size_t size) +{ OPERATOR_NEW_BODY(FromNewArray, /*NoThrow=*/false); } +CXX_OPERATOR_ATTRIBUTE +void *operator new(size_t size, std::nothrow_t const&) +{ OPERATOR_NEW_BODY(FromNew, /*NoThrow=*/true); } +CXX_OPERATOR_ATTRIBUTE +void *operator new[](size_t size, std::nothrow_t const&) +{ OPERATOR_NEW_BODY(FromNewArray, /*NoThrow=*/true); } +CXX_OPERATOR_ATTRIBUTE +void *operator new(size_t size, std::align_val_t align) +{ OPERATOR_NEW_BODY_ALIGN(FromNew, align, /*NoThrow=*/false); } +CXX_OPERATOR_ATTRIBUTE +void *operator new[](size_t size, std::align_val_t align) +{ OPERATOR_NEW_BODY_ALIGN(FromNewArray, align, /*NoThrow=*/false); } +CXX_OPERATOR_ATTRIBUTE +void *operator new(size_t size, std::align_val_t align, std::nothrow_t const&) +{ OPERATOR_NEW_BODY_ALIGN(FromNew, align, /*NoThrow=*/true); } CXX_OPERATOR_ATTRIBUTE -void *operator new(size_t size) { - void *res = scudoMalloc(size, FromNew); - if (UNLIKELY(!res)) DieOnFailure::OnOOM(); - return res; -} -CXX_OPERATOR_ATTRIBUTE -void *operator new[](size_t size) { - void *res = scudoMalloc(size, FromNewArray); - if (UNLIKELY(!res)) DieOnFailure::OnOOM(); - return res; -} -CXX_OPERATOR_ATTRIBUTE -void *operator new(size_t size, std::nothrow_t const&) { - return scudoMalloc(size, FromNew); -} -CXX_OPERATOR_ATTRIBUTE -void *operator new[](size_t size, std::nothrow_t const&) { - return scudoMalloc(size, FromNewArray); -} +void *operator new[](size_t size, std::align_val_t align, std::nothrow_t const&) +{ OPERATOR_NEW_BODY_ALIGN(FromNewArray, align, /*NoThrow=*/true); } +#define OPERATOR_DELETE_BODY(Type) \ + scudoDeallocate(ptr, 0, 0, Type); +#define OPERATOR_DELETE_BODY_SIZE(Type) \ + scudoDeallocate(ptr, size, 0, Type); +#define OPERATOR_DELETE_BODY_ALIGN(Type) \ + scudoDeallocate(ptr, 0, static_cast(align), Type); +#define OPERATOR_DELETE_BODY_SIZE_ALIGN(Type) \ + scudoDeallocate(ptr, size, static_cast(align), Type); + +CXX_OPERATOR_ATTRIBUTE +void operator delete(void *ptr) NOEXCEPT +{ OPERATOR_DELETE_BODY(FromNew); } +CXX_OPERATOR_ATTRIBUTE +void operator delete[](void *ptr) NOEXCEPT +{ OPERATOR_DELETE_BODY(FromNewArray); } +CXX_OPERATOR_ATTRIBUTE +void operator delete(void *ptr, std::nothrow_t const&) +{ OPERATOR_DELETE_BODY(FromNew); } +CXX_OPERATOR_ATTRIBUTE +void operator delete[](void *ptr, std::nothrow_t const&) +{ OPERATOR_DELETE_BODY(FromNewArray); } +CXX_OPERATOR_ATTRIBUTE +void operator delete(void *ptr, size_t size) NOEXCEPT +{ OPERATOR_DELETE_BODY_SIZE(FromNew); } +CXX_OPERATOR_ATTRIBUTE +void operator delete[](void *ptr, size_t size) NOEXCEPT +{ OPERATOR_DELETE_BODY_SIZE(FromNewArray); } CXX_OPERATOR_ATTRIBUTE -void operator delete(void *ptr) NOEXCEPT { - return scudoFree(ptr, FromNew); -} +void operator delete(void *ptr, std::align_val_t align) NOEXCEPT +{ OPERATOR_DELETE_BODY_ALIGN(FromNew); } CXX_OPERATOR_ATTRIBUTE -void operator delete[](void *ptr) NOEXCEPT { - return scudoFree(ptr, FromNewArray); -} +void operator delete[](void *ptr, std::align_val_t align) NOEXCEPT +{ OPERATOR_DELETE_BODY_ALIGN(FromNewArray); } CXX_OPERATOR_ATTRIBUTE -void operator delete(void *ptr, std::nothrow_t const&) NOEXCEPT { - return scudoFree(ptr, FromNew); -} +void operator delete(void *ptr, std::align_val_t align, std::nothrow_t const&) +{ OPERATOR_DELETE_BODY_ALIGN(FromNew); } CXX_OPERATOR_ATTRIBUTE -void operator delete[](void *ptr, std::nothrow_t const&) NOEXCEPT { - return scudoFree(ptr, FromNewArray); -} +void operator delete[](void *ptr, std::align_val_t align, std::nothrow_t const&) +{ OPERATOR_DELETE_BODY_ALIGN(FromNewArray); } CXX_OPERATOR_ATTRIBUTE -void operator delete(void *ptr, size_t size) NOEXCEPT { - scudoSizedFree(ptr, size, FromNew); -} +void operator delete(void *ptr, size_t size, std::align_val_t align) NOEXCEPT +{ OPERATOR_DELETE_BODY_SIZE_ALIGN(FromNew); } CXX_OPERATOR_ATTRIBUTE -void operator delete[](void *ptr, size_t size) NOEXCEPT { - scudoSizedFree(ptr, size, FromNewArray); -} +void operator delete[](void *ptr, size_t size, std::align_val_t align) NOEXCEPT +{ OPERATOR_DELETE_BODY_SIZE_ALIGN(FromNewArray); } -- cgit v1.2.3