diff options
author | Kostya Serebryany <kcc@google.com> | 2016-07-22 01:13:13 +0000 |
---|---|---|
committer | Kostya Serebryany <kcc@google.com> | 2016-07-22 01:13:13 +0000 |
commit | 35fed244180ca14cc1b1f84dce0379528c81b284 (patch) | |
tree | 97933e9ec80767c6c5055e3e94928f72b816fb35 /lib/sanitizer_common/sanitizer_allocator_size_class_map.h | |
parent | 60d3255d02f40bd6cbd45768203fd40c81fbff7d (diff) | |
download | compiler-rt-35fed244180ca14cc1b1f84dce0379528c81b284.tar.gz |
[sanitizer] allocator: introduce kUseSeparateSizeClassForBatch (false by default). When true, it will cause all TransferBatches to be allocated on a separate dedicated size class, which improves security and may potentially simplify memory reclamation. However in the current state this may cause up to 3% extra memory usage. Subsequent changes should bring this overhead down
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@276377 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/sanitizer_common/sanitizer_allocator_size_class_map.h')
-rw-r--r-- | lib/sanitizer_common/sanitizer_allocator_size_class_map.h | 35 |
1 files changed, 29 insertions, 6 deletions
diff --git a/lib/sanitizer_common/sanitizer_allocator_size_class_map.h b/lib/sanitizer_common/sanitizer_allocator_size_class_map.h index 9d0566a84..212614b2d 100644 --- a/lib/sanitizer_common/sanitizer_allocator_size_class_map.h +++ b/lib/sanitizer_common/sanitizer_allocator_size_class_map.h @@ -32,6 +32,9 @@ // - kMaxNumCached is the maximal number of chunks per size class. // - (1 << kMaxBytesCachedLog) is the maximal number of bytes per size class. // +// There is one extra size class kBatchClassID that is used for allocating +// objects of TransferBatch type when kUseSeparateSizeClassForBatch is true. +// // Part of output of SizeClassMap::Print(): // c00 => s: 0 diff: +0 00% l 0 cached: 0 0; id 0 // c01 => s: 16 diff: +16 00% l 4 cached: 256 4096; id 1 @@ -97,11 +100,22 @@ class SizeClassMap { uptr count; void *batch[kMaxNumCached]; }; - COMPILER_CHECK((sizeof(TransferBatch) & (sizeof(TransferBatch) - 1)) == 0); + static const uptr kBatchSize = sizeof(TransferBatch); + COMPILER_CHECK((kBatchSize & (kBatchSize - 1)) == 0); + + // If true, all TransferBatch objects are allocated from kBatchClassID + // size class (except for those that are needed for kBatchClassID itself). + // The goal is to have TransferBatches in a totally different region of RAM + // to improve security and allow more efficient RAM reclamation. + // This is experimental and may currently increase memory usage by up to 3% + // in extreme cases. + static const bool kUseSeparateSizeClassForBatch = false; + static const uptr kMaxSize = 1UL << kMaxSizeLog; static const uptr kNumClasses = - kMidClass + ((kMaxSizeLog - kMidSizeLog) << S) + 1; + kMidClass + ((kMaxSizeLog - kMidSizeLog) << S) + 1 + 1; + static const uptr kBatchClassID = kNumClasses - 1; COMPILER_CHECK(kNumClasses >= 32 && kNumClasses <= 256); static const uptr kNumClassesRounded = kNumClasses == 32 ? 32 : @@ -111,6 +125,8 @@ class SizeClassMap { static uptr Size(uptr class_id) { if (class_id <= kMidClass) return kMinSize * class_id; + if (class_id == kBatchClassID) + return kBatchSize; class_id -= kMidClass; uptr t = kMidSize << (class_id >> S); return t + (t >> S) * (class_id & M); @@ -144,6 +160,8 @@ class SizeClassMap { uptr p = prev_s ? (d * 100 / prev_s) : 0; uptr l = s ? MostSignificantSetBitIndex(s) : 0; uptr cached = MaxCached(i) * s; + if (i == kBatchClassID) + d = l = p = 0; Printf("c%02zd => s: %zd diff: +%zd %02zd%% l %zd " "cached: %zd %zd; id %zd\n", i, Size(i), d, p, l, MaxCached(i), cached, ClassID(s)); @@ -153,18 +171,23 @@ class SizeClassMap { Printf("Total cached: %zd\n", total_cached); } - static bool SizeClassRequiresSeparateTransferBatch(uptr class_id) { - return Size(class_id) < sizeof(TransferBatch) - - sizeof(uptr) * (kMaxNumCached - MaxCached(class_id)); + static uptr SizeClassForTransferBatch(uptr class_id) { + if (kUseSeparateSizeClassForBatch) + return class_id == kBatchClassID ? 0 : kBatchClassID; + if (Size(class_id) < sizeof(TransferBatch) - + sizeof(uptr) * (kMaxNumCached - MaxCached(class_id))) + return ClassID(sizeof(TransferBatch)); + return 0; } static void Validate() { for (uptr c = 1; c < kNumClasses; c++) { + if (c == kBatchClassID) continue; // Printf("Validate: c%zd\n", c); uptr s = Size(c); CHECK_NE(s, 0U); CHECK_EQ(ClassID(s), c); - if (c != kNumClasses - 1) + if (c != kBatchClassID - 1 && c != kNumClasses - 1) CHECK_EQ(ClassID(s + 1), c + 1); CHECK_EQ(ClassID(s - 1), c); if (c) |