[compiler-rt] 3580a45 - [GWP-ASan] Move random-related code in the allocator (redo)
Kostya Kortchinsky via llvm-commits
llvm-commits at lists.llvm.org
Thu Oct 22 13:56:42 PDT 2020
Author: Kostya Kortchinsky
Date: 2020-10-22T13:56:24-07:00
New Revision: 3580a45014e90a9895cc2dec28ab2e7f78c47470
URL: https://github.com/llvm/llvm-project/commit/3580a45014e90a9895cc2dec28ab2e7f78c47470
DIFF: https://github.com/llvm/llvm-project/commit/3580a45014e90a9895cc2dec28ab2e7f78c47470.diff
LOG: [GWP-ASan] Move random-related code in the allocator (redo)
This is a redo of D89908, which triggered some `-Werror=conversion`
errors with GCC due to assignments to the 31-bit variable.
This CL adds to the original one a 31-bit mask variable that is used
at every assignment to silence the warning.
Differential Revision: https://reviews.llvm.org/D89984
Added:
Modified:
compiler-rt/lib/gwp_asan/CMakeLists.txt
compiler-rt/lib/gwp_asan/guarded_pool_allocator.cpp
compiler-rt/lib/gwp_asan/guarded_pool_allocator.h
compiler-rt/lib/gwp_asan/options.inc
compiler-rt/lib/gwp_asan/platform_specific/guarded_pool_allocator_posix.cpp
Removed:
compiler-rt/lib/gwp_asan/random.cpp
compiler-rt/lib/gwp_asan/random.h
################################################################################
diff --git a/compiler-rt/lib/gwp_asan/CMakeLists.txt b/compiler-rt/lib/gwp_asan/CMakeLists.txt
index 60efc8a39e62e..6bfb3cab13ef0 100644
--- a/compiler-rt/lib/gwp_asan/CMakeLists.txt
+++ b/compiler-rt/lib/gwp_asan/CMakeLists.txt
@@ -10,7 +10,6 @@ set(GWP_ASAN_SOURCES
platform_specific/mutex_posix.cpp
platform_specific/utilities_posix.cpp
guarded_pool_allocator.cpp
- random.cpp
stack_trace_compressor.cpp
utilities.cpp
)
@@ -23,7 +22,6 @@ set(GWP_ASAN_HEADERS
mutex.h
options.h
options.inc
- random.h
stack_trace_compressor.h
utilities.h
)
diff --git a/compiler-rt/lib/gwp_asan/guarded_pool_allocator.cpp b/compiler-rt/lib/gwp_asan/guarded_pool_allocator.cpp
index b2602e4caa596..17e6f76727f91 100644
--- a/compiler-rt/lib/gwp_asan/guarded_pool_allocator.cpp
+++ b/compiler-rt/lib/gwp_asan/guarded_pool_allocator.cpp
@@ -10,7 +10,6 @@
#include "gwp_asan/optional/segv_handler.h"
#include "gwp_asan/options.h"
-#include "gwp_asan/random.h"
#include "gwp_asan/utilities.h"
// RHEL creates the PRIu64 format macro (for printing uint64_t's) only when this
@@ -38,15 +37,6 @@ namespace {
// referenced by users outside this translation unit, in order to avoid
// init-order-fiasco.
GuardedPoolAllocator *SingletonPtr = nullptr;
-
-class ScopedBoolean {
-public:
- ScopedBoolean(bool &B) : Bool(B) { Bool = true; }
- ~ScopedBoolean() { Bool = false; }
-
-private:
- bool &Bool;
-};
} // anonymous namespace
// Gets the singleton implementation of this class. Thread-compatible until
@@ -64,7 +54,7 @@ void GuardedPoolAllocator::init(const options::Options &Opts) {
return;
Check(Opts.SampleRate >= 0, "GWP-ASan Error: SampleRate is < 0.");
- Check(Opts.SampleRate <= INT32_MAX, "GWP-ASan Error: SampleRate is > 2^31.");
+ Check(Opts.SampleRate < (1 << 30), "GWP-ASan Error: SampleRate is >= 2^30.");
Check(Opts.MaxSimultaneousAllocations >= 0,
"GWP-ASan Error: MaxSimultaneousAllocations is < 0.");
@@ -102,7 +92,8 @@ void GuardedPoolAllocator::init(const options::Options &Opts) {
initPRNG();
ThreadLocals.NextSampleCounter =
- (getRandomUnsigned32() % (AdjustedSampleRatePlusOne - 1)) + 1;
+ ((getRandomUnsigned32() % (AdjustedSampleRatePlusOne - 1)) + 1) &
+ ThreadLocalPackedVariables::NextSampleCounterMask;
State.GuardedPagePool = reinterpret_cast<uintptr_t>(GuardedPoolMemory);
State.GuardedPagePoolEnd =
@@ -155,13 +146,17 @@ static uintptr_t getPageAddr(uintptr_t Ptr, uintptr_t PageSize) {
void *GuardedPoolAllocator::allocate(size_t Size) {
// GuardedPagePoolEnd == 0 when GWP-ASan is disabled. If we are disabled, fall
// back to the supporting allocator.
- if (State.GuardedPagePoolEnd == 0)
+ if (State.GuardedPagePoolEnd == 0) {
+ ThreadLocals.NextSampleCounter =
+ (AdjustedSampleRatePlusOne - 1) &
+ ThreadLocalPackedVariables::NextSampleCounterMask;
return nullptr;
+ }
// Protect against recursivity.
if (ThreadLocals.RecursiveGuard)
return nullptr;
- ScopedBoolean SB(ThreadLocals.RecursiveGuard);
+ ScopedRecursiveGuard SRG;
if (Size == 0 || Size > State.maximumAllocationSize())
return nullptr;
@@ -241,7 +236,7 @@ void GuardedPoolAllocator::deallocate(void *Ptr) {
// Ensure that the unwinder is not called if the recursive flag is set,
// otherwise non-reentrant unwinders may deadlock.
if (!ThreadLocals.RecursiveGuard) {
- ScopedBoolean B(ThreadLocals.RecursiveGuard);
+ ScopedRecursiveGuard SRG;
Meta->DeallocationTrace.RecordBacktrace(Backtrace);
}
}
@@ -286,6 +281,15 @@ void GuardedPoolAllocator::freeSlot(size_t SlotIndex) {
FreeSlots[FreeSlotsLength++] = SlotIndex;
}
+uint32_t GuardedPoolAllocator::getRandomUnsigned32() {
+ uint32_t RandomState = ThreadLocals.RandomState;
+ RandomState ^= RandomState << 13;
+ RandomState ^= RandomState >> 17;
+ RandomState ^= RandomState << 5;
+ ThreadLocals.RandomState = RandomState;
+ return RandomState;
+}
+
GWP_ASAN_TLS_INITIAL_EXEC
GuardedPoolAllocator::ThreadLocalPackedVariables
GuardedPoolAllocator::ThreadLocals;
diff --git a/compiler-rt/lib/gwp_asan/guarded_pool_allocator.h b/compiler-rt/lib/gwp_asan/guarded_pool_allocator.h
index 12049e1ab9d13..801f33e3f9ed6 100644
--- a/compiler-rt/lib/gwp_asan/guarded_pool_allocator.h
+++ b/compiler-rt/lib/gwp_asan/guarded_pool_allocator.h
@@ -13,7 +13,6 @@
#include "gwp_asan/definitions.h"
#include "gwp_asan/mutex.h"
#include "gwp_asan/options.h"
-#include "gwp_asan/random.h"
#include "gwp_asan/stack_trace_compressor.h"
#include <stddef.h>
@@ -80,7 +79,8 @@ class GuardedPoolAllocator {
// UINT32_MAX.
if (GWP_ASAN_UNLIKELY(ThreadLocals.NextSampleCounter == 0))
ThreadLocals.NextSampleCounter =
- (getRandomUnsigned32() % (AdjustedSampleRatePlusOne - 1)) + 1;
+ ((getRandomUnsigned32() % (AdjustedSampleRatePlusOne - 1)) + 1) &
+ ThreadLocalPackedVariables::NextSampleCounterMask;
return GWP_ASAN_UNLIKELY(--ThreadLocals.NextSampleCounter == 0);
}
@@ -195,17 +195,42 @@ class GuardedPoolAllocator {
// the same cache line for performance reasons. These are the most touched
// variables in GWP-ASan.
struct alignas(8) ThreadLocalPackedVariables {
- constexpr ThreadLocalPackedVariables() {}
+ constexpr ThreadLocalPackedVariables()
+ : RandomState(0xff82eb50), NextSampleCounter(0), RecursiveGuard(false) {
+ }
+ // Initialised to a magic constant so that an uninitialised GWP-ASan won't
+ // regenerate its sample counter for as long as possible. The xorshift32()
+ // algorithm used below results in getRandomUnsigned32(0xff82eb50) ==
+ // 0xfffffea4.
+ uint32_t RandomState;
// Thread-local decrementing counter that indicates that a given allocation
// should be sampled when it reaches zero.
- uint32_t NextSampleCounter = 0;
+ uint32_t NextSampleCounter : 31;
+ // The mask is needed to silence conversion errors.
+ static const uint32_t NextSampleCounterMask = (1U << 31) - 1;
// Guard against recursivity. Unwinders often contain complex behaviour that
// may not be safe for the allocator (i.e. the unwinder calls dlopen(),
// which calls malloc()). When recursive behaviour is detected, we will
// automatically fall back to the supporting allocator to supply the
// allocation.
- bool RecursiveGuard = false;
+ bool RecursiveGuard : 1;
};
+ static_assert(sizeof(ThreadLocalPackedVariables) == sizeof(uint64_t),
+ "thread local data does not fit in a uint64_t");
+
+ class ScopedRecursiveGuard {
+ public:
+ ScopedRecursiveGuard() { ThreadLocals.RecursiveGuard = true; }
+ ~ScopedRecursiveGuard() { ThreadLocals.RecursiveGuard = false; }
+ };
+
+ // Initialise the PRNG, platform-specific.
+ void initPRNG();
+
+ // xorshift (32-bit output), extremely fast PRNG that uses arithmetic
+ // operations only. Seeded using platform-specific mechanisms by initPRNG().
+ uint32_t getRandomUnsigned32();
+
static GWP_ASAN_TLS_INITIAL_EXEC ThreadLocalPackedVariables ThreadLocals;
};
} // namespace gwp_asan
diff --git a/compiler-rt/lib/gwp_asan/options.inc b/compiler-rt/lib/gwp_asan/options.inc
index 6cdddfbad84d8..c81e1f47c7224 100644
--- a/compiler-rt/lib/gwp_asan/options.inc
+++ b/compiler-rt/lib/gwp_asan/options.inc
@@ -29,7 +29,7 @@ GWP_ASAN_OPTION(int, MaxSimultaneousAllocations, 16,
GWP_ASAN_OPTION(int, SampleRate, 5000,
"The probability (1 / SampleRate) that an allocation is "
"selected for GWP-ASan sampling. Default is 5000. Sample rates "
- "up to (2^31 - 1) are supported.")
+ "up to (2^30 - 1) are supported.")
// Developer note - This option is not actually processed by GWP-ASan itself. It
// is included here so that a user can specify whether they want signal handlers
diff --git a/compiler-rt/lib/gwp_asan/platform_specific/guarded_pool_allocator_posix.cpp b/compiler-rt/lib/gwp_asan/platform_specific/guarded_pool_allocator_posix.cpp
index a8767a4cb8089..c2cd24454fa25 100644
--- a/compiler-rt/lib/gwp_asan/platform_specific/guarded_pool_allocator_posix.cpp
+++ b/compiler-rt/lib/gwp_asan/platform_specific/guarded_pool_allocator_posix.cpp
@@ -16,6 +16,7 @@
#include <string.h>
#include <sys/mman.h>
#include <sys/types.h>
+#include <time.h>
#include <unistd.h>
#ifdef ANDROID
@@ -33,6 +34,11 @@ void MaybeSetMappingName(void *Mapping, size_t Size, const char *Name) {
}
namespace gwp_asan {
+
+void GuardedPoolAllocator::initPRNG() {
+ ThreadLocals.RandomState = time(nullptr) + getThreadID();
+}
+
void *GuardedPoolAllocator::mapMemory(size_t Size, const char *Name) const {
void *Ptr =
mmap(nullptr, Size, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
diff --git a/compiler-rt/lib/gwp_asan/random.cpp b/compiler-rt/lib/gwp_asan/random.cpp
deleted file mode 100644
index 927709abc42b0..0000000000000
--- a/compiler-rt/lib/gwp_asan/random.cpp
+++ /dev/null
@@ -1,29 +0,0 @@
-//===-- random.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 "gwp_asan/random.h"
-#include "gwp_asan/common.h"
-
-#include <time.h>
-
-// Initialised to a magic constant so that an uninitialised GWP-ASan won't
-// regenerate its sample counter for as long as possible. The xorshift32()
-// algorithm used below results in getRandomUnsigned32(0xff82eb50) ==
-// 0xfffffea4.
-GWP_ASAN_TLS_INITIAL_EXEC uint32_t RandomState = 0xff82eb50;
-
-namespace gwp_asan {
-void initPRNG() { RandomState = time(nullptr) + getThreadID(); }
-
-uint32_t getRandomUnsigned32() {
- RandomState ^= RandomState << 13;
- RandomState ^= RandomState >> 17;
- RandomState ^= RandomState << 5;
- return RandomState;
-}
-} // namespace gwp_asan
diff --git a/compiler-rt/lib/gwp_asan/random.h b/compiler-rt/lib/gwp_asan/random.h
deleted file mode 100644
index 953b98909e958..0000000000000
--- a/compiler-rt/lib/gwp_asan/random.h
+++ /dev/null
@@ -1,23 +0,0 @@
-//===-- random.h ------------------------------------------------*- 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
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef GWP_ASAN_RANDOM_H_
-#define GWP_ASAN_RANDOM_H_
-
-#include <stdint.h>
-
-namespace gwp_asan {
-// Initialise the PRNG, using time and thread ID as the seed.
-void initPRNG();
-
-// xorshift (32-bit output), extremely fast PRNG that uses arithmetic operations
-// only. Seeded using walltime.
-uint32_t getRandomUnsigned32();
-} // namespace gwp_asan
-
-#endif // GWP_ASAN_RANDOM_H_
More information about the llvm-commits
mailing list