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 19 namespace __msan { 20 21 struct Metadata { 22 uptr requested_size; 23 }; 24 25 static const uptr kAllocatorSpace = 0x600000000000ULL; 26 static const uptr kAllocatorSize = 0x80000000000; // 8T. 27 static const uptr kMetadataSize = sizeof(Metadata); 28 29 typedef SizeClassAllocator64<kAllocatorSpace, kAllocatorSize, kMetadataSize, 30 DefaultSizeClassMap> PrimaryAllocator; 31 typedef SizeClassAllocatorLocalCache<PrimaryAllocator> AllocatorCache; 32 typedef LargeMmapAllocator<> SecondaryAllocator; 33 typedef CombinedAllocator<PrimaryAllocator, AllocatorCache, 34 SecondaryAllocator> Allocator; 35 36 static THREADLOCAL AllocatorCache cache; 37 static Allocator allocator; 38 39 static int inited = 0; 40 41 static 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 48 static 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 67 void 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 80 void *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