[compiler-rt] r334505 - [scudo] Add C++17 aligned new/delete operators support
Kostya Kortchinsky via llvm-commits
llvm-commits at lists.llvm.org
Tue Jun 12 07:42:41 PDT 2018
Author: cryptoad
Date: Tue Jun 12 07:42:40 2018
New Revision: 334505
URL: http://llvm.org/viewvc/llvm-project?rev=334505&view=rev
Log:
[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
Added:
compiler-rt/trunk/test/scudo/aligned-new.cpp
Modified:
compiler-rt/trunk/lib/scudo/scudo_allocator.cpp
compiler-rt/trunk/lib/scudo/scudo_allocator.h
compiler-rt/trunk/lib/scudo/scudo_malloc.cpp
compiler-rt/trunk/lib/scudo/scudo_new_delete.cpp
Modified: compiler-rt/trunk/lib/scudo/scudo_allocator.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/scudo/scudo_allocator.cpp?rev=334505&r1=334504&r2=334505&view=diff
==============================================================================
--- compiler-rt/trunk/lib/scudo/scudo_allocator.cpp (original)
+++ compiler-rt/trunk/lib/scudo/scudo_allocator.cpp Tue Jun 12 07:42:40 2018
@@ -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();
Modified: compiler-rt/trunk/lib/scudo/scudo_allocator.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/scudo/scudo_allocator.h?rev=334505&r1=334504&r2=334505&view=diff
==============================================================================
--- compiler-rt/trunk/lib/scudo/scudo_allocator.h (original)
+++ compiler-rt/trunk/lib/scudo/scudo_allocator.h Tue Jun 12 07:42:40 2018
@@ -115,12 +115,10 @@ typedef ScudoCombinedAllocator<PrimaryAl
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);
Modified: compiler-rt/trunk/lib/scudo/scudo_malloc.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/scudo/scudo_malloc.cpp?rev=334505&r1=334504&r2=334505&view=diff
==============================================================================
--- compiler-rt/trunk/lib/scudo/scudo_malloc.cpp (original)
+++ compiler-rt/trunk/lib/scudo/scudo_malloc.cpp Tue Jun 12 07:42:40 2018
@@ -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 *p
#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
Modified: compiler-rt/trunk/lib/scudo/scudo_new_delete.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/scudo/scudo_new_delete.cpp?rev=334505&r1=334504&r2=334505&view=diff
==============================================================================
--- compiler-rt/trunk/lib/scudo/scudo_new_delete.cpp (original)
+++ compiler-rt/trunk/lib/scudo/scudo_new_delete.cpp Tue Jun 12 07:42:40 2018
@@ -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) {
- 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)
+{ 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, 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, std::align_val_t align) NOEXCEPT
+{ OPERATOR_DELETE_BODY_ALIGN(FromNew); }
+CXX_OPERATOR_ATTRIBUTE
+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::align_val_t align, std::nothrow_t const&)
+{ OPERATOR_DELETE_BODY_ALIGN(FromNew); }
+CXX_OPERATOR_ATTRIBUTE
+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, std::align_val_t align) NOEXCEPT
+{ OPERATOR_DELETE_BODY_SIZE_ALIGN(FromNew); }
CXX_OPERATOR_ATTRIBUTE
-void operator delete(void *ptr) NOEXCEPT {
- return scudoFree(ptr, FromNew);
-}
-CXX_OPERATOR_ATTRIBUTE
-void operator delete[](void *ptr) NOEXCEPT {
- return scudoFree(ptr, FromNewArray);
-}
-CXX_OPERATOR_ATTRIBUTE
-void operator delete(void *ptr, std::nothrow_t const&) NOEXCEPT {
- return scudoFree(ptr, FromNew);
-}
-CXX_OPERATOR_ATTRIBUTE
-void operator delete[](void *ptr, std::nothrow_t const&) NOEXCEPT {
- return scudoFree(ptr, FromNewArray);
-}
-CXX_OPERATOR_ATTRIBUTE
-void operator delete(void *ptr, size_t size) NOEXCEPT {
- scudoSizedFree(ptr, size, 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); }
Added: compiler-rt/trunk/test/scudo/aligned-new.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/scudo/aligned-new.cpp?rev=334505&view=auto
==============================================================================
--- compiler-rt/trunk/test/scudo/aligned-new.cpp (added)
+++ compiler-rt/trunk/test/scudo/aligned-new.cpp Tue Jun 12 07:42:40 2018
@@ -0,0 +1,84 @@
+// RUN: %clangxx_scudo -std=c++1z -faligned-allocation %s -o %t
+// RUN: %run %t valid 2>&1
+// RUN: %env_scudo_opts=allocator_may_return_null=1 %run %t invalid 2>&1
+
+// Tests that the C++17 aligned new/delete operators are working as expected.
+// Currently we do not check the consistency of the alignment on deallocation,
+// so this just tests that the APIs work.
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+
+// Define all new/delete to not depend on the version provided by the platform.
+
+namespace std {
+struct nothrow_t {};
+static const nothrow_t nothrow;
+enum class align_val_t : size_t {};
+} // namespace std
+
+void *operator new(size_t);
+void *operator new[](size_t);
+void *operator new(size_t, std::nothrow_t const&);
+void *operator new[](size_t, std::nothrow_t const&);
+void *operator new(size_t, std::align_val_t);
+void *operator new[](size_t, std::align_val_t);
+void *operator new(size_t, std::align_val_t, std::nothrow_t const&);
+void *operator new[](size_t, std::align_val_t, std::nothrow_t const&);
+
+void operator delete(void*) throw();
+void operator delete[](void*) throw();
+void operator delete(void*, std::nothrow_t const&);
+void operator delete[](void*, std::nothrow_t const&);
+void operator delete(void*, size_t) throw();
+void operator delete[](void*, size_t) throw();
+void operator delete(void*, std::align_val_t) throw();
+void operator delete[](void*, std::align_val_t) throw();
+void operator delete(void*, std::align_val_t, std::nothrow_t const&);
+void operator delete[](void*, std::align_val_t, std::nothrow_t const&);
+void operator delete(void*, size_t, std::align_val_t) throw();
+void operator delete[](void*, size_t, std::align_val_t) throw();
+
+template<typename T>
+inline T* break_optimization(T *arg) {
+ __asm__ __volatile__("" : : "r" (arg) : "memory");
+ return arg;
+}
+
+struct S12 { int a, b, c; };
+struct alignas(128) S12_128 { int a, b, c; };
+struct alignas(256) S12_256 { int a, b, c; };
+struct alignas(512) S1024_512 { char a[1024]; };
+struct alignas(1024) S1024_1024 { char a[1024]; };
+
+int main(int argc, char **argv) {
+ assert(argc == 2);
+
+ if (!strcmp(argv[1], "valid")) {
+ // Standard use case.
+ delete break_optimization(new S12);
+ delete break_optimization(new S12_128);
+ delete[] break_optimization(new S12_128[4]);
+ delete break_optimization(new S12_256);
+ delete break_optimization(new S1024_512);
+ delete[] break_optimization(new S1024_512[4]);
+ delete break_optimization(new S1024_1024);
+
+ // Call directly the aligned versions of the operators.
+ const size_t alignment = 1U << 8;
+ void *p = operator new(1, static_cast<std::align_val_t>(alignment));
+ assert((reinterpret_cast<uintptr_t>(p) & (alignment - 1)) == 0);
+ operator delete(p, static_cast<std::align_val_t>(alignment));
+ }
+ if (!strcmp(argv[1], "invalid")) {
+ // Alignment must be a power of 2.
+ const size_t alignment = (1U << 8) - 1;
+ void *p = operator new(1, static_cast<std::align_val_t>(alignment),
+ std::nothrow);
+ assert(!p);
+ }
+
+ return 0;
+}
More information about the llvm-commits
mailing list