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
18 namespace __scudo {
19
20 enum 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
27 enum 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.
38 typedef u64 PackedHeader;
39 struct 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
52 typedef atomic_uint64_t AtomicPackedHeader;
53 COMPILER_CHECK(sizeof(UnpackedHeader) == sizeof(PackedHeader));
54
55 // Minimum alignment of 8 bytes for 32-bit, 16 for 64-bit
56 const uptr MinAlignmentLog = FIRST_32_SECOND_64(3, 4);
57 const uptr MaxAlignmentLog = 24; // 16 MB
58 const uptr MinAlignment = 1 << MinAlignmentLog;
59 const 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.
RoundUpTo(uptr Size,uptr Boundary)63 constexpr uptr RoundUpTo(uptr Size, uptr Boundary) {
64 return (Size + Boundary - 1) & ~(Boundary - 1);
65 }
66
67 namespace Chunk {
getHeaderSize()68 constexpr uptr getHeaderSize() {
69 return RoundUpTo(sizeof(PackedHeader), MinAlignment);
70 }
71 }
72
73 #if SANITIZER_CAN_USE_ALLOCATOR64
74 const uptr AllocatorSpace = ~0ULL;
75 struct 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 };
85 typedef SizeClassAllocator64<AP64> PrimaryT;
86 #else
87 struct 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 };
99 typedef SizeClassAllocator32<AP32> PrimaryT;
100 #endif // SANITIZER_CAN_USE_ALLOCATOR64
101
102 #include "scudo_allocator_secondary.h"
103
104 typedef LargeMmapAllocator SecondaryT;
105
106 #include "scudo_allocator_combined.h"
107
108 typedef CombinedAllocator BackendT;
109 typedef CombinedAllocator::AllocatorCache AllocatorCacheT;
110
111 void initScudo();
112
113 void *scudoAllocate(uptr Size, uptr Alignment, AllocType Type);
114 void scudoDeallocate(void *Ptr, uptr Size, uptr Alignment, AllocType Type);
115 void *scudoRealloc(void *Ptr, uptr Size);
116 void *scudoCalloc(uptr NMemB, uptr Size);
117 void *scudoValloc(uptr Size);
118 void *scudoPvalloc(uptr Size);
119 int scudoPosixMemalign(void **MemPtr, uptr Alignment, uptr Size);
120 void *scudoAlignedAlloc(uptr Alignment, uptr Size);
121 uptr scudoMallocUsableSize(void *Ptr);
122
123 } // namespace __scudo
124
125 #endif // SCUDO_ALLOCATOR_H_
126