diff options
| author | Kostya Kortchinsky <kostyak@google.com> | 2018-06-12 14:42:40 +0000 |
|---|---|---|
| committer | Kostya Kortchinsky <kostyak@google.com> | 2018-06-12 14:42:40 +0000 |
| commit | 76969eaf3d386df61f4891d439a50b9c471a31e6 (patch) | |
| tree | 9bdf07546facf9c59bdfe2a318f34f3742e767a9 /compiler-rt/lib/scudo | |
| parent | c3466d2568f5f949d9caf229ab2301b5a79cacaf (diff) | |
| download | bcm5719-llvm-76969eaf3d386df61f4891d439a50b9c471a31e6.tar.gz bcm5719-llvm-76969eaf3d386df61f4891d439a50b9c471a31e6.zip | |
[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
Diffstat (limited to 'compiler-rt/lib/scudo')
| -rw-r--r-- | compiler-rt/lib/scudo/scudo_allocator.cpp | 30 | ||||
| -rw-r--r-- | compiler-rt/lib/scudo/scudo_allocator.h | 6 | ||||
| -rw-r--r-- | compiler-rt/lib/scudo/scudo_malloc.cpp | 6 | ||||
| -rw-r--r-- | compiler-rt/lib/scudo/scudo_new_delete.cpp | 107 |
4 files changed, 87 insertions, 62 deletions
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<PrimaryAllocator, AllocatorCache, void initScudo(); -void *scudoMalloc(uptr Size, AllocType Type); -void scudoFree(void *Ptr, AllocType Type); -void scudoSizedFree(void *Ptr, uptr Size, AllocType Type); +void *scudoAllocate(uptr Size, uptr Alignment, AllocType Type); +void scudoDeallocate(void *Ptr, uptr Size, uptr Alignment, AllocType Type); void *scudoRealloc(void *Ptr, uptr Size); void *scudoCalloc(uptr NMemB, uptr Size); -void *scudoMemalign(uptr Alignment, uptr Size); void *scudoValloc(uptr Size); void *scudoPvalloc(uptr Size); int scudoPosixMemalign(void **MemPtr, uptr Alignment, uptr Size); diff --git a/compiler-rt/lib/scudo/scudo_malloc.cpp b/compiler-rt/lib/scudo/scudo_malloc.cpp index eb1047ac075..6e83be42224 100644 --- a/compiler-rt/lib/scudo/scudo_malloc.cpp +++ b/compiler-rt/lib/scudo/scudo_malloc.cpp @@ -20,11 +20,11 @@ using namespace __scudo; extern "C" { INTERCEPTOR_ATTRIBUTE void free(void *ptr) { - scudoFree(ptr, FromMalloc); + scudoDeallocate(ptr, 0, 0, FromMalloc); } INTERCEPTOR_ATTRIBUTE void *malloc(SIZE_T size) { - return scudoMalloc(size, FromMalloc); + return scudoAllocate(size, 0, FromMalloc); } INTERCEPTOR_ATTRIBUTE void *realloc(void *ptr, SIZE_T size) { @@ -50,7 +50,7 @@ INTERCEPTOR_ATTRIBUTE void cfree(void *ptr) ALIAS("free"); #if SANITIZER_INTERCEPT_MEMALIGN INTERCEPTOR_ATTRIBUTE void *memalign(SIZE_T alignment, SIZE_T size) { - return scudoMemalign(alignment, size); + return scudoAllocate(size, alignment, FromMemalign); } INTERCEPTOR_ATTRIBUTE diff --git a/compiler-rt/lib/scudo/scudo_new_delete.cpp b/compiler-rt/lib/scudo/scudo_new_delete.cpp index c5a1abbed82..948d07a5210 100644 --- a/compiler-rt/lib/scudo/scudo_new_delete.cpp +++ b/compiler-rt/lib/scudo/scudo_new_delete.cpp @@ -24,51 +24,84 @@ using namespace __scudo; // Fake std::nothrow_t to avoid including <new>. 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<uptr>(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<uptr>(align), Type); +#define OPERATOR_DELETE_BODY_SIZE_ALIGN(Type) \ + scudoDeallocate(ptr, size, static_cast<uptr>(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); } |

