[compiler-rt] 4f76810 - [scudo] Detach the hooks from Scudo's internal implementation
Chia-hung Duan via llvm-commits
llvm-commits at lists.llvm.org
Fri Aug 25 09:22:10 PDT 2023
Author: Chia-hung Duan
Date: 2023-08-25T16:19:56Z
New Revision: 4f76810d4860d851f069aa0caca24c54ab698c3b
URL: https://github.com/llvm/llvm-project/commit/4f76810d4860d851f069aa0caca24c54ab698c3b
DIFF: https://github.com/llvm/llvm-project/commit/4f76810d4860d851f069aa0caca24c54ab698c3b.diff
LOG: [scudo] Detach the hooks from Scudo's internal implementation
Move the invocation of hooks from Scudo internal to wrapper_c.cpp and
wrapper_c_bionic.cpp respectively. Therefore, Scudo's core algorithm
doesnt need to worry about the reentrant of hooks and leave the caring
of reentrant to the hook users.
Reviewed By: hctim, cferris, chelfi
Differential Revision: https://reviews.llvm.org/D152188
Added:
Modified:
compiler-rt/lib/scudo/standalone/combined.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:
compiler-rt/lib/scudo/standalone/tests/scudo_hooks_test.cpp
################################################################################
diff --git a/compiler-rt/lib/scudo/standalone/combined.h b/compiler-rt/lib/scudo/standalone/combined.h
index e1db7a70301184..8cc84adcd4843b 100644
--- a/compiler-rt/lib/scudo/standalone/combined.h
+++ b/compiler-rt/lib/scudo/standalone/combined.h
@@ -329,8 +329,6 @@ class Allocator {
#ifdef GWP_ASAN_HOOKS
if (UNLIKELY(GuardedAlloc.shouldSample())) {
if (void *Ptr = GuardedAlloc.allocate(Size, Alignment)) {
- if (UNLIKELY(&__scudo_allocate_hook))
- __scudo_allocate_hook(Ptr, Size);
Stats.lock();
Stats.add(StatAllocated, GuardedAllocSlotSize);
Stats.sub(StatFree, GuardedAllocSlotSize);
@@ -535,9 +533,6 @@ class Allocator {
Chunk::SizeOrUnusedBytesMask;
Chunk::storeHeader(Cookie, Ptr, &Header);
- if (UNLIKELY(&__scudo_allocate_hook))
- __scudo_allocate_hook(TaggedPtr, Size);
-
return TaggedPtr;
}
@@ -551,9 +546,6 @@ class Allocator {
// being destroyed properly. Any other heap operation will do a full init.
initThreadMaybe(/*MinimalInit=*/true);
- if (UNLIKELY(&__scudo_deallocate_hook))
- __scudo_deallocate_hook(Ptr);
-
if (UNLIKELY(!Ptr))
return;
@@ -697,8 +689,6 @@ class Allocator {
void *NewPtr = allocate(NewSize, Chunk::Origin::Malloc, Alignment);
if (LIKELY(NewPtr)) {
memcpy(NewPtr, OldTaggedPtr, Min(NewSize, OldSize));
- if (UNLIKELY(&__scudo_deallocate_hook))
- __scudo_deallocate_hook(OldTaggedPtr);
quarantineOrDeallocateChunk(Options, OldTaggedPtr, &OldHeader, OldSize);
}
return NewPtr;
diff --git a/compiler-rt/lib/scudo/standalone/tests/CMakeLists.txt b/compiler-rt/lib/scudo/standalone/tests/CMakeLists.txt
index cbb85ce3ec2e20..71ad3830c88ca3 100644
--- a/compiler-rt/lib/scudo/standalone/tests/CMakeLists.txt
+++ b/compiler-rt/lib/scudo/standalone/tests/CMakeLists.txt
@@ -137,11 +137,3 @@ set(SCUDO_CXX_UNIT_TEST_SOURCES
add_scudo_unittest(ScudoCxxUnitTest
SOURCES ${SCUDO_CXX_UNIT_TEST_SOURCES}
ADDITIONAL_RTOBJECTS RTScudoStandaloneCWrappers RTScudoStandaloneCxxWrappers)
-
-set(SCUDO_HOOKS_UNIT_TEST_SOURCES
- scudo_hooks_test.cpp
- scudo_unit_test_main.cpp
- )
-
-add_scudo_unittest(ScudoHooksUnitTest
- SOURCES ${SCUDO_HOOKS_UNIT_TEST_SOURCES})
diff --git a/compiler-rt/lib/scudo/standalone/tests/scudo_hooks_test.cpp b/compiler-rt/lib/scudo/standalone/tests/scudo_hooks_test.cpp
deleted file mode 100644
index 7184ec12a8bb30..00000000000000
--- a/compiler-rt/lib/scudo/standalone/tests/scudo_hooks_test.cpp
+++ /dev/null
@@ -1,114 +0,0 @@
-//===-- scudo_hooks_test.cpp ------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "tests/scudo_unit_test.h"
-
-#include "allocator_config.h"
-#include "combined.h"
-
-namespace {
-void *LastAllocatedPtr = nullptr;
-size_t LastRequestSize = 0;
-void *LastDeallocatedPtr = nullptr;
-} // namespace
-
-// Scudo defines weak symbols that can be defined by a client binary
-// to register callbacks at key points in the allocation timeline. In
-// order to enforce those invariants, we provide definitions that
-// update some global state every time they are called, so that tests
-// can inspect their effects. An unfortunate side effect of this
-// setup is that because those symbols are part of the binary, they
-// can't be selectively enabled; that means that they will get called
-// on unrelated tests in the same compilation unit. To mitigate this
-// issue, we insulate those tests in a separate compilation unit.
-extern "C" {
-__attribute__((visibility("default"))) void __scudo_allocate_hook(void *Ptr,
- size_t Size) {
- LastAllocatedPtr = Ptr;
- LastRequestSize = Size;
-}
-__attribute__((visibility("default"))) void __scudo_deallocate_hook(void *Ptr) {
- LastDeallocatedPtr = Ptr;
-}
-}
-
-// Simple check that allocation callbacks, when registered, are called:
-// 1) __scudo_allocate_hook is called when allocating.
-// 2) __scudo_deallocate_hook is called when deallocating.
-// 3) Both hooks are called when reallocating.
-// 4) Neither are called for a no-op reallocation.
-TEST(ScudoHooksTest, AllocateHooks) {
- scudo::Allocator<scudo::DefaultConfig> Allocator;
- constexpr scudo::uptr DefaultSize = 16U;
- constexpr scudo::Chunk::Origin Origin = scudo::Chunk::Origin::Malloc;
-
- // Simple allocation and deallocation.
- {
- LastAllocatedPtr = nullptr;
- LastRequestSize = 0;
-
- void *Ptr = Allocator.allocate(DefaultSize, Origin);
-
- EXPECT_EQ(Ptr, LastAllocatedPtr);
- EXPECT_EQ(DefaultSize, LastRequestSize);
-
- LastDeallocatedPtr = nullptr;
-
- Allocator.deallocate(Ptr, Origin);
-
- EXPECT_EQ(Ptr, LastDeallocatedPtr);
- }
-
- // Simple no-op, same size reallocation.
- {
- void *Ptr = Allocator.allocate(DefaultSize, Origin);
-
- LastAllocatedPtr = nullptr;
- LastRequestSize = 0;
- LastDeallocatedPtr = nullptr;
-
- void *NewPtr = Allocator.reallocate(Ptr, DefaultSize);
-
- EXPECT_EQ(Ptr, NewPtr);
- EXPECT_EQ(nullptr, LastAllocatedPtr);
- EXPECT_EQ(0U, LastRequestSize);
- EXPECT_EQ(nullptr, LastDeallocatedPtr);
- }
-
- // Reallocation in increasing size classes. This ensures that at
- // least one of the reallocations will be meaningful.
- {
- void *Ptr = Allocator.allocate(0, Origin);
-
- for (scudo::uptr ClassId = 1U;
- ClassId <= scudo::DefaultConfig::Primary::SizeClassMap::LargestClassId;
- ++ClassId) {
- const scudo::uptr Size =
- scudo::DefaultConfig::Primary::SizeClassMap::getSizeByClassId(
- ClassId);
-
- LastAllocatedPtr = nullptr;
- LastRequestSize = 0;
- LastDeallocatedPtr = nullptr;
-
- void *NewPtr = Allocator.reallocate(Ptr, Size);
-
- if (NewPtr != Ptr) {
- EXPECT_EQ(NewPtr, LastAllocatedPtr);
- EXPECT_EQ(Size, LastRequestSize);
- EXPECT_EQ(Ptr, LastDeallocatedPtr);
- } else {
- EXPECT_EQ(nullptr, LastAllocatedPtr);
- EXPECT_EQ(0U, LastRequestSize);
- EXPECT_EQ(nullptr, LastDeallocatedPtr);
- }
-
- Ptr = NewPtr;
- }
- }
-}
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 c921da980cad48..d0cc0fa3c6508c 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,16 @@
#define HAVE_VALLOC 1
#endif
+struct AllocContext {
+ void *Ptr;
+ size_t Size;
+};
+struct DeallocContext {
+ void *Ptr;
+};
+static AllocContext AC;
+static DeallocContext DC;
+
extern "C" {
void malloc_enable(void);
void malloc_disable(void);
@@ -45,6 +55,15 @@ int malloc_iterate(uintptr_t base, size_t size,
void *arg);
void *valloc(size_t size);
void *pvalloc(size_t size);
+
+__attribute__((visibility("default"))) void __scudo_allocate_hook(void *Ptr,
+ size_t Size) {
+ AC.Ptr = Ptr;
+ AC.Size = Size;
+}
+__attribute__((visibility("default"))) void __scudo_deallocate_hook(void *Ptr) {
+ DC.Ptr = Ptr;
+}
}
// Note that every C allocation function in the test binary will be fulfilled
@@ -64,6 +83,8 @@ TEST(ScudoWrappersCDeathTest, Malloc) {
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);
// 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.
@@ -78,6 +99,7 @@ TEST(ScudoWrappersCDeathTest, Malloc) {
#endif
free(P);
+ EXPECT_EQ(P, DC.Ptr);
EXPECT_DEATH(free(P), "");
P = malloc(0U);
@@ -93,9 +115,12 @@ TEST(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);
for (size_t I = 0; I < Size; I++)
EXPECT_EQ((reinterpret_cast<uint8_t *>(P))[I], 0U);
free(P);
+ EXPECT_EQ(P, DC.Ptr);
P = calloc(1U, 0U);
EXPECT_NE(P, nullptr);
@@ -146,14 +171,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);
free(P);
+ EXPECT_EQ(P, DC.Ptr);
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);
free(P);
+ EXPECT_EQ(P, DC.Ptr);
}
EXPECT_EQ(memalign(4096U, SIZE_MAX), nullptr);
@@ -165,7 +196,10 @@ 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);
free(P);
+ EXPECT_EQ(P, DC.Ptr);
}
}
}
@@ -176,7 +210,10 @@ TEST(ScudoWrappersCTest, AlignedAlloc) {
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);
free(P);
+ EXPECT_EQ(P, DC.Ptr);
errno = 0;
P = aligned_alloc(Alignment, Size);
@@ -186,31 +223,52 @@ TEST(ScudoWrappersCTest, AlignedAlloc) {
TEST(ScudoWrappersCDeathTest, Realloc) {
// realloc(nullptr, N) is malloc(N)
- void *P = realloc(nullptr, 0U);
+ void *P = realloc(nullptr, Size);
EXPECT_NE(P, nullptr);
+ EXPECT_EQ(P, AC.Ptr);
+ EXPECT_EQ(Size, AC.Size);
free(P);
+ EXPECT_EQ(P, DC.Ptr);
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);
P = malloc(Size);
EXPECT_NE(P, nullptr);
EXPECT_LE(Size, malloc_usable_size(P));
memset(P, 0x42, Size);
+ AC.Ptr = reinterpret_cast<void *>(0xdeadbeef);
+ void *OldP = P;
P = realloc(P, Size * 2U);
EXPECT_NE(P, nullptr);
EXPECT_LE(Size * 2U, malloc_usable_size(P));
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));
+ } else {
+ EXPECT_EQ(P, AC.Ptr);
+ EXPECT_EQ(Size * 2U, AC.Size);
+ EXPECT_EQ(OldP, DC.Ptr);
+ }
+ AC.Ptr = reinterpret_cast<void *>(0xdeadbeef);
+ OldP = P;
P = realloc(P, Size / 2U);
EXPECT_NE(P, nullptr);
EXPECT_LE(Size / 2U, malloc_usable_size(P));
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));
+ } else {
+ EXPECT_EQ(P, AC.Ptr);
+ EXPECT_EQ(Size / 2U, AC.Size);
+ }
free(P);
EXPECT_DEATH(P = realloc(P, Size), "");
@@ -273,7 +331,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);
+ // Size will be rounded up to PageSize.
+ EXPECT_EQ(PageSize, AC.Size);
free(P);
+ EXPECT_EQ(P, DC.Ptr);
EXPECT_EQ(pvalloc(SIZE_MAX), nullptr);
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 987e4099aa77dd..654bf547317809 100644
--- a/compiler-rt/lib/scudo/standalone/tests/wrappers_cpp_test.cpp
+++ b/compiler-rt/lib/scudo/standalone/tests/wrappers_cpp_test.cpp
@@ -24,47 +24,81 @@
#define SKIP_MISMATCH_TESTS 0
#endif
+struct AllocContext {
+ void *Ptr;
+ size_t Size;
+};
+struct DeallocContext {
+ void *Ptr;
+};
+static AllocContext AC;
+static DeallocContext DC;
+
void operator delete(void *, size_t) noexcept;
void operator delete[](void *, size_t) noexcept;
+extern "C" {
+__attribute__((visibility("default"))) void __scudo_allocate_hook(void *Ptr,
+ size_t Size) {
+ AC.Ptr = Ptr;
+ AC.Size = Size;
+}
+__attribute__((visibility("default"))) void __scudo_deallocate_hook(void *Ptr) {
+ DC.Ptr = Ptr;
+}
+}
// 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 Pixel {
diff --git a/compiler-rt/lib/scudo/standalone/wrappers_c.cpp b/compiler-rt/lib/scudo/standalone/wrappers_c.cpp
index b4d51be716ccef..0b204271c81ce7 100644
--- a/compiler-rt/lib/scudo/standalone/wrappers_c.cpp
+++ b/compiler-rt/lib/scudo/standalone/wrappers_c.cpp
@@ -12,6 +12,7 @@
#if !SCUDO_ANDROID || !_BIONIC
#include "allocator_config.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 a475927b9f51af..0bd5eddfa0b1c1 100644
--- a/compiler-rt/lib/scudo/standalone/wrappers_c.inc
+++ b/compiler-rt/lib/scudo/standalone/wrappers_c.inc
@@ -17,6 +17,16 @@
#define SCUDO_MALLOC_ALIGNMENT FIRST_32_SECOND_64(8U, 16U)
#endif
+static void reportAllocation(void *ptr, size_t size) {
+ if (__scudo_allocate_hook && ptr)
+ __scudo_allocate_hook(ptr, size);
+}
+
+static void reportDeallocation(void *ptr) {
+ if (__scudo_deallocate_hook)
+ __scudo_deallocate_hook(ptr);
+}
+
extern "C" {
INTERFACE WEAK void *SCUDO_PREFIX(calloc)(size_t nmemb, size_t size) {
@@ -28,11 +38,14 @@ INTERFACE WEAK void *SCUDO_PREFIX(calloc)(size_t nmemb, size_t size) {
}
scudo::reportCallocOverflow(nmemb, size);
}
- return scudo::setErrnoOnNull(SCUDO_ALLOCATOR.allocate(
- Product, scudo::Chunk::Origin::Malloc, SCUDO_MALLOC_ALIGNMENT, true));
+ void *Ptr = SCUDO_ALLOCATOR.allocate(Product, scudo::Chunk::Origin::Malloc,
+ SCUDO_MALLOC_ALIGNMENT, true);
+ reportAllocation(Ptr, Product);
+ return scudo::setErrnoOnNull(Ptr);
}
INTERFACE WEAK void SCUDO_PREFIX(free)(void *ptr) {
+ reportDeallocation(ptr);
SCUDO_ALLOCATOR.deallocate(ptr, scudo::Chunk::Origin::Malloc);
}
@@ -75,8 +88,10 @@ INTERFACE WEAK struct __scudo_mallinfo2 SCUDO_PREFIX(mallinfo2)(void) {
#endif
INTERFACE WEAK void *SCUDO_PREFIX(malloc)(size_t size) {
- return scudo::setErrnoOnNull(SCUDO_ALLOCATOR.allocate(
- size, scudo::Chunk::Origin::Malloc, SCUDO_MALLOC_ALIGNMENT));
+ void *Ptr = SCUDO_ALLOCATOR.allocate(size, scudo::Chunk::Origin::Malloc,
+ SCUDO_MALLOC_ALIGNMENT);
+ reportAllocation(Ptr, size);
+ return scudo::setErrnoOnNull(Ptr);
}
#if SCUDO_ANDROID
@@ -105,8 +120,10 @@ INTERFACE WEAK void *SCUDO_PREFIX(memalign)(size_t alignment, size_t size) {
scudo::reportAlignmentNotPowerOfTwo(alignment);
}
}
- return SCUDO_ALLOCATOR.allocate(size, scudo::Chunk::Origin::Memalign,
- alignment);
+ void *Ptr =
+ SCUDO_ALLOCATOR.allocate(size, scudo::Chunk::Origin::Memalign, alignment);
+ reportAllocation(Ptr, size);
+ return Ptr;
}
INTERFACE WEAK int SCUDO_PREFIX(posix_memalign)(void **memptr, size_t alignment,
@@ -120,6 +137,8 @@ INTERFACE WEAK int SCUDO_PREFIX(posix_memalign)(void **memptr, size_t alignment,
SCUDO_ALLOCATOR.allocate(size, scudo::Chunk::Origin::Memalign, alignment);
if (UNLIKELY(!Ptr))
return ENOMEM;
+ reportAllocation(Ptr, size);
+
*memptr = Ptr;
return 0;
}
@@ -134,26 +153,42 @@ INTERFACE WEAK void *SCUDO_PREFIX(pvalloc)(size_t size) {
scudo::reportPvallocOverflow(size);
}
// pvalloc(0) should allocate one page.
- return scudo::setErrnoOnNull(
+ void *Ptr =
SCUDO_ALLOCATOR.allocate(size ? scudo::roundUp(size, PageSize) : PageSize,
- scudo::Chunk::Origin::Memalign, PageSize));
+ scudo::Chunk::Origin::Memalign, PageSize);
+ reportAllocation(Ptr, scudo::roundUp(size, PageSize));
+
+ return scudo::setErrnoOnNull(Ptr);
}
INTERFACE WEAK void *SCUDO_PREFIX(realloc)(void *ptr, size_t size) {
- if (!ptr)
- return scudo::setErrnoOnNull(SCUDO_ALLOCATOR.allocate(
- size, scudo::Chunk::Origin::Malloc, SCUDO_MALLOC_ALIGNMENT));
+ if (!ptr) {
+ void *Ptr = SCUDO_ALLOCATOR.allocate(size, scudo::Chunk::Origin::Malloc,
+ SCUDO_MALLOC_ALIGNMENT);
+ reportAllocation(Ptr, size);
+ return scudo::setErrnoOnNull(Ptr);
+ }
if (size == 0) {
+ reportDeallocation(ptr);
SCUDO_ALLOCATOR.deallocate(ptr, scudo::Chunk::Origin::Malloc);
return nullptr;
}
- return scudo::setErrnoOnNull(
- SCUDO_ALLOCATOR.reallocate(ptr, size, SCUDO_MALLOC_ALIGNMENT));
+
+ void *NewPtr = SCUDO_ALLOCATOR.reallocate(ptr, size, SCUDO_MALLOC_ALIGNMENT);
+ if (NewPtr != ptr) {
+ reportAllocation(NewPtr, size);
+ reportDeallocation(ptr);
+ }
+
+ return scudo::setErrnoOnNull(NewPtr);
}
INTERFACE WEAK void *SCUDO_PREFIX(valloc)(size_t size) {
- return scudo::setErrnoOnNull(SCUDO_ALLOCATOR.allocate(
- size, scudo::Chunk::Origin::Memalign, scudo::getPageSizeCached()));
+ void *Ptr = SCUDO_ALLOCATOR.allocate(size, scudo::Chunk::Origin::Memalign,
+ scudo::getPageSizeCached());
+ reportAllocation(Ptr, size);
+
+ return scudo::setErrnoOnNull(Ptr);
}
INTERFACE WEAK int SCUDO_PREFIX(malloc_iterate)(
@@ -234,8 +269,12 @@ INTERFACE WEAK void *SCUDO_PREFIX(aligned_alloc)(size_t alignment,
}
scudo::reportInvalidAlignedAllocAlignment(alignment, size);
}
- return scudo::setErrnoOnNull(
- SCUDO_ALLOCATOR.allocate(size, scudo::Chunk::Origin::Malloc, alignment));
+
+ void *Ptr =
+ SCUDO_ALLOCATOR.allocate(size, scudo::Chunk::Origin::Malloc, alignment);
+ reportAllocation(Ptr, size);
+
+ return scudo::setErrnoOnNull(Ptr);
}
INTERFACE WEAK int SCUDO_PREFIX(malloc_info)(UNUSED int options, FILE *stream) {
diff --git a/compiler-rt/lib/scudo/standalone/wrappers_c_bionic.cpp b/compiler-rt/lib/scudo/standalone/wrappers_c_bionic.cpp
index 1b9fe67d920c36..db824e6f754737 100644
--- a/compiler-rt/lib/scudo/standalone/wrappers_c_bionic.cpp
+++ b/compiler-rt/lib/scudo/standalone/wrappers_c_bionic.cpp
@@ -12,6 +12,7 @@
#if SCUDO_ANDROID && _BIONIC
#include "allocator_config.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 374e36d72b3d9e..9ea2aaed1e7857 100644
--- a/compiler-rt/lib/scudo/standalone/wrappers_cpp.cpp
+++ b/compiler-rt/lib/scudo/standalone/wrappers_cpp.cpp
@@ -12,6 +12,7 @@
#if !SCUDO_ANDROID || !_BIONIC
#include "allocator_config.h"
+#include "scudo/interface.h"
#include "wrappers_c.h"
#include <stdint.h>
@@ -21,86 +22,124 @@ struct nothrow_t {};
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);
+}
+
+static void reportDeallocation(void *ptr) {
+ if (__scudo_deallocate_hook)
+ __scudo_deallocate_hook(ptr);
+}
+
INTERFACE WEAK void *operator new(size_t size) {
- return Allocator.allocate(size, scudo::Chunk::Origin::New);
+ void *Ptr = Allocator.allocate(size, scudo::Chunk::Origin::New);
+ reportAllocation(Ptr, size);
+ return Ptr;
}
INTERFACE WEAK void *operator new[](size_t size) {
- return Allocator.allocate(size, scudo::Chunk::Origin::NewArray);
+ void *Ptr = Allocator.allocate(size, scudo::Chunk::Origin::NewArray);
+ reportAllocation(Ptr, size);
+ return Ptr;
}
INTERFACE WEAK void *operator new(size_t size,
std::nothrow_t const &) NOEXCEPT {
- return Allocator.allocate(size, scudo::Chunk::Origin::New);
+ void *Ptr = Allocator.allocate(size, scudo::Chunk::Origin::New);
+ reportAllocation(Ptr, size);
+ return Ptr;
}
INTERFACE WEAK void *operator new[](size_t size,
std::nothrow_t const &) NOEXCEPT {
- return Allocator.allocate(size, scudo::Chunk::Origin::NewArray);
+ void *Ptr = Allocator.allocate(size, scudo::Chunk::Origin::NewArray);
+ reportAllocation(Ptr, size);
+ return Ptr;
}
INTERFACE WEAK void *operator new(size_t size, std::align_val_t align) {
- return Allocator.allocate(size, scudo::Chunk::Origin::New,
- static_cast<scudo::uptr>(align));
+ void *Ptr = Allocator.allocate(size, scudo::Chunk::Origin::New,
+ static_cast<scudo::uptr>(align));
+ reportAllocation(Ptr, size);
+ return Ptr;
}
INTERFACE WEAK void *operator new[](size_t size, std::align_val_t align) {
- return Allocator.allocate(size, scudo::Chunk::Origin::NewArray,
- static_cast<scudo::uptr>(align));
+ void *Ptr = Allocator.allocate(size, scudo::Chunk::Origin::NewArray,
+ static_cast<scudo::uptr>(align));
+ reportAllocation(Ptr, size);
+ return Ptr;
}
INTERFACE WEAK void *operator new(size_t size, std::align_val_t align,
std::nothrow_t const &) NOEXCEPT {
- return Allocator.allocate(size, scudo::Chunk::Origin::New,
- static_cast<scudo::uptr>(align));
+ void *Ptr = Allocator.allocate(size, scudo::Chunk::Origin::New,
+ static_cast<scudo::uptr>(align));
+ reportAllocation(Ptr, size);
+ return Ptr;
}
INTERFACE WEAK void *operator new[](size_t size, std::align_val_t align,
std::nothrow_t const &) NOEXCEPT {
- return Allocator.allocate(size, scudo::Chunk::Origin::NewArray,
- static_cast<scudo::uptr>(align));
+ void *Ptr = Allocator.allocate(size, scudo::Chunk::Origin::NewArray,
+ static_cast<scudo::uptr>(align));
+ reportAllocation(Ptr, size);
+ return Ptr;
}
INTERFACE WEAK void operator delete(void *ptr) NOEXCEPT {
+ reportDeallocation(ptr);
Allocator.deallocate(ptr, scudo::Chunk::Origin::New);
}
INTERFACE WEAK void operator delete[](void *ptr) NOEXCEPT {
+ reportDeallocation(ptr);
Allocator.deallocate(ptr, scudo::Chunk::Origin::NewArray);
}
INTERFACE WEAK void operator delete(void *ptr,
std::nothrow_t const &) NOEXCEPT {
+ reportDeallocation(ptr);
Allocator.deallocate(ptr, scudo::Chunk::Origin::New);
}
INTERFACE WEAK void operator delete[](void *ptr,
std::nothrow_t const &) NOEXCEPT {
+ reportDeallocation(ptr);
Allocator.deallocate(ptr, scudo::Chunk::Origin::NewArray);
}
INTERFACE WEAK void operator delete(void *ptr, size_t size) NOEXCEPT {
+ reportDeallocation(ptr);
Allocator.deallocate(ptr, scudo::Chunk::Origin::New, size);
}
INTERFACE WEAK void operator delete[](void *ptr, size_t size) NOEXCEPT {
+ reportDeallocation(ptr);
Allocator.deallocate(ptr, scudo::Chunk::Origin::NewArray, size);
}
INTERFACE WEAK void operator delete(void *ptr,
std::align_val_t align) NOEXCEPT {
+ reportDeallocation(ptr);
Allocator.deallocate(ptr, scudo::Chunk::Origin::New, 0,
static_cast<scudo::uptr>(align));
}
INTERFACE WEAK void operator delete[](void *ptr,
std::align_val_t align) NOEXCEPT {
+ reportDeallocation(ptr);
Allocator.deallocate(ptr, scudo::Chunk::Origin::NewArray, 0,
static_cast<scudo::uptr>(align));
}
INTERFACE WEAK void operator delete(void *ptr, std::align_val_t align,
std::nothrow_t const &) NOEXCEPT {
+ reportDeallocation(ptr);
Allocator.deallocate(ptr, scudo::Chunk::Origin::New, 0,
static_cast<scudo::uptr>(align));
}
INTERFACE WEAK void operator delete[](void *ptr, std::align_val_t align,
std::nothrow_t const &) NOEXCEPT {
+ reportDeallocation(ptr);
Allocator.deallocate(ptr, scudo::Chunk::Origin::NewArray, 0,
static_cast<scudo::uptr>(align));
}
INTERFACE WEAK void operator delete(void *ptr, size_t size,
std::align_val_t align) NOEXCEPT {
+ reportDeallocation(ptr);
Allocator.deallocate(ptr, scudo::Chunk::Origin::New, size,
static_cast<scudo::uptr>(align));
}
INTERFACE WEAK void operator delete[](void *ptr, size_t size,
std::align_val_t align) NOEXCEPT {
+ reportDeallocation(ptr);
Allocator.deallocate(ptr, scudo::Chunk::Origin::NewArray, size,
static_cast<scudo::uptr>(align));
}
More information about the llvm-commits
mailing list