diff options
author | Evgeniy Stepanov <eugeni.stepanov@gmail.com> | 2012-12-11 12:27:27 +0000 |
---|---|---|
committer | Evgeniy Stepanov <eugeni.stepanov@gmail.com> | 2012-12-11 12:27:27 +0000 |
commit | 78c56c3c407d2c92825c86e6af7a0230d6019a1c (patch) | |
tree | 808c7192ad93fb80b58a7b32ab855fa21961e31e /lib/msan/msan_allocator.cc | |
parent | 8416e2110049d4f53f790b2486c6f1add6729ea4 (diff) |
[msan] MemorySanitizer runtime.
Initial commit of the MemorySanitizer runtime library.
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@169858 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/msan/msan_allocator.cc')
-rw-r--r-- | lib/msan/msan_allocator.cc | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/lib/msan/msan_allocator.cc b/lib/msan/msan_allocator.cc new file mode 100644 index 000000000..5d865c30b --- /dev/null +++ b/lib/msan/msan_allocator.cc @@ -0,0 +1,107 @@ +//===-- msan_allocator.cc --------------------------- ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a part of MemorySanitizer. +// +// MemorySanitizer allocator. +//===----------------------------------------------------------------------===// + +#include "sanitizer_common/sanitizer_allocator.h" +#include "sanitizer_common/sanitizer_stackdepot.h" +#include "msan.h" + +namespace __msan { + +struct Metadata { + uptr requested_size; +}; + +static const uptr kAllocatorSpace = 0x600000000000ULL; +static const uptr kAllocatorSize = 0x80000000000; // 8T. +static const uptr kMetadataSize = sizeof(Metadata); + +typedef SizeClassAllocator64<kAllocatorSpace, kAllocatorSize, kMetadataSize, + DefaultSizeClassMap> PrimaryAllocator; +typedef SizeClassAllocatorLocalCache<PrimaryAllocator> AllocatorCache; +typedef LargeMmapAllocator SecondaryAllocator; +typedef CombinedAllocator<PrimaryAllocator, AllocatorCache, + SecondaryAllocator> Allocator; + +static THREADLOCAL AllocatorCache cache; +static Allocator allocator; + +static int inited = 0; + +static inline void Init() { + if (inited) return; + __msan_init(); + inited = true; // this must happen before any threads are created. + allocator.Init(); +} + +static void *MsanAllocate(StackTrace *stack, uptr size, + uptr alignment, bool zeroise) { + Init(); + void *res = allocator.Allocate(&cache, size, alignment, false); + Metadata *meta = reinterpret_cast<Metadata*>(allocator.GetMetaData(res)); + meta->requested_size = size; + if (zeroise) + __msan_clear_and_unpoison(res, size); + else if (flags()->poison_in_malloc) + __msan_poison(res, size); + if (__msan_get_track_origins()) { + u32 stack_id = StackDepotPut(stack->trace, stack->size); + CHECK(stack_id); + CHECK_EQ((stack_id >> 31), 0); // Higher bit is occupied by stack origins. + __msan_set_origin(res, size, stack_id); + } + return res; +} + +void MsanDeallocate(void *p) { + CHECK(p); + Init(); + Metadata *meta = reinterpret_cast<Metadata*>(allocator.GetMetaData(p)); + uptr size = meta->requested_size; + // This memory will not be reused by anyone else, so we are free to keep it + // poisoned. + __msan_poison(p, size); + if (__msan_get_track_origins()) + __msan_set_origin(p, size, -1); + allocator.Deallocate(&cache, p); +} + +void *MsanReallocate(StackTrace *stack, void *old_p, uptr new_size, + uptr alignment, bool zeroise) { + if (!old_p) + return MsanAllocate(stack, new_size, alignment, zeroise); + if (!new_size) { + MsanDeallocate(old_p); + return 0; + } + Metadata *meta = reinterpret_cast<Metadata*>(allocator.GetMetaData(old_p)); + uptr old_size = meta->requested_size; + uptr actually_allocated_size = allocator.GetActuallyAllocatedSize(old_p); + if (new_size <= actually_allocated_size) { + // We are not reallocating here. + meta->requested_size = new_size; + if (new_size > old_size) + __msan_poison((char*)old_p + old_size, new_size - old_size); + return old_p; + } + uptr memcpy_size = Min(new_size, old_size); + void *new_p = MsanAllocate(stack, new_size, alignment, zeroise); + // Printf("realloc: old_size %zd new_size %zd\n", old_size, new_size); + if (new_p) + __msan_memcpy(new_p, old_p, memcpy_size); + MsanDeallocate(old_p); + return new_p; +} + +} // namespace __msan |