xref: /aosp_15_r20/external/compiler-rt/lib/asan/asan_allocator.h (revision 7c3d14c8b49c529e04be81a3ce6f5cc23712e4c6)
1*7c3d14c8STreehugger Robot //===-- asan_allocator.h ----------------------------------------*- C++ -*-===//
2*7c3d14c8STreehugger Robot //
3*7c3d14c8STreehugger Robot //                     The LLVM Compiler Infrastructure
4*7c3d14c8STreehugger Robot //
5*7c3d14c8STreehugger Robot // This file is distributed under the University of Illinois Open Source
6*7c3d14c8STreehugger Robot // License. See LICENSE.TXT for details.
7*7c3d14c8STreehugger Robot //
8*7c3d14c8STreehugger Robot //===----------------------------------------------------------------------===//
9*7c3d14c8STreehugger Robot //
10*7c3d14c8STreehugger Robot // This file is a part of AddressSanitizer, an address sanity checker.
11*7c3d14c8STreehugger Robot //
12*7c3d14c8STreehugger Robot // ASan-private header for asan_allocator.cc.
13*7c3d14c8STreehugger Robot //===----------------------------------------------------------------------===//
14*7c3d14c8STreehugger Robot 
15*7c3d14c8STreehugger Robot #ifndef ASAN_ALLOCATOR_H
16*7c3d14c8STreehugger Robot #define ASAN_ALLOCATOR_H
17*7c3d14c8STreehugger Robot 
18*7c3d14c8STreehugger Robot #include "asan_flags.h"
19*7c3d14c8STreehugger Robot #include "asan_internal.h"
20*7c3d14c8STreehugger Robot #include "asan_interceptors.h"
21*7c3d14c8STreehugger Robot #include "sanitizer_common/sanitizer_allocator.h"
22*7c3d14c8STreehugger Robot #include "sanitizer_common/sanitizer_list.h"
23*7c3d14c8STreehugger Robot 
24*7c3d14c8STreehugger Robot namespace __asan {
25*7c3d14c8STreehugger Robot 
26*7c3d14c8STreehugger Robot enum AllocType {
27*7c3d14c8STreehugger Robot   FROM_MALLOC = 1,  // Memory block came from malloc, calloc, realloc, etc.
28*7c3d14c8STreehugger Robot   FROM_NEW = 2,     // Memory block came from operator new.
29*7c3d14c8STreehugger Robot   FROM_NEW_BR = 3   // Memory block came from operator new [ ]
30*7c3d14c8STreehugger Robot };
31*7c3d14c8STreehugger Robot 
32*7c3d14c8STreehugger Robot struct AsanChunk;
33*7c3d14c8STreehugger Robot 
34*7c3d14c8STreehugger Robot struct AllocatorOptions {
35*7c3d14c8STreehugger Robot   u32 quarantine_size_mb;
36*7c3d14c8STreehugger Robot   u16 min_redzone;
37*7c3d14c8STreehugger Robot   u16 max_redzone;
38*7c3d14c8STreehugger Robot   u8 may_return_null;
39*7c3d14c8STreehugger Robot   u8 alloc_dealloc_mismatch;
40*7c3d14c8STreehugger Robot 
41*7c3d14c8STreehugger Robot   void SetFrom(const Flags *f, const CommonFlags *cf);
42*7c3d14c8STreehugger Robot   void CopyTo(Flags *f, CommonFlags *cf);
43*7c3d14c8STreehugger Robot };
44*7c3d14c8STreehugger Robot 
45*7c3d14c8STreehugger Robot void InitializeAllocator(const AllocatorOptions &options);
46*7c3d14c8STreehugger Robot void ReInitializeAllocator(const AllocatorOptions &options);
47*7c3d14c8STreehugger Robot void GetAllocatorOptions(AllocatorOptions *options);
48*7c3d14c8STreehugger Robot 
49*7c3d14c8STreehugger Robot class AsanChunkView {
50*7c3d14c8STreehugger Robot  public:
AsanChunkView(AsanChunk * chunk)51*7c3d14c8STreehugger Robot   explicit AsanChunkView(AsanChunk *chunk) : chunk_(chunk) {}
52*7c3d14c8STreehugger Robot   bool IsValid();        // Checks if AsanChunkView points to a valid allocated
53*7c3d14c8STreehugger Robot                          // or quarantined chunk.
54*7c3d14c8STreehugger Robot   bool IsAllocated();    // Checks if the memory is currently allocated.
55*7c3d14c8STreehugger Robot   uptr Beg();            // First byte of user memory.
56*7c3d14c8STreehugger Robot   uptr End();            // Last byte of user memory.
57*7c3d14c8STreehugger Robot   uptr UsedSize();       // Size requested by the user.
58*7c3d14c8STreehugger Robot   uptr AllocTid();
59*7c3d14c8STreehugger Robot   uptr FreeTid();
Eq(const AsanChunkView & c)60*7c3d14c8STreehugger Robot   bool Eq(const AsanChunkView &c) const { return chunk_ == c.chunk_; }
61*7c3d14c8STreehugger Robot   u32 GetAllocStackId();
62*7c3d14c8STreehugger Robot   u32 GetFreeStackId();
63*7c3d14c8STreehugger Robot   StackTrace GetAllocStack();
64*7c3d14c8STreehugger Robot   StackTrace GetFreeStack();
AddrIsInside(uptr addr,uptr access_size,sptr * offset)65*7c3d14c8STreehugger Robot   bool AddrIsInside(uptr addr, uptr access_size, sptr *offset) {
66*7c3d14c8STreehugger Robot     if (addr >= Beg() && (addr + access_size) <= End()) {
67*7c3d14c8STreehugger Robot       *offset = addr - Beg();
68*7c3d14c8STreehugger Robot       return true;
69*7c3d14c8STreehugger Robot     }
70*7c3d14c8STreehugger Robot     return false;
71*7c3d14c8STreehugger Robot   }
AddrIsAtLeft(uptr addr,uptr access_size,sptr * offset)72*7c3d14c8STreehugger Robot   bool AddrIsAtLeft(uptr addr, uptr access_size, sptr *offset) {
73*7c3d14c8STreehugger Robot     (void)access_size;
74*7c3d14c8STreehugger Robot     if (addr < Beg()) {
75*7c3d14c8STreehugger Robot       *offset = Beg() - addr;
76*7c3d14c8STreehugger Robot       return true;
77*7c3d14c8STreehugger Robot     }
78*7c3d14c8STreehugger Robot     return false;
79*7c3d14c8STreehugger Robot   }
AddrIsAtRight(uptr addr,uptr access_size,sptr * offset)80*7c3d14c8STreehugger Robot   bool AddrIsAtRight(uptr addr, uptr access_size, sptr *offset) {
81*7c3d14c8STreehugger Robot     if (addr + access_size > End()) {
82*7c3d14c8STreehugger Robot       *offset = addr - End();
83*7c3d14c8STreehugger Robot       return true;
84*7c3d14c8STreehugger Robot     }
85*7c3d14c8STreehugger Robot     return false;
86*7c3d14c8STreehugger Robot   }
87*7c3d14c8STreehugger Robot 
88*7c3d14c8STreehugger Robot  private:
89*7c3d14c8STreehugger Robot   AsanChunk *const chunk_;
90*7c3d14c8STreehugger Robot };
91*7c3d14c8STreehugger Robot 
92*7c3d14c8STreehugger Robot AsanChunkView FindHeapChunkByAddress(uptr address);
93*7c3d14c8STreehugger Robot 
94*7c3d14c8STreehugger Robot // List of AsanChunks with total size.
95*7c3d14c8STreehugger Robot class AsanChunkFifoList: public IntrusiveList<AsanChunk> {
96*7c3d14c8STreehugger Robot  public:
AsanChunkFifoList(LinkerInitialized)97*7c3d14c8STreehugger Robot   explicit AsanChunkFifoList(LinkerInitialized) { }
AsanChunkFifoList()98*7c3d14c8STreehugger Robot   AsanChunkFifoList() { clear(); }
99*7c3d14c8STreehugger Robot   void Push(AsanChunk *n);
100*7c3d14c8STreehugger Robot   void PushList(AsanChunkFifoList *q);
101*7c3d14c8STreehugger Robot   AsanChunk *Pop();
size()102*7c3d14c8STreehugger Robot   uptr size() { return size_; }
clear()103*7c3d14c8STreehugger Robot   void clear() {
104*7c3d14c8STreehugger Robot     IntrusiveList<AsanChunk>::clear();
105*7c3d14c8STreehugger Robot     size_ = 0;
106*7c3d14c8STreehugger Robot   }
107*7c3d14c8STreehugger Robot  private:
108*7c3d14c8STreehugger Robot   uptr size_;
109*7c3d14c8STreehugger Robot };
110*7c3d14c8STreehugger Robot 
111*7c3d14c8STreehugger Robot struct AsanMapUnmapCallback {
112*7c3d14c8STreehugger Robot   void OnMap(uptr p, uptr size) const;
113*7c3d14c8STreehugger Robot   void OnUnmap(uptr p, uptr size) const;
114*7c3d14c8STreehugger Robot };
115*7c3d14c8STreehugger Robot 
116*7c3d14c8STreehugger Robot #if SANITIZER_CAN_USE_ALLOCATOR64
117*7c3d14c8STreehugger Robot # if defined(__powerpc64__)
118*7c3d14c8STreehugger Robot const uptr kAllocatorSpace =  0xa0000000000ULL;
119*7c3d14c8STreehugger Robot const uptr kAllocatorSize  =  0x20000000000ULL;  // 2T.
120*7c3d14c8STreehugger Robot # elif defined(__aarch64__)
121*7c3d14c8STreehugger Robot // AArch64/SANITIZIER_CAN_USER_ALLOCATOR64 is only for 42-bit VMA
122*7c3d14c8STreehugger Robot // so no need to different values for different VMA.
123*7c3d14c8STreehugger Robot const uptr kAllocatorSpace =  0x10000000000ULL;
124*7c3d14c8STreehugger Robot const uptr kAllocatorSize  =  0x10000000000ULL;  // 3T.
125*7c3d14c8STreehugger Robot # else
126*7c3d14c8STreehugger Robot const uptr kAllocatorSpace = 0x600000000000ULL;
127*7c3d14c8STreehugger Robot const uptr kAllocatorSize  =  0x40000000000ULL;  // 4T.
128*7c3d14c8STreehugger Robot # endif
129*7c3d14c8STreehugger Robot typedef DefaultSizeClassMap SizeClassMap;
130*7c3d14c8STreehugger Robot typedef SizeClassAllocator64<kAllocatorSpace, kAllocatorSize, 0 /*metadata*/,
131*7c3d14c8STreehugger Robot     SizeClassMap, AsanMapUnmapCallback> PrimaryAllocator;
132*7c3d14c8STreehugger Robot #else  // Fallback to SizeClassAllocator32.
133*7c3d14c8STreehugger Robot static const uptr kRegionSizeLog = 20;
134*7c3d14c8STreehugger Robot static const uptr kNumRegions = SANITIZER_MMAP_RANGE_SIZE >> kRegionSizeLog;
135*7c3d14c8STreehugger Robot # if SANITIZER_WORDSIZE == 32
136*7c3d14c8STreehugger Robot typedef FlatByteMap<kNumRegions> ByteMap;
137*7c3d14c8STreehugger Robot # elif SANITIZER_WORDSIZE == 64
138*7c3d14c8STreehugger Robot typedef TwoLevelByteMap<(kNumRegions >> 12), 1 << 12> ByteMap;
139*7c3d14c8STreehugger Robot # endif
140*7c3d14c8STreehugger Robot typedef CompactSizeClassMap SizeClassMap;
141*7c3d14c8STreehugger Robot typedef SizeClassAllocator32<0, SANITIZER_MMAP_RANGE_SIZE, 16,
142*7c3d14c8STreehugger Robot   SizeClassMap, kRegionSizeLog,
143*7c3d14c8STreehugger Robot   ByteMap,
144*7c3d14c8STreehugger Robot   AsanMapUnmapCallback> PrimaryAllocator;
145*7c3d14c8STreehugger Robot #endif  // SANITIZER_CAN_USE_ALLOCATOR64
146*7c3d14c8STreehugger Robot 
147*7c3d14c8STreehugger Robot static const uptr kNumberOfSizeClasses = SizeClassMap::kNumClasses;
148*7c3d14c8STreehugger Robot typedef SizeClassAllocatorLocalCache<PrimaryAllocator> AllocatorCache;
149*7c3d14c8STreehugger Robot typedef LargeMmapAllocator<AsanMapUnmapCallback> SecondaryAllocator;
150*7c3d14c8STreehugger Robot typedef CombinedAllocator<PrimaryAllocator, AllocatorCache,
151*7c3d14c8STreehugger Robot     SecondaryAllocator> AsanAllocator;
152*7c3d14c8STreehugger Robot 
153*7c3d14c8STreehugger Robot 
154*7c3d14c8STreehugger Robot struct AsanThreadLocalMallocStorage {
155*7c3d14c8STreehugger Robot   uptr quarantine_cache[16];
156*7c3d14c8STreehugger Robot   AllocatorCache allocator_cache;
157*7c3d14c8STreehugger Robot   void CommitBack();
158*7c3d14c8STreehugger Robot  private:
159*7c3d14c8STreehugger Robot   // These objects are allocated via mmap() and are zero-initialized.
AsanThreadLocalMallocStorageAsanThreadLocalMallocStorage160*7c3d14c8STreehugger Robot   AsanThreadLocalMallocStorage() {}
161*7c3d14c8STreehugger Robot };
162*7c3d14c8STreehugger Robot 
163*7c3d14c8STreehugger Robot void *asan_memalign(uptr alignment, uptr size, BufferedStackTrace *stack,
164*7c3d14c8STreehugger Robot                     AllocType alloc_type);
165*7c3d14c8STreehugger Robot void asan_free(void *ptr, BufferedStackTrace *stack, AllocType alloc_type);
166*7c3d14c8STreehugger Robot void asan_sized_free(void *ptr, uptr size, BufferedStackTrace *stack,
167*7c3d14c8STreehugger Robot                      AllocType alloc_type);
168*7c3d14c8STreehugger Robot 
169*7c3d14c8STreehugger Robot void *asan_malloc(uptr size, BufferedStackTrace *stack);
170*7c3d14c8STreehugger Robot void *asan_calloc(uptr nmemb, uptr size, BufferedStackTrace *stack);
171*7c3d14c8STreehugger Robot void *asan_realloc(void *p, uptr size, BufferedStackTrace *stack);
172*7c3d14c8STreehugger Robot void *asan_valloc(uptr size, BufferedStackTrace *stack);
173*7c3d14c8STreehugger Robot void *asan_pvalloc(uptr size, BufferedStackTrace *stack);
174*7c3d14c8STreehugger Robot 
175*7c3d14c8STreehugger Robot int asan_posix_memalign(void **memptr, uptr alignment, uptr size,
176*7c3d14c8STreehugger Robot                         BufferedStackTrace *stack);
177*7c3d14c8STreehugger Robot uptr asan_malloc_usable_size(const void *ptr, uptr pc, uptr bp);
178*7c3d14c8STreehugger Robot 
179*7c3d14c8STreehugger Robot uptr asan_mz_size(const void *ptr);
180*7c3d14c8STreehugger Robot void asan_mz_force_lock();
181*7c3d14c8STreehugger Robot void asan_mz_force_unlock();
182*7c3d14c8STreehugger Robot 
183*7c3d14c8STreehugger Robot void PrintInternalAllocatorStats();
184*7c3d14c8STreehugger Robot void AsanSoftRssLimitExceededCallback(bool exceeded);
185*7c3d14c8STreehugger Robot 
186*7c3d14c8STreehugger Robot }  // namespace __asan
187*7c3d14c8STreehugger Robot #endif  // ASAN_ALLOCATOR_H
188