Summary:
This is a follow up patch to r346956 for the `SizeClassAllocator32`
allocator.
This patch makes `AddressSpaceView` a template parameter both to the
`ByteMap` implementations (but makes `LocalAddressSpaceView` the
default), some `AP32` implementations and is used in `SizeClassAllocator32`.
The actual changes to `ByteMap` implementations and
`SizeClassAllocator32` are very simple. However the patch is large
because it requires changing all the `AP32` definitions, and users of
those definitions.
For ASan and LSan we make `AP32` and `ByteMap` templateds type that take
a single `AddressSpaceView` argument. This has been done because we will
instantiate the allocator with a type that isn't `LocalAddressSpaceView`
in the future patches. For the allocators used in the other sanitizers
(i.e. HWAsan, MSan, Scudo, and TSan) use of `LocalAddressSpaceView` is
hard coded because we do not intend to instantiate the allocators with
any other type.
In the cases where untemplated types have become templated on a single
`AddressSpaceView` parameter (e.g. `PrimaryAllocator`) their name has
been changed to have a `ASVT` suffix (Address Space View Type) to
indicate they are templated. The only exception to this are the `AP32`
types due to the desire to keep the type name as short as possible.
In order to check that template is instantiated in the correct a way a
`static_assert(...)` has been added that checks that the
`AddressSpaceView` type used by `Params::ByteMap::AddressSpaceView` matches
the `Params::AddressSpaceView`. This uses the new `sanitizer_type_traits.h`
header.
rdar://problem/
45284065
Reviewers: kcc, dvyukov, vitalybuka, cryptoad, eugenis, kubamracek, george.karpenkov
Subscribers: mgorny, llvm-commits, #sanitizers
Differential Revision: https://reviews.llvm.org/D54904
llvm-svn: 349138
static const uptr kRegionSizeLog = 20;
static const uptr kNumRegions = SANITIZER_MMAP_RANGE_SIZE >> kRegionSizeLog;
# if SANITIZER_WORDSIZE == 32
-typedef FlatByteMap<kNumRegions> ByteMap;
+template <typename AddressSpaceView>
+using ByteMapASVT = FlatByteMap<kNumRegions, AddressSpaceView>;
# elif SANITIZER_WORDSIZE == 64
-typedef TwoLevelByteMap<(kNumRegions >> 12), 1 << 12> ByteMap;
+template <typename AddressSpaceView>
+using ByteMapASVT =
+ TwoLevelByteMap<(kNumRegions >> 12), 1 << 12, AddressSpaceView>;
# endif
typedef CompactSizeClassMap SizeClassMap;
+template <typename AddressSpaceViewTy>
struct AP32 {
static const uptr kSpaceBeg = 0;
static const u64 kSpaceSize = SANITIZER_MMAP_RANGE_SIZE;
static const uptr kMetadataSize = 16;
typedef __asan::SizeClassMap SizeClassMap;
static const uptr kRegionSizeLog = __asan::kRegionSizeLog;
- typedef __asan::ByteMap ByteMap;
+ using AddressSpaceView = AddressSpaceViewTy;
+ using ByteMap = __asan::ByteMapASVT<AddressSpaceView>;
typedef AsanMapUnmapCallback MapUnmapCallback;
static const uptr kFlags = 0;
};
-typedef SizeClassAllocator32<AP32> PrimaryAllocator;
+template <typename AddressSpaceView>
+using PrimaryAllocatorASVT = SizeClassAllocator32<AP32<AddressSpaceView> >;
+using PrimaryAllocator = PrimaryAllocatorASVT<LocalAddressSpaceView>;
#endif // SANITIZER_CAN_USE_ALLOCATOR64
static const uptr kNumberOfSizeClasses = SizeClassMap::kNumClasses;
static const uptr kMetadataSize = sizeof(Metadata);
typedef __sanitizer::CompactSizeClassMap SizeClassMap;
static const uptr kRegionSizeLog = __hwasan::kRegionSizeLog;
- typedef __hwasan::ByteMap ByteMap;
+ using AddressSpaceView = LocalAddressSpaceView;
+ using ByteMap = __hwasan::ByteMap;
typedef HwasanMapUnmapCallback MapUnmapCallback;
static const uptr kFlags = 0;
};
defined(__arm__)
static const uptr kRegionSizeLog = 20;
static const uptr kNumRegions = SANITIZER_MMAP_RANGE_SIZE >> kRegionSizeLog;
-typedef TwoLevelByteMap<(kNumRegions >> 12), 1 << 12> ByteMap;
+template <typename AddressSpaceView>
+using ByteMapASVT =
+ TwoLevelByteMap<(kNumRegions >> 12), 1 << 12, AddressSpaceView>;
+template <typename AddressSpaceViewTy>
struct AP32 {
static const uptr kSpaceBeg = 0;
static const u64 kSpaceSize = SANITIZER_MMAP_RANGE_SIZE;
static const uptr kMetadataSize = sizeof(ChunkMetadata);
typedef __sanitizer::CompactSizeClassMap SizeClassMap;
static const uptr kRegionSizeLog = __lsan::kRegionSizeLog;
- typedef __lsan::ByteMap ByteMap;
+ using AddressSpaceView = AddressSpaceViewTy;
+ using ByteMap = __lsan::ByteMapASVT<AddressSpaceView>;
typedef NoOpMapUnmapCallback MapUnmapCallback;
static const uptr kFlags = 0;
};
-typedef SizeClassAllocator32<AP32> PrimaryAllocator;
+template <typename AddressSpaceView>
+using PrimaryAllocatorASVT = SizeClassAllocator32<AP32<AddressSpaceView>>;
+using PrimaryAllocator = PrimaryAllocatorASVT<LocalAddressSpaceView>;
#elif defined(__x86_64__) || defined(__powerpc64__)
# if defined(__powerpc64__)
const uptr kAllocatorSpace = 0xa0000000000ULL;
static const uptr kMetadataSize = sizeof(Metadata);
typedef __sanitizer::CompactSizeClassMap SizeClassMap;
static const uptr kRegionSizeLog = __msan::kRegionSizeLog;
- typedef __msan::ByteMap ByteMap;
+ using AddressSpaceView = LocalAddressSpaceView;
+ using ByteMap = __msan::ByteMap;
typedef MsanMapUnmapCallback MapUnmapCallback;
static const uptr kFlags = 0;
};
static const uptr kMetadataSize = sizeof(Metadata);
typedef __sanitizer::CompactSizeClassMap SizeClassMap;
static const uptr kRegionSizeLog = __msan::kRegionSizeLog;
- typedef __msan::ByteMap ByteMap;
+ using AddressSpaceView = LocalAddressSpaceView;
+ using ByteMap = __msan::ByteMap;
typedef MsanMapUnmapCallback MapUnmapCallback;
static const uptr kFlags = 0;
};
#include "sanitizer_local_address_space_view.h"
#include "sanitizer_mutex.h"
#include "sanitizer_procmaps.h"
+#include "sanitizer_type_traits.h"
namespace __sanitizer {
#endif
// Maps integers in rage [0, kSize) to u8 values.
-template<u64 kSize>
+template <u64 kSize, typename AddressSpaceViewTy = LocalAddressSpaceView>
class FlatByteMap {
public:
+ using AddressSpaceView = AddressSpaceViewTy;
void Init() {
internal_memset(map_, 0, sizeof(map_));
}
// to kSize2-byte arrays. The secondary arrays are mmaped on demand.
// Each value is initially zero and can be set to something else only once.
// Setting and getting values from multiple threads is safe w/o extra locking.
-template <u64 kSize1, u64 kSize2, class MapUnmapCallback = NoOpMapUnmapCallback>
+template <u64 kSize1, u64 kSize2,
+ typename AddressSpaceViewTy = LocalAddressSpaceView,
+ class MapUnmapCallback = NoOpMapUnmapCallback>
class TwoLevelByteMap {
public:
+ using AddressSpaceView = AddressSpaceViewTy;
void Init() {
internal_memset(map1_, 0, sizeof(map1_));
mu_.Init();
CHECK_LT(idx, kSize1 * kSize2);
u8 *map2 = Get(idx / kSize2);
if (!map2) return 0;
- return map2[idx % kSize2];
+ auto value_ptr = AddressSpaceView::Load(&map2[idx % kSize2]);
+ return *value_ptr;
}
private:
static const uptr kMetadataSize = 0;
typedef InternalSizeClassMap SizeClassMap;
static const uptr kRegionSizeLog = kInternalAllocatorRegionSizeLog;
- typedef __sanitizer::ByteMap ByteMap;
+ using AddressSpaceView = LocalAddressSpaceView;
+ using ByteMap = __sanitizer::ByteMap;
typedef NoOpMapUnmapCallback MapUnmapCallback;
static const uptr kFlags = 0;
};
template <class Params>
class SizeClassAllocator32 {
public:
+ using AddressSpaceView = typename Params::AddressSpaceView;
static const uptr kSpaceBeg = Params::kSpaceBeg;
static const u64 kSpaceSize = Params::kSpaceSize;
static const uptr kMetadataSize = Params::kMetadataSize;
typedef SizeClassAllocator32LocalCache<ThisT> AllocatorCache;
void Init(s32 release_to_os_interval_ms) {
+ static_assert(
+ is_same<typename ByteMap::AddressSpaceView, AddressSpaceView>::value,
+ "AddressSpaceView type mismatch");
possible_regions.Init();
internal_memset(size_class_info_array, 0, sizeof(size_class_info_array));
}
static const uptr kRegionSizeLog = FIRST_32_SECOND_64(20, 24);
static const uptr kFlatByteMapSize = kAddressSpaceSize >> kRegionSizeLog;
+template <typename AddressSpaceViewTy>
struct AP32Compact {
static const uptr kSpaceBeg = 0;
static const u64 kSpaceSize = kAddressSpaceSize;
static const uptr kMetadataSize = 16;
typedef CompactSizeClassMap SizeClassMap;
static const uptr kRegionSizeLog = ::kRegionSizeLog;
- typedef FlatByteMap<kFlatByteMapSize> ByteMap;
+ using AddressSpaceView = AddressSpaceViewTy;
+ using ByteMap = FlatByteMap<kFlatByteMapSize, AddressSpaceView>;
typedef NoOpMapUnmapCallback MapUnmapCallback;
static const uptr kFlags = 0;
};
-typedef SizeClassAllocator32<AP32Compact> Allocator32Compact;
+template <typename AddressSpaceView>
+using Allocator32CompactASVT =
+ SizeClassAllocator32<AP32Compact<AddressSpaceView>>;
+using Allocator32Compact = Allocator32CompactASVT<LocalAddressSpaceView>;
template <class SizeClassMap>
void TestSizeClassMap() {
TestSizeClassAllocator<Allocator32Compact>();
}
+template <typename AddressSpaceViewTy>
struct AP32SeparateBatches {
static const uptr kSpaceBeg = 0;
static const u64 kSpaceSize = kAddressSpaceSize;
static const uptr kMetadataSize = 16;
typedef DefaultSizeClassMap SizeClassMap;
static const uptr kRegionSizeLog = ::kRegionSizeLog;
- typedef FlatByteMap<kFlatByteMapSize> ByteMap;
+ using AddressSpaceView = AddressSpaceViewTy;
+ using ByteMap = FlatByteMap<kFlatByteMapSize, AddressSpaceView>;
typedef NoOpMapUnmapCallback MapUnmapCallback;
static const uptr kFlags =
SizeClassAllocator32FlagMasks::kUseSeparateSizeClassForBatch;
};
-typedef SizeClassAllocator32<AP32SeparateBatches> Allocator32SeparateBatches;
+template <typename AddressSpaceView>
+using Allocator32SeparateBatchesASVT =
+ SizeClassAllocator32<AP32SeparateBatches<AddressSpaceView>>;
+using Allocator32SeparateBatches =
+ Allocator32SeparateBatchesASVT<LocalAddressSpaceView>;
TEST(SanitizerCommon, SizeClassAllocator32SeparateBatches) {
TestSizeClassAllocator<Allocator32SeparateBatches>();
#endif
#endif
+template <typename AddressSpaceViewTy = LocalAddressSpaceView>
struct AP32WithCallback {
static const uptr kSpaceBeg = 0;
static const u64 kSpaceSize = kAddressSpaceSize;
static const uptr kMetadataSize = 16;
typedef CompactSizeClassMap SizeClassMap;
static const uptr kRegionSizeLog = ::kRegionSizeLog;
- typedef FlatByteMap<kFlatByteMapSize> ByteMap;
+ using AddressSpaceView = AddressSpaceViewTy;
+ using ByteMap = FlatByteMap<kFlatByteMapSize, AddressSpaceView>;
typedef TestMapUnmapCallback MapUnmapCallback;
static const uptr kFlags = 0;
};
TEST(SanitizerCommon, SizeClassAllocator32MapUnmapCallback) {
TestMapUnmapCallback::map_count = 0;
TestMapUnmapCallback::unmap_count = 0;
- typedef SizeClassAllocator32<AP32WithCallback> Allocator32WithCallBack;
+ typedef SizeClassAllocator32<AP32WithCallback<>> Allocator32WithCallBack;
Allocator32WithCallBack *a = new Allocator32WithCallBack;
a->Init(kReleaseToOSIntervalNever);
EXPECT_EQ(TestMapUnmapCallback::map_count, 0);
m.TestOnlyUnmap();
}
-
-typedef TwoLevelByteMap<1 << 12, 1 << 13, TestMapUnmapCallback> TestByteMap;
+template <typename AddressSpaceView>
+using TestByteMapASVT =
+ TwoLevelByteMap<1 << 12, 1 << 13, AddressSpaceView, TestMapUnmapCallback>;
+using TestByteMap = TestByteMapASVT<LocalAddressSpaceView>;
struct TestByteMapParam {
TestByteMap *m;
static const uptr kMetadataSize = 0;
typedef __scudo::SizeClassMap SizeClassMap;
static const uptr kRegionSizeLog = RegionSizeLog;
- typedef __scudo::ByteMap ByteMap;
+ using AddressSpaceView = LocalAddressSpaceView;
+ using ByteMap = __scudo::ByteMap;
typedef NoOpMapUnmapCallback MapUnmapCallback;
static const uptr kFlags =
SizeClassAllocator32FlagMasks::kRandomShuffleChunks |
static const uptr kAllocatorRegionSizeLog = 20;
static const uptr kAllocatorNumRegions =
SANITIZER_MMAP_RANGE_SIZE >> kAllocatorRegionSizeLog;
-typedef TwoLevelByteMap<(kAllocatorNumRegions >> 12), 1 << 12,
- MapUnmapCallback> ByteMap;
+using ByteMap = TwoLevelByteMap<(kAllocatorNumRegions >> 12), 1 << 12,
+ LocalAddressSpaceView, MapUnmapCallback>;
struct AP32 {
static const uptr kSpaceBeg = 0;
static const u64 kSpaceSize = SANITIZER_MMAP_RANGE_SIZE;
static const uptr kMetadataSize = 0;
typedef __sanitizer::CompactSizeClassMap SizeClassMap;
static const uptr kRegionSizeLog = kAllocatorRegionSizeLog;
- typedef __tsan::ByteMap ByteMap;
+ using AddressSpaceView = LocalAddressSpaceView;
+ using ByteMap = __tsan::ByteMap;
typedef __tsan::MapUnmapCallback MapUnmapCallback;
static const uptr kFlags = 0;
};