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