1//===-- msan_allocator.cc --------------------------- ---------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file is a part of MemorySanitizer. 11// 12// MemorySanitizer allocator. 13//===----------------------------------------------------------------------===// 14 15#include "sanitizer_common/sanitizer_allocator.h" 16#include "sanitizer_common/sanitizer_stackdepot.h" 17#include "msan.h" 18 19namespace __msan { 20 21struct Metadata { 22 uptr requested_size; 23}; 24 25static const uptr kAllocatorSpace = 0x600000000000ULL; 26static const uptr kAllocatorSize = 0x80000000000; // 8T. 27static const uptr kMetadataSize = sizeof(Metadata); 28 29typedef SizeClassAllocator64<kAllocatorSpace, kAllocatorSize, kMetadataSize, 30 DefaultSizeClassMap> PrimaryAllocator; 31typedef SizeClassAllocatorLocalCache<PrimaryAllocator> AllocatorCache; 32typedef LargeMmapAllocator<> SecondaryAllocator; 33typedef CombinedAllocator<PrimaryAllocator, AllocatorCache, 34 SecondaryAllocator> Allocator; 35 36static THREADLOCAL AllocatorCache cache; 37static Allocator allocator; 38 39static int inited = 0; 40 41static inline void Init() { 42 if (inited) return; 43 __msan_init(); 44 inited = true; // this must happen before any threads are created. 45 allocator.Init(); 46} 47 48static void *MsanAllocate(StackTrace *stack, uptr size, 49 uptr alignment, bool zeroise) { 50 Init(); 51 void *res = allocator.Allocate(&cache, size, alignment, false); 52 Metadata *meta = reinterpret_cast<Metadata*>(allocator.GetMetaData(res)); 53 meta->requested_size = size; 54 if (zeroise) 55 __msan_clear_and_unpoison(res, size); 56 else if (flags()->poison_in_malloc) 57 __msan_poison(res, size); 58 if (__msan_get_track_origins()) { 59 u32 stack_id = StackDepotPut(stack->trace, stack->size); 60 CHECK(stack_id); 61 CHECK_EQ((stack_id >> 31), 0); // Higher bit is occupied by stack origins. 62 __msan_set_origin(res, size, stack_id); 63 } 64 return res; 65} 66 67void MsanDeallocate(void *p) { 68 CHECK(p); 69 Init(); 70 Metadata *meta = reinterpret_cast<Metadata*>(allocator.GetMetaData(p)); 71 uptr size = meta->requested_size; 72 // This memory will not be reused by anyone else, so we are free to keep it 73 // poisoned. 74 __msan_poison(p, size); 75 if (__msan_get_track_origins()) 76 __msan_set_origin(p, size, -1); 77 allocator.Deallocate(&cache, p); 78} 79 80void *MsanReallocate(StackTrace *stack, void *old_p, uptr new_size, 81 uptr alignment, bool zeroise) { 82 if (!old_p) 83 return MsanAllocate(stack, new_size, alignment, zeroise); 84 if (!new_size) { 85 MsanDeallocate(old_p); 86 return 0; 87 } 88 Metadata *meta = reinterpret_cast<Metadata*>(allocator.GetMetaData(old_p)); 89 uptr old_size = meta->requested_size; 90 uptr actually_allocated_size = allocator.GetActuallyAllocatedSize(old_p); 91 if (new_size <= actually_allocated_size) { 92 // We are not reallocating here. 93 meta->requested_size = new_size; 94 if (new_size > old_size) 95 __msan_poison((char*)old_p + old_size, new_size - old_size); 96 return old_p; 97 } 98 uptr memcpy_size = Min(new_size, old_size); 99 void *new_p = MsanAllocate(stack, new_size, alignment, zeroise); 100 // Printf("realloc: old_size %zd new_size %zd\n", old_size, new_size); 101 if (new_p) 102 __msan_memcpy(new_p, old_p, memcpy_size); 103 MsanDeallocate(old_p); 104 return new_p; 105} 106 107} // namespace __msan 108