]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/compiler-rt/lib/scudo/scudo_allocator.h
Merge llvm, clang, lld, lldb, compiler-rt and libc++ r302418, and update
[FreeBSD/FreeBSD.git] / contrib / compiler-rt / lib / scudo / scudo_allocator.h
1 //===-- scudo_allocator.h ---------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 ///
10 /// Header for scudo_allocator.cpp.
11 ///
12 //===----------------------------------------------------------------------===//
13
14 #ifndef SCUDO_ALLOCATOR_H_
15 #define SCUDO_ALLOCATOR_H_
16
17 #include "scudo_flags.h"
18
19 #include "sanitizer_common/sanitizer_allocator.h"
20
21 #if !SANITIZER_LINUX
22 # error "The Scudo hardened allocator is currently only supported on Linux."
23 #endif
24
25 namespace __scudo {
26
27 enum AllocType : u8 {
28   FromMalloc    = 0, // Memory block came from malloc, realloc, calloc, etc.
29   FromNew       = 1, // Memory block came from operator new.
30   FromNewArray  = 2, // Memory block came from operator new [].
31   FromMemalign  = 3, // Memory block came from memalign, posix_memalign, etc.
32 };
33
34 enum ChunkState : u8 {
35   ChunkAvailable  = 0,
36   ChunkAllocated  = 1,
37   ChunkQuarantine = 2
38 };
39
40 // Our header requires 64 bits of storage. Having the offset saves us from
41 // using functions such as GetBlockBegin, that is fairly costly. Our first
42 // implementation used the MetaData as well, which offers the advantage of
43 // being stored away from the chunk itself, but accessing it was costly as
44 // well. The header will be atomically loaded and stored.
45 typedef u64 PackedHeader;
46 struct UnpackedHeader {
47   u64 Checksum          : 16;
48   u64 SizeOrUnusedBytes : 19; // Size for Primary backed allocations, amount of
49                               // unused bytes in the chunk for Secondary ones.
50   u64 FromPrimary       : 1;
51   u64 State             : 2;  // available, allocated, or quarantined
52   u64 AllocType         : 2;  // malloc, new, new[], or memalign
53   u64 Offset            : 16; // Offset from the beginning of the backend
54                               // allocation to the beginning of the chunk
55                               // itself, in multiples of MinAlignment. See
56                               // comment about its maximum value and in init().
57   u64 Salt              : 8;
58 };
59
60 typedef atomic_uint64_t AtomicPackedHeader;
61 COMPILER_CHECK(sizeof(UnpackedHeader) == sizeof(PackedHeader));
62
63 // Minimum alignment of 8 bytes for 32-bit, 16 for 64-bit
64 const uptr MinAlignmentLog = FIRST_32_SECOND_64(3, 4);
65 const uptr MaxAlignmentLog = 24;  // 16 MB
66 const uptr MinAlignment = 1 << MinAlignmentLog;
67 const uptr MaxAlignment = 1 << MaxAlignmentLog;
68
69 const uptr ChunkHeaderSize = sizeof(PackedHeader);
70 const uptr AlignedChunkHeaderSize =
71     (ChunkHeaderSize + MinAlignment - 1) & ~(MinAlignment - 1);
72
73 #if SANITIZER_CAN_USE_ALLOCATOR64
74 const uptr AllocatorSpace = ~0ULL;
75 # if defined(__aarch64__) && SANITIZER_ANDROID
76 const uptr AllocatorSize = 0x4000000000ULL;  // 256G.
77 # elif defined(__aarch64__)
78 const uptr AllocatorSize = 0x10000000000ULL;  // 1T.
79 # else
80 const uptr AllocatorSize = 0x40000000000ULL;  // 4T.
81 # endif
82 typedef DefaultSizeClassMap SizeClassMap;
83 struct AP {
84   static const uptr kSpaceBeg = AllocatorSpace;
85   static const uptr kSpaceSize = AllocatorSize;
86   static const uptr kMetadataSize = 0;
87   typedef __scudo::SizeClassMap SizeClassMap;
88   typedef NoOpMapUnmapCallback MapUnmapCallback;
89   static const uptr kFlags =
90       SizeClassAllocator64FlagMasks::kRandomShuffleChunks;
91 };
92 typedef SizeClassAllocator64<AP> PrimaryAllocator;
93 #else
94 // Currently, the 32-bit Sanitizer allocator has not yet benefited from all the
95 // security improvements brought to the 64-bit one. This makes the 32-bit
96 // version of Scudo slightly less toughened.
97 static const uptr RegionSizeLog = 20;
98 static const uptr NumRegions = SANITIZER_MMAP_RANGE_SIZE >> RegionSizeLog;
99 # if SANITIZER_WORDSIZE == 32
100 typedef FlatByteMap<NumRegions> ByteMap;
101 # elif SANITIZER_WORDSIZE == 64
102 typedef TwoLevelByteMap<(NumRegions >> 12), 1 << 12> ByteMap;
103 # endif  // SANITIZER_WORDSIZE
104 typedef DefaultSizeClassMap SizeClassMap;
105 typedef SizeClassAllocator32<0, SANITIZER_MMAP_RANGE_SIZE, 0, SizeClassMap,
106     RegionSizeLog, ByteMap> PrimaryAllocator;
107 #endif  // SANITIZER_CAN_USE_ALLOCATOR64
108
109 #include "scudo_allocator_secondary.h"
110
111 typedef SizeClassAllocatorLocalCache<PrimaryAllocator> AllocatorCache;
112 typedef ScudoLargeMmapAllocator SecondaryAllocator;
113 typedef CombinedAllocator<PrimaryAllocator, AllocatorCache, SecondaryAllocator>
114     ScudoBackendAllocator;
115
116 void initScudo();
117
118 void *scudoMalloc(uptr Size, AllocType Type);
119 void scudoFree(void *Ptr, AllocType Type);
120 void scudoSizedFree(void *Ptr, uptr Size, AllocType Type);
121 void *scudoRealloc(void *Ptr, uptr Size);
122 void *scudoCalloc(uptr NMemB, uptr Size);
123 void *scudoMemalign(uptr Alignment, uptr Size);
124 void *scudoValloc(uptr Size);
125 void *scudoPvalloc(uptr Size);
126 int scudoPosixMemalign(void **MemPtr, uptr Alignment, uptr Size);
127 void *scudoAlignedAlloc(uptr Alignment, uptr Size);
128 uptr scudoMallocUsableSize(void *Ptr);
129
130 }  // namespace __scudo
131
132 #endif  // SCUDO_ALLOCATOR_H_