[NFC][sanitizer] Add OnMapSecondary callback

Now it implemented as OnMap everywhere, but in follow up patches
we can optimize Asan handler.
This commit is contained in:
Vitaly Buka 2023-06-21 13:30:44 -07:00
parent 04a7c672ab
commit 38dfcf96df
10 changed files with 31 additions and 12 deletions

View File

@ -248,6 +248,15 @@ void AsanMapUnmapCallback::OnMap(uptr p, uptr size) const {
thread_stats.mmaps++;
thread_stats.mmaped += size;
}
void AsanMapUnmapCallback::OnMapSecondary(uptr p, uptr size) const {
PoisonShadow(p, size, kAsanHeapLeftRedzoneMagic);
// Statistics.
AsanStats &thread_stats = GetCurrentThreadStats();
thread_stats.mmaps++;
thread_stats.mmaped += size;
}
void AsanMapUnmapCallback::OnUnmap(uptr p, uptr size) const {
PoisonShadow(p, size, 0);
// We are about to unmap a chunk of user memory.

View File

@ -114,6 +114,7 @@ class AsanChunkFifoList: public IntrusiveList<AsanChunk> {
struct AsanMapUnmapCallback {
void OnMap(uptr p, uptr size) const;
void OnMapSecondary(uptr p, uptr size) const;
void OnUnmap(uptr p, uptr size) const;
};

View File

@ -30,6 +30,7 @@ struct Metadata {
struct DFsanMapUnmapCallback {
void OnMap(uptr p, uptr size) const { dfsan_set_label(0, (void *)p, size); }
void OnMapSecondary(uptr p, uptr size) const { OnMap(p, size); }
void OnUnmap(uptr p, uptr size) const { dfsan_set_label(0, (void *)p, size); }
};

View File

@ -54,6 +54,7 @@ static_assert(sizeof(Metadata) == 16);
struct HwasanMapUnmapCallback {
void OnMap(uptr p, uptr size) const { UpdateMemoryUsage(); }
void OnMapSecondary(uptr p, uptr size) const { UpdateMemoryUsage(); }
void OnUnmap(uptr p, uptr size) const {
// We are about to unmap a chunk of user memory.
// It can return as user-requested mmap() or another thread stack.

View File

@ -39,6 +39,7 @@ void InitializeAllocator();
struct MemprofMapUnmapCallback {
void OnMap(uptr p, uptr size) const;
void OnMapSecondary(uptr p, uptr size) const { OnMap(p, size); }
void OnUnmap(uptr p, uptr size) const;
};

View File

@ -30,6 +30,7 @@ struct Metadata {
struct MsanMapUnmapCallback {
void OnMap(uptr p, uptr size) const {}
void OnMapSecondary(uptr p, uptr size) const {}
void OnUnmap(uptr p, uptr size) const {
__msan_unpoison((void *)p, size);

View File

@ -64,6 +64,7 @@ inline void RandomShuffle(T *a, u32 n, u32 *rand_state) {
struct NoOpMapUnmapCallback {
void OnMap(uptr p, uptr size) const {}
void OnMapSecondary(uptr p, uptr size) const {}
void OnUnmap(uptr p, uptr size) const {}
};

View File

@ -99,7 +99,7 @@ class LargeMmapAllocator {
if (!map_beg)
return nullptr;
CHECK(IsAligned(map_beg, page_size_));
MapUnmapCallback().OnMap(map_beg, map_size);
MapUnmapCallback().OnMapSecondary(map_beg, map_size);
uptr map_end = map_beg + map_size;
uptr res = map_beg + page_size_;
if (res & (alignment - 1)) // Align.

View File

@ -476,11 +476,15 @@ TEST(SanitizerCommon, SizeClassAllocator32CompactGetBlockBegin) {
#endif // SANITIZER_CAN_USE_ALLOCATOR64
struct TestMapUnmapCallback {
static int map_count, unmap_count;
static int map_count, map_secondary_count, unmap_count;
void OnMap(uptr p, uptr size) const { map_count++; }
void OnMapSecondary(uptr p, uptr size) const { map_secondary_count++; }
void OnUnmap(uptr p, uptr size) const { unmap_count++; }
static void Reset() { map_count = map_secondary_count = unmap_count = 0; }
};
int TestMapUnmapCallback::map_count;
int TestMapUnmapCallback::map_secondary_count;
int TestMapUnmapCallback::unmap_count;
#if SANITIZER_CAN_USE_ALLOCATOR64
@ -500,12 +504,12 @@ struct AP64WithCallback {
};
TEST(SanitizerCommon, SizeClassAllocator64MapUnmapCallback) {
TestMapUnmapCallback::map_count = 0;
TestMapUnmapCallback::unmap_count = 0;
TestMapUnmapCallback::Reset();
typedef SizeClassAllocator64<AP64WithCallback<>> Allocator64WithCallBack;
Allocator64WithCallBack *a = new Allocator64WithCallBack;
a->Init(kReleaseToOSIntervalNever);
EXPECT_EQ(TestMapUnmapCallback::map_count, 1); // Allocator state.
EXPECT_EQ(TestMapUnmapCallback::map_secondary_count, 0);
typename Allocator64WithCallBack::AllocatorCache cache;
memset(&cache, 0, sizeof(cache));
cache.Init(0);
@ -516,6 +520,7 @@ TEST(SanitizerCommon, SizeClassAllocator64MapUnmapCallback) {
a->GetFromAllocator(&stats, 30, chunks, kNumChunks);
// State + alloc + metadata + freearray.
EXPECT_EQ(TestMapUnmapCallback::map_count, 4);
EXPECT_EQ(TestMapUnmapCallback::map_secondary_count, 0);
a->TestOnlyUnmap();
EXPECT_EQ(TestMapUnmapCallback::unmap_count, 1); // The whole thing.
delete a;
@ -536,12 +541,12 @@ struct AP32WithCallback {
};
TEST(SanitizerCommon, SizeClassAllocator32MapUnmapCallback) {
TestMapUnmapCallback::map_count = 0;
TestMapUnmapCallback::unmap_count = 0;
TestMapUnmapCallback::Reset();
typedef SizeClassAllocator32<AP32WithCallback<>> Allocator32WithCallBack;
Allocator32WithCallBack *a = new Allocator32WithCallBack;
a->Init(kReleaseToOSIntervalNever);
EXPECT_EQ(TestMapUnmapCallback::map_count, 0);
EXPECT_EQ(TestMapUnmapCallback::map_secondary_count, 0);
Allocator32WithCallBack::AllocatorCache cache;
memset(&cache, 0, sizeof(cache));
cache.Init(0);
@ -549,23 +554,21 @@ TEST(SanitizerCommon, SizeClassAllocator32MapUnmapCallback) {
stats.Init();
a->AllocateBatch(&stats, &cache, 32);
EXPECT_EQ(TestMapUnmapCallback::map_count, 1);
EXPECT_EQ(TestMapUnmapCallback::map_secondary_count, 0);
a->TestOnlyUnmap();
EXPECT_EQ(TestMapUnmapCallback::unmap_count, 1);
delete a;
// fprintf(stderr, "Map: %d Unmap: %d\n",
// TestMapUnmapCallback::map_count,
// TestMapUnmapCallback::unmap_count);
}
TEST(SanitizerCommon, LargeMmapAllocatorMapUnmapCallback) {
TestMapUnmapCallback::map_count = 0;
TestMapUnmapCallback::unmap_count = 0;
TestMapUnmapCallback::Reset();
LargeMmapAllocator<TestMapUnmapCallback> a;
a.Init();
AllocatorStats stats;
stats.Init();
void *x = a.Allocate(&stats, 1 << 20, 1);
EXPECT_EQ(TestMapUnmapCallback::map_count, 1);
EXPECT_EQ(TestMapUnmapCallback::map_count, 0);
EXPECT_EQ(TestMapUnmapCallback::map_secondary_count, 1);
a.Deallocate(&stats, x);
EXPECT_EQ(TestMapUnmapCallback::unmap_count, 1);
}

View File

@ -25,6 +25,7 @@ namespace __tsan {
struct MapUnmapCallback {
void OnMap(uptr p, uptr size) const { }
void OnMapSecondary(uptr p, uptr size) const {};
void OnUnmap(uptr p, uptr size) const {
// We are about to unmap a chunk of user memory.
// Mark the corresponding shadow memory as not needed.