13cab2bb3Spatrick //===-- asan_allocator.h ----------------------------------------*- C++ -*-===// 23cab2bb3Spatrick // 33cab2bb3Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 43cab2bb3Spatrick // See https://llvm.org/LICENSE.txt for license information. 53cab2bb3Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 63cab2bb3Spatrick // 73cab2bb3Spatrick //===----------------------------------------------------------------------===// 83cab2bb3Spatrick // 93cab2bb3Spatrick // This file is a part of AddressSanitizer, an address sanity checker. 103cab2bb3Spatrick // 113cab2bb3Spatrick // ASan-private header for asan_allocator.cpp. 123cab2bb3Spatrick //===----------------------------------------------------------------------===// 133cab2bb3Spatrick 143cab2bb3Spatrick #ifndef ASAN_ALLOCATOR_H 153cab2bb3Spatrick #define ASAN_ALLOCATOR_H 163cab2bb3Spatrick 173cab2bb3Spatrick #include "asan_flags.h" 183cab2bb3Spatrick #include "asan_interceptors.h" 19*d89ec533Spatrick #include "asan_internal.h" 203cab2bb3Spatrick #include "sanitizer_common/sanitizer_allocator.h" 213cab2bb3Spatrick #include "sanitizer_common/sanitizer_list.h" 22*d89ec533Spatrick #include "sanitizer_common/sanitizer_platform.h" 233cab2bb3Spatrick 243cab2bb3Spatrick namespace __asan { 253cab2bb3Spatrick 263cab2bb3Spatrick enum AllocType { 273cab2bb3Spatrick FROM_MALLOC = 1, // Memory block came from malloc, calloc, realloc, etc. 283cab2bb3Spatrick FROM_NEW = 2, // Memory block came from operator new. 293cab2bb3Spatrick FROM_NEW_BR = 3 // Memory block came from operator new [ ] 303cab2bb3Spatrick }; 313cab2bb3Spatrick 32*d89ec533Spatrick class AsanChunk; 333cab2bb3Spatrick 343cab2bb3Spatrick struct AllocatorOptions { 353cab2bb3Spatrick u32 quarantine_size_mb; 363cab2bb3Spatrick u32 thread_local_quarantine_size_kb; 373cab2bb3Spatrick u16 min_redzone; 383cab2bb3Spatrick u16 max_redzone; 393cab2bb3Spatrick u8 may_return_null; 403cab2bb3Spatrick u8 alloc_dealloc_mismatch; 413cab2bb3Spatrick s32 release_to_os_interval_ms; 423cab2bb3Spatrick 433cab2bb3Spatrick void SetFrom(const Flags *f, const CommonFlags *cf); 443cab2bb3Spatrick void CopyTo(Flags *f, CommonFlags *cf); 453cab2bb3Spatrick }; 463cab2bb3Spatrick 473cab2bb3Spatrick void InitializeAllocator(const AllocatorOptions &options); 483cab2bb3Spatrick void ReInitializeAllocator(const AllocatorOptions &options); 493cab2bb3Spatrick void GetAllocatorOptions(AllocatorOptions *options); 503cab2bb3Spatrick 513cab2bb3Spatrick class AsanChunkView { 523cab2bb3Spatrick public: AsanChunkView(AsanChunk * chunk)533cab2bb3Spatrick explicit AsanChunkView(AsanChunk *chunk) : chunk_(chunk) {} 543cab2bb3Spatrick bool IsValid() const; // Checks if AsanChunkView points to a valid 553cab2bb3Spatrick // allocated or quarantined chunk. 563cab2bb3Spatrick bool IsAllocated() const; // Checks if the memory is currently allocated. 573cab2bb3Spatrick bool IsQuarantined() const; // Checks if the memory is currently quarantined. 583cab2bb3Spatrick uptr Beg() const; // First byte of user memory. 593cab2bb3Spatrick uptr End() const; // Last byte of user memory. 603cab2bb3Spatrick uptr UsedSize() const; // Size requested by the user. 613cab2bb3Spatrick u32 UserRequestedAlignment() const; // Originally requested alignment. 623cab2bb3Spatrick uptr AllocTid() const; 633cab2bb3Spatrick uptr FreeTid() const; Eq(const AsanChunkView & c)643cab2bb3Spatrick bool Eq(const AsanChunkView &c) const { return chunk_ == c.chunk_; } 653cab2bb3Spatrick u32 GetAllocStackId() const; 663cab2bb3Spatrick u32 GetFreeStackId() const; 673cab2bb3Spatrick AllocType GetAllocType() const; AddrIsInside(uptr addr,uptr access_size,sptr * offset)683cab2bb3Spatrick bool AddrIsInside(uptr addr, uptr access_size, sptr *offset) const { 693cab2bb3Spatrick if (addr >= Beg() && (addr + access_size) <= End()) { 703cab2bb3Spatrick *offset = addr - Beg(); 713cab2bb3Spatrick return true; 723cab2bb3Spatrick } 733cab2bb3Spatrick return false; 743cab2bb3Spatrick } AddrIsAtLeft(uptr addr,uptr access_size,sptr * offset)753cab2bb3Spatrick bool AddrIsAtLeft(uptr addr, uptr access_size, sptr *offset) const { 763cab2bb3Spatrick (void)access_size; 773cab2bb3Spatrick if (addr < Beg()) { 783cab2bb3Spatrick *offset = Beg() - addr; 793cab2bb3Spatrick return true; 803cab2bb3Spatrick } 813cab2bb3Spatrick return false; 823cab2bb3Spatrick } AddrIsAtRight(uptr addr,uptr access_size,sptr * offset)833cab2bb3Spatrick bool AddrIsAtRight(uptr addr, uptr access_size, sptr *offset) const { 843cab2bb3Spatrick if (addr + access_size > End()) { 853cab2bb3Spatrick *offset = addr - End(); 863cab2bb3Spatrick return true; 873cab2bb3Spatrick } 883cab2bb3Spatrick return false; 893cab2bb3Spatrick } 903cab2bb3Spatrick 913cab2bb3Spatrick private: 923cab2bb3Spatrick AsanChunk *const chunk_; 933cab2bb3Spatrick }; 943cab2bb3Spatrick 953cab2bb3Spatrick AsanChunkView FindHeapChunkByAddress(uptr address); 963cab2bb3Spatrick AsanChunkView FindHeapChunkByAllocBeg(uptr address); 973cab2bb3Spatrick 983cab2bb3Spatrick // List of AsanChunks with total size. 993cab2bb3Spatrick class AsanChunkFifoList: public IntrusiveList<AsanChunk> { 1003cab2bb3Spatrick public: AsanChunkFifoList(LinkerInitialized)1013cab2bb3Spatrick explicit AsanChunkFifoList(LinkerInitialized) { } AsanChunkFifoList()1023cab2bb3Spatrick AsanChunkFifoList() { clear(); } 1033cab2bb3Spatrick void Push(AsanChunk *n); 1043cab2bb3Spatrick void PushList(AsanChunkFifoList *q); 1053cab2bb3Spatrick AsanChunk *Pop(); size()1063cab2bb3Spatrick uptr size() { return size_; } clear()1073cab2bb3Spatrick void clear() { 1083cab2bb3Spatrick IntrusiveList<AsanChunk>::clear(); 1093cab2bb3Spatrick size_ = 0; 1103cab2bb3Spatrick } 1113cab2bb3Spatrick private: 1123cab2bb3Spatrick uptr size_; 1133cab2bb3Spatrick }; 1143cab2bb3Spatrick 1153cab2bb3Spatrick struct AsanMapUnmapCallback { 1163cab2bb3Spatrick void OnMap(uptr p, uptr size) const; 1173cab2bb3Spatrick void OnUnmap(uptr p, uptr size) const; 1183cab2bb3Spatrick }; 1193cab2bb3Spatrick 1203cab2bb3Spatrick #if SANITIZER_CAN_USE_ALLOCATOR64 1213cab2bb3Spatrick # if SANITIZER_FUCHSIA 1223cab2bb3Spatrick const uptr kAllocatorSpace = ~(uptr)0; 1233cab2bb3Spatrick const uptr kAllocatorSize = 0x40000000000ULL; // 4T. 1243cab2bb3Spatrick typedef DefaultSizeClassMap SizeClassMap; 1253cab2bb3Spatrick # elif defined(__powerpc64__) 1263cab2bb3Spatrick const uptr kAllocatorSpace = ~(uptr)0; 1273cab2bb3Spatrick const uptr kAllocatorSize = 0x20000000000ULL; // 2T. 1283cab2bb3Spatrick typedef DefaultSizeClassMap SizeClassMap; 1293cab2bb3Spatrick # elif defined(__aarch64__) && SANITIZER_ANDROID 1303cab2bb3Spatrick // Android needs to support 39, 42 and 48 bit VMA. 1313cab2bb3Spatrick const uptr kAllocatorSpace = ~(uptr)0; 1323cab2bb3Spatrick const uptr kAllocatorSize = 0x2000000000ULL; // 128G. 1333cab2bb3Spatrick typedef VeryCompactSizeClassMap SizeClassMap; 134*d89ec533Spatrick #elif SANITIZER_RISCV64 135*d89ec533Spatrick const uptr kAllocatorSpace = ~(uptr)0; 136*d89ec533Spatrick const uptr kAllocatorSize = 0x2000000000ULL; // 128G. 137*d89ec533Spatrick typedef VeryDenseSizeClassMap SizeClassMap; 1383cab2bb3Spatrick #elif defined(__sparc__) 1393cab2bb3Spatrick const uptr kAllocatorSpace = ~(uptr)0; 1403cab2bb3Spatrick const uptr kAllocatorSize = 0x20000000000ULL; // 2T. 1413cab2bb3Spatrick typedef DefaultSizeClassMap SizeClassMap; 1423cab2bb3Spatrick # elif SANITIZER_WINDOWS 1433cab2bb3Spatrick const uptr kAllocatorSpace = ~(uptr)0; 1443cab2bb3Spatrick const uptr kAllocatorSize = 0x8000000000ULL; // 500G 1453cab2bb3Spatrick typedef DefaultSizeClassMap SizeClassMap; 1463cab2bb3Spatrick # else 1473cab2bb3Spatrick const uptr kAllocatorSpace = 0x600000000000ULL; 1483cab2bb3Spatrick const uptr kAllocatorSize = 0x40000000000ULL; // 4T. 1493cab2bb3Spatrick typedef DefaultSizeClassMap SizeClassMap; 1503cab2bb3Spatrick # endif 1513cab2bb3Spatrick template <typename AddressSpaceViewTy> 1523cab2bb3Spatrick struct AP64 { // Allocator64 parameters. Deliberately using a short name. 1533cab2bb3Spatrick static const uptr kSpaceBeg = kAllocatorSpace; 1543cab2bb3Spatrick static const uptr kSpaceSize = kAllocatorSize; 1553cab2bb3Spatrick static const uptr kMetadataSize = 0; 1563cab2bb3Spatrick typedef __asan::SizeClassMap SizeClassMap; 1573cab2bb3Spatrick typedef AsanMapUnmapCallback MapUnmapCallback; 1583cab2bb3Spatrick static const uptr kFlags = 0; 1593cab2bb3Spatrick using AddressSpaceView = AddressSpaceViewTy; 1603cab2bb3Spatrick }; 1613cab2bb3Spatrick 1623cab2bb3Spatrick template <typename AddressSpaceView> 1633cab2bb3Spatrick using PrimaryAllocatorASVT = SizeClassAllocator64<AP64<AddressSpaceView>>; 1643cab2bb3Spatrick using PrimaryAllocator = PrimaryAllocatorASVT<LocalAddressSpaceView>; 1653cab2bb3Spatrick #else // Fallback to SizeClassAllocator32. 1663cab2bb3Spatrick typedef CompactSizeClassMap SizeClassMap; 1673cab2bb3Spatrick template <typename AddressSpaceViewTy> 1683cab2bb3Spatrick struct AP32 { 1693cab2bb3Spatrick static const uptr kSpaceBeg = 0; 1703cab2bb3Spatrick static const u64 kSpaceSize = SANITIZER_MMAP_RANGE_SIZE; 171*d89ec533Spatrick static const uptr kMetadataSize = 0; 1723cab2bb3Spatrick typedef __asan::SizeClassMap SizeClassMap; 1733cab2bb3Spatrick static const uptr kRegionSizeLog = 20; 1743cab2bb3Spatrick using AddressSpaceView = AddressSpaceViewTy; 1753cab2bb3Spatrick typedef AsanMapUnmapCallback MapUnmapCallback; 1763cab2bb3Spatrick static const uptr kFlags = 0; 1773cab2bb3Spatrick }; 1783cab2bb3Spatrick template <typename AddressSpaceView> 1793cab2bb3Spatrick using PrimaryAllocatorASVT = SizeClassAllocator32<AP32<AddressSpaceView> >; 1803cab2bb3Spatrick using PrimaryAllocator = PrimaryAllocatorASVT<LocalAddressSpaceView>; 1813cab2bb3Spatrick #endif // SANITIZER_CAN_USE_ALLOCATOR64 1823cab2bb3Spatrick 1833cab2bb3Spatrick static const uptr kNumberOfSizeClasses = SizeClassMap::kNumClasses; 1843cab2bb3Spatrick 1853cab2bb3Spatrick template <typename AddressSpaceView> 1863cab2bb3Spatrick using AsanAllocatorASVT = 1873cab2bb3Spatrick CombinedAllocator<PrimaryAllocatorASVT<AddressSpaceView>>; 1883cab2bb3Spatrick using AsanAllocator = AsanAllocatorASVT<LocalAddressSpaceView>; 1893cab2bb3Spatrick using AllocatorCache = AsanAllocator::AllocatorCache; 1903cab2bb3Spatrick 1913cab2bb3Spatrick struct AsanThreadLocalMallocStorage { 1923cab2bb3Spatrick uptr quarantine_cache[16]; 1933cab2bb3Spatrick AllocatorCache allocator_cache; 1943cab2bb3Spatrick void CommitBack(); 1953cab2bb3Spatrick private: 1963cab2bb3Spatrick // These objects are allocated via mmap() and are zero-initialized. AsanThreadLocalMallocStorageAsanThreadLocalMallocStorage1973cab2bb3Spatrick AsanThreadLocalMallocStorage() {} 1983cab2bb3Spatrick }; 1993cab2bb3Spatrick 2003cab2bb3Spatrick void *asan_memalign(uptr alignment, uptr size, BufferedStackTrace *stack, 2013cab2bb3Spatrick AllocType alloc_type); 2023cab2bb3Spatrick void asan_free(void *ptr, BufferedStackTrace *stack, AllocType alloc_type); 2033cab2bb3Spatrick void asan_delete(void *ptr, uptr size, uptr alignment, 2043cab2bb3Spatrick BufferedStackTrace *stack, AllocType alloc_type); 2053cab2bb3Spatrick 2063cab2bb3Spatrick void *asan_malloc(uptr size, BufferedStackTrace *stack); 2073cab2bb3Spatrick void *asan_calloc(uptr nmemb, uptr size, BufferedStackTrace *stack); 2083cab2bb3Spatrick void *asan_realloc(void *p, uptr size, BufferedStackTrace *stack); 2093cab2bb3Spatrick void *asan_reallocarray(void *p, uptr nmemb, uptr size, 2103cab2bb3Spatrick BufferedStackTrace *stack); 2113cab2bb3Spatrick void *asan_valloc(uptr size, BufferedStackTrace *stack); 2123cab2bb3Spatrick void *asan_pvalloc(uptr size, BufferedStackTrace *stack); 2133cab2bb3Spatrick 2143cab2bb3Spatrick void *asan_aligned_alloc(uptr alignment, uptr size, BufferedStackTrace *stack); 2153cab2bb3Spatrick int asan_posix_memalign(void **memptr, uptr alignment, uptr size, 2163cab2bb3Spatrick BufferedStackTrace *stack); 2173cab2bb3Spatrick uptr asan_malloc_usable_size(const void *ptr, uptr pc, uptr bp); 2183cab2bb3Spatrick 2193cab2bb3Spatrick uptr asan_mz_size(const void *ptr); 2203cab2bb3Spatrick void asan_mz_force_lock(); 2213cab2bb3Spatrick void asan_mz_force_unlock(); 2223cab2bb3Spatrick 2233cab2bb3Spatrick void PrintInternalAllocatorStats(); 2243cab2bb3Spatrick void AsanSoftRssLimitExceededCallback(bool exceeded); 2253cab2bb3Spatrick 2263cab2bb3Spatrick } // namespace __asan 2273cab2bb3Spatrick #endif // ASAN_ALLOCATOR_H 228