1*7c3d14c8STreehugger Robot //===-- asan_allocator.h ----------------------------------------*- C++ -*-===// 2*7c3d14c8STreehugger Robot // 3*7c3d14c8STreehugger Robot // The LLVM Compiler Infrastructure 4*7c3d14c8STreehugger Robot // 5*7c3d14c8STreehugger Robot // This file is distributed under the University of Illinois Open Source 6*7c3d14c8STreehugger Robot // License. See LICENSE.TXT for details. 7*7c3d14c8STreehugger Robot // 8*7c3d14c8STreehugger Robot //===----------------------------------------------------------------------===// 9*7c3d14c8STreehugger Robot // 10*7c3d14c8STreehugger Robot // This file is a part of AddressSanitizer, an address sanity checker. 11*7c3d14c8STreehugger Robot // 12*7c3d14c8STreehugger Robot // ASan-private header for asan_allocator.cc. 13*7c3d14c8STreehugger Robot //===----------------------------------------------------------------------===// 14*7c3d14c8STreehugger Robot 15*7c3d14c8STreehugger Robot #ifndef ASAN_ALLOCATOR_H 16*7c3d14c8STreehugger Robot #define ASAN_ALLOCATOR_H 17*7c3d14c8STreehugger Robot 18*7c3d14c8STreehugger Robot #include "asan_flags.h" 19*7c3d14c8STreehugger Robot #include "asan_internal.h" 20*7c3d14c8STreehugger Robot #include "asan_interceptors.h" 21*7c3d14c8STreehugger Robot #include "sanitizer_common/sanitizer_allocator.h" 22*7c3d14c8STreehugger Robot #include "sanitizer_common/sanitizer_list.h" 23*7c3d14c8STreehugger Robot 24*7c3d14c8STreehugger Robot namespace __asan { 25*7c3d14c8STreehugger Robot 26*7c3d14c8STreehugger Robot enum AllocType { 27*7c3d14c8STreehugger Robot FROM_MALLOC = 1, // Memory block came from malloc, calloc, realloc, etc. 28*7c3d14c8STreehugger Robot FROM_NEW = 2, // Memory block came from operator new. 29*7c3d14c8STreehugger Robot FROM_NEW_BR = 3 // Memory block came from operator new [ ] 30*7c3d14c8STreehugger Robot }; 31*7c3d14c8STreehugger Robot 32*7c3d14c8STreehugger Robot struct AsanChunk; 33*7c3d14c8STreehugger Robot 34*7c3d14c8STreehugger Robot struct AllocatorOptions { 35*7c3d14c8STreehugger Robot u32 quarantine_size_mb; 36*7c3d14c8STreehugger Robot u16 min_redzone; 37*7c3d14c8STreehugger Robot u16 max_redzone; 38*7c3d14c8STreehugger Robot u8 may_return_null; 39*7c3d14c8STreehugger Robot u8 alloc_dealloc_mismatch; 40*7c3d14c8STreehugger Robot 41*7c3d14c8STreehugger Robot void SetFrom(const Flags *f, const CommonFlags *cf); 42*7c3d14c8STreehugger Robot void CopyTo(Flags *f, CommonFlags *cf); 43*7c3d14c8STreehugger Robot }; 44*7c3d14c8STreehugger Robot 45*7c3d14c8STreehugger Robot void InitializeAllocator(const AllocatorOptions &options); 46*7c3d14c8STreehugger Robot void ReInitializeAllocator(const AllocatorOptions &options); 47*7c3d14c8STreehugger Robot void GetAllocatorOptions(AllocatorOptions *options); 48*7c3d14c8STreehugger Robot 49*7c3d14c8STreehugger Robot class AsanChunkView { 50*7c3d14c8STreehugger Robot public: AsanChunkView(AsanChunk * chunk)51*7c3d14c8STreehugger Robot explicit AsanChunkView(AsanChunk *chunk) : chunk_(chunk) {} 52*7c3d14c8STreehugger Robot bool IsValid(); // Checks if AsanChunkView points to a valid allocated 53*7c3d14c8STreehugger Robot // or quarantined chunk. 54*7c3d14c8STreehugger Robot bool IsAllocated(); // Checks if the memory is currently allocated. 55*7c3d14c8STreehugger Robot uptr Beg(); // First byte of user memory. 56*7c3d14c8STreehugger Robot uptr End(); // Last byte of user memory. 57*7c3d14c8STreehugger Robot uptr UsedSize(); // Size requested by the user. 58*7c3d14c8STreehugger Robot uptr AllocTid(); 59*7c3d14c8STreehugger Robot uptr FreeTid(); Eq(const AsanChunkView & c)60*7c3d14c8STreehugger Robot bool Eq(const AsanChunkView &c) const { return chunk_ == c.chunk_; } 61*7c3d14c8STreehugger Robot u32 GetAllocStackId(); 62*7c3d14c8STreehugger Robot u32 GetFreeStackId(); 63*7c3d14c8STreehugger Robot StackTrace GetAllocStack(); 64*7c3d14c8STreehugger Robot StackTrace GetFreeStack(); AddrIsInside(uptr addr,uptr access_size,sptr * offset)65*7c3d14c8STreehugger Robot bool AddrIsInside(uptr addr, uptr access_size, sptr *offset) { 66*7c3d14c8STreehugger Robot if (addr >= Beg() && (addr + access_size) <= End()) { 67*7c3d14c8STreehugger Robot *offset = addr - Beg(); 68*7c3d14c8STreehugger Robot return true; 69*7c3d14c8STreehugger Robot } 70*7c3d14c8STreehugger Robot return false; 71*7c3d14c8STreehugger Robot } AddrIsAtLeft(uptr addr,uptr access_size,sptr * offset)72*7c3d14c8STreehugger Robot bool AddrIsAtLeft(uptr addr, uptr access_size, sptr *offset) { 73*7c3d14c8STreehugger Robot (void)access_size; 74*7c3d14c8STreehugger Robot if (addr < Beg()) { 75*7c3d14c8STreehugger Robot *offset = Beg() - addr; 76*7c3d14c8STreehugger Robot return true; 77*7c3d14c8STreehugger Robot } 78*7c3d14c8STreehugger Robot return false; 79*7c3d14c8STreehugger Robot } AddrIsAtRight(uptr addr,uptr access_size,sptr * offset)80*7c3d14c8STreehugger Robot bool AddrIsAtRight(uptr addr, uptr access_size, sptr *offset) { 81*7c3d14c8STreehugger Robot if (addr + access_size > End()) { 82*7c3d14c8STreehugger Robot *offset = addr - End(); 83*7c3d14c8STreehugger Robot return true; 84*7c3d14c8STreehugger Robot } 85*7c3d14c8STreehugger Robot return false; 86*7c3d14c8STreehugger Robot } 87*7c3d14c8STreehugger Robot 88*7c3d14c8STreehugger Robot private: 89*7c3d14c8STreehugger Robot AsanChunk *const chunk_; 90*7c3d14c8STreehugger Robot }; 91*7c3d14c8STreehugger Robot 92*7c3d14c8STreehugger Robot AsanChunkView FindHeapChunkByAddress(uptr address); 93*7c3d14c8STreehugger Robot 94*7c3d14c8STreehugger Robot // List of AsanChunks with total size. 95*7c3d14c8STreehugger Robot class AsanChunkFifoList: public IntrusiveList<AsanChunk> { 96*7c3d14c8STreehugger Robot public: AsanChunkFifoList(LinkerInitialized)97*7c3d14c8STreehugger Robot explicit AsanChunkFifoList(LinkerInitialized) { } AsanChunkFifoList()98*7c3d14c8STreehugger Robot AsanChunkFifoList() { clear(); } 99*7c3d14c8STreehugger Robot void Push(AsanChunk *n); 100*7c3d14c8STreehugger Robot void PushList(AsanChunkFifoList *q); 101*7c3d14c8STreehugger Robot AsanChunk *Pop(); size()102*7c3d14c8STreehugger Robot uptr size() { return size_; } clear()103*7c3d14c8STreehugger Robot void clear() { 104*7c3d14c8STreehugger Robot IntrusiveList<AsanChunk>::clear(); 105*7c3d14c8STreehugger Robot size_ = 0; 106*7c3d14c8STreehugger Robot } 107*7c3d14c8STreehugger Robot private: 108*7c3d14c8STreehugger Robot uptr size_; 109*7c3d14c8STreehugger Robot }; 110*7c3d14c8STreehugger Robot 111*7c3d14c8STreehugger Robot struct AsanMapUnmapCallback { 112*7c3d14c8STreehugger Robot void OnMap(uptr p, uptr size) const; 113*7c3d14c8STreehugger Robot void OnUnmap(uptr p, uptr size) const; 114*7c3d14c8STreehugger Robot }; 115*7c3d14c8STreehugger Robot 116*7c3d14c8STreehugger Robot #if SANITIZER_CAN_USE_ALLOCATOR64 117*7c3d14c8STreehugger Robot # if defined(__powerpc64__) 118*7c3d14c8STreehugger Robot const uptr kAllocatorSpace = 0xa0000000000ULL; 119*7c3d14c8STreehugger Robot const uptr kAllocatorSize = 0x20000000000ULL; // 2T. 120*7c3d14c8STreehugger Robot # elif defined(__aarch64__) 121*7c3d14c8STreehugger Robot // AArch64/SANITIZIER_CAN_USER_ALLOCATOR64 is only for 42-bit VMA 122*7c3d14c8STreehugger Robot // so no need to different values for different VMA. 123*7c3d14c8STreehugger Robot const uptr kAllocatorSpace = 0x10000000000ULL; 124*7c3d14c8STreehugger Robot const uptr kAllocatorSize = 0x10000000000ULL; // 3T. 125*7c3d14c8STreehugger Robot # else 126*7c3d14c8STreehugger Robot const uptr kAllocatorSpace = 0x600000000000ULL; 127*7c3d14c8STreehugger Robot const uptr kAllocatorSize = 0x40000000000ULL; // 4T. 128*7c3d14c8STreehugger Robot # endif 129*7c3d14c8STreehugger Robot typedef DefaultSizeClassMap SizeClassMap; 130*7c3d14c8STreehugger Robot typedef SizeClassAllocator64<kAllocatorSpace, kAllocatorSize, 0 /*metadata*/, 131*7c3d14c8STreehugger Robot SizeClassMap, AsanMapUnmapCallback> PrimaryAllocator; 132*7c3d14c8STreehugger Robot #else // Fallback to SizeClassAllocator32. 133*7c3d14c8STreehugger Robot static const uptr kRegionSizeLog = 20; 134*7c3d14c8STreehugger Robot static const uptr kNumRegions = SANITIZER_MMAP_RANGE_SIZE >> kRegionSizeLog; 135*7c3d14c8STreehugger Robot # if SANITIZER_WORDSIZE == 32 136*7c3d14c8STreehugger Robot typedef FlatByteMap<kNumRegions> ByteMap; 137*7c3d14c8STreehugger Robot # elif SANITIZER_WORDSIZE == 64 138*7c3d14c8STreehugger Robot typedef TwoLevelByteMap<(kNumRegions >> 12), 1 << 12> ByteMap; 139*7c3d14c8STreehugger Robot # endif 140*7c3d14c8STreehugger Robot typedef CompactSizeClassMap SizeClassMap; 141*7c3d14c8STreehugger Robot typedef SizeClassAllocator32<0, SANITIZER_MMAP_RANGE_SIZE, 16, 142*7c3d14c8STreehugger Robot SizeClassMap, kRegionSizeLog, 143*7c3d14c8STreehugger Robot ByteMap, 144*7c3d14c8STreehugger Robot AsanMapUnmapCallback> PrimaryAllocator; 145*7c3d14c8STreehugger Robot #endif // SANITIZER_CAN_USE_ALLOCATOR64 146*7c3d14c8STreehugger Robot 147*7c3d14c8STreehugger Robot static const uptr kNumberOfSizeClasses = SizeClassMap::kNumClasses; 148*7c3d14c8STreehugger Robot typedef SizeClassAllocatorLocalCache<PrimaryAllocator> AllocatorCache; 149*7c3d14c8STreehugger Robot typedef LargeMmapAllocator<AsanMapUnmapCallback> SecondaryAllocator; 150*7c3d14c8STreehugger Robot typedef CombinedAllocator<PrimaryAllocator, AllocatorCache, 151*7c3d14c8STreehugger Robot SecondaryAllocator> AsanAllocator; 152*7c3d14c8STreehugger Robot 153*7c3d14c8STreehugger Robot 154*7c3d14c8STreehugger Robot struct AsanThreadLocalMallocStorage { 155*7c3d14c8STreehugger Robot uptr quarantine_cache[16]; 156*7c3d14c8STreehugger Robot AllocatorCache allocator_cache; 157*7c3d14c8STreehugger Robot void CommitBack(); 158*7c3d14c8STreehugger Robot private: 159*7c3d14c8STreehugger Robot // These objects are allocated via mmap() and are zero-initialized. AsanThreadLocalMallocStorageAsanThreadLocalMallocStorage160*7c3d14c8STreehugger Robot AsanThreadLocalMallocStorage() {} 161*7c3d14c8STreehugger Robot }; 162*7c3d14c8STreehugger Robot 163*7c3d14c8STreehugger Robot void *asan_memalign(uptr alignment, uptr size, BufferedStackTrace *stack, 164*7c3d14c8STreehugger Robot AllocType alloc_type); 165*7c3d14c8STreehugger Robot void asan_free(void *ptr, BufferedStackTrace *stack, AllocType alloc_type); 166*7c3d14c8STreehugger Robot void asan_sized_free(void *ptr, uptr size, BufferedStackTrace *stack, 167*7c3d14c8STreehugger Robot AllocType alloc_type); 168*7c3d14c8STreehugger Robot 169*7c3d14c8STreehugger Robot void *asan_malloc(uptr size, BufferedStackTrace *stack); 170*7c3d14c8STreehugger Robot void *asan_calloc(uptr nmemb, uptr size, BufferedStackTrace *stack); 171*7c3d14c8STreehugger Robot void *asan_realloc(void *p, uptr size, BufferedStackTrace *stack); 172*7c3d14c8STreehugger Robot void *asan_valloc(uptr size, BufferedStackTrace *stack); 173*7c3d14c8STreehugger Robot void *asan_pvalloc(uptr size, BufferedStackTrace *stack); 174*7c3d14c8STreehugger Robot 175*7c3d14c8STreehugger Robot int asan_posix_memalign(void **memptr, uptr alignment, uptr size, 176*7c3d14c8STreehugger Robot BufferedStackTrace *stack); 177*7c3d14c8STreehugger Robot uptr asan_malloc_usable_size(const void *ptr, uptr pc, uptr bp); 178*7c3d14c8STreehugger Robot 179*7c3d14c8STreehugger Robot uptr asan_mz_size(const void *ptr); 180*7c3d14c8STreehugger Robot void asan_mz_force_lock(); 181*7c3d14c8STreehugger Robot void asan_mz_force_unlock(); 182*7c3d14c8STreehugger Robot 183*7c3d14c8STreehugger Robot void PrintInternalAllocatorStats(); 184*7c3d14c8STreehugger Robot void AsanSoftRssLimitExceededCallback(bool exceeded); 185*7c3d14c8STreehugger Robot 186*7c3d14c8STreehugger Robot } // namespace __asan 187*7c3d14c8STreehugger Robot #endif // ASAN_ALLOCATOR_H 188