This is an archive of the discontinued LLVM Phabricator instance.

[msan] Refactor allocator instantiation
AbandonedPublic

Authored by stephan.yichao.zhao on Apr 30 2021, 12:10 AM.

Details

Reviewers
morehouse
eugenis
Summary

This is to support D101204.

We introduced a new class AllocatorAPI that can be shared with MSan and DFSan.

Diff Detail

Event Timeline

stephan.yichao.zhao requested review of this revision.Apr 30 2021, 12:10 AM
Herald added a project: Restricted Project. · View Herald TranscriptApr 30 2021, 12:10 AM
Herald added a subscriber: Restricted Project. · View Herald Transcript
vitalybuka added inline comments.
compiler-rt/lib/sanitizer_common/sanitizer_allocator_api.h
72

How we going to be sure that it's still linker initialized...

stephan.yichao.zhao retitled this revision from [msan] Refactor allocator instantiation to [msan] Refactor allocator instantiation.

update

compiler-rt/lib/sanitizer_common/sanitizer_allocator_api.h
72

This template class with virtual method will be extended by clients.
For example, MSan defines a child class MSanAllocatorAPI, then in msan_allocator.cpp, we declare a static variable as before:

static MSanAllocatorAPI allocator_api("MemorySanitizer", kMaxAllowedMallocSize);

Regarding the main point of the patch, I understand that's you are doing this to avoid duplicating code.
As negatives of this approach:

  • another abstraction layer
  • fixing one sanitizer we will have to think about affect on another

Probably check with @eugenis before fixing my comments if he is ok with this approach.

compiler-rt/lib/sanitizer_common/sanitizer_allocator_api.h
52

please use "using"

55

I guess you can just make it a stadalone function and drop two template arguments from class

template <class Thread, class ThreadLocalMallocStorage>
ThreadLocalMallocStorage *GetAllocatorCache(Thread *t);

62–69

Could you avoid victuals with CRTP, it's template anyway?
Or even better simply assume that such standalone function exist, because they probably do not need to access internals of AllocatorAPI

72

Initialized concern is not about virtuals.
Pre C++20 it's hard to be sure that global of complex type is linker initialized, we just investigated the scudo crash when two globals were linker initialized, but when we moved one inside of another compiler switched to dynamic initialization.

That's should not block the patch, but it's the reason to carefully watch msan bots or reports of unexplained crashes.

152

The point of Metadata to keep sanitizer_common unaware about content of sanitizer specific info there.
This patch breakes this.

In case of DFSan and msan, they have very similar info there, but it's still not nice.

What I see is that you just need something like this on sanitizer derived side:

uptr GetRequestedSize(uptr ptr) {
  return allocator.GetMetaData(ptr)->requested_size;
}

void SetRequestedSize(uptr ptr, uptr size) {
  allocator.GetMetaData(ptr)->requested_size = size;
}

Then you can throw away another template arg Metadata.

I would probably go even to standalone functions:

template<class Allocator>
uptr GetRequestedSize(Allocator& allocator, uptr ptr) {
  return allocator.GetMetaData(ptr)->requested_size;
}

template<class Allocator>
void SetRequestedSize(Allocator& allocator, uptr ptr, uptr size) {
  allocator.GetMetaData(ptr)->requested_size = size;
}
329–332

to my taste its more readable to keep methods definitions inside of the class

I'm not sure if this is worth the code savings.

One way of thinking about it - can it be used in ASan? TSan? Usually, you do not start factoring out common parts until you are about to add a 3rd copy of a thing.

Perhaps a more incremental approach would be better. For example, most of the Allocate method - handling of allocator cache, fallback allocator, out of memory check - is clearly common code, but Reallocate logic seems a bit too complicated and sanitizer-specific. I especially dislike the hooks, the make the code hard to follow.

requested_size works great as a common allocator concept, but I think you'll have issues if you try applying this refactoring to ASan, which does not use metadata.

compiler-rt/lib/sanitizer_common/sanitizer_allocator_api.h
143

Are these hooks really necessary? If it is called at the end of the function (or at the beginning, like DeallocateHook) MSan/DFSan could wrap the common method instead.

Thank you for the feedback. I feel the following takeaways make sense

  • another abstraction layer
  • fixing one sanitizer we will have to think about affect on another
  • can it be used in ASan? TSan? ...: I think it is not straightforward after looking into their use cases

Although Allocate and Deallocate have some similar code, but because of Thread and ThreadLocalMallocStorage, those 10-20 lines of code need a template too...

To support D101204, adding a separate allocator seems better because of the above trade-offs. I would deprecate this one.