[compiler-rt] 0dcf332 - Revert "[GWP-ASan] Add aligned allocations."
Mitch Phillips via llvm-commits
llvm-commits at lists.llvm.org
Tue Feb 2 14:47:29 PST 2021
Author: Mitch Phillips
Date: 2021-02-02T14:46:25-08:00
New Revision: 0dcf3324cfb4429e85b54e857f9bb86f423ffc5e
URL: https://github.com/llvm/llvm-project/commit/0dcf3324cfb4429e85b54e857f9bb86f423ffc5e
DIFF: https://github.com/llvm/llvm-project/commit/0dcf3324cfb4429e85b54e857f9bb86f423ffc5e.diff
LOG: Revert "[GWP-ASan] Add aligned allocations."
This reverts commit 9dc06762470cb5a6cde8de5833cb75262e1bacb0.
Should not have been committed, was a bad rebase. Review still
continuing on D94830.
Added:
compiler-rt/lib/gwp_asan/utilities.cpp
Modified:
compiler-rt/lib/gwp_asan/CMakeLists.txt
compiler-rt/lib/gwp_asan/common.cpp
compiler-rt/lib/gwp_asan/common.h
compiler-rt/lib/gwp_asan/crash_handler.cpp
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/tests/alignment.cpp
compiler-rt/lib/gwp_asan/tests/basic.cpp
compiler-rt/lib/gwp_asan/tests/crash_handler_api.cpp
compiler-rt/lib/gwp_asan/utilities.h
Removed:
################################################################################
diff --git a/compiler-rt/lib/gwp_asan/CMakeLists.txt b/compiler-rt/lib/gwp_asan/CMakeLists.txt
index 638f7034d9f9..599fa9904e47 100644
--- a/compiler-rt/lib/gwp_asan/CMakeLists.txt
+++ b/compiler-rt/lib/gwp_asan/CMakeLists.txt
@@ -11,6 +11,7 @@ set(GWP_ASAN_SOURCES
platform_specific/utilities_posix.cpp
guarded_pool_allocator.cpp
stack_trace_compressor.cpp
+ utilities.cpp
)
set(GWP_ASAN_HEADERS
diff --git a/compiler-rt/lib/gwp_asan/common.cpp b/compiler-rt/lib/gwp_asan/common.cpp
index b0f6c58bf496..483694d57b7e 100644
--- a/compiler-rt/lib/gwp_asan/common.cpp
+++ b/compiler-rt/lib/gwp_asan/common.cpp
@@ -40,7 +40,7 @@ constexpr size_t AllocationMetadata::kMaxTraceLengthToCollect;
void AllocationMetadata::RecordAllocation(uintptr_t AllocAddr,
size_t AllocSize) {
Addr = AllocAddr;
- RequestedSize = AllocSize;
+ Size = AllocSize;
IsDeallocated = false;
AllocationTrace.ThreadID = getThreadID();
diff --git a/compiler-rt/lib/gwp_asan/common.h b/compiler-rt/lib/gwp_asan/common.h
index ee8f9d1bcae9..d197711c77fc 100644
--- a/compiler-rt/lib/gwp_asan/common.h
+++ b/compiler-rt/lib/gwp_asan/common.h
@@ -49,7 +49,7 @@ struct AllocationMetadata {
static constexpr size_t kMaxTraceLengthToCollect = 128;
// Records the given allocation metadata into this struct.
- void RecordAllocation(uintptr_t Addr, size_t RequestedSize);
+ void RecordAllocation(uintptr_t Addr, size_t Size);
// Record that this allocation is now deallocated.
void RecordDeallocation();
@@ -70,7 +70,7 @@ struct AllocationMetadata {
// valid, as the allocation has never occurred.
uintptr_t Addr = 0;
// Represents the actual size of the allocation.
- size_t RequestedSize = 0;
+ size_t Size = 0;
CallSiteInfo AllocationTrace;
CallSiteInfo DeallocationTrace;
diff --git a/compiler-rt/lib/gwp_asan/crash_handler.cpp b/compiler-rt/lib/gwp_asan/crash_handler.cpp
index 6b4c39edb294..bd7ca5abbb6b 100644
--- a/compiler-rt/lib/gwp_asan/crash_handler.cpp
+++ b/compiler-rt/lib/gwp_asan/crash_handler.cpp
@@ -103,7 +103,7 @@ uintptr_t __gwp_asan_get_allocation_address(
size_t __gwp_asan_get_allocation_size(
const gwp_asan::AllocationMetadata *AllocationMeta) {
- return AllocationMeta->RequestedSize;
+ return AllocationMeta->Size;
}
uint64_t __gwp_asan_get_allocation_thread_id(
diff --git a/compiler-rt/lib/gwp_asan/guarded_pool_allocator.cpp b/compiler-rt/lib/gwp_asan/guarded_pool_allocator.cpp
index 5e3455e54ef9..400c9ca5d7a1 100644
--- a/compiler-rt/lib/gwp_asan/guarded_pool_allocator.cpp
+++ b/compiler-rt/lib/gwp_asan/guarded_pool_allocator.cpp
@@ -12,7 +12,6 @@
#include "gwp_asan/utilities.h"
#include <assert.h>
-#include <stddef.h>
using AllocationMetadata = gwp_asan::AllocationMetadata;
using Error = gwp_asan::Error;
@@ -33,8 +32,6 @@ size_t roundUpTo(size_t Size, size_t Boundary) {
uintptr_t getPageAddr(uintptr_t Ptr, uintptr_t PageSize) {
return Ptr & ~(PageSize - 1);
}
-
-bool isPowerOfTwo(uintptr_t x) { return (x & (x - 1)) == 0; }
} // anonymous namespace
// Gets the singleton implementation of this class. Thread-compatible until
@@ -66,6 +63,8 @@ void GuardedPoolAllocator::init(const options::Options &Opts) {
assert((PageSize & (PageSize - 1)) == 0);
State.PageSize = PageSize;
+ PerfectlyRightAlign = Opts.PerfectlyRightAlign;
+
size_t PoolBytesRequired =
PageSize * (1 + State.MaxSimultaneousAllocations) +
State.MaxSimultaneousAllocations * State.maximumAllocationSize();
@@ -120,7 +119,7 @@ void GuardedPoolAllocator::iterate(void *Base, size_t Size, iterate_callback Cb,
const AllocationMetadata &Meta = Metadata[i];
if (Meta.Addr && !Meta.IsDeallocated && Meta.Addr >= Start &&
Meta.Addr < Start + Size)
- Cb(Meta.Addr, Meta.RequestedSize, Arg);
+ Cb(Meta.Addr, Meta.Size, Arg);
}
}
@@ -145,39 +144,7 @@ void GuardedPoolAllocator::uninitTestOnly() {
*getThreadLocals() = ThreadLocalPackedVariables();
}
-// Note, minimum backing allocation size in GWP-ASan is always one page, and
-// each slot could potentially be multiple pages (but always in
-// page-increments). Thus, for anything that requires less than page size
-// alignment, we don't need to allocate extra padding to ensure the alignment
-// can be met.
-size_t GuardedPoolAllocator::getRequiredBackingSize(size_t Size,
- size_t Alignment,
- size_t PageSize) {
- assert(isPowerOfTwo(Alignment) && "Alignment must be a power of two!");
- assert(Alignment != 0 && "Alignment should be non-zero");
- assert(Size != 0 && "Size should be non-zero");
-
- if (Alignment <= PageSize)
- return Size;
-
- return Size + Alignment - PageSize;
-}
-
-uintptr_t GuardedPoolAllocator::getAlignedPtr(uintptr_t Ptr, size_t Alignment,
- bool IsRightAligned) {
- assert(isPowerOfTwo(Alignment) && "Alignment must be a power of two!");
- assert(Alignment != 0 && "Alignment should be non-zero");
- if ((Ptr & (Alignment - 1)) == 0)
- return Ptr;
-
- if (IsRightAligned)
- Ptr -= Ptr & (Alignment - 1);
- else
- Ptr += Alignment - (Ptr & (Alignment - 1));
- return Ptr;
-}
-
-void *GuardedPoolAllocator::allocate(size_t Size, size_t Alignment) {
+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) {
@@ -187,24 +154,14 @@ void *GuardedPoolAllocator::allocate(size_t Size, size_t Alignment) {
return nullptr;
}
- if (Size == 0)
- Size = 1;
- if (Alignment == 0)
- Alignment = 1;
-
- if (!isPowerOfTwo(Alignment) || Alignment > State.maximumAllocationSize() ||
- Size > State.maximumAllocationSize())
- return nullptr;
-
- size_t BackingSize = getRequiredBackingSize(Size, Alignment, State.PageSize);
- if (BackingSize > State.maximumAllocationSize())
- return nullptr;
-
// Protect against recursivity.
if (getThreadLocals()->RecursiveGuard)
return nullptr;
ScopedRecursiveGuard SRG;
+ if (Size == 0 || Size > State.maximumAllocationSize())
+ return nullptr;
+
size_t Index;
{
ScopedLock L(PoolMutex);
@@ -214,36 +171,31 @@ void *GuardedPoolAllocator::allocate(size_t Size, size_t Alignment) {
if (Index == kInvalidSlotID)
return nullptr;
- uintptr_t SlotStart = State.slotToAddr(Index);
- AllocationMetadata *Meta = addrToMetadata(SlotStart);
- uintptr_t SlotEnd = State.slotToAddr(Index) + State.maximumAllocationSize();
- uintptr_t UserPtr;
- // Randomly choose whether to left-align or right-align the allocation, and
- // then apply the necessary adjustments to get an aligned pointer.
- if (getRandomUnsigned32() % 2 == 0)
- UserPtr = getAlignedPtr(SlotStart, Alignment, /* IsRightAligned */ false);
- else
- UserPtr =
- getAlignedPtr(SlotEnd - Size, Alignment, /* IsRightAligned */ true);
-
- assert(UserPtr >= SlotStart);
- assert(UserPtr + Size <= SlotEnd);
+ uintptr_t Ptr = State.slotToAddr(Index);
+ // Should we right-align this allocation?
+ if (getRandomUnsigned32() % 2 == 0) {
+ AlignmentStrategy Align = AlignmentStrategy::DEFAULT;
+ if (PerfectlyRightAlign)
+ Align = AlignmentStrategy::PERFECT;
+ Ptr +=
+ State.maximumAllocationSize() - rightAlignedAllocationSize(Size, Align);
+ }
+ AllocationMetadata *Meta = addrToMetadata(Ptr);
// If a slot is multiple pages in size, and the allocation takes up a single
// page, we can improve overflow detection by leaving the unused pages as
// unmapped.
const size_t PageSize = State.PageSize;
- allocateInGuardedPool(
- reinterpret_cast<void *>(getPageAddr(UserPtr, PageSize)),
- roundUpTo(Size, PageSize));
+ allocateInGuardedPool(reinterpret_cast<void *>(getPageAddr(Ptr, PageSize)),
+ roundUpTo(Size, PageSize));
- Meta->RecordAllocation(UserPtr, Size);
+ Meta->RecordAllocation(Ptr, Size);
{
ScopedLock UL(BacktraceMutex);
Meta->AllocationTrace.RecordBacktrace(Backtrace);
}
- return reinterpret_cast<void *>(UserPtr);
+ return reinterpret_cast<void *>(Ptr);
}
void GuardedPoolAllocator::trapOnAddress(uintptr_t Address, Error E) {
@@ -308,7 +260,7 @@ size_t GuardedPoolAllocator::getSize(const void *Ptr) {
ScopedLock L(PoolMutex);
AllocationMetadata *Meta = addrToMetadata(reinterpret_cast<uintptr_t>(Ptr));
assert(Meta->Addr == reinterpret_cast<uintptr_t>(Ptr));
- return Meta->RequestedSize;
+ return Meta->Size;
}
AllocationMetadata *GuardedPoolAllocator::addrToMetadata(uintptr_t Ptr) const {
diff --git a/compiler-rt/lib/gwp_asan/guarded_pool_allocator.h b/compiler-rt/lib/gwp_asan/guarded_pool_allocator.h
index 26a459925a4c..638df9b28596 100644
--- a/compiler-rt/lib/gwp_asan/guarded_pool_allocator.h
+++ b/compiler-rt/lib/gwp_asan/guarded_pool_allocator.h
@@ -19,7 +19,6 @@
#include <stddef.h>
#include <stdint.h>
-// IWYU pragma: no_include <__stddef_max_align_t.h>
namespace gwp_asan {
// This class is the primary implementation of the allocator portion of GWP-
@@ -94,13 +93,10 @@ class GuardedPoolAllocator {
return State.pointerIsMine(Ptr);
}
- // Allocate memory in a guarded slot, with the specified `Alignment`. Returns
- // nullptr if the pool is empty, if the alignnment is not a power of two, or
- // if the size/alignment makes the allocation too large for this pool to
- // handle. By default, uses strong alignment (i.e. `max_align_t`), see
- // http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2293.htm for discussion of
- // alignment issues in the standard.
- void *allocate(size_t Size, size_t Alignment = alignof(max_align_t));
+ // Allocate memory in a guarded slot, and return a pointer to the new
+ // allocation. Returns nullptr if the pool is empty, the requested size is too
+ // large for this pool to handle, or the requested size is zero.
+ void *allocate(size_t Size);
// Deallocate memory in a guarded slot. The provided pointer must have been
// allocated using this pool. This will set the guarded slot as inaccessible.
@@ -115,18 +111,6 @@ class GuardedPoolAllocator {
// Returns a pointer to the AllocatorState region.
const AllocatorState *getAllocatorState() const { return &State; }
- // Exposed as protected for testing.
-protected:
- // Returns the actual allocation size required to service an allocation with
- // the provided Size and Alignment.
- static size_t getRequiredBackingSize(size_t Size, size_t Alignment,
- size_t PageSize);
-
- // Returns the provided pointer that meets the specified alignment, depending
- // on whether it's left or right aligned.
- static uintptr_t getAlignedPtr(uintptr_t Ptr, size_t Alignment,
- bool IsRightAligned);
-
private:
// Name of actively-occupied slot mappings.
static constexpr const char *kGwpAsanAliveSlotName = "GWP-ASan Alive Slot";
diff --git a/compiler-rt/lib/gwp_asan/options.inc b/compiler-rt/lib/gwp_asan/options.inc
index 9900a2ac40df..4834daef6003 100644
--- a/compiler-rt/lib/gwp_asan/options.inc
+++ b/compiler-rt/lib/gwp_asan/options.inc
@@ -23,6 +23,16 @@ GWP_ASAN_OPTION(bool, Enabled, GWP_ASAN_DEFAULT_ENABLED,
"Is GWP-ASan enabled? Defaults to " GWP_ASAN_STRINGIFY(
GWP_ASAN_DEFAULT_ENABLED) ".")
+GWP_ASAN_OPTION(
+ bool, PerfectlyRightAlign, false,
+ "When allocations are right-aligned, should we perfectly align them up to "
+ "the page boundary? By default (false), we round up allocation size to the "
+ "nearest power of two (1, 2, 4, 8, 16) up to a maximum of 16-byte "
+ "alignment for performance reasons. For Bionic, we use 8-byte alignment by "
+ "default. Setting this to true can find single byte buffer-overflows for "
+ "multibyte allocations at the cost of performance, and may be incompatible "
+ "with some architectures.")
+
GWP_ASAN_OPTION(int, MaxSimultaneousAllocations, 16,
"Number of simultaneously-guarded allocations available in the "
"pool. Defaults to 16.")
diff --git a/compiler-rt/lib/gwp_asan/tests/alignment.cpp b/compiler-rt/lib/gwp_asan/tests/alignment.cpp
index 458902c891c9..2489ff888d16 100644
--- a/compiler-rt/lib/gwp_asan/tests/alignment.cpp
+++ b/compiler-rt/lib/gwp_asan/tests/alignment.cpp
@@ -6,119 +6,41 @@
//
//===----------------------------------------------------------------------===//
-#include "gwp_asan/guarded_pool_allocator.h"
#include "gwp_asan/tests/harness.h"
+#include "gwp_asan/utilities.h"
-class AlignmentTestGPA : public gwp_asan::GuardedPoolAllocator {
-public:
- static size_t getRequiredBackingSize(size_t Size, size_t Alignment,
- size_t PageSize) {
- return GuardedPoolAllocator::getRequiredBackingSize(Size, Alignment,
- PageSize);
- }
- static uintptr_t getAlignedPtr(uintptr_t Ptr, size_t Alignment,
- bool IsRightAligned) {
- return GuardedPoolAllocator::getAlignedPtr(Ptr, Alignment, IsRightAligned);
- }
-};
-
-// Global assumptions for these tests:
-// 1. Page size is 0x1000.
-// 2. All tests assume a slot is multipage, between 0x4000 - 0x8000. While we
-// don't use multipage slots right now, this tests more boundary conditions
-// and allows us to add this feature at a later date without rewriting the
-// alignment functionality.
-// These aren't actual requirements of the allocator - but just simplifies the
-// numerics of the testing.
-TEST(AlignmentTest, LeftAlignedAllocs) {
- // Alignment < Page Size.
- EXPECT_EQ(0x4000, AlignmentTestGPA::getAlignedPtr(
- /* Ptr */ 0x4000, /* Alignment */ 0x1,
- /* IsRightAligned */ false));
- // Alignment == Page Size.
- EXPECT_EQ(0x4000, AlignmentTestGPA::getAlignedPtr(
- /* Ptr */ 0x4000, /* Alignment */ 0x1000,
- /* IsRightAligned */ false));
- // Alignment > Page Size.
- EXPECT_EQ(0x4000, AlignmentTestGPA::getAlignedPtr(
- /* Ptr */ 0x4000, /* Alignment */ 0x4000,
- /* IsRightAligned */ false));
-}
-
-TEST(AlignmentTest, SingleByteAllocs) {
- // Alignment < Page Size.
- EXPECT_EQ(0x1,
- AlignmentTestGPA::getRequiredBackingSize(
- /* Size */ 0x1, /* Alignment */ 0x1, /* PageSize */ 0x1000));
- EXPECT_EQ(0x7fff, AlignmentTestGPA::getAlignedPtr(
- /* Ptr */ 0x8000 - 0x1, /* Alignment */ 0x1,
- /* IsRightAligned */ true));
+#include <vector>
- // Alignment == Page Size.
- EXPECT_EQ(0x1,
- AlignmentTestGPA::getRequiredBackingSize(
- /* Size */ 0x1, /* Alignment */ 0x1000, /* PageSize */ 0x1000));
- EXPECT_EQ(0x7000, AlignmentTestGPA::getAlignedPtr(
- /* Ptr */ 0x8000 - 0x1, /* Alignment */ 0x1000,
- /* IsRightAligned */ true));
+TEST(AlignmentTest, PowerOfTwo) {
+ std::vector<std::pair<size_t, size_t>> AskedSizeToAlignedSize = {
+ {1, 1}, {2, 2}, {3, 4}, {4, 4}, {5, 8}, {7, 8},
+ {8, 8}, {9, 16}, {15, 16}, {16, 16}, {17, 32}, {31, 32},
+ {32, 32}, {33, 48}, {4095, 4096}, {4096, 4096},
+ };
- // Alignment > Page Size.
- EXPECT_EQ(0x3001,
- AlignmentTestGPA::getRequiredBackingSize(
- /* Size */ 0x1, /* Alignment */ 0x4000, /* PageSize */ 0x1000));
- EXPECT_EQ(0x4000, AlignmentTestGPA::getAlignedPtr(
- /* Ptr */ 0x8000 - 0x1, /* Alignment */ 0x4000,
- /* IsRightAligned */ true));
+ for (const auto &KV : AskedSizeToAlignedSize) {
+ EXPECT_EQ(KV.second,
+ gwp_asan::rightAlignedAllocationSize(
+ KV.first, gwp_asan::AlignmentStrategy::POWER_OF_TWO));
+ }
}
-TEST(AlignmentTest, PageSizedAllocs) {
- // Alignment < Page Size.
- EXPECT_EQ(0x1000,
- AlignmentTestGPA::getRequiredBackingSize(
- /* Size */ 0x1000, /* Alignment */ 0x1, /* PageSize */ 0x1000));
- EXPECT_EQ(0x7000, AlignmentTestGPA::getAlignedPtr(
- /* Ptr */ 0x8000 - 0x1000, /* Alignment */ 0x1,
- /* IsRightAligned */ true));
+TEST(AlignmentTest, AlignBionic) {
+ std::vector<std::pair<size_t, size_t>> AskedSizeToAlignedSize = {
+ {1, 8}, {2, 8}, {3, 8}, {4, 8}, {5, 8}, {7, 8},
+ {8, 8}, {9, 16}, {15, 16}, {16, 16}, {17, 24}, {31, 32},
+ {32, 32}, {33, 40}, {4095, 4096}, {4096, 4096},
+ };
- // Alignment == Page Size.
- EXPECT_EQ(0x1000, AlignmentTestGPA::getRequiredBackingSize(
- /* Size */ 0x1000, /* Alignment */ 0x1000,
- /* PageSize */ 0x1000));
- EXPECT_EQ(0x7000, AlignmentTestGPA::getAlignedPtr(
- /* Ptr */ 0x8000 - 0x1000, /* Alignment */ 0x1000,
- /* IsRightAligned */ true));
-
- // Alignment > Page Size.
- EXPECT_EQ(0x4000, AlignmentTestGPA::getRequiredBackingSize(
- /* Size */ 0x1000, /* Alignment */ 0x4000,
- /* PageSize */ 0x1000));
- EXPECT_EQ(0x4000, AlignmentTestGPA::getAlignedPtr(
- /* Ptr */ 0x8000 - 0x1000, /* Alignment */ 0x4000,
- /* IsRightAligned */ true));
+ for (const auto &KV : AskedSizeToAlignedSize) {
+ EXPECT_EQ(KV.second, gwp_asan::rightAlignedAllocationSize(
+ KV.first, gwp_asan::AlignmentStrategy::BIONIC));
+ }
}
-TEST(AlignmentTest, MoreThanPageAllocs) {
- // Alignment < Page Size.
- EXPECT_EQ(0x2fff,
- AlignmentTestGPA::getRequiredBackingSize(
- /* Size */ 0x2fff, /* Alignment */ 0x1, /* PageSize */ 0x1000));
- EXPECT_EQ(0x5001, AlignmentTestGPA::getAlignedPtr(
- /* Ptr */ 0x8000 - 0x2fff, /* Alignment */ 0x1,
- /* IsRightAligned */ true));
-
- // Alignment == Page Size.
- EXPECT_EQ(0x2fff, AlignmentTestGPA::getRequiredBackingSize(
- /* Size */ 0x2fff, /* Alignment */ 0x1000,
- /* PageSize */ 0x1000));
- EXPECT_EQ(0x5000, AlignmentTestGPA::getAlignedPtr(
- /* Ptr */ 0x8000 - 0x2fff, /* Alignment */ 0x1000,
- /* IsRightAligned */ true));
-
- // Alignment > Page Size.
- EXPECT_EQ(0x5fff, AlignmentTestGPA::getRequiredBackingSize(
- /* Size */ 0x2fff, /* Alignment */ 0x4000,
- /* PageSize */ 0x1000));
- EXPECT_EQ(0x4000, AlignmentTestGPA::getAlignedPtr(
- /* Ptr */ 0x8000 - 0x2fff, /* Alignment */ 0x4000,
- /* IsRightAligned */ true));
+TEST(AlignmentTest, PerfectAlignment) {
+ for (size_t i = 1; i <= 4096; ++i) {
+ EXPECT_EQ(i, gwp_asan::rightAlignedAllocationSize(
+ i, gwp_asan::AlignmentStrategy::PERFECT));
+ }
}
diff --git a/compiler-rt/lib/gwp_asan/tests/basic.cpp b/compiler-rt/lib/gwp_asan/tests/basic.cpp
index 88e7ed14a5c2..29f420d3027c 100644
--- a/compiler-rt/lib/gwp_asan/tests/basic.cpp
+++ b/compiler-rt/lib/gwp_asan/tests/basic.cpp
@@ -39,37 +39,6 @@ TEST_F(CustomGuardedPoolAllocator, SizedAllocations) {
TEST_F(DefaultGuardedPoolAllocator, TooLargeAllocation) {
EXPECT_EQ(nullptr,
GPA.allocate(GPA.getAllocatorState()->maximumAllocationSize() + 1));
- EXPECT_EQ(nullptr, GPA.allocate(SIZE_MAX, 0));
- EXPECT_EQ(nullptr, GPA.allocate(SIZE_MAX, 1));
- EXPECT_EQ(nullptr, GPA.allocate(0, SIZE_MAX / 2));
- EXPECT_EQ(nullptr, GPA.allocate(1, SIZE_MAX / 2));
- EXPECT_EQ(nullptr, GPA.allocate(SIZE_MAX, SIZE_MAX / 2));
-}
-
-TEST_F(DefaultGuardedPoolAllocator, ZeroSizeAndAlignmentAllocations) {
- void *P;
- EXPECT_NE(nullptr, (P = GPA.allocate(0, 0)));
- GPA.deallocate(P);
- EXPECT_NE(nullptr, (P = GPA.allocate(1, 0)));
- GPA.deallocate(P);
- EXPECT_NE(nullptr, (P = GPA.allocate(0, 1)));
- GPA.deallocate(P);
-}
-
-TEST_F(DefaultGuardedPoolAllocator, NonPowerOfTwoAlignment) {
- EXPECT_EQ(nullptr, GPA.allocate(0, 3));
- EXPECT_EQ(nullptr, GPA.allocate(1, 3));
- EXPECT_EQ(nullptr, GPA.allocate(0, SIZE_MAX));
- EXPECT_EQ(nullptr, GPA.allocate(1, SIZE_MAX));
-}
-
-// Added multi-page slots? You'll need to expand this test.
-TEST_F(DefaultGuardedPoolAllocator, TooBigForSinglePageSlots) {
- EXPECT_EQ(nullptr, GPA.allocate(0x1001, 0));
- EXPECT_EQ(nullptr, GPA.allocate(0x1001, 1));
- EXPECT_EQ(nullptr, GPA.allocate(0x1001, 0x1000));
- EXPECT_EQ(nullptr, GPA.allocate(1, 0x2000));
- EXPECT_EQ(nullptr, GPA.allocate(0, 0x2000));
}
TEST_F(CustomGuardedPoolAllocator, AllocAllSlots) {
diff --git a/compiler-rt/lib/gwp_asan/tests/crash_handler_api.cpp b/compiler-rt/lib/gwp_asan/tests/crash_handler_api.cpp
index 4cdb5694842f..cb3063631b11 100644
--- a/compiler-rt/lib/gwp_asan/tests/crash_handler_api.cpp
+++ b/compiler-rt/lib/gwp_asan/tests/crash_handler_api.cpp
@@ -29,7 +29,7 @@ class CrashHandlerAPITest : public Test {
size_t Slot = State.getNearestSlot(Addr);
Metadata[Slot].Addr = Addr;
- Metadata[Slot].RequestedSize = Size;
+ Metadata[Slot].Size = Size;
Metadata[Slot].IsDeallocated = IsDeallocated;
Metadata[Slot].AllocationTrace.ThreadID = 123;
Metadata[Slot].DeallocationTrace.ThreadID = 321;
@@ -80,8 +80,7 @@ class CrashHandlerAPITest : public Test {
__gwp_asan_get_metadata(&State, Metadata, ErrorPtr);
EXPECT_NE(nullptr, Meta);
EXPECT_EQ(Metadata[Index].Addr, __gwp_asan_get_allocation_address(Meta));
- EXPECT_EQ(Metadata[Index].RequestedSize,
- __gwp_asan_get_allocation_size(Meta));
+ EXPECT_EQ(Metadata[Index].Size, __gwp_asan_get_allocation_size(Meta));
EXPECT_EQ(Metadata[Index].AllocationTrace.ThreadID,
__gwp_asan_get_allocation_thread_id(Meta));
diff --git a/compiler-rt/lib/gwp_asan/utilities.cpp b/compiler-rt/lib/gwp_asan/utilities.cpp
new file mode 100644
index 000000000000..287630f89531
--- /dev/null
+++ b/compiler-rt/lib/gwp_asan/utilities.cpp
@@ -0,0 +1,63 @@
+//===-- utilities.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/utilities.h"
+
+#include <assert.h>
+
+namespace gwp_asan {
+// See `bionic/tests/malloc_test.cpp` in the Android source for documentation
+// regarding their alignment guarantees. We always round up to the closest
+// 8-byte window. As GWP-ASan's malloc(X) can always get exactly an X-sized
+// allocation, an allocation that rounds up to 16-bytes will always be given a
+// 16-byte aligned allocation.
+static size_t alignBionic(size_t RealAllocationSize) {
+ if (RealAllocationSize % 8 == 0)
+ return RealAllocationSize;
+ return RealAllocationSize + 8 - (RealAllocationSize % 8);
+}
+
+static size_t alignPowerOfTwo(size_t RealAllocationSize) {
+ if (RealAllocationSize <= 2)
+ return RealAllocationSize;
+ if (RealAllocationSize <= 4)
+ return 4;
+ if (RealAllocationSize <= 8)
+ return 8;
+ if (RealAllocationSize % 16 == 0)
+ return RealAllocationSize;
+ return RealAllocationSize + 16 - (RealAllocationSize % 16);
+}
+
+#ifdef __BIONIC__
+static constexpr AlignmentStrategy PlatformDefaultAlignment =
+ AlignmentStrategy::BIONIC;
+#else // __BIONIC__
+static constexpr AlignmentStrategy PlatformDefaultAlignment =
+ AlignmentStrategy::POWER_OF_TWO;
+#endif // __BIONIC__
+
+size_t rightAlignedAllocationSize(size_t RealAllocationSize,
+ AlignmentStrategy Align) {
+ assert(RealAllocationSize > 0);
+ if (Align == AlignmentStrategy::DEFAULT)
+ Align = PlatformDefaultAlignment;
+
+ switch (Align) {
+ case AlignmentStrategy::BIONIC:
+ return alignBionic(RealAllocationSize);
+ case AlignmentStrategy::POWER_OF_TWO:
+ return alignPowerOfTwo(RealAllocationSize);
+ case AlignmentStrategy::PERFECT:
+ return RealAllocationSize;
+ case AlignmentStrategy::DEFAULT:
+ __builtin_unreachable();
+ }
+ __builtin_unreachable();
+}
+} // namespace gwp_asan
diff --git a/compiler-rt/lib/gwp_asan/utilities.h b/compiler-rt/lib/gwp_asan/utilities.h
index d8bc0e491a3d..cee5672b491d 100644
--- a/compiler-rt/lib/gwp_asan/utilities.h
+++ b/compiler-rt/lib/gwp_asan/utilities.h
@@ -23,6 +23,19 @@ GWP_ASAN_ALWAYS_INLINE void Check(bool Condition, const char *Message) {
return;
die(Message);
}
+
+enum class AlignmentStrategy {
+ // Default => POWER_OF_TWO on most platforms, BIONIC for Android Bionic.
+ DEFAULT,
+ POWER_OF_TWO,
+ BIONIC,
+ PERFECT,
+};
+
+// Returns the real size of a right-aligned allocation.
+size_t rightAlignedAllocationSize(
+ size_t RealAllocationSize,
+ AlignmentStrategy Align = AlignmentStrategy::DEFAULT);
} // namespace gwp_asan
#endif // GWP_ASAN_UTILITIES_H_
More information about the llvm-commits
mailing list