[compiler-rt] 8885296 - [scudo] Add SCUDO_ENABLE_HOOKS to enable hooks at compilation time
Chia-hung Duan via llvm-commits
llvm-commits at lists.llvm.org
Mon Aug 28 15:16:38 PDT 2023
Author: Chia-hung Duan
Date: 2023-08-28T22:11:18Z
New Revision: 88852964ecae94be71e98e9881ed8ed182df8c0c
URL: https://github.com/llvm/llvm-project/commit/88852964ecae94be71e98e9881ed8ed182df8c0c
DIFF: https://github.com/llvm/llvm-project/commit/88852964ecae94be71e98e9881ed8ed182df8c0c.diff
LOG: [scudo] Add SCUDO_ENABLE_HOOKS to enable hooks at compilation time
Accessing the PLT entries of hooks can lead a certain amount of
performance overhead. This is observed on certain tasks which will do a
bunch of malloc/free and their throughputs are impacted by the null
check of hooks.
Also add SCUDO_ENABLE_HOOKS_TESTS to select if we want to run the hook
tests. On some platforms they may have different ways to run the
wrappers tests (end-to-end tests) and test the hooks along with the
wrappers tests may not be feasible. Provide an option to turn it ON/OFF.
By default, we only verify the hook behavior in the scudo standalone
tests if SCUDO_ENABLE_HOOKS is defined or COMPILER_RT_DEBUG is true.
Reviewed By: cferris, fabio-d
Differential Revision: https://reviews.llvm.org/D158784
Added:
Modified:
compiler-rt/lib/scudo/standalone/CMakeLists.txt
compiler-rt/lib/scudo/standalone/platform.h
compiler-rt/lib/scudo/standalone/tests/CMakeLists.txt
compiler-rt/lib/scudo/standalone/tests/wrappers_c_test.cpp
compiler-rt/lib/scudo/standalone/tests/wrappers_cpp_test.cpp
compiler-rt/lib/scudo/standalone/wrappers_c.cpp
compiler-rt/lib/scudo/standalone/wrappers_c.inc
compiler-rt/lib/scudo/standalone/wrappers_c_bionic.cpp
compiler-rt/lib/scudo/standalone/wrappers_cpp.cpp
Removed:
################################################################################
diff --git a/compiler-rt/lib/scudo/standalone/CMakeLists.txt b/compiler-rt/lib/scudo/standalone/CMakeLists.txt
index a5d9a4651c2039..52c3a2e5a52956 100644
--- a/compiler-rt/lib/scudo/standalone/CMakeLists.txt
+++ b/compiler-rt/lib/scudo/standalone/CMakeLists.txt
@@ -25,7 +25,7 @@ append_list_if(COMPILER_RT_HAS_WNO_PEDANTIC -Wno-pedantic SCUDO_CFLAGS)
append_list_if(COMPILER_RT_HAS_FNO_LTO_FLAG -fno-lto SCUDO_CFLAGS)
if(COMPILER_RT_DEBUG)
- list(APPEND SCUDO_CFLAGS -O0 -DSCUDO_DEBUG=1)
+ list(APPEND SCUDO_CFLAGS -O0 -DSCUDO_DEBUG=1 -DSCUDO_ENABLE_HOOKS=1)
else()
list(APPEND SCUDO_CFLAGS -O3)
endif()
diff --git a/compiler-rt/lib/scudo/standalone/platform.h b/compiler-rt/lib/scudo/standalone/platform.h
index 7504c9d142f990..b71a86be7669f3 100644
--- a/compiler-rt/lib/scudo/standalone/platform.h
+++ b/compiler-rt/lib/scudo/standalone/platform.h
@@ -73,6 +73,10 @@
#endif
#endif
+#ifndef SCUDO_ENABLE_HOOKS
+#define SCUDO_ENABLE_HOOKS 0
+#endif
+
#ifndef SCUDO_MIN_ALIGNMENT_LOG
// We force malloc-type functions to be aligned to std::max_align_t, but there
// is no reason why the minimum alignment for all other functions can't be 8
diff --git a/compiler-rt/lib/scudo/standalone/tests/CMakeLists.txt b/compiler-rt/lib/scudo/standalone/tests/CMakeLists.txt
index 71ad3830c88ca3..e5d32f33d8cc4a 100644
--- a/compiler-rt/lib/scudo/standalone/tests/CMakeLists.txt
+++ b/compiler-rt/lib/scudo/standalone/tests/CMakeLists.txt
@@ -19,7 +19,10 @@ set(SCUDO_UNITTEST_CFLAGS
-Wno-mismatched-new-delete)
if(COMPILER_RT_DEBUG)
- list(APPEND SCUDO_UNITTEST_CFLAGS -DSCUDO_DEBUG=1)
+ list(APPEND SCUDO_UNITTEST_CFLAGS -DSCUDO_DEBUG=1 -DSCUDO_ENABLE_HOOKS=1)
+ if (NOT FUCHSIA)
+ list(APPEND SCUDO_UNITTEST_CFLAGS -DSCUDO_ENABLE_HOOKS_TESTS=1)
+ endif()
endif()
if(ANDROID)
diff --git a/compiler-rt/lib/scudo/standalone/tests/wrappers_c_test.cpp b/compiler-rt/lib/scudo/standalone/tests/wrappers_c_test.cpp
index d0cc0fa3c6508c..0e82813df8c0d5 100644
--- a/compiler-rt/lib/scudo/standalone/tests/wrappers_c_test.cpp
+++ b/compiler-rt/lib/scudo/standalone/tests/wrappers_c_test.cpp
@@ -37,6 +37,23 @@
#define HAVE_VALLOC 1
#endif
+extern "C" {
+void malloc_enable(void);
+void malloc_disable(void);
+int malloc_iterate(uintptr_t base, size_t size,
+ void (*callback)(uintptr_t base, size_t size, void *arg),
+ void *arg);
+void *valloc(size_t size);
+void *pvalloc(size_t size);
+
+#ifndef SCUDO_ENABLE_HOOKS_TESTS
+#define SCUDO_ENABLE_HOOKS_TESTS 0
+#endif
+
+#if (SCUDO_ENABLE_HOOKS_TESTS == 1) && (SCUDO_ENABLE_HOOKS == 0)
+#error "Hooks tests should have hooks enabled as well!"
+#endif
+
struct AllocContext {
void *Ptr;
size_t Size;
@@ -47,15 +64,7 @@ struct DeallocContext {
static AllocContext AC;
static DeallocContext DC;
-extern "C" {
-void malloc_enable(void);
-void malloc_disable(void);
-int malloc_iterate(uintptr_t base, size_t size,
- void (*callback)(uintptr_t base, size_t size, void *arg),
- void *arg);
-void *valloc(size_t size);
-void *pvalloc(size_t size);
-
+#if (SCUDO_ENABLE_HOOKS_TESTS == 1)
__attribute__((visibility("default"))) void __scudo_allocate_hook(void *Ptr,
size_t Size) {
AC.Ptr = Ptr;
@@ -64,8 +73,35 @@ __attribute__((visibility("default"))) void __scudo_allocate_hook(void *Ptr,
__attribute__((visibility("default"))) void __scudo_deallocate_hook(void *Ptr) {
DC.Ptr = Ptr;
}
+#endif // (SCUDO_ENABLE_HOOKS_TESTS == 1)
}
+class ScudoWrappersCTest : public Test {
+protected:
+ void SetUp() override {
+ if (SCUDO_ENABLE_HOOKS && !SCUDO_ENABLE_HOOKS_TESTS)
+ printf("Hooks are enabled but hooks tests are disabled.\n");
+ }
+
+ void invalidateAllocHookPtrAs(UNUSED void *Ptr) {
+ if (SCUDO_ENABLE_HOOKS_TESTS)
+ AC.Ptr = Ptr;
+ }
+ void verifyAllocHookPtr(UNUSED void *Ptr) {
+ if (SCUDO_ENABLE_HOOKS_TESTS)
+ EXPECT_EQ(Ptr, AC.Ptr);
+ }
+ void verifyAllocHookSize(UNUSED size_t Size) {
+ if (SCUDO_ENABLE_HOOKS_TESTS)
+ EXPECT_EQ(Size, AC.Size);
+ }
+ void verifyDeallocHookPtr(UNUSED void *Ptr) {
+ if (SCUDO_ENABLE_HOOKS_TESTS)
+ EXPECT_EQ(Ptr, DC.Ptr);
+ }
+};
+using ScudoWrappersCDeathTest = ScudoWrappersCTest;
+
// Note that every C allocation function in the test binary will be fulfilled
// by Scudo (this includes the gtest APIs, etc.), which is a test by itself.
// But this might also lead to unexpected side-effects, since the allocation and
@@ -78,13 +114,13 @@ __attribute__((visibility("default"))) void __scudo_deallocate_hook(void *Ptr) {
static const size_t Size = 100U;
-TEST(ScudoWrappersCDeathTest, Malloc) {
+TEST_F(ScudoWrappersCDeathTest, Malloc) {
void *P = malloc(Size);
EXPECT_NE(P, nullptr);
EXPECT_LE(Size, malloc_usable_size(P));
EXPECT_EQ(reinterpret_cast<uintptr_t>(P) % FIRST_32_SECOND_64(8U, 16U), 0U);
- EXPECT_EQ(P, AC.Ptr);
- EXPECT_EQ(Size, AC.Size);
+ verifyAllocHookPtr(P);
+ verifyAllocHookSize(Size);
// An update to this warning in Clang now triggers in this line, but it's ok
// because the check is expecting a bad pointer and should fail.
@@ -99,7 +135,7 @@ TEST(ScudoWrappersCDeathTest, Malloc) {
#endif
free(P);
- EXPECT_EQ(P, DC.Ptr);
+ verifyDeallocHookPtr(P);
EXPECT_DEATH(free(P), "");
P = malloc(0U);
@@ -111,16 +147,16 @@ TEST(ScudoWrappersCDeathTest, Malloc) {
EXPECT_EQ(errno, ENOMEM);
}
-TEST(ScudoWrappersCTest, Calloc) {
+TEST_F(ScudoWrappersCTest, Calloc) {
void *P = calloc(1U, Size);
EXPECT_NE(P, nullptr);
EXPECT_LE(Size, malloc_usable_size(P));
- EXPECT_EQ(P, AC.Ptr);
- EXPECT_EQ(Size, AC.Size);
+ verifyAllocHookPtr(P);
+ verifyAllocHookSize(Size);
for (size_t I = 0; I < Size; I++)
EXPECT_EQ((reinterpret_cast<uint8_t *>(P))[I], 0U);
free(P);
- EXPECT_EQ(P, DC.Ptr);
+ verifyDeallocHookPtr(P);
P = calloc(1U, 0U);
EXPECT_NE(P, nullptr);
@@ -141,7 +177,7 @@ TEST(ScudoWrappersCTest, Calloc) {
EXPECT_EQ(errno, ENOMEM);
}
-TEST(ScudoWrappersCTest, SmallAlign) {
+TEST_F(ScudoWrappersCTest, SmallAlign) {
// Allocating pointers by the powers of 2 from 1 to 0x10000
// Using powers of 2 due to memalign using powers of 2 and test more sizes
constexpr size_t MaxSize = 0x10000;
@@ -162,7 +198,7 @@ TEST(ScudoWrappersCTest, SmallAlign) {
free(ptr);
}
-TEST(ScudoWrappersCTest, Memalign) {
+TEST_F(ScudoWrappersCTest, Memalign) {
void *P;
for (size_t I = FIRST_32_SECOND_64(2U, 3U); I <= 18U; I++) {
const size_t Alignment = 1U << I;
@@ -171,20 +207,20 @@ TEST(ScudoWrappersCTest, Memalign) {
EXPECT_NE(P, nullptr);
EXPECT_LE(Size, malloc_usable_size(P));
EXPECT_EQ(reinterpret_cast<uintptr_t>(P) % Alignment, 0U);
- EXPECT_EQ(P, AC.Ptr);
- EXPECT_EQ(Size, AC.Size);
+ verifyAllocHookPtr(P);
+ verifyAllocHookSize(Size);
free(P);
- EXPECT_EQ(P, DC.Ptr);
+ verifyDeallocHookPtr(P);
P = nullptr;
EXPECT_EQ(posix_memalign(&P, Alignment, Size), 0);
EXPECT_NE(P, nullptr);
EXPECT_LE(Size, malloc_usable_size(P));
EXPECT_EQ(reinterpret_cast<uintptr_t>(P) % Alignment, 0U);
- EXPECT_EQ(P, AC.Ptr);
- EXPECT_EQ(Size, AC.Size);
+ verifyAllocHookPtr(P);
+ verifyAllocHookSize(Size);
free(P);
- EXPECT_EQ(P, DC.Ptr);
+ verifyDeallocHookPtr(P);
}
EXPECT_EQ(memalign(4096U, SIZE_MAX), nullptr);
@@ -196,24 +232,24 @@ TEST(ScudoWrappersCTest, Memalign) {
for (size_t Alignment = 0U; Alignment <= 128U; Alignment++) {
P = memalign(Alignment, 1024U);
EXPECT_NE(P, nullptr);
- EXPECT_EQ(P, AC.Ptr);
- EXPECT_EQ(Size, AC.Size);
+ verifyAllocHookPtr(P);
+ verifyAllocHookSize(Size);
free(P);
- EXPECT_EQ(P, DC.Ptr);
+ verifyDeallocHookPtr(P);
}
}
}
-TEST(ScudoWrappersCTest, AlignedAlloc) {
+TEST_F(ScudoWrappersCTest, AlignedAlloc) {
const size_t Alignment = 4096U;
void *P = aligned_alloc(Alignment, Alignment * 4U);
EXPECT_NE(P, nullptr);
EXPECT_LE(Alignment * 4U, malloc_usable_size(P));
EXPECT_EQ(reinterpret_cast<uintptr_t>(P) % Alignment, 0U);
- EXPECT_EQ(P, AC.Ptr);
- EXPECT_EQ(Alignment * 4U, AC.Size);
+ verifyAllocHookPtr(P);
+ verifyAllocHookSize(Alignment * 4U);
free(P);
- EXPECT_EQ(P, DC.Ptr);
+ verifyDeallocHookPtr(P);
errno = 0;
P = aligned_alloc(Alignment, Size);
@@ -221,27 +257,27 @@ TEST(ScudoWrappersCTest, AlignedAlloc) {
EXPECT_EQ(errno, EINVAL);
}
-TEST(ScudoWrappersCDeathTest, Realloc) {
+TEST_F(ScudoWrappersCDeathTest, Realloc) {
// realloc(nullptr, N) is malloc(N)
void *P = realloc(nullptr, Size);
EXPECT_NE(P, nullptr);
- EXPECT_EQ(P, AC.Ptr);
- EXPECT_EQ(Size, AC.Size);
+ verifyAllocHookPtr(P);
+ verifyAllocHookSize(Size);
free(P);
- EXPECT_EQ(P, DC.Ptr);
+ verifyDeallocHookPtr(P);
P = malloc(Size);
EXPECT_NE(P, nullptr);
// realloc(P, 0U) is free(P) and returns nullptr
EXPECT_EQ(realloc(P, 0U), nullptr);
- EXPECT_EQ(P, DC.Ptr);
+ verifyDeallocHookPtr(P);
P = malloc(Size);
EXPECT_NE(P, nullptr);
EXPECT_LE(Size, malloc_usable_size(P));
memset(P, 0x42, Size);
- AC.Ptr = reinterpret_cast<void *>(0xdeadbeef);
+ invalidateAllocHookPtrAs(reinterpret_cast<void *>(0xdeadbeef));
void *OldP = P;
P = realloc(P, Size * 2U);
EXPECT_NE(P, nullptr);
@@ -249,14 +285,14 @@ TEST(ScudoWrappersCDeathTest, Realloc) {
for (size_t I = 0; I < Size; I++)
EXPECT_EQ(0x42, (reinterpret_cast<uint8_t *>(P))[I]);
if (OldP == P) {
- EXPECT_EQ(AC.Ptr, reinterpret_cast<void *>(0xdeadbeef));
+ verifyAllocHookPtr(reinterpret_cast<void *>(0xdeadbeef));
} else {
- EXPECT_EQ(P, AC.Ptr);
- EXPECT_EQ(Size * 2U, AC.Size);
- EXPECT_EQ(OldP, DC.Ptr);
+ verifyAllocHookPtr(P);
+ verifyAllocHookSize(Size * 2U);
+ verifyDeallocHookPtr(OldP);
}
- AC.Ptr = reinterpret_cast<void *>(0xdeadbeef);
+ invalidateAllocHookPtrAs(reinterpret_cast<void *>(0xdeadbeef));
OldP = P;
P = realloc(P, Size / 2U);
EXPECT_NE(P, nullptr);
@@ -264,10 +300,10 @@ TEST(ScudoWrappersCDeathTest, Realloc) {
for (size_t I = 0; I < Size / 2U; I++)
EXPECT_EQ(0x42, (reinterpret_cast<uint8_t *>(P))[I]);
if (OldP == P) {
- EXPECT_EQ(AC.Ptr, reinterpret_cast<void *>(0xdeadbeef));
+ verifyAllocHookPtr(reinterpret_cast<void *>(0xdeadbeef));
} else {
- EXPECT_EQ(P, AC.Ptr);
- EXPECT_EQ(Size / 2U, AC.Size);
+ verifyAllocHookPtr(P);
+ verifyAllocHookSize(Size / 2U);
}
free(P);
@@ -302,7 +338,7 @@ TEST(ScudoWrappersCDeathTest, Realloc) {
}
#if !SCUDO_FUCHSIA
-TEST(ScudoWrappersCTest, MallOpt) {
+TEST_F(ScudoWrappersCTest, MallOpt) {
errno = 0;
EXPECT_EQ(mallopt(-1000, 1), 0);
// mallopt doesn't set errno.
@@ -323,7 +359,7 @@ TEST(ScudoWrappersCTest, MallOpt) {
}
#endif
-TEST(ScudoWrappersCTest, OtherAlloc) {
+TEST_F(ScudoWrappersCTest, OtherAlloc) {
#if HAVE_PVALLOC
const size_t PageSize = static_cast<size_t>(sysconf(_SC_PAGESIZE));
@@ -331,11 +367,11 @@ TEST(ScudoWrappersCTest, OtherAlloc) {
EXPECT_NE(P, nullptr);
EXPECT_EQ(reinterpret_cast<uintptr_t>(P) & (PageSize - 1), 0U);
EXPECT_LE(PageSize, malloc_usable_size(P));
- EXPECT_EQ(P, AC.Ptr);
+ verifyAllocHookPtr(P);
// Size will be rounded up to PageSize.
- EXPECT_EQ(PageSize, AC.Size);
+ verifyAllocHookSize(PageSize);
free(P);
- EXPECT_EQ(P, DC.Ptr);
+ verifyDeallocHookPtr(P);
EXPECT_EQ(pvalloc(SIZE_MAX), nullptr);
@@ -351,7 +387,7 @@ TEST(ScudoWrappersCTest, OtherAlloc) {
}
#if !SCUDO_FUCHSIA
-TEST(ScudoWrappersCTest, MallInfo) {
+TEST_F(ScudoWrappersCTest, MallInfo) {
// mallinfo is deprecated.
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
@@ -372,7 +408,7 @@ TEST(ScudoWrappersCTest, MallInfo) {
#endif
#if __GLIBC_PREREQ(2, 33)
-TEST(ScudoWrappersCTest, MallInfo2) {
+TEST_F(ScudoWrappersCTest, MallInfo2) {
const size_t BypassQuarantineSize = 1024U;
struct mallinfo2 MI = mallinfo2();
size_t Allocated = MI.uordblks;
@@ -404,7 +440,7 @@ static void callback(uintptr_t Base, UNUSED size_t Size, UNUSED void *Arg) {
// To achieve this, we allocate a chunk for which the backing block will be
// aligned on a page, then run the malloc_iterate on both the pages that the
// block is a boundary for. It must only be seen once by the callback function.
-TEST(ScudoWrappersCTest, MallocIterateBoundary) {
+TEST_F(ScudoWrappersCTest, MallocIterateBoundary) {
const size_t PageSize = static_cast<size_t>(sysconf(_SC_PAGESIZE));
#if SCUDO_ANDROID
// Android uses a 16 byte alignment for both 32 bit and 64 bit.
@@ -456,7 +492,7 @@ TEST(ScudoWrappersCTest, MallocIterateBoundary) {
// Fuchsia doesn't have alarm, fork or malloc_info.
#if !SCUDO_FUCHSIA
-TEST(ScudoWrappersCDeathTest, MallocDisableDeadlock) {
+TEST_F(ScudoWrappersCDeathTest, MallocDisableDeadlock) {
// We expect heap operations within a disable/enable scope to deadlock.
EXPECT_DEATH(
{
@@ -471,7 +507,7 @@ TEST(ScudoWrappersCDeathTest, MallocDisableDeadlock) {
"");
}
-TEST(ScudoWrappersCTest, MallocInfo) {
+TEST_F(ScudoWrappersCTest, MallocInfo) {
// Use volatile so that the allocations don't get optimized away.
void *volatile P1 = malloc(1234);
void *volatile P2 = malloc(4321);
@@ -491,7 +527,7 @@ TEST(ScudoWrappersCTest, MallocInfo) {
free(P2);
}
-TEST(ScudoWrappersCDeathTest, Fork) {
+TEST_F(ScudoWrappersCDeathTest, Fork) {
void *P;
pid_t Pid = fork();
EXPECT_GE(Pid, 0) << strerror(errno);
@@ -543,7 +579,7 @@ static void *enableMalloc(UNUSED void *Unused) {
return nullptr;
}
-TEST(ScudoWrappersCTest, DisableForkEnable) {
+TEST_F(ScudoWrappersCTest, DisableForkEnable) {
pthread_t ThreadId;
Ready = false;
EXPECT_EQ(pthread_create(&ThreadId, nullptr, &enableMalloc, nullptr), 0);
diff --git a/compiler-rt/lib/scudo/standalone/tests/wrappers_cpp_test.cpp b/compiler-rt/lib/scudo/standalone/tests/wrappers_cpp_test.cpp
index 654bf547317809..c802ed22fbad00 100644
--- a/compiler-rt/lib/scudo/standalone/tests/wrappers_cpp_test.cpp
+++ b/compiler-rt/lib/scudo/standalone/tests/wrappers_cpp_test.cpp
@@ -24,6 +24,18 @@
#define SKIP_MISMATCH_TESTS 0
#endif
+void operator delete(void *, size_t) noexcept;
+void operator delete[](void *, size_t) noexcept;
+
+extern "C" {
+#ifndef SCUDO_ENABLE_HOOKS_TESTS
+#define SCUDO_ENABLE_HOOKS_TESTS 0
+#endif
+
+#if (SCUDO_ENABLE_HOOKS_TESTS == 1) && (SCUDO_ENABLE_HOOKS == 0)
+#error "Hooks tests should have hooks enabled as well!"
+#endif
+
struct AllocContext {
void *Ptr;
size_t Size;
@@ -34,10 +46,7 @@ struct DeallocContext {
static AllocContext AC;
static DeallocContext DC;
-void operator delete(void *, size_t) noexcept;
-void operator delete[](void *, size_t) noexcept;
-
-extern "C" {
+#if (SCUDO_ENABLE_HOOKS_TESTS == 1)
__attribute__((visibility("default"))) void __scudo_allocate_hook(void *Ptr,
size_t Size) {
AC.Ptr = Ptr;
@@ -46,60 +55,81 @@ __attribute__((visibility("default"))) void __scudo_allocate_hook(void *Ptr,
__attribute__((visibility("default"))) void __scudo_deallocate_hook(void *Ptr) {
DC.Ptr = Ptr;
}
+#endif // (SCUDO_ENABLE_HOOKS_TESTS == 1)
}
-// Note that every Cxx allocation function in the test binary will be fulfilled
-// by Scudo. See the comment in the C counterpart of this file.
-template <typename T> static void testCxxNew() {
- T *P = new T;
- EXPECT_NE(P, nullptr);
- EXPECT_EQ(P, AC.Ptr);
- EXPECT_EQ(sizeof(T), AC.Size);
- memset(P, 0x42, sizeof(T));
- EXPECT_DEATH(delete[] P, "");
- delete P;
- EXPECT_EQ(P, DC.Ptr);
- EXPECT_DEATH(delete P, "");
-
- P = new T;
- EXPECT_NE(P, nullptr);
- memset(P, 0x42, sizeof(T));
- operator delete(P, sizeof(T));
- EXPECT_EQ(P, DC.Ptr);
-
- P = new (std::nothrow) T;
- EXPECT_EQ(P, AC.Ptr);
- EXPECT_EQ(sizeof(T), AC.Size);
- EXPECT_NE(P, nullptr);
- memset(P, 0x42, sizeof(T));
- delete P;
- EXPECT_EQ(P, DC.Ptr);
-
- const size_t N = 16U;
- T *A = new T[N];
- EXPECT_NE(A, nullptr);
- EXPECT_EQ(A, AC.Ptr);
- EXPECT_EQ(sizeof(T) * N, AC.Size);
- memset(A, 0x42, sizeof(T) * N);
- EXPECT_DEATH(delete A, "");
- delete[] A;
- EXPECT_EQ(A, DC.Ptr);
- EXPECT_DEATH(delete[] A, "");
-
- A = new T[N];
- EXPECT_NE(A, nullptr);
- memset(A, 0x42, sizeof(T) * N);
- operator delete[](A, sizeof(T) * N);
- EXPECT_EQ(A, DC.Ptr);
-
- A = new (std::nothrow) T[N];
- EXPECT_EQ(A, AC.Ptr);
- EXPECT_EQ(sizeof(T) * N, AC.Size);
- EXPECT_NE(A, nullptr);
- memset(A, 0x42, sizeof(T) * N);
- delete[] A;
- EXPECT_EQ(A, DC.Ptr);
-}
+class ScudoWrappersCppTest : public Test {
+protected:
+ void SetUp() override {
+ if (SCUDO_ENABLE_HOOKS && !SCUDO_ENABLE_HOOKS_TESTS)
+ printf("Hooks are enabled but hooks tests are disabled.\n");
+ }
+
+ void verifyAllocHookPtr(UNUSED void *Ptr) {
+ if (SCUDO_ENABLE_HOOKS_TESTS)
+ EXPECT_EQ(Ptr, AC.Ptr);
+ }
+ void verifyAllocHookSize(UNUSED size_t Size) {
+ if (SCUDO_ENABLE_HOOKS_TESTS)
+ EXPECT_EQ(Size, AC.Size);
+ }
+ void verifyDeallocHookPtr(UNUSED void *Ptr) {
+ if (SCUDO_ENABLE_HOOKS_TESTS)
+ EXPECT_EQ(Ptr, DC.Ptr);
+ }
+
+ template <typename T> void testCxxNew() {
+ T *P = new T;
+ EXPECT_NE(P, nullptr);
+ verifyAllocHookPtr(P);
+ verifyAllocHookSize(sizeof(T));
+ memset(P, 0x42, sizeof(T));
+ EXPECT_DEATH(delete[] P, "");
+ delete P;
+ verifyDeallocHookPtr(P);
+ EXPECT_DEATH(delete P, "");
+
+ P = new T;
+ EXPECT_NE(P, nullptr);
+ memset(P, 0x42, sizeof(T));
+ operator delete(P, sizeof(T));
+ verifyDeallocHookPtr(P);
+
+ P = new (std::nothrow) T;
+ verifyAllocHookPtr(P);
+ verifyAllocHookSize(sizeof(T));
+ EXPECT_NE(P, nullptr);
+ memset(P, 0x42, sizeof(T));
+ delete P;
+ verifyDeallocHookPtr(P);
+
+ const size_t N = 16U;
+ T *A = new T[N];
+ EXPECT_NE(A, nullptr);
+ verifyAllocHookPtr(A);
+ verifyAllocHookSize(sizeof(T) * N);
+ memset(A, 0x42, sizeof(T) * N);
+ EXPECT_DEATH(delete A, "");
+ delete[] A;
+ verifyDeallocHookPtr(A);
+ EXPECT_DEATH(delete[] A, "");
+
+ A = new T[N];
+ EXPECT_NE(A, nullptr);
+ memset(A, 0x42, sizeof(T) * N);
+ operator delete[](A, sizeof(T) * N);
+ verifyDeallocHookPtr(A);
+
+ A = new (std::nothrow) T[N];
+ verifyAllocHookPtr(A);
+ verifyAllocHookSize(sizeof(T) * N);
+ EXPECT_NE(A, nullptr);
+ memset(A, 0x42, sizeof(T) * N);
+ delete[] A;
+ verifyDeallocHookPtr(A);
+ }
+};
+using ScudoWrappersCppDeathTest = ScudoWrappersCppTest;
class Pixel {
public:
@@ -109,7 +139,10 @@ class Pixel {
Color C = Color::Red;
};
-TEST(ScudoWrappersCppDeathTest, New) {
+// Note that every Cxx allocation function in the test binary will be fulfilled
+// by Scudo. See the comment in the C counterpart of this file.
+
+TEST_F(ScudoWrappersCppDeathTest, New) {
if (getenv("SKIP_TYPE_MISMATCH") || SKIP_MISMATCH_TESTS) {
printf("Skipped type mismatch tests.\n");
return;
@@ -150,7 +183,7 @@ static void stressNew() {
}
}
-TEST(ScudoWrappersCppTest, ThreadedNew) {
+TEST_F(ScudoWrappersCppTest, ThreadedNew) {
// TODO: Investigate why libc sometimes crashes with tag missmatch in
// __pthread_clockjoin_ex.
std::unique_ptr<scudo::ScopedDisableMemoryTagChecks> NoTags;
@@ -172,7 +205,7 @@ TEST(ScudoWrappersCppTest, ThreadedNew) {
}
#if !SCUDO_FUCHSIA
-TEST(ScudoWrappersCppTest, AllocAfterFork) {
+TEST_F(ScudoWrappersCppTest, AllocAfterFork) {
// This test can fail flakily when ran as a part of large number of
// other tests if the maxmimum number of mappings allowed is low.
// We tried to reduce the number of iterations of the loops with
diff --git a/compiler-rt/lib/scudo/standalone/wrappers_c.cpp b/compiler-rt/lib/scudo/standalone/wrappers_c.cpp
index 0b204271c81ce7..60014a0f66bf54 100644
--- a/compiler-rt/lib/scudo/standalone/wrappers_c.cpp
+++ b/compiler-rt/lib/scudo/standalone/wrappers_c.cpp
@@ -12,6 +12,8 @@
#if !SCUDO_ANDROID || !_BIONIC
#include "allocator_config.h"
+#include "internal_defs.h"
+#include "platform.h"
#include "scudo/interface.h"
#include "wrappers_c.h"
#include "wrappers_c_checks.h"
diff --git a/compiler-rt/lib/scudo/standalone/wrappers_c.inc b/compiler-rt/lib/scudo/standalone/wrappers_c.inc
index 0bd5eddfa0b1c1..e213da73393b5d 100644
--- a/compiler-rt/lib/scudo/standalone/wrappers_c.inc
+++ b/compiler-rt/lib/scudo/standalone/wrappers_c.inc
@@ -18,13 +18,14 @@
#endif
static void reportAllocation(void *ptr, size_t size) {
- if (__scudo_allocate_hook && ptr)
- __scudo_allocate_hook(ptr, size);
+ if (SCUDO_ENABLE_HOOKS)
+ if (__scudo_allocate_hook && ptr)
+ __scudo_allocate_hook(ptr, size);
}
-
static void reportDeallocation(void *ptr) {
- if (__scudo_deallocate_hook)
- __scudo_deallocate_hook(ptr);
+ if (SCUDO_ENABLE_HOOKS)
+ if (__scudo_deallocate_hook)
+ __scudo_deallocate_hook(ptr);
}
extern "C" {
diff --git a/compiler-rt/lib/scudo/standalone/wrappers_c_bionic.cpp b/compiler-rt/lib/scudo/standalone/wrappers_c_bionic.cpp
index db824e6f754737..4e8e37ac293b86 100644
--- a/compiler-rt/lib/scudo/standalone/wrappers_c_bionic.cpp
+++ b/compiler-rt/lib/scudo/standalone/wrappers_c_bionic.cpp
@@ -12,6 +12,8 @@
#if SCUDO_ANDROID && _BIONIC
#include "allocator_config.h"
+#include "internal_defs.h"
+#include "platform.h"
#include "scudo/interface.h"
#include "wrappers_c.h"
#include "wrappers_c_checks.h"
diff --git a/compiler-rt/lib/scudo/standalone/wrappers_cpp.cpp b/compiler-rt/lib/scudo/standalone/wrappers_cpp.cpp
index 9ea2aaed1e7857..098d4f71acc4af 100644
--- a/compiler-rt/lib/scudo/standalone/wrappers_cpp.cpp
+++ b/compiler-rt/lib/scudo/standalone/wrappers_cpp.cpp
@@ -12,6 +12,8 @@
#if !SCUDO_ANDROID || !_BIONIC
#include "allocator_config.h"
+#include "internal_defs.h"
+#include "platform.h"
#include "scudo/interface.h"
#include "wrappers_c.h"
@@ -23,13 +25,14 @@ enum class align_val_t : size_t {};
} // namespace std
static void reportAllocation(void *ptr, size_t size) {
- if (__scudo_allocate_hook && ptr)
- __scudo_allocate_hook(ptr, size);
+ if (SCUDO_ENABLE_HOOKS)
+ if (__scudo_allocate_hook && ptr)
+ __scudo_allocate_hook(ptr, size);
}
-
static void reportDeallocation(void *ptr) {
- if (__scudo_deallocate_hook)
- __scudo_deallocate_hook(ptr);
+ if (SCUDO_ENABLE_HOOKS)
+ if (__scudo_deallocate_hook)
+ __scudo_deallocate_hook(ptr);
}
INTERFACE WEAK void *operator new(size_t size) {
More information about the llvm-commits
mailing list