1//===-- scudo_allocator.h ---------------------------------------*- C++ -*-===// 2// 3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4// See https://llvm.org/LICENSE.txt for license information. 5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6// 7//===----------------------------------------------------------------------===// 8/// 9/// Header for scudo_allocator.cpp. 10/// 11//===----------------------------------------------------------------------===// 12 13#ifndef SCUDO_ALLOCATOR_H_ 14#define SCUDO_ALLOCATOR_H_ 15 16#include "scudo_platform.h" 17 18namespace __scudo { 19 20enum AllocType : u8 { 21 FromMalloc = 0, // Memory block came from malloc, realloc, calloc, etc. 22 FromNew = 1, // Memory block came from operator new. 23 FromNewArray = 2, // Memory block came from operator new []. 24 FromMemalign = 3, // Memory block came from memalign, posix_memalign, etc. 25}; 26 27enum ChunkState : u8 { 28 ChunkAvailable = 0, 29 ChunkAllocated = 1, 30 ChunkQuarantine = 2 31}; 32 33// Our header requires 64 bits of storage. Having the offset saves us from 34// using functions such as GetBlockBegin, that is fairly costly. Our first 35// implementation used the MetaData as well, which offers the advantage of 36// being stored away from the chunk itself, but accessing it was costly as 37// well. The header will be atomically loaded and stored. 38typedef u64 PackedHeader; 39struct UnpackedHeader { 40 u64 Checksum : 16; 41 u64 ClassId : 8; 42 u64 SizeOrUnusedBytes : 20; // Size for Primary backed allocations, amount of 43 // unused bytes in the chunk for Secondary ones. 44 u64 State : 2; // available, allocated, or quarantined 45 u64 AllocType : 2; // malloc, new, new[], or memalign 46 u64 Offset : 16; // Offset from the beginning of the backend 47 // allocation to the beginning of the chunk 48 // itself, in multiples of MinAlignment. See 49 // comment about its maximum value and in init(). 50}; 51 52typedef atomic_uint64_t AtomicPackedHeader; 53COMPILER_CHECK(sizeof(UnpackedHeader) == sizeof(PackedHeader)); 54 55// Minimum alignment of 8 bytes for 32-bit, 16 for 64-bit 56const uptr MinAlignmentLog = FIRST_32_SECOND_64(3, 4); 57const uptr MaxAlignmentLog = 24; // 16 MB 58const uptr MinAlignment = 1 << MinAlignmentLog; 59const uptr MaxAlignment = 1 << MaxAlignmentLog; 60 61// constexpr version of __sanitizer::RoundUp without the extraneous CHECK. 62// This way we can use it in constexpr variables and functions declarations. 63constexpr uptr RoundUpTo(uptr Size, uptr Boundary) { 64 return (Size + Boundary - 1) & ~(Boundary - 1); 65} 66 67namespace Chunk { 68 constexpr uptr getHeaderSize() { 69 return RoundUpTo(sizeof(PackedHeader), MinAlignment); 70 } 71} 72 73#if SANITIZER_CAN_USE_ALLOCATOR64 74const uptr AllocatorSpace = ~0ULL; 75struct AP64 { 76 static const uptr kSpaceBeg = AllocatorSpace; 77 static const uptr kSpaceSize = AllocatorSize; 78 static const uptr kMetadataSize = 0; 79 typedef __scudo::SizeClassMap SizeClassMap; 80 typedef NoOpMapUnmapCallback MapUnmapCallback; 81 static const uptr kFlags = 82 SizeClassAllocator64FlagMasks::kRandomShuffleChunks; 83 using AddressSpaceView = LocalAddressSpaceView; 84}; 85typedef SizeClassAllocator64<AP64> PrimaryT; 86#else 87struct AP32 { 88 static const uptr kSpaceBeg = 0; 89 static const u64 kSpaceSize = SANITIZER_MMAP_RANGE_SIZE; 90 static const uptr kMetadataSize = 0; 91 typedef __scudo::SizeClassMap SizeClassMap; 92 static const uptr kRegionSizeLog = RegionSizeLog; 93 using AddressSpaceView = LocalAddressSpaceView; 94 typedef NoOpMapUnmapCallback MapUnmapCallback; 95 static const uptr kFlags = 96 SizeClassAllocator32FlagMasks::kRandomShuffleChunks | 97 SizeClassAllocator32FlagMasks::kUseSeparateSizeClassForBatch; 98}; 99typedef SizeClassAllocator32<AP32> PrimaryT; 100#endif // SANITIZER_CAN_USE_ALLOCATOR64 101 102#include "scudo_allocator_secondary.h" 103 104typedef LargeMmapAllocator SecondaryT; 105 106#include "scudo_allocator_combined.h" 107 108typedef CombinedAllocator BackendT; 109typedef CombinedAllocator::AllocatorCache AllocatorCacheT; 110 111void initScudo(); 112 113void *scudoAllocate(uptr Size, uptr Alignment, AllocType Type); 114void scudoDeallocate(void *Ptr, uptr Size, uptr Alignment, AllocType Type); 115void *scudoRealloc(void *Ptr, uptr Size); 116void *scudoCalloc(uptr NMemB, uptr Size); 117void *scudoValloc(uptr Size); 118void *scudoPvalloc(uptr Size); 119int scudoPosixMemalign(void **MemPtr, uptr Alignment, uptr Size); 120void *scudoAlignedAlloc(uptr Alignment, uptr Size); 121uptr scudoMallocUsableSize(void *Ptr); 122 123} // namespace __scudo 124 125#endif // SCUDO_ALLOCATOR_H_ 126