• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 static const uptr kNumberOfSizeClasses = 255;
33 struct AsanChunk;
34 
35 struct AllocatorOptions {
36   u32 quarantine_size_mb;
37   u16 min_redzone;
38   u16 max_redzone;
39   u8 may_return_null;
40   u8 alloc_dealloc_mismatch;
41 
42   void SetFrom(const Flags *f, const CommonFlags *cf);
43   void CopyTo(Flags *f, CommonFlags *cf);
44 };
45 
46 void InitializeAllocator(const AllocatorOptions &options);
47 void ReInitializeAllocator(const AllocatorOptions &options);
48 void GetAllocatorOptions(AllocatorOptions *options);
49 
50 class AsanChunkView {
51  public:
AsanChunkView(AsanChunk * chunk)52   explicit AsanChunkView(AsanChunk *chunk) : chunk_(chunk) {}
53   bool IsValid();   // Checks if AsanChunkView points to a valid allocated
54                     // or quarantined chunk.
55   uptr Beg();       // First byte of user memory.
56   uptr End();       // Last byte of user memory.
57   uptr UsedSize();  // Size requested by the user.
58   uptr AllocTid();
59   uptr FreeTid();
Eq(const AsanChunkView & c)60   bool Eq(const AsanChunkView &c) const { return chunk_ == c.chunk_; }
61   StackTrace GetAllocStack();
62   StackTrace GetFreeStack();
AddrIsInside(uptr addr,uptr access_size,sptr * offset)63   bool AddrIsInside(uptr addr, uptr access_size, sptr *offset) {
64     if (addr >= Beg() && (addr + access_size) <= End()) {
65       *offset = addr - Beg();
66       return true;
67     }
68     return false;
69   }
AddrIsAtLeft(uptr addr,uptr access_size,sptr * offset)70   bool AddrIsAtLeft(uptr addr, uptr access_size, sptr *offset) {
71     (void)access_size;
72     if (addr < Beg()) {
73       *offset = Beg() - addr;
74       return true;
75     }
76     return false;
77   }
AddrIsAtRight(uptr addr,uptr access_size,sptr * offset)78   bool AddrIsAtRight(uptr addr, uptr access_size, sptr *offset) {
79     if (addr + access_size > End()) {
80       *offset = addr - End();
81       return true;
82     }
83     return false;
84   }
85 
86  private:
87   AsanChunk *const chunk_;
88 };
89 
90 AsanChunkView FindHeapChunkByAddress(uptr address);
91 
92 // List of AsanChunks with total size.
93 class AsanChunkFifoList: public IntrusiveList<AsanChunk> {
94  public:
AsanChunkFifoList(LinkerInitialized)95   explicit AsanChunkFifoList(LinkerInitialized) { }
AsanChunkFifoList()96   AsanChunkFifoList() { clear(); }
97   void Push(AsanChunk *n);
98   void PushList(AsanChunkFifoList *q);
99   AsanChunk *Pop();
size()100   uptr size() { return size_; }
clear()101   void clear() {
102     IntrusiveList<AsanChunk>::clear();
103     size_ = 0;
104   }
105  private:
106   uptr size_;
107 };
108 
109 struct AsanMapUnmapCallback {
110   void OnMap(uptr p, uptr size) const;
111   void OnUnmap(uptr p, uptr size) const;
112 };
113 
114 #if SANITIZER_CAN_USE_ALLOCATOR64
115 # if defined(__powerpc64__)
116 const uptr kAllocatorSpace =  0xa0000000000ULL;
117 const uptr kAllocatorSize  =  0x20000000000ULL;  // 2T.
118 # else
119 const uptr kAllocatorSpace = 0x600000000000ULL;
120 const uptr kAllocatorSize  =  0x40000000000ULL;  // 4T.
121 # endif
122 typedef DefaultSizeClassMap SizeClassMap;
123 typedef SizeClassAllocator64<kAllocatorSpace, kAllocatorSize, 0 /*metadata*/,
124     SizeClassMap, AsanMapUnmapCallback> PrimaryAllocator;
125 #else  // Fallback to SizeClassAllocator32.
126 static const uptr kRegionSizeLog = 20;
127 static const uptr kNumRegions = SANITIZER_MMAP_RANGE_SIZE >> kRegionSizeLog;
128 # if SANITIZER_WORDSIZE == 32
129 typedef FlatByteMap<kNumRegions> ByteMap;
130 # elif SANITIZER_WORDSIZE == 64
131 typedef TwoLevelByteMap<(kNumRegions >> 12), 1 << 12> ByteMap;
132 # endif
133 typedef CompactSizeClassMap SizeClassMap;
134 typedef SizeClassAllocator32<0, SANITIZER_MMAP_RANGE_SIZE, 16,
135   SizeClassMap, kRegionSizeLog,
136   ByteMap,
137   AsanMapUnmapCallback> PrimaryAllocator;
138 #endif  // SANITIZER_CAN_USE_ALLOCATOR64
139 
140 typedef SizeClassAllocatorLocalCache<PrimaryAllocator> AllocatorCache;
141 typedef LargeMmapAllocator<AsanMapUnmapCallback> SecondaryAllocator;
142 typedef CombinedAllocator<PrimaryAllocator, AllocatorCache,
143     SecondaryAllocator> AsanAllocator;
144 
145 
146 struct AsanThreadLocalMallocStorage {
147   uptr quarantine_cache[16];
148   AllocatorCache allocator_cache;
149   void CommitBack();
150  private:
151   // These objects are allocated via mmap() and are zero-initialized.
AsanThreadLocalMallocStorageAsanThreadLocalMallocStorage152   AsanThreadLocalMallocStorage() {}
153 };
154 
155 void *asan_memalign(uptr alignment, uptr size, BufferedStackTrace *stack,
156                     AllocType alloc_type);
157 void asan_free(void *ptr, BufferedStackTrace *stack, AllocType alloc_type);
158 void asan_sized_free(void *ptr, uptr size, BufferedStackTrace *stack,
159                      AllocType alloc_type);
160 
161 void *asan_malloc(uptr size, BufferedStackTrace *stack);
162 void *asan_calloc(uptr nmemb, uptr size, BufferedStackTrace *stack);
163 void *asan_realloc(void *p, uptr size, BufferedStackTrace *stack);
164 void *asan_valloc(uptr size, BufferedStackTrace *stack);
165 void *asan_pvalloc(uptr size, BufferedStackTrace *stack);
166 
167 int asan_posix_memalign(void **memptr, uptr alignment, uptr size,
168                         BufferedStackTrace *stack);
169 uptr asan_malloc_usable_size(void *ptr, uptr pc, uptr bp);
170 
171 uptr asan_mz_size(const void *ptr);
172 void asan_mz_force_lock();
173 void asan_mz_force_unlock();
174 
175 void PrintInternalAllocatorStats();
176 void AsanSoftRssLimitExceededCallback(bool exceeded);
177 
178 }  // namespace __asan
179 #endif  // ASAN_ALLOCATOR_H
180