asan_allocator.h revision 321369
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. 61314564Sdim uptr AllocTid() const; 62314564Sdim uptr FreeTid() const; 63276789Sdim bool Eq(const AsanChunkView &c) const { return chunk_ == c.chunk_; } 64314564Sdim u32 GetAllocStackId() const; 65314564Sdim u32 GetFreeStackId() const; 66314564Sdim StackTrace GetAllocStack() const; 67314564Sdim StackTrace GetFreeStack() const; 68314564Sdim AllocType GetAllocType() const; 69314564Sdim bool AddrIsInside(uptr addr, uptr access_size, sptr *offset) const { 70245614Sandrew if (addr >= Beg() && (addr + access_size) <= End()) { 71245614Sandrew *offset = addr - Beg(); 72245614Sandrew return true; 73245614Sandrew } 74245614Sandrew return false; 75245614Sandrew } 76314564Sdim bool AddrIsAtLeft(uptr addr, uptr access_size, sptr *offset) const { 77245614Sandrew (void)access_size; 78245614Sandrew if (addr < Beg()) { 79245614Sandrew *offset = Beg() - addr; 80245614Sandrew return true; 81245614Sandrew } 82245614Sandrew return false; 83245614Sandrew } 84314564Sdim bool AddrIsAtRight(uptr addr, uptr access_size, sptr *offset) const { 85251034Sed if (addr + access_size > End()) { 86251034Sed *offset = addr - End(); 87245614Sandrew return true; 88245614Sandrew } 89245614Sandrew return false; 90245614Sandrew } 91245614Sandrew 92245614Sandrew private: 93245614Sandrew AsanChunk *const chunk_; 94245614Sandrew}; 95245614Sandrew 96245614SandrewAsanChunkView FindHeapChunkByAddress(uptr address); 97314564SdimAsanChunkView FindHeapChunkByAllocBeg(uptr address); 98245614Sandrew 99245614Sandrew// List of AsanChunks with total size. 100245614Sandrewclass AsanChunkFifoList: public IntrusiveList<AsanChunk> { 101245614Sandrew public: 102229109Sed explicit AsanChunkFifoList(LinkerInitialized) { } 103229109Sed AsanChunkFifoList() { clear(); } 104229109Sed void Push(AsanChunk *n); 105229109Sed void PushList(AsanChunkFifoList *q); 106229109Sed AsanChunk *Pop(); 107238901Sandrew uptr size() { return size_; } 108229109Sed void clear() { 109245614Sandrew IntrusiveList<AsanChunk>::clear(); 110229109Sed size_ = 0; 111229109Sed } 112229109Sed private: 113238901Sandrew uptr size_; 114229109Sed}; 115229109Sed 116276789Sdimstruct AsanMapUnmapCallback { 117276789Sdim void OnMap(uptr p, uptr size) const; 118276789Sdim void OnUnmap(uptr p, uptr size) const; 119276789Sdim}; 120276789Sdim 121276789Sdim#if SANITIZER_CAN_USE_ALLOCATOR64 122276789Sdim# if defined(__powerpc64__) 123276789Sdimconst uptr kAllocatorSpace = 0xa0000000000ULL; 124276789Sdimconst uptr kAllocatorSize = 0x20000000000ULL; // 2T. 125314564Sdimtypedef DefaultSizeClassMap SizeClassMap; 126314564Sdim# elif defined(__aarch64__) && SANITIZER_ANDROID 127314564Sdimconst uptr kAllocatorSpace = 0x3000000000ULL; 128314564Sdimconst uptr kAllocatorSize = 0x2000000000ULL; // 128G. 129314564Sdimtypedef VeryCompactSizeClassMap SizeClassMap; 130296417Sdim# elif defined(__aarch64__) 131314564Sdim// AArch64/SANITIZER_CAN_USER_ALLOCATOR64 is only for 42-bit VMA 132296417Sdim// so no need to different values for different VMA. 133296417Sdimconst uptr kAllocatorSpace = 0x10000000000ULL; 134296417Sdimconst uptr kAllocatorSize = 0x10000000000ULL; // 3T. 135314564Sdimtypedef DefaultSizeClassMap SizeClassMap; 136314564Sdim# elif SANITIZER_WINDOWS 137314564Sdimconst uptr kAllocatorSpace = ~(uptr)0; 138314564Sdimconst uptr kAllocatorSize = 0x8000000000ULL; // 500G 139314564Sdimtypedef DefaultSizeClassMap SizeClassMap; 140276789Sdim# else 141276789Sdimconst uptr kAllocatorSpace = 0x600000000000ULL; 142276789Sdimconst uptr kAllocatorSize = 0x40000000000ULL; // 4T. 143314564Sdimtypedef DefaultSizeClassMap SizeClassMap; 144276789Sdim# endif 145314564Sdimstruct AP64 { // Allocator64 parameters. Deliberately using a short name. 146314564Sdim static const uptr kSpaceBeg = kAllocatorSpace; 147314564Sdim static const uptr kSpaceSize = kAllocatorSize; 148314564Sdim static const uptr kMetadataSize = 0; 149314564Sdim typedef __asan::SizeClassMap SizeClassMap; 150314564Sdim typedef AsanMapUnmapCallback MapUnmapCallback; 151314564Sdim static const uptr kFlags = 0; 152314564Sdim}; 153314564Sdim 154314564Sdimtypedef SizeClassAllocator64<AP64> PrimaryAllocator; 155276789Sdim#else // Fallback to SizeClassAllocator32. 156276789Sdimstatic const uptr kRegionSizeLog = 20; 157276789Sdimstatic const uptr kNumRegions = SANITIZER_MMAP_RANGE_SIZE >> kRegionSizeLog; 158276789Sdim# if SANITIZER_WORDSIZE == 32 159276789Sdimtypedef FlatByteMap<kNumRegions> ByteMap; 160276789Sdim# elif SANITIZER_WORDSIZE == 64 161276789Sdimtypedef TwoLevelByteMap<(kNumRegions >> 12), 1 << 12> ByteMap; 162276789Sdim# endif 163276789Sdimtypedef CompactSizeClassMap SizeClassMap; 164321369Sdimstruct AP32 { 165321369Sdim static const uptr kSpaceBeg = 0; 166321369Sdim static const u64 kSpaceSize = SANITIZER_MMAP_RANGE_SIZE; 167321369Sdim static const uptr kMetadataSize = 16; 168321369Sdim typedef __asan::SizeClassMap SizeClassMap; 169321369Sdim static const uptr kRegionSizeLog = __asan::kRegionSizeLog; 170321369Sdim typedef __asan::ByteMap ByteMap; 171321369Sdim typedef AsanMapUnmapCallback MapUnmapCallback; 172321369Sdim static const uptr kFlags = 0; 173321369Sdim}; 174321369Sdimtypedef SizeClassAllocator32<AP32> PrimaryAllocator; 175276789Sdim#endif // SANITIZER_CAN_USE_ALLOCATOR64 176276789Sdim 177288943Sdimstatic const uptr kNumberOfSizeClasses = SizeClassMap::kNumClasses; 178276789Sdimtypedef SizeClassAllocatorLocalCache<PrimaryAllocator> AllocatorCache; 179276789Sdimtypedef LargeMmapAllocator<AsanMapUnmapCallback> SecondaryAllocator; 180276789Sdimtypedef CombinedAllocator<PrimaryAllocator, AllocatorCache, 181280031Sdim SecondaryAllocator> AsanAllocator; 182276789Sdim 183276789Sdim 184229109Sedstruct AsanThreadLocalMallocStorage { 185245614Sandrew uptr quarantine_cache[16]; 186280031Sdim AllocatorCache allocator_cache; 187229109Sed void CommitBack(); 188276789Sdim private: 189276789Sdim // These objects are allocated via mmap() and are zero-initialized. 190276789Sdim AsanThreadLocalMallocStorage() {} 191229109Sed}; 192229109Sed 193276789Sdimvoid *asan_memalign(uptr alignment, uptr size, BufferedStackTrace *stack, 194245614Sandrew AllocType alloc_type); 195276789Sdimvoid asan_free(void *ptr, BufferedStackTrace *stack, AllocType alloc_type); 196276789Sdimvoid asan_sized_free(void *ptr, uptr size, BufferedStackTrace *stack, 197276789Sdim AllocType alloc_type); 198229109Sed 199276789Sdimvoid *asan_malloc(uptr size, BufferedStackTrace *stack); 200276789Sdimvoid *asan_calloc(uptr nmemb, uptr size, BufferedStackTrace *stack); 201276789Sdimvoid *asan_realloc(void *p, uptr size, BufferedStackTrace *stack); 202276789Sdimvoid *asan_valloc(uptr size, BufferedStackTrace *stack); 203276789Sdimvoid *asan_pvalloc(uptr size, BufferedStackTrace *stack); 204229109Sed 205238901Sandrewint asan_posix_memalign(void **memptr, uptr alignment, uptr size, 206276789Sdim BufferedStackTrace *stack); 207309124Sdimuptr asan_malloc_usable_size(const void *ptr, uptr pc, uptr bp); 208229109Sed 209238901Sandrewuptr asan_mz_size(const void *ptr); 210238901Sandrewvoid asan_mz_force_lock(); 211238901Sandrewvoid asan_mz_force_unlock(); 212229109Sed 213245614Sandrewvoid PrintInternalAllocatorStats(); 214280031Sdimvoid AsanSoftRssLimitExceededCallback(bool exceeded); 215245614Sandrew 216229109Sed} // namespace __asan 217229109Sed#endif // ASAN_ALLOCATOR_H 218