//===-- scudo_allocator.h ---------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// /// /// Header for scudo_allocator.cpp. /// //===----------------------------------------------------------------------===// #ifndef SCUDO_ALLOCATOR_H_ #define SCUDO_ALLOCATOR_H_ #ifndef __x86_64__ # error "The Scudo hardened allocator currently only supports x86_64." #endif #include "scudo_flags.h" #include "sanitizer_common/sanitizer_allocator.h" #include namespace __scudo { enum AllocType : u8 { FromMalloc = 0, // Memory block came from malloc, realloc, calloc, etc. FromNew = 1, // Memory block came from operator new. FromNewArray = 2, // Memory block came from operator new []. FromMemalign = 3, // Memory block came from memalign, posix_memalign, etc. }; enum ChunkState : u8 { ChunkAvailable = 0, ChunkAllocated = 1, ChunkQuarantine = 2 }; #if SANITIZER_WORDSIZE == 64 // Our header requires 128 bits of storage on 64-bit platforms, which fits // nicely with the alignment requirements. Having the offset saves us from // using functions such as GetBlockBegin, that is fairly costly. Our first // implementation used the MetaData as well, which offers the advantage of // being stored away from the chunk itself, but accessing it was costly as // well. The header will be atomically loaded and stored using the 16-byte // primitives offered by the platform (likely requires cmpxchg16b support). typedef unsigned __int128 PackedHeader; struct UnpackedHeader { u16 Checksum : 16; uptr RequestedSize : 40; // Needed for reallocation purposes. u8 State : 2; // available, allocated, or quarantined u8 AllocType : 2; // malloc, new, new[], or memalign u8 Unused_0_ : 4; uptr Offset : 12; // Offset from the beginning of the backend // allocation to the beginning of the chunk itself, // in multiples of MinAlignment. See comment about // its maximum value and test in init(). u64 Unused_1_ : 36; u16 Salt : 16; }; #elif SANITIZER_WORDSIZE == 32 // On 32-bit platforms, our header requires 64 bits. typedef u64 PackedHeader; struct UnpackedHeader { u16 Checksum : 12; uptr RequestedSize : 32; // Needed for reallocation purposes. u8 State : 2; // available, allocated, or quarantined u8 AllocType : 2; // malloc, new, new[], or memalign uptr Offset : 12; // Offset from the beginning of the backend // allocation to the beginning of the chunk itself, // in multiples of MinAlignment. See comment about // its maximum value and test in Allocator::init(). u16 Salt : 4; }; #else # error "Unsupported SANITIZER_WORDSIZE." #endif // SANITIZER_WORDSIZE typedef std::atomic AtomicPackedHeader; COMPILER_CHECK(sizeof(UnpackedHeader) == sizeof(PackedHeader)); const uptr ChunkHeaderSize = sizeof(PackedHeader); // Minimum alignment of 8 bytes for 32-bit, 16 for 64-bit const uptr MinAlignmentLog = FIRST_32_SECOND_64(3, 4); const uptr MaxAlignmentLog = 24; // 16 MB const uptr MinAlignment = 1 << MinAlignmentLog; const uptr MaxAlignment = 1 << MaxAlignmentLog; struct AllocatorOptions { u32 QuarantineSizeMb; u32 ThreadLocalQuarantineSizeKb; bool MayReturnNull; bool DeallocationTypeMismatch; bool DeleteSizeMismatch; bool ZeroContents; void setFrom(const Flags *f, const CommonFlags *cf); void copyTo(Flags *f, CommonFlags *cf) const; }; void initAllocator(const AllocatorOptions &options); void drainQuarantine(); void *scudoMalloc(uptr Size, AllocType Type); void scudoFree(void *Ptr, AllocType Type); void scudoSizedFree(void *Ptr, uptr Size, AllocType Type); void *scudoRealloc(void *Ptr, uptr Size); void *scudoCalloc(uptr NMemB, uptr Size); void *scudoMemalign(uptr Alignment, uptr Size); void *scudoValloc(uptr Size); void *scudoPvalloc(uptr Size); int scudoPosixMemalign(void **MemPtr, uptr Alignment, uptr Size); void *scudoAlignedAlloc(uptr Alignment, uptr Size); uptr scudoMallocUsableSize(void *Ptr); #include "scudo_allocator_secondary.h" } // namespace __scudo #endif // SCUDO_ALLOCATOR_H_