Home | History | Annotate | Line # | Download | only in asan
      1 //===-- asan_allocator.h ----------------------------------------*- C++ -*-===//
      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 AddressSanitizer, an address sanity checker.
     11 //
     12 // ASan-private header for asan_allocator.cc.
     13 //===----------------------------------------------------------------------===//
     14 
     15 #ifndef ASAN_ALLOCATOR_H
     16 #define ASAN_ALLOCATOR_H
     17 
     18 #include "asan_flags.h"
     19 #include "asan_internal.h"
     20 #include "asan_interceptors.h"
     21 #include "sanitizer_common/sanitizer_allocator.h"
     22 #include "sanitizer_common/sanitizer_list.h"
     23 
     24 namespace __asan {
     25 
     26 enum AllocType {
     27   FROM_MALLOC = 1,  // Memory block came from malloc, calloc, realloc, etc.
     28   FROM_NEW = 2,     // Memory block came from operator new.
     29   FROM_NEW_BR = 3   // Memory block came from operator new [ ]
     30 };
     31 
     32 struct AsanChunk;
     33 
     34 struct AllocatorOptions {
     35   u32 quarantine_size_mb;
     36   u32 thread_local_quarantine_size_kb;
     37   u16 min_redzone;
     38   u16 max_redzone;
     39   u8 may_return_null;
     40   u8 alloc_dealloc_mismatch;
     41   s32 release_to_os_interval_ms;
     42 
     43   void SetFrom(const Flags *f, const CommonFlags *cf);
     44   void CopyTo(Flags *f, CommonFlags *cf);
     45 };
     46 
     47 void InitializeAllocator(const AllocatorOptions &options);
     48 void ReInitializeAllocator(const AllocatorOptions &options);
     49 void GetAllocatorOptions(AllocatorOptions *options);
     50 
     51 class AsanChunkView {
     52  public:
     53   explicit AsanChunkView(AsanChunk *chunk) : chunk_(chunk) {}
     54   bool IsValid() const;        // Checks if AsanChunkView points to a valid
     55                                // allocated or quarantined chunk.
     56   bool IsAllocated() const;    // Checks if the memory is currently allocated.
     57   bool IsQuarantined() const;  // Checks if the memory is currently quarantined.
     58   uptr Beg() const;            // First byte of user memory.
     59   uptr End() const;            // Last byte of user memory.
     60   uptr UsedSize() const;       // Size requested by the user.
     61   u32 UserRequestedAlignment() const;  // Originally requested alignment.
     62   uptr AllocTid() const;
     63   uptr FreeTid() const;
     64   bool Eq(const AsanChunkView &c) const { return chunk_ == c.chunk_; }
     65   u32 GetAllocStackId() const;
     66   u32 GetFreeStackId() const;
     67   StackTrace GetAllocStack() const;
     68   StackTrace GetFreeStack() const;
     69   AllocType GetAllocType() const;
     70   bool AddrIsInside(uptr addr, uptr access_size, sptr *offset) const {
     71     if (addr >= Beg() && (addr + access_size) <= End()) {
     72       *offset = addr - Beg();
     73       return true;
     74     }
     75     return false;
     76   }
     77   bool AddrIsAtLeft(uptr addr, uptr access_size, sptr *offset) const {
     78     (void)access_size;
     79     if (addr < Beg()) {
     80       *offset = Beg() - addr;
     81       return true;
     82     }
     83     return false;
     84   }
     85   bool AddrIsAtRight(uptr addr, uptr access_size, sptr *offset) const {
     86     if (addr + access_size > End()) {
     87       *offset = addr - End();
     88       return true;
     89     }
     90     return false;
     91   }
     92 
     93  private:
     94   AsanChunk *const chunk_;
     95 };
     96 
     97 AsanChunkView FindHeapChunkByAddress(uptr address);
     98 AsanChunkView FindHeapChunkByAllocBeg(uptr address);
     99 
    100 // List of AsanChunks with total size.
    101 class AsanChunkFifoList: public IntrusiveList<AsanChunk> {
    102  public:
    103   explicit AsanChunkFifoList(LinkerInitialized) { }
    104   AsanChunkFifoList() { clear(); }
    105   void Push(AsanChunk *n);
    106   void PushList(AsanChunkFifoList *q);
    107   AsanChunk *Pop();
    108   uptr size() { return size_; }
    109   void clear() {
    110     IntrusiveList<AsanChunk>::clear();
    111     size_ = 0;
    112   }
    113  private:
    114   uptr size_;
    115 };
    116 
    117 struct AsanMapUnmapCallback {
    118   void OnMap(uptr p, uptr size) const;
    119   void OnUnmap(uptr p, uptr size) const;
    120 };
    121 
    122 #if SANITIZER_CAN_USE_ALLOCATOR64
    123 # if SANITIZER_FUCHSIA
    124 const uptr kAllocatorSpace = ~(uptr)0;
    125 const uptr kAllocatorSize  =  0x40000000000ULL;  // 4T.
    126 typedef DefaultSizeClassMap SizeClassMap;
    127 # elif defined(__powerpc64__)
    128 const uptr kAllocatorSpace = ~(uptr)0;
    129 const uptr kAllocatorSize  =  0x20000000000ULL;  // 2T.
    130 typedef DefaultSizeClassMap SizeClassMap;
    131 # elif defined(__aarch64__) && SANITIZER_ANDROID
    132 // Android needs to support 39, 42 and 48 bit VMA.
    133 const uptr kAllocatorSpace =  ~(uptr)0;
    134 const uptr kAllocatorSize  =  0x2000000000ULL;  // 128G.
    135 typedef VeryCompactSizeClassMap SizeClassMap;
    136 # elif defined(__aarch64__)
    137 // AArch64/SANITIZER_CAN_USER_ALLOCATOR64 is only for 42-bit VMA
    138 // so no need to different values for different VMA.
    139 const uptr kAllocatorSpace =  0x10000000000ULL;
    140 const uptr kAllocatorSize  =  0x10000000000ULL;  // 3T.
    141 typedef DefaultSizeClassMap SizeClassMap;
    142 # elif SANITIZER_WINDOWS
    143 const uptr kAllocatorSpace = ~(uptr)0;
    144 const uptr kAllocatorSize  =  0x8000000000ULL;  // 500G
    145 typedef DefaultSizeClassMap SizeClassMap;
    146 # else
    147 const uptr kAllocatorSpace = 0x600000000000ULL;
    148 const uptr kAllocatorSize  =  0x40000000000ULL;  // 4T.
    149 typedef DefaultSizeClassMap SizeClassMap;
    150 # endif
    151 template <typename AddressSpaceViewTy>
    152 struct AP64 {  // Allocator64 parameters. Deliberately using a short name.
    153   static const uptr kSpaceBeg = kAllocatorSpace;
    154   static const uptr kSpaceSize = kAllocatorSize;
    155   static const uptr kMetadataSize = 0;
    156   typedef __asan::SizeClassMap SizeClassMap;
    157   typedef AsanMapUnmapCallback MapUnmapCallback;
    158   static const uptr kFlags = 0;
    159   using AddressSpaceView = AddressSpaceViewTy;
    160 };
    161 
    162 template <typename AddressSpaceView>
    163 using PrimaryAllocatorASVT = SizeClassAllocator64<AP64<AddressSpaceView>>;
    164 using PrimaryAllocator = PrimaryAllocatorASVT<LocalAddressSpaceView>;
    165 #else  // Fallback to SizeClassAllocator32.
    166 static const uptr kRegionSizeLog = 20;
    167 static const uptr kNumRegions = SANITIZER_MMAP_RANGE_SIZE >> kRegionSizeLog;
    168 # if SANITIZER_WORDSIZE == 32
    169 template <typename AddressSpaceView>
    170 using ByteMapASVT = FlatByteMap<kNumRegions, AddressSpaceView>;
    171 # elif SANITIZER_WORDSIZE == 64
    172 template <typename AddressSpaceView>
    173 using ByteMapASVT =
    174     TwoLevelByteMap<(kNumRegions >> 12), 1 << 12, AddressSpaceView>;
    175 # endif
    176 typedef CompactSizeClassMap SizeClassMap;
    177 template <typename AddressSpaceViewTy>
    178 struct AP32 {
    179   static const uptr kSpaceBeg = 0;
    180   static const u64 kSpaceSize = SANITIZER_MMAP_RANGE_SIZE;
    181   static const uptr kMetadataSize = 16;
    182   typedef __asan::SizeClassMap SizeClassMap;
    183   static const uptr kRegionSizeLog = __asan::kRegionSizeLog;
    184   using AddressSpaceView = AddressSpaceViewTy;
    185   using ByteMap = __asan::ByteMapASVT<AddressSpaceView>;
    186   typedef AsanMapUnmapCallback MapUnmapCallback;
    187   static const uptr kFlags = 0;
    188 };
    189 template <typename AddressSpaceView>
    190 using PrimaryAllocatorASVT = SizeClassAllocator32<AP32<AddressSpaceView> >;
    191 using PrimaryAllocator = PrimaryAllocatorASVT<LocalAddressSpaceView>;
    192 #endif  // SANITIZER_CAN_USE_ALLOCATOR64
    193 
    194 static const uptr kNumberOfSizeClasses = SizeClassMap::kNumClasses;
    195 template <typename AddressSpaceView>
    196 using AllocatorCacheASVT =
    197     SizeClassAllocatorLocalCache<PrimaryAllocatorASVT<AddressSpaceView>>;
    198 using AllocatorCache = AllocatorCacheASVT<LocalAddressSpaceView>;
    199 
    200 template <typename AddressSpaceView>
    201 using SecondaryAllocatorASVT =
    202     LargeMmapAllocator<AsanMapUnmapCallback, DefaultLargeMmapAllocatorPtrArray,
    203                        AddressSpaceView>;
    204 template <typename AddressSpaceView>
    205 using AsanAllocatorASVT =
    206     CombinedAllocator<PrimaryAllocatorASVT<AddressSpaceView>,
    207                       AllocatorCacheASVT<AddressSpaceView>,
    208                       SecondaryAllocatorASVT<AddressSpaceView>>;
    209 using AsanAllocator = AsanAllocatorASVT<LocalAddressSpaceView>;
    210 
    211 struct AsanThreadLocalMallocStorage {
    212   uptr quarantine_cache[16];
    213   AllocatorCache allocator_cache;
    214   void CommitBack();
    215  private:
    216   // These objects are allocated via mmap() and are zero-initialized.
    217   AsanThreadLocalMallocStorage() {}
    218 };
    219 
    220 void *asan_memalign(uptr alignment, uptr size, BufferedStackTrace *stack,
    221                     AllocType alloc_type);
    222 void asan_free(void *ptr, BufferedStackTrace *stack, AllocType alloc_type);
    223 void asan_delete(void *ptr, uptr size, uptr alignment,
    224                  BufferedStackTrace *stack, AllocType alloc_type);
    225 
    226 void *asan_malloc(uptr size, BufferedStackTrace *stack);
    227 void *asan_calloc(uptr nmemb, uptr size, BufferedStackTrace *stack);
    228 void *asan_realloc(void *p, uptr size, BufferedStackTrace *stack);
    229 void *asan_valloc(uptr size, BufferedStackTrace *stack);
    230 void *asan_pvalloc(uptr size, BufferedStackTrace *stack);
    231 
    232 void *asan_aligned_alloc(uptr alignment, uptr size, BufferedStackTrace *stack);
    233 int asan_posix_memalign(void **memptr, uptr alignment, uptr size,
    234                         BufferedStackTrace *stack);
    235 uptr asan_malloc_usable_size(const void *ptr, uptr pc, uptr bp);
    236 
    237 uptr asan_mz_size(const void *ptr);
    238 void asan_mz_force_lock();
    239 void asan_mz_force_unlock();
    240 
    241 void PrintInternalAllocatorStats();
    242 void AsanSoftRssLimitExceededCallback(bool exceeded);
    243 
    244 }  // namespace __asan
    245 #endif  // ASAN_ALLOCATOR_H
    246