1229109Sed//===-- asan_allocator.h ----------------------------------------*- C++ -*-===// 2229109Sed// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6229109Sed// 7229109Sed//===----------------------------------------------------------------------===// 8229109Sed// 9229109Sed// This file is a part of AddressSanitizer, an address sanity checker. 10229109Sed// 11360784Sdim// ASan-private header for asan_allocator.cpp. 12229109Sed//===----------------------------------------------------------------------===// 13229109Sed 14229109Sed#ifndef ASAN_ALLOCATOR_H 15229109Sed#define ASAN_ALLOCATOR_H 16229109Sed 17280031Sdim#include "asan_flags.h" 18229109Sed#include "asan_internal.h" 19229109Sed#include "asan_interceptors.h" 20276789Sdim#include "sanitizer_common/sanitizer_allocator.h" 21245614Sandrew#include "sanitizer_common/sanitizer_list.h" 22229109Sed 23229109Sednamespace __asan { 24229109Sed 25245614Sandrewenum AllocType { 26245614Sandrew FROM_MALLOC = 1, // Memory block came from malloc, calloc, realloc, etc. 27245614Sandrew FROM_NEW = 2, // Memory block came from operator new. 28245614Sandrew FROM_NEW_BR = 3 // Memory block came from operator new [ ] 29245614Sandrew}; 30245614Sandrew 31229109Sedstruct AsanChunk; 32229109Sed 33280031Sdimstruct AllocatorOptions { 34280031Sdim u32 quarantine_size_mb; 35314564Sdim u32 thread_local_quarantine_size_kb; 36280031Sdim u16 min_redzone; 37280031Sdim u16 max_redzone; 38280031Sdim u8 may_return_null; 39280031Sdim u8 alloc_dealloc_mismatch; 40314564Sdim s32 release_to_os_interval_ms; 41251034Sed 42280031Sdim void SetFrom(const Flags *f, const CommonFlags *cf); 43280031Sdim void CopyTo(Flags *f, CommonFlags *cf); 44280031Sdim}; 45280031Sdim 46280031Sdimvoid InitializeAllocator(const AllocatorOptions &options); 47280031Sdimvoid ReInitializeAllocator(const AllocatorOptions &options); 48280031Sdimvoid GetAllocatorOptions(AllocatorOptions *options); 49280031Sdim 50245614Sandrewclass AsanChunkView { 51229109Sed public: 52245614Sandrew explicit AsanChunkView(AsanChunk *chunk) : chunk_(chunk) {} 53314564Sdim bool IsValid() const; // Checks if AsanChunkView points to a valid 54314564Sdim // allocated or quarantined chunk. 55314564Sdim bool IsAllocated() const; // Checks if the memory is currently allocated. 56314564Sdim bool IsQuarantined() const; // Checks if the memory is currently quarantined. 57314564Sdim uptr Beg() const; // First byte of user memory. 58314564Sdim uptr End() const; // Last byte of user memory. 59314564Sdim uptr UsedSize() const; // Size requested by the user. 60327952Sdim u32 UserRequestedAlignment() const; // Originally requested alignment. 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 122327952Sdim# if SANITIZER_FUCHSIA 123327952Sdimconst uptr kAllocatorSpace = ~(uptr)0; 124327952Sdimconst uptr kAllocatorSize = 0x40000000000ULL; // 4T. 125327952Sdimtypedef DefaultSizeClassMap SizeClassMap; 126327952Sdim# elif defined(__powerpc64__) 127341825Sdimconst uptr kAllocatorSpace = ~(uptr)0; 128276789Sdimconst uptr kAllocatorSize = 0x20000000000ULL; // 2T. 129314564Sdimtypedef DefaultSizeClassMap SizeClassMap; 130314564Sdim# elif defined(__aarch64__) && SANITIZER_ANDROID 131341825Sdim// Android needs to support 39, 42 and 48 bit VMA. 132341825Sdimconst uptr kAllocatorSpace = ~(uptr)0; 133314564Sdimconst uptr kAllocatorSize = 0x2000000000ULL; // 128G. 134314564Sdimtypedef VeryCompactSizeClassMap SizeClassMap; 135296417Sdim# elif defined(__aarch64__) 136353358Sdim// AArch64/SANITIZER_CAN_USE_ALLOCATOR64 is only for 42-bit VMA 137296417Sdim// so no need to different values for different VMA. 138296417Sdimconst uptr kAllocatorSpace = 0x10000000000ULL; 139296417Sdimconst uptr kAllocatorSize = 0x10000000000ULL; // 3T. 140314564Sdimtypedef DefaultSizeClassMap SizeClassMap; 141353358Sdim#elif defined(__sparc__) 142353358Sdimconst uptr kAllocatorSpace = ~(uptr)0; 143353358Sdimconst uptr kAllocatorSize = 0x20000000000ULL; // 2T. 144353358Sdimtypedef DefaultSizeClassMap SizeClassMap; 145314564Sdim# elif SANITIZER_WINDOWS 146314564Sdimconst uptr kAllocatorSpace = ~(uptr)0; 147314564Sdimconst uptr kAllocatorSize = 0x8000000000ULL; // 500G 148314564Sdimtypedef DefaultSizeClassMap SizeClassMap; 149276789Sdim# else 150276789Sdimconst uptr kAllocatorSpace = 0x600000000000ULL; 151276789Sdimconst uptr kAllocatorSize = 0x40000000000ULL; // 4T. 152314564Sdimtypedef DefaultSizeClassMap SizeClassMap; 153276789Sdim# endif 154344779Sdimtemplate <typename AddressSpaceViewTy> 155314564Sdimstruct AP64 { // Allocator64 parameters. Deliberately using a short name. 156314564Sdim static const uptr kSpaceBeg = kAllocatorSpace; 157314564Sdim static const uptr kSpaceSize = kAllocatorSize; 158314564Sdim static const uptr kMetadataSize = 0; 159314564Sdim typedef __asan::SizeClassMap SizeClassMap; 160314564Sdim typedef AsanMapUnmapCallback MapUnmapCallback; 161314564Sdim static const uptr kFlags = 0; 162344779Sdim using AddressSpaceView = AddressSpaceViewTy; 163314564Sdim}; 164314564Sdim 165344779Sdimtemplate <typename AddressSpaceView> 166344779Sdimusing PrimaryAllocatorASVT = SizeClassAllocator64<AP64<AddressSpaceView>>; 167344779Sdimusing PrimaryAllocator = PrimaryAllocatorASVT<LocalAddressSpaceView>; 168276789Sdim#else // Fallback to SizeClassAllocator32. 169276789Sdimtypedef CompactSizeClassMap SizeClassMap; 170344779Sdimtemplate <typename AddressSpaceViewTy> 171321369Sdimstruct AP32 { 172321369Sdim static const uptr kSpaceBeg = 0; 173321369Sdim static const u64 kSpaceSize = SANITIZER_MMAP_RANGE_SIZE; 174321369Sdim static const uptr kMetadataSize = 16; 175321369Sdim typedef __asan::SizeClassMap SizeClassMap; 176353358Sdim static const uptr kRegionSizeLog = 20; 177344779Sdim using AddressSpaceView = AddressSpaceViewTy; 178321369Sdim typedef AsanMapUnmapCallback MapUnmapCallback; 179321369Sdim static const uptr kFlags = 0; 180321369Sdim}; 181344779Sdimtemplate <typename AddressSpaceView> 182344779Sdimusing PrimaryAllocatorASVT = SizeClassAllocator32<AP32<AddressSpaceView> >; 183344779Sdimusing PrimaryAllocator = PrimaryAllocatorASVT<LocalAddressSpaceView>; 184276789Sdim#endif // SANITIZER_CAN_USE_ALLOCATOR64 185276789Sdim 186288943Sdimstatic const uptr kNumberOfSizeClasses = SizeClassMap::kNumClasses; 187276789Sdim 188344779Sdimtemplate <typename AddressSpaceView> 189344779Sdimusing AsanAllocatorASVT = 190353358Sdim CombinedAllocator<PrimaryAllocatorASVT<AddressSpaceView>>; 191344779Sdimusing AsanAllocator = AsanAllocatorASVT<LocalAddressSpaceView>; 192353358Sdimusing AllocatorCache = AsanAllocator::AllocatorCache; 193276789Sdim 194229109Sedstruct AsanThreadLocalMallocStorage { 195245614Sandrew uptr quarantine_cache[16]; 196280031Sdim AllocatorCache allocator_cache; 197229109Sed void CommitBack(); 198276789Sdim private: 199276789Sdim // These objects are allocated via mmap() and are zero-initialized. 200276789Sdim AsanThreadLocalMallocStorage() {} 201229109Sed}; 202229109Sed 203276789Sdimvoid *asan_memalign(uptr alignment, uptr size, BufferedStackTrace *stack, 204245614Sandrew AllocType alloc_type); 205276789Sdimvoid asan_free(void *ptr, BufferedStackTrace *stack, AllocType alloc_type); 206327952Sdimvoid asan_delete(void *ptr, uptr size, uptr alignment, 207327952Sdim BufferedStackTrace *stack, AllocType alloc_type); 208229109Sed 209276789Sdimvoid *asan_malloc(uptr size, BufferedStackTrace *stack); 210276789Sdimvoid *asan_calloc(uptr nmemb, uptr size, BufferedStackTrace *stack); 211276789Sdimvoid *asan_realloc(void *p, uptr size, BufferedStackTrace *stack); 212353358Sdimvoid *asan_reallocarray(void *p, uptr nmemb, uptr size, 213353358Sdim BufferedStackTrace *stack); 214276789Sdimvoid *asan_valloc(uptr size, BufferedStackTrace *stack); 215276789Sdimvoid *asan_pvalloc(uptr size, BufferedStackTrace *stack); 216229109Sed 217341825Sdimvoid *asan_aligned_alloc(uptr alignment, uptr size, BufferedStackTrace *stack); 218238901Sandrewint asan_posix_memalign(void **memptr, uptr alignment, uptr size, 219276789Sdim BufferedStackTrace *stack); 220309124Sdimuptr asan_malloc_usable_size(const void *ptr, uptr pc, uptr bp); 221229109Sed 222238901Sandrewuptr asan_mz_size(const void *ptr); 223238901Sandrewvoid asan_mz_force_lock(); 224238901Sandrewvoid asan_mz_force_unlock(); 225229109Sed 226245614Sandrewvoid PrintInternalAllocatorStats(); 227280031Sdimvoid AsanSoftRssLimitExceededCallback(bool exceeded); 228245614Sandrew 229229109Sed} // namespace __asan 230229109Sed#endif // ASAN_ALLOCATOR_H 231