110d565efSmrg //===-- asan_allocator.h ----------------------------------------*- C++ -*-===// 210d565efSmrg // 310d565efSmrg // This file is distributed under the University of Illinois Open Source 410d565efSmrg // License. See LICENSE.TXT for details. 510d565efSmrg // 610d565efSmrg //===----------------------------------------------------------------------===// 710d565efSmrg // 810d565efSmrg // This file is a part of AddressSanitizer, an address sanity checker. 910d565efSmrg // 1010d565efSmrg // ASan-private header for asan_allocator.cc. 1110d565efSmrg //===----------------------------------------------------------------------===// 1210d565efSmrg 1310d565efSmrg #ifndef ASAN_ALLOCATOR_H 1410d565efSmrg #define ASAN_ALLOCATOR_H 1510d565efSmrg 1610d565efSmrg #include "asan_flags.h" 1710d565efSmrg #include "asan_internal.h" 1810d565efSmrg #include "asan_interceptors.h" 1910d565efSmrg #include "sanitizer_common/sanitizer_allocator.h" 2010d565efSmrg #include "sanitizer_common/sanitizer_list.h" 2110d565efSmrg 2210d565efSmrg namespace __asan { 2310d565efSmrg 2410d565efSmrg enum AllocType { 2510d565efSmrg FROM_MALLOC = 1, // Memory block came from malloc, calloc, realloc, etc. 2610d565efSmrg FROM_NEW = 2, // Memory block came from operator new. 2710d565efSmrg FROM_NEW_BR = 3 // Memory block came from operator new [ ] 2810d565efSmrg }; 2910d565efSmrg 3010d565efSmrg struct AsanChunk; 3110d565efSmrg 3210d565efSmrg struct AllocatorOptions { 3310d565efSmrg u32 quarantine_size_mb; 34c7a68eb7Smrg u32 thread_local_quarantine_size_kb; 3510d565efSmrg u16 min_redzone; 3610d565efSmrg u16 max_redzone; 3710d565efSmrg u8 may_return_null; 3810d565efSmrg u8 alloc_dealloc_mismatch; 39c7a68eb7Smrg s32 release_to_os_interval_ms; 4010d565efSmrg 4110d565efSmrg void SetFrom(const Flags *f, const CommonFlags *cf); 4210d565efSmrg void CopyTo(Flags *f, CommonFlags *cf); 4310d565efSmrg }; 4410d565efSmrg 4510d565efSmrg void InitializeAllocator(const AllocatorOptions &options); 4610d565efSmrg void ReInitializeAllocator(const AllocatorOptions &options); 4710d565efSmrg void GetAllocatorOptions(AllocatorOptions *options); 4810d565efSmrg 4910d565efSmrg class AsanChunkView { 5010d565efSmrg public: AsanChunkView(AsanChunk * chunk)5110d565efSmrg explicit AsanChunkView(AsanChunk *chunk) : chunk_(chunk) {} 52c7a68eb7Smrg bool IsValid() const; // Checks if AsanChunkView points to a valid 53c7a68eb7Smrg // allocated or quarantined chunk. 54c7a68eb7Smrg bool IsAllocated() const; // Checks if the memory is currently allocated. 55c7a68eb7Smrg bool IsQuarantined() const; // Checks if the memory is currently quarantined. 56c7a68eb7Smrg uptr Beg() const; // First byte of user memory. 57c7a68eb7Smrg uptr End() const; // Last byte of user memory. 58c7a68eb7Smrg uptr UsedSize() const; // Size requested by the user. 59*0fc04c29Smrg u32 UserRequestedAlignment() const; // Originally requested alignment. 60c7a68eb7Smrg uptr AllocTid() const; 61c7a68eb7Smrg uptr FreeTid() const; Eq(const AsanChunkView & c)6210d565efSmrg bool Eq(const AsanChunkView &c) const { return chunk_ == c.chunk_; } 63c7a68eb7Smrg u32 GetAllocStackId() const; 64c7a68eb7Smrg u32 GetFreeStackId() const; 65c7a68eb7Smrg StackTrace GetAllocStack() const; 66c7a68eb7Smrg StackTrace GetFreeStack() const; 67c7a68eb7Smrg AllocType GetAllocType() const; AddrIsInside(uptr addr,uptr access_size,sptr * offset)68c7a68eb7Smrg bool AddrIsInside(uptr addr, uptr access_size, sptr *offset) const { 6910d565efSmrg if (addr >= Beg() && (addr + access_size) <= End()) { 7010d565efSmrg *offset = addr - Beg(); 7110d565efSmrg return true; 7210d565efSmrg } 7310d565efSmrg return false; 7410d565efSmrg } AddrIsAtLeft(uptr addr,uptr access_size,sptr * offset)75c7a68eb7Smrg bool AddrIsAtLeft(uptr addr, uptr access_size, sptr *offset) const { 7610d565efSmrg (void)access_size; 7710d565efSmrg if (addr < Beg()) { 7810d565efSmrg *offset = Beg() - addr; 7910d565efSmrg return true; 8010d565efSmrg } 8110d565efSmrg return false; 8210d565efSmrg } AddrIsAtRight(uptr addr,uptr access_size,sptr * offset)83c7a68eb7Smrg bool AddrIsAtRight(uptr addr, uptr access_size, sptr *offset) const { 8410d565efSmrg if (addr + access_size > End()) { 8510d565efSmrg *offset = addr - End(); 8610d565efSmrg return true; 8710d565efSmrg } 8810d565efSmrg return false; 8910d565efSmrg } 9010d565efSmrg 9110d565efSmrg private: 9210d565efSmrg AsanChunk *const chunk_; 9310d565efSmrg }; 9410d565efSmrg 9510d565efSmrg AsanChunkView FindHeapChunkByAddress(uptr address); 9610d565efSmrg AsanChunkView FindHeapChunkByAllocBeg(uptr address); 9710d565efSmrg 9810d565efSmrg // List of AsanChunks with total size. 9910d565efSmrg class AsanChunkFifoList: public IntrusiveList<AsanChunk> { 10010d565efSmrg public: AsanChunkFifoList(LinkerInitialized)10110d565efSmrg explicit AsanChunkFifoList(LinkerInitialized) { } AsanChunkFifoList()10210d565efSmrg AsanChunkFifoList() { clear(); } 10310d565efSmrg void Push(AsanChunk *n); 10410d565efSmrg void PushList(AsanChunkFifoList *q); 10510d565efSmrg AsanChunk *Pop(); size()10610d565efSmrg uptr size() { return size_; } clear()10710d565efSmrg void clear() { 10810d565efSmrg IntrusiveList<AsanChunk>::clear(); 10910d565efSmrg size_ = 0; 11010d565efSmrg } 11110d565efSmrg private: 11210d565efSmrg uptr size_; 11310d565efSmrg }; 11410d565efSmrg 11510d565efSmrg struct AsanMapUnmapCallback { 11610d565efSmrg void OnMap(uptr p, uptr size) const; 11710d565efSmrg void OnUnmap(uptr p, uptr size) const; 11810d565efSmrg }; 11910d565efSmrg 12010d565efSmrg #if SANITIZER_CAN_USE_ALLOCATOR64 121c7a68eb7Smrg # if SANITIZER_FUCHSIA 122c7a68eb7Smrg const uptr kAllocatorSpace = ~(uptr)0; 123c7a68eb7Smrg const uptr kAllocatorSize = 0x40000000000ULL; // 4T. 124c7a68eb7Smrg typedef DefaultSizeClassMap SizeClassMap; 125c7a68eb7Smrg # elif defined(__powerpc64__) 12610d565efSmrg const uptr kAllocatorSpace = ~(uptr)0; 12710d565efSmrg const uptr kAllocatorSize = 0x20000000000ULL; // 2T. 12810d565efSmrg typedef DefaultSizeClassMap SizeClassMap; 12910d565efSmrg # elif defined(__aarch64__) && SANITIZER_ANDROID 130*0fc04c29Smrg // Android needs to support 39, 42 and 48 bit VMA. 131*0fc04c29Smrg const uptr kAllocatorSpace = ~(uptr)0; 13210d565efSmrg const uptr kAllocatorSize = 0x2000000000ULL; // 128G. 13310d565efSmrg typedef VeryCompactSizeClassMap SizeClassMap; 13410d565efSmrg # elif defined(__aarch64__) 135*0fc04c29Smrg // AArch64/SANITIZER_CAN_USE_ALLOCATOR64 is only for 42-bit VMA 13610d565efSmrg // so no need to different values for different VMA. 13710d565efSmrg const uptr kAllocatorSpace = 0x10000000000ULL; 13810d565efSmrg const uptr kAllocatorSize = 0x10000000000ULL; // 3T. 13910d565efSmrg typedef DefaultSizeClassMap SizeClassMap; 140*0fc04c29Smrg # elif defined(__sparc__) 141*0fc04c29Smrg const uptr kAllocatorSpace = ~(uptr)0; 142*0fc04c29Smrg const uptr kAllocatorSize = 0x20000000000ULL; // 2T. 143*0fc04c29Smrg typedef DefaultSizeClassMap SizeClassMap; 14410d565efSmrg # elif SANITIZER_WINDOWS 14510d565efSmrg const uptr kAllocatorSpace = ~(uptr)0; 14610d565efSmrg const uptr kAllocatorSize = 0x8000000000ULL; // 500G 14710d565efSmrg typedef DefaultSizeClassMap SizeClassMap; 14810d565efSmrg # else 149c7a68eb7Smrg #if _LP64 15010d565efSmrg const uptr kAllocatorSpace = 0x600000000000ULL; 15110d565efSmrg const uptr kAllocatorSize = 0x40000000000ULL; // 4T. 152c7a68eb7Smrg #else 153c7a68eb7Smrg const uptr kAllocatorSpace = 0x60000000UL; 154c7a68eb7Smrg const uptr kAllocatorSize = 0x40000000ULL; // 2G. 155c7a68eb7Smrg #endif 15610d565efSmrg typedef DefaultSizeClassMap SizeClassMap; 15710d565efSmrg # endif 15810d565efSmrg struct AP64 { // Allocator64 parameters. Deliberately using a short name. 15910d565efSmrg static const uptr kSpaceBeg = kAllocatorSpace; 16010d565efSmrg static const uptr kSpaceSize = kAllocatorSize; 16110d565efSmrg static const uptr kMetadataSize = 0; 16210d565efSmrg typedef __asan::SizeClassMap SizeClassMap; 16310d565efSmrg typedef AsanMapUnmapCallback MapUnmapCallback; 16410d565efSmrg static const uptr kFlags = 0; 16510d565efSmrg }; 16610d565efSmrg 16710d565efSmrg typedef SizeClassAllocator64<AP64> PrimaryAllocator; 16810d565efSmrg #else // Fallback to SizeClassAllocator32. 16910d565efSmrg static const uptr kRegionSizeLog = 20; 17010d565efSmrg static const uptr kNumRegions = SANITIZER_MMAP_RANGE_SIZE >> kRegionSizeLog; 17110d565efSmrg # if SANITIZER_WORDSIZE == 32 17210d565efSmrg typedef FlatByteMap<kNumRegions> ByteMap; 17310d565efSmrg # elif SANITIZER_WORDSIZE == 64 17410d565efSmrg typedef TwoLevelByteMap<(kNumRegions >> 12), 1 << 12> ByteMap; 17510d565efSmrg # endif 17610d565efSmrg typedef CompactSizeClassMap SizeClassMap; 177c7a68eb7Smrg struct AP32 { 178c7a68eb7Smrg static const uptr kSpaceBeg = 0; 179c7a68eb7Smrg static const u64 kSpaceSize = SANITIZER_MMAP_RANGE_SIZE; 180c7a68eb7Smrg static const uptr kMetadataSize = 16; 181c7a68eb7Smrg typedef __asan::SizeClassMap SizeClassMap; 182c7a68eb7Smrg static const uptr kRegionSizeLog = __asan::kRegionSizeLog; 183c7a68eb7Smrg typedef __asan::ByteMap ByteMap; 184c7a68eb7Smrg typedef AsanMapUnmapCallback MapUnmapCallback; 185c7a68eb7Smrg static const uptr kFlags = 0; 186c7a68eb7Smrg }; 187c7a68eb7Smrg typedef SizeClassAllocator32<AP32> PrimaryAllocator; 18810d565efSmrg #endif // SANITIZER_CAN_USE_ALLOCATOR64 18910d565efSmrg 19010d565efSmrg static const uptr kNumberOfSizeClasses = SizeClassMap::kNumClasses; 19110d565efSmrg typedef SizeClassAllocatorLocalCache<PrimaryAllocator> AllocatorCache; 19210d565efSmrg typedef LargeMmapAllocator<AsanMapUnmapCallback> SecondaryAllocator; 19310d565efSmrg typedef CombinedAllocator<PrimaryAllocator, AllocatorCache, 19410d565efSmrg SecondaryAllocator> AsanAllocator; 19510d565efSmrg 19610d565efSmrg 19710d565efSmrg struct AsanThreadLocalMallocStorage { 19810d565efSmrg uptr quarantine_cache[16]; 19910d565efSmrg AllocatorCache allocator_cache; 20010d565efSmrg void CommitBack(); 20110d565efSmrg private: 20210d565efSmrg // These objects are allocated via mmap() and are zero-initialized. AsanThreadLocalMallocStorageAsanThreadLocalMallocStorage20310d565efSmrg AsanThreadLocalMallocStorage() {} 20410d565efSmrg }; 20510d565efSmrg 20610d565efSmrg void *asan_memalign(uptr alignment, uptr size, BufferedStackTrace *stack, 20710d565efSmrg AllocType alloc_type); 20810d565efSmrg void asan_free(void *ptr, BufferedStackTrace *stack, AllocType alloc_type); 209*0fc04c29Smrg void asan_delete(void *ptr, uptr size, uptr alignment, 210*0fc04c29Smrg BufferedStackTrace *stack, AllocType alloc_type); 21110d565efSmrg 21210d565efSmrg void *asan_malloc(uptr size, BufferedStackTrace *stack); 21310d565efSmrg void *asan_calloc(uptr nmemb, uptr size, BufferedStackTrace *stack); 21410d565efSmrg void *asan_realloc(void *p, uptr size, BufferedStackTrace *stack); 21510d565efSmrg void *asan_valloc(uptr size, BufferedStackTrace *stack); 21610d565efSmrg void *asan_pvalloc(uptr size, BufferedStackTrace *stack); 21710d565efSmrg 218*0fc04c29Smrg void *asan_aligned_alloc(uptr alignment, uptr size, BufferedStackTrace *stack); 21910d565efSmrg int asan_posix_memalign(void **memptr, uptr alignment, uptr size, 22010d565efSmrg BufferedStackTrace *stack); 22110d565efSmrg uptr asan_malloc_usable_size(const void *ptr, uptr pc, uptr bp); 22210d565efSmrg 22310d565efSmrg uptr asan_mz_size(const void *ptr); 22410d565efSmrg void asan_mz_force_lock(); 22510d565efSmrg void asan_mz_force_unlock(); 22610d565efSmrg 22710d565efSmrg void PrintInternalAllocatorStats(); 22810d565efSmrg void AsanSoftRssLimitExceededCallback(bool exceeded); 22910d565efSmrg 23010d565efSmrg } // namespace __asan 23110d565efSmrg #endif // ASAN_ALLOCATOR_H 232