blob: b9fc82dc6721d571f84a49da01e2d9cbb8e7410f [file] [log] [blame]
Kostya Serebryany712fc982016-06-07 01:20:26 +00001//===-- 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
Kostya Serebryany712fc982016-06-07 01:20:26 +000017#include "scudo_flags.h"
18
19#include "sanitizer_common/sanitizer_allocator.h"
20
Kostya Kortchinskyb39dff42017-01-18 17:11:17 +000021#if !SANITIZER_LINUX
22# error "The Scudo hardened allocator is currently only supported on Linux."
23#endif
24
Kostya Kortchinsky71dcc332016-10-26 16:16:58 +000025#include <atomic>
26
Kostya Serebryany712fc982016-06-07 01:20:26 +000027namespace __scudo {
28
29enum AllocType : u8 {
30 FromMalloc = 0, // Memory block came from malloc, realloc, calloc, etc.
31 FromNew = 1, // Memory block came from operator new.
32 FromNewArray = 2, // Memory block came from operator new [].
33 FromMemalign = 3, // Memory block came from memalign, posix_memalign, etc.
34};
35
Kostya Kortchinsky71dcc332016-10-26 16:16:58 +000036enum ChunkState : u8 {
37 ChunkAvailable = 0,
38 ChunkAllocated = 1,
39 ChunkQuarantine = 2
40};
41
Kostya Kortchinsky1148dc52016-11-30 17:32:20 +000042// Our header requires 64 bits of storage. Having the offset saves us from
Kostya Kortchinsky71dcc332016-10-26 16:16:58 +000043// using functions such as GetBlockBegin, that is fairly costly. Our first
44// implementation used the MetaData as well, which offers the advantage of
45// being stored away from the chunk itself, but accessing it was costly as
46// well. The header will be atomically loaded and stored using the 16-byte
47// primitives offered by the platform (likely requires cmpxchg16b support).
Kostya Kortchinsky71dcc332016-10-26 16:16:58 +000048typedef u64 PackedHeader;
49struct UnpackedHeader {
Kostya Kortchinsky1148dc52016-11-30 17:32:20 +000050 u64 Checksum : 16;
Kostya Kortchinsky47be0ed2016-12-15 18:06:55 +000051 u64 UnusedBytes : 20; // Needed for reallocation purposes.
Kostya Kortchinsky1148dc52016-11-30 17:32:20 +000052 u64 State : 2; // available, allocated, or quarantined
53 u64 AllocType : 2; // malloc, new, new[], or memalign
Kostya Kortchinsky47be0ed2016-12-15 18:06:55 +000054 u64 Offset : 16; // Offset from the beginning of the backend
Kostya Kortchinsky1148dc52016-11-30 17:32:20 +000055 // allocation to the beginning of the chunk itself,
56 // in multiples of MinAlignment. See comment about
57 // its maximum value and test in init().
58 u64 Salt : 8;
Kostya Kortchinsky71dcc332016-10-26 16:16:58 +000059};
Kostya Kortchinsky71dcc332016-10-26 16:16:58 +000060
61typedef std::atomic<PackedHeader> AtomicPackedHeader;
62COMPILER_CHECK(sizeof(UnpackedHeader) == sizeof(PackedHeader));
63
Kostya Kortchinsky71dcc332016-10-26 16:16:58 +000064// Minimum alignment of 8 bytes for 32-bit, 16 for 64-bit
65const uptr MinAlignmentLog = FIRST_32_SECOND_64(3, 4);
66const uptr MaxAlignmentLog = 24; // 16 MB
67const uptr MinAlignment = 1 << MinAlignmentLog;
68const uptr MaxAlignment = 1 << MaxAlignmentLog;
69
Kostya Kortchinsky1148dc52016-11-30 17:32:20 +000070const uptr ChunkHeaderSize = sizeof(PackedHeader);
71const uptr AlignedChunkHeaderSize =
72 (ChunkHeaderSize + MinAlignment - 1) & ~(MinAlignment - 1);
73
Kostya Serebryany712fc982016-06-07 01:20:26 +000074struct AllocatorOptions {
75 u32 QuarantineSizeMb;
76 u32 ThreadLocalQuarantineSizeKb;
77 bool MayReturnNull;
Evgeniy Stepanovd3305af2016-11-29 00:22:50 +000078 s32 ReleaseToOSIntervalMs;
Kostya Serebryany712fc982016-06-07 01:20:26 +000079 bool DeallocationTypeMismatch;
80 bool DeleteSizeMismatch;
81 bool ZeroContents;
82
83 void setFrom(const Flags *f, const CommonFlags *cf);
84 void copyTo(Flags *f, CommonFlags *cf) const;
85};
86
87void initAllocator(const AllocatorOptions &options);
88void drainQuarantine();
89
90void *scudoMalloc(uptr Size, AllocType Type);
91void scudoFree(void *Ptr, AllocType Type);
92void scudoSizedFree(void *Ptr, uptr Size, AllocType Type);
93void *scudoRealloc(void *Ptr, uptr Size);
94void *scudoCalloc(uptr NMemB, uptr Size);
95void *scudoMemalign(uptr Alignment, uptr Size);
96void *scudoValloc(uptr Size);
97void *scudoPvalloc(uptr Size);
98int scudoPosixMemalign(void **MemPtr, uptr Alignment, uptr Size);
99void *scudoAlignedAlloc(uptr Alignment, uptr Size);
100uptr scudoMallocUsableSize(void *Ptr);
101
Kostya Kortchinsky71dcc332016-10-26 16:16:58 +0000102#include "scudo_allocator_secondary.h"
103
Kostya Kortchinsky1148dc52016-11-30 17:32:20 +0000104} // namespace __scudo
Kostya Serebryany712fc982016-06-07 01:20:26 +0000105
106#endif // SCUDO_ALLOCATOR_H_