asan_allocator.h revision 344779
1229109Sed//===-- asan_allocator.h ----------------------------------------*- C++ -*-===// 2229109Sed// 3229109Sed// The LLVM Compiler Infrastructure 4229109Sed// 5229109Sed// This file is distributed under the University of Illinois Open Source 6229109Sed// License. See LICENSE.TXT for details. 7229109Sed// 8229109Sed//===----------------------------------------------------------------------===// 9229109Sed// 10229109Sed// This file is a part of AddressSanitizer, an address sanity checker. 11229109Sed// 12280031Sdim// ASan-private header for asan_allocator.cc. 13229109Sed//===----------------------------------------------------------------------===// 14229109Sed 15229109Sed#ifndef ASAN_ALLOCATOR_H 16229109Sed#define ASAN_ALLOCATOR_H 17229109Sed 18280031Sdim#include "asan_flags.h" 19229109Sed#include "asan_internal.h" 20229109Sed#include "asan_interceptors.h" 21276789Sdim#include "sanitizer_common/sanitizer_allocator.h" 22245614Sandrew#include "sanitizer_common/sanitizer_list.h" 23229109Sed 24229109Sednamespace __asan { 25229109Sed 26245614Sandrewenum AllocType { 27245614Sandrew FROM_MALLOC = 1, // Memory block came from malloc, calloc, realloc, etc. 28245614Sandrew FROM_NEW = 2, // Memory block came from operator new. 29245614Sandrew FROM_NEW_BR = 3 // Memory block came from operator new [ ] 30245614Sandrew}; 31245614Sandrew 32229109Sedstruct AsanChunk; 33229109Sed 34280031Sdimstruct AllocatorOptions { 35280031Sdim u32 quarantine_size_mb; 36314564Sdim u32 thread_local_quarantine_size_kb; 37280031Sdim u16 min_redzone; 38280031Sdim u16 max_redzone; 39280031Sdim u8 may_return_null; 40280031Sdim u8 alloc_dealloc_mismatch; 41314564Sdim s32 release_to_os_interval_ms; 42251034Sed 43280031Sdim void SetFrom(const Flags *f, const CommonFlags *cf); 44280031Sdim void CopyTo(Flags *f, CommonFlags *cf); 45280031Sdim}; 46280031Sdim 47280031Sdimvoid InitializeAllocator(const AllocatorOptions &options); 48280031Sdimvoid ReInitializeAllocator(const AllocatorOptions &options); 49280031Sdimvoid GetAllocatorOptions(AllocatorOptions *options); 50280031Sdim 51245614Sandrewclass AsanChunkView { 52229109Sed public: 53245614Sandrew explicit AsanChunkView(AsanChunk *chunk) : chunk_(chunk) {} 54314564Sdim bool IsValid() const; // Checks if AsanChunkView points to a valid 55314564Sdim // allocated or quarantined chunk. 56314564Sdim bool IsAllocated() const; // Checks if the memory is currently allocated. 57314564Sdim bool IsQuarantined() const; // Checks if the memory is currently quarantined. 58314564Sdim uptr Beg() const; // First byte of user memory. 59314564Sdim uptr End() const; // Last byte of user memory. 60314564Sdim uptr UsedSize() const; // Size requested by the user. 61327952Sdim u32 UserRequestedAlignment() const; // Originally requested alignment. 62314564Sdim uptr AllocTid() const; 63314564Sdim uptr FreeTid() const; 64276789Sdim bool Eq(const AsanChunkView &c) const { return chunk_ == c.chunk_; } 65314564Sdim u32 GetAllocStackId() const; 66314564Sdim u32 GetFreeStackId() const; 67314564Sdim StackTrace GetAllocStack() const; 68314564Sdim StackTrace GetFreeStack() const; 69314564Sdim AllocType GetAllocType() const; 70314564Sdim bool AddrIsInside(uptr addr, uptr access_size, sptr *offset) const { 71245614Sandrew if (addr >= Beg() && (addr + access_size) <= End()) { 72245614Sandrew *offset = addr - Beg(); 73245614Sandrew return true; 74245614Sandrew } 75245614Sandrew return false; 76245614Sandrew } 77314564Sdim bool AddrIsAtLeft(uptr addr, uptr access_size, sptr *offset) const { 78245614Sandrew (void)access_size; 79245614Sandrew if (addr < Beg()) { 80245614Sandrew *offset = Beg() - addr; 81245614Sandrew return true; 82245614Sandrew } 83245614Sandrew return false; 84245614Sandrew } 85314564Sdim bool AddrIsAtRight(uptr addr, uptr access_size, sptr *offset) const { 86251034Sed if (addr + access_size > End()) { 87251034Sed *offset = addr - End(); 88245614Sandrew return true; 89245614Sandrew } 90245614Sandrew return false; 91245614Sandrew } 92245614Sandrew 93245614Sandrew private: 94245614Sandrew AsanChunk *const chunk_; 95245614Sandrew}; 96245614Sandrew 97245614SandrewAsanChunkView FindHeapChunkByAddress(uptr address); 98314564SdimAsanChunkView FindHeapChunkByAllocBeg(uptr address); 99245614Sandrew 100245614Sandrew// List of AsanChunks with total size. 101245614Sandrewclass AsanChunkFifoList: public IntrusiveList<AsanChunk> { 102245614Sandrew public: 103229109Sed explicit AsanChunkFifoList(LinkerInitialized) { } 104229109Sed AsanChunkFifoList() { clear(); } 105229109Sed void Push(AsanChunk *n); 106229109Sed void PushList(AsanChunkFifoList *q); 107229109Sed AsanChunk *Pop(); 108238901Sandrew uptr size() { return size_; } 109229109Sed void clear() { 110245614Sandrew IntrusiveList<AsanChunk>::clear(); 111229109Sed size_ = 0; 112229109Sed } 113229109Sed private: 114238901Sandrew uptr size_; 115229109Sed}; 116229109Sed 117276789Sdimstruct AsanMapUnmapCallback { 118276789Sdim void OnMap(uptr p, uptr size) const; 119276789Sdim void OnUnmap(uptr p, uptr size) const; 120276789Sdim}; 121276789Sdim 122276789Sdim#if SANITIZER_CAN_USE_ALLOCATOR64 123327952Sdim# if SANITIZER_FUCHSIA 124327952Sdimconst uptr kAllocatorSpace = ~(uptr)0; 125327952Sdimconst uptr kAllocatorSize = 0x40000000000ULL; // 4T. 126327952Sdimtypedef DefaultSizeClassMap SizeClassMap; 127327952Sdim# elif defined(__powerpc64__) 128341825Sdimconst uptr kAllocatorSpace = ~(uptr)0; 129276789Sdimconst uptr kAllocatorSize = 0x20000000000ULL; // 2T. 130314564Sdimtypedef DefaultSizeClassMap SizeClassMap; 131314564Sdim# elif defined(__aarch64__) && SANITIZER_ANDROID 132341825Sdim// Android needs to support 39, 42 and 48 bit VMA. 133341825Sdimconst uptr kAllocatorSpace = ~(uptr)0; 134314564Sdimconst uptr kAllocatorSize = 0x2000000000ULL; // 128G. 135314564Sdimtypedef VeryCompactSizeClassMap SizeClassMap; 136296417Sdim# elif defined(__aarch64__) 137314564Sdim// AArch64/SANITIZER_CAN_USER_ALLOCATOR64 is only for 42-bit VMA 138296417Sdim// so no need to different values for different VMA. 139296417Sdimconst uptr kAllocatorSpace = 0x10000000000ULL; 140296417Sdimconst uptr kAllocatorSize = 0x10000000000ULL; // 3T. 141314564Sdimtypedef DefaultSizeClassMap SizeClassMap; 142314564Sdim# elif SANITIZER_WINDOWS 143314564Sdimconst uptr kAllocatorSpace = ~(uptr)0; 144314564Sdimconst uptr kAllocatorSize = 0x8000000000ULL; // 500G 145314564Sdimtypedef DefaultSizeClassMap SizeClassMap; 146276789Sdim# else 147276789Sdimconst uptr kAllocatorSpace = 0x600000000000ULL; 148276789Sdimconst uptr kAllocatorSize = 0x40000000000ULL; // 4T. 149314564Sdimtypedef DefaultSizeClassMap SizeClassMap; 150276789Sdim# endif 151344779Sdimtemplate <typename AddressSpaceViewTy> 152314564Sdimstruct AP64 { // Allocator64 parameters. Deliberately using a short name. 153314564Sdim static const uptr kSpaceBeg = kAllocatorSpace; 154314564Sdim static const uptr kSpaceSize = kAllocatorSize; 155314564Sdim static const uptr kMetadataSize = 0; 156314564Sdim typedef __asan::SizeClassMap SizeClassMap; 157314564Sdim typedef AsanMapUnmapCallback MapUnmapCallback; 158314564Sdim static const uptr kFlags = 0; 159344779Sdim using AddressSpaceView = AddressSpaceViewTy; 160314564Sdim}; 161314564Sdim 162344779Sdimtemplate <typename AddressSpaceView> 163344779Sdimusing PrimaryAllocatorASVT = SizeClassAllocator64<AP64<AddressSpaceView>>; 164344779Sdimusing PrimaryAllocator = PrimaryAllocatorASVT<LocalAddressSpaceView>; 165276789Sdim#else // Fallback to SizeClassAllocator32. 166276789Sdimstatic const uptr kRegionSizeLog = 20; 167276789Sdimstatic const uptr kNumRegions = SANITIZER_MMAP_RANGE_SIZE >> kRegionSizeLog; 168276789Sdim# if SANITIZER_WORDSIZE == 32 169344779Sdimtemplate <typename AddressSpaceView> 170344779Sdimusing ByteMapASVT = FlatByteMap<kNumRegions, AddressSpaceView>; 171276789Sdim# elif SANITIZER_WORDSIZE == 64 172344779Sdimtemplate <typename AddressSpaceView> 173344779Sdimusing ByteMapASVT = 174344779Sdim TwoLevelByteMap<(kNumRegions >> 12), 1 << 12, AddressSpaceView>; 175276789Sdim# endif 176276789Sdimtypedef CompactSizeClassMap SizeClassMap; 177344779Sdimtemplate <typename AddressSpaceViewTy> 178321369Sdimstruct AP32 { 179321369Sdim static const uptr kSpaceBeg = 0; 180321369Sdim static const u64 kSpaceSize = SANITIZER_MMAP_RANGE_SIZE; 181321369Sdim static const uptr kMetadataSize = 16; 182321369Sdim typedef __asan::SizeClassMap SizeClassMap; 183321369Sdim static const uptr kRegionSizeLog = __asan::kRegionSizeLog; 184344779Sdim using AddressSpaceView = AddressSpaceViewTy; 185344779Sdim using ByteMap = __asan::ByteMapASVT<AddressSpaceView>; 186321369Sdim typedef AsanMapUnmapCallback MapUnmapCallback; 187321369Sdim static const uptr kFlags = 0; 188321369Sdim}; 189344779Sdimtemplate <typename AddressSpaceView> 190344779Sdimusing PrimaryAllocatorASVT = SizeClassAllocator32<AP32<AddressSpaceView> >; 191344779Sdimusing PrimaryAllocator = PrimaryAllocatorASVT<LocalAddressSpaceView>; 192276789Sdim#endif // SANITIZER_CAN_USE_ALLOCATOR64 193276789Sdim 194288943Sdimstatic const uptr kNumberOfSizeClasses = SizeClassMap::kNumClasses; 195344779Sdimtemplate <typename AddressSpaceView> 196344779Sdimusing AllocatorCacheASVT = 197344779Sdim SizeClassAllocatorLocalCache<PrimaryAllocatorASVT<AddressSpaceView>>; 198344779Sdimusing AllocatorCache = AllocatorCacheASVT<LocalAddressSpaceView>; 199276789Sdim 200344779Sdimtemplate <typename AddressSpaceView> 201344779Sdimusing SecondaryAllocatorASVT = 202344779Sdim LargeMmapAllocator<AsanMapUnmapCallback, DefaultLargeMmapAllocatorPtrArray, 203344779Sdim AddressSpaceView>; 204344779Sdimtemplate <typename AddressSpaceView> 205344779Sdimusing AsanAllocatorASVT = 206344779Sdim CombinedAllocator<PrimaryAllocatorASVT<AddressSpaceView>, 207344779Sdim AllocatorCacheASVT<AddressSpaceView>, 208344779Sdim SecondaryAllocatorASVT<AddressSpaceView>>; 209344779Sdimusing AsanAllocator = AsanAllocatorASVT<LocalAddressSpaceView>; 210276789Sdim 211229109Sedstruct AsanThreadLocalMallocStorage { 212245614Sandrew uptr quarantine_cache[16]; 213280031Sdim AllocatorCache allocator_cache; 214229109Sed void CommitBack(); 215276789Sdim private: 216276789Sdim // These objects are allocated via mmap() and are zero-initialized. 217276789Sdim AsanThreadLocalMallocStorage() {} 218229109Sed}; 219229109Sed 220276789Sdimvoid *asan_memalign(uptr alignment, uptr size, BufferedStackTrace *stack, 221245614Sandrew AllocType alloc_type); 222276789Sdimvoid asan_free(void *ptr, BufferedStackTrace *stack, AllocType alloc_type); 223327952Sdimvoid asan_delete(void *ptr, uptr size, uptr alignment, 224327952Sdim BufferedStackTrace *stack, AllocType alloc_type); 225229109Sed 226276789Sdimvoid *asan_malloc(uptr size, BufferedStackTrace *stack); 227276789Sdimvoid *asan_calloc(uptr nmemb, uptr size, BufferedStackTrace *stack); 228276789Sdimvoid *asan_realloc(void *p, uptr size, BufferedStackTrace *stack); 229276789Sdimvoid *asan_valloc(uptr size, BufferedStackTrace *stack); 230276789Sdimvoid *asan_pvalloc(uptr size, BufferedStackTrace *stack); 231229109Sed 232341825Sdimvoid *asan_aligned_alloc(uptr alignment, uptr size, BufferedStackTrace *stack); 233238901Sandrewint asan_posix_memalign(void **memptr, uptr alignment, uptr size, 234276789Sdim BufferedStackTrace *stack); 235309124Sdimuptr asan_malloc_usable_size(const void *ptr, uptr pc, uptr bp); 236229109Sed 237238901Sandrewuptr asan_mz_size(const void *ptr); 238238901Sandrewvoid asan_mz_force_lock(); 239238901Sandrewvoid asan_mz_force_unlock(); 240229109Sed 241245614Sandrewvoid PrintInternalAllocatorStats(); 242280031Sdimvoid AsanSoftRssLimitExceededCallback(bool exceeded); 243245614Sandrew 244229109Sed} // namespace __asan 245229109Sed#endif // ASAN_ALLOCATOR_H 246