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