168d75effSDimitry Andric //===-- msan_allocator.cpp -------------------------- ---------------------===// 268d75effSDimitry Andric // 368d75effSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 468d75effSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 568d75effSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 668d75effSDimitry Andric // 768d75effSDimitry Andric //===----------------------------------------------------------------------===// 868d75effSDimitry Andric // 968d75effSDimitry Andric // This file is a part of MemorySanitizer. 1068d75effSDimitry Andric // 1168d75effSDimitry Andric // MemorySanitizer allocator. 1268d75effSDimitry Andric //===----------------------------------------------------------------------===// 1368d75effSDimitry Andric 1468d75effSDimitry Andric #include "sanitizer_common/sanitizer_allocator.h" 1568d75effSDimitry Andric #include "sanitizer_common/sanitizer_allocator_checks.h" 1668d75effSDimitry Andric #include "sanitizer_common/sanitizer_allocator_interface.h" 1768d75effSDimitry Andric #include "sanitizer_common/sanitizer_allocator_report.h" 1868d75effSDimitry Andric #include "sanitizer_common/sanitizer_errno.h" 1968d75effSDimitry Andric #include "msan.h" 2068d75effSDimitry Andric #include "msan_allocator.h" 2168d75effSDimitry Andric #include "msan_origin.h" 2268d75effSDimitry Andric #include "msan_thread.h" 2368d75effSDimitry Andric #include "msan_poisoning.h" 2468d75effSDimitry Andric 2568d75effSDimitry Andric namespace __msan { 2668d75effSDimitry Andric 2768d75effSDimitry Andric struct Metadata { 2868d75effSDimitry Andric uptr requested_size; 2968d75effSDimitry Andric }; 3068d75effSDimitry Andric 3168d75effSDimitry Andric struct MsanMapUnmapCallback { 3268d75effSDimitry Andric void OnMap(uptr p, uptr size) const {} 3368d75effSDimitry Andric void OnUnmap(uptr p, uptr size) const { 3468d75effSDimitry Andric __msan_unpoison((void *)p, size); 3568d75effSDimitry Andric 3668d75effSDimitry Andric // We are about to unmap a chunk of user memory. 3768d75effSDimitry Andric // Mark the corresponding shadow memory as not needed. 3868d75effSDimitry Andric uptr shadow_p = MEM_TO_SHADOW(p); 3968d75effSDimitry Andric ReleaseMemoryPagesToOS(shadow_p, shadow_p + size); 4068d75effSDimitry Andric if (__msan_get_track_origins()) { 4168d75effSDimitry Andric uptr origin_p = MEM_TO_ORIGIN(p); 4268d75effSDimitry Andric ReleaseMemoryPagesToOS(origin_p, origin_p + size); 4368d75effSDimitry Andric } 4468d75effSDimitry Andric } 4568d75effSDimitry Andric }; 4668d75effSDimitry Andric 4768d75effSDimitry Andric #if defined(__mips64) 4868d75effSDimitry Andric static const uptr kMaxAllowedMallocSize = 2UL << 30; 4968d75effSDimitry Andric 5068d75effSDimitry Andric struct AP32 { 5168d75effSDimitry Andric static const uptr kSpaceBeg = 0; 5268d75effSDimitry Andric static const u64 kSpaceSize = SANITIZER_MMAP_RANGE_SIZE; 5368d75effSDimitry Andric static const uptr kMetadataSize = sizeof(Metadata); 5468d75effSDimitry Andric typedef __sanitizer::CompactSizeClassMap SizeClassMap; 5568d75effSDimitry Andric static const uptr kRegionSizeLog = 20; 5668d75effSDimitry Andric using AddressSpaceView = LocalAddressSpaceView; 5768d75effSDimitry Andric typedef MsanMapUnmapCallback MapUnmapCallback; 5868d75effSDimitry Andric static const uptr kFlags = 0; 5968d75effSDimitry Andric }; 6068d75effSDimitry Andric typedef SizeClassAllocator32<AP32> PrimaryAllocator; 6168d75effSDimitry Andric #elif defined(__x86_64__) 6268d75effSDimitry Andric #if SANITIZER_NETBSD || \ 6368d75effSDimitry Andric (SANITIZER_LINUX && !defined(MSAN_LINUX_X86_64_OLD_MAPPING)) 6468d75effSDimitry Andric static const uptr kAllocatorSpace = 0x700000000000ULL; 6568d75effSDimitry Andric #else 6668d75effSDimitry Andric static const uptr kAllocatorSpace = 0x600000000000ULL; 6768d75effSDimitry Andric #endif 6868d75effSDimitry Andric static const uptr kMaxAllowedMallocSize = 8UL << 30; 6968d75effSDimitry Andric 7068d75effSDimitry Andric struct AP64 { // Allocator64 parameters. Deliberately using a short name. 7168d75effSDimitry Andric static const uptr kSpaceBeg = kAllocatorSpace; 7268d75effSDimitry Andric static const uptr kSpaceSize = 0x40000000000; // 4T. 7368d75effSDimitry Andric static const uptr kMetadataSize = sizeof(Metadata); 7468d75effSDimitry Andric typedef DefaultSizeClassMap SizeClassMap; 7568d75effSDimitry Andric typedef MsanMapUnmapCallback MapUnmapCallback; 7668d75effSDimitry Andric static const uptr kFlags = 0; 7768d75effSDimitry Andric using AddressSpaceView = LocalAddressSpaceView; 7868d75effSDimitry Andric }; 7968d75effSDimitry Andric 8068d75effSDimitry Andric typedef SizeClassAllocator64<AP64> PrimaryAllocator; 8168d75effSDimitry Andric 8268d75effSDimitry Andric #elif defined(__powerpc64__) 8368d75effSDimitry Andric static const uptr kMaxAllowedMallocSize = 2UL << 30; // 2G 8468d75effSDimitry Andric 8568d75effSDimitry Andric struct AP64 { // Allocator64 parameters. Deliberately using a short name. 8668d75effSDimitry Andric static const uptr kSpaceBeg = 0x300000000000; 8768d75effSDimitry Andric static const uptr kSpaceSize = 0x020000000000; // 2T. 8868d75effSDimitry Andric static const uptr kMetadataSize = sizeof(Metadata); 8968d75effSDimitry Andric typedef DefaultSizeClassMap SizeClassMap; 9068d75effSDimitry Andric typedef MsanMapUnmapCallback MapUnmapCallback; 9168d75effSDimitry Andric static const uptr kFlags = 0; 9268d75effSDimitry Andric using AddressSpaceView = LocalAddressSpaceView; 9368d75effSDimitry Andric }; 9468d75effSDimitry Andric 9568d75effSDimitry Andric typedef SizeClassAllocator64<AP64> PrimaryAllocator; 96*5ffd83dbSDimitry Andric #elif defined(__s390x__) 97*5ffd83dbSDimitry Andric static const uptr kMaxAllowedMallocSize = 2UL << 30; // 2G 98*5ffd83dbSDimitry Andric 99*5ffd83dbSDimitry Andric struct AP64 { // Allocator64 parameters. Deliberately using a short name. 100*5ffd83dbSDimitry Andric static const uptr kSpaceBeg = 0x440000000000; 101*5ffd83dbSDimitry Andric static const uptr kSpaceSize = 0x020000000000; // 2T. 102*5ffd83dbSDimitry Andric static const uptr kMetadataSize = sizeof(Metadata); 103*5ffd83dbSDimitry Andric typedef DefaultSizeClassMap SizeClassMap; 104*5ffd83dbSDimitry Andric typedef MsanMapUnmapCallback MapUnmapCallback; 105*5ffd83dbSDimitry Andric static const uptr kFlags = 0; 106*5ffd83dbSDimitry Andric using AddressSpaceView = LocalAddressSpaceView; 107*5ffd83dbSDimitry Andric }; 108*5ffd83dbSDimitry Andric 109*5ffd83dbSDimitry Andric typedef SizeClassAllocator64<AP64> PrimaryAllocator; 11068d75effSDimitry Andric #elif defined(__aarch64__) 11168d75effSDimitry Andric static const uptr kMaxAllowedMallocSize = 2UL << 30; // 2G 11268d75effSDimitry Andric 11368d75effSDimitry Andric struct AP32 { 11468d75effSDimitry Andric static const uptr kSpaceBeg = 0; 11568d75effSDimitry Andric static const u64 kSpaceSize = SANITIZER_MMAP_RANGE_SIZE; 11668d75effSDimitry Andric static const uptr kMetadataSize = sizeof(Metadata); 11768d75effSDimitry Andric typedef __sanitizer::CompactSizeClassMap SizeClassMap; 11868d75effSDimitry Andric static const uptr kRegionSizeLog = 20; 11968d75effSDimitry Andric using AddressSpaceView = LocalAddressSpaceView; 12068d75effSDimitry Andric typedef MsanMapUnmapCallback MapUnmapCallback; 12168d75effSDimitry Andric static const uptr kFlags = 0; 12268d75effSDimitry Andric }; 12368d75effSDimitry Andric typedef SizeClassAllocator32<AP32> PrimaryAllocator; 12468d75effSDimitry Andric #endif 12568d75effSDimitry Andric typedef CombinedAllocator<PrimaryAllocator> Allocator; 12668d75effSDimitry Andric typedef Allocator::AllocatorCache AllocatorCache; 12768d75effSDimitry Andric 12868d75effSDimitry Andric static Allocator allocator; 12968d75effSDimitry Andric static AllocatorCache fallback_allocator_cache; 13068d75effSDimitry Andric static StaticSpinMutex fallback_mutex; 13168d75effSDimitry Andric 132480093f4SDimitry Andric static uptr max_malloc_size; 133480093f4SDimitry Andric 13468d75effSDimitry Andric void MsanAllocatorInit() { 13568d75effSDimitry Andric SetAllocatorMayReturnNull(common_flags()->allocator_may_return_null); 13668d75effSDimitry Andric allocator.Init(common_flags()->allocator_release_to_os_interval_ms); 137480093f4SDimitry Andric if (common_flags()->max_allocation_size_mb) 138480093f4SDimitry Andric max_malloc_size = Min(common_flags()->max_allocation_size_mb << 20, 139480093f4SDimitry Andric kMaxAllowedMallocSize); 140480093f4SDimitry Andric else 141480093f4SDimitry Andric max_malloc_size = kMaxAllowedMallocSize; 14268d75effSDimitry Andric } 14368d75effSDimitry Andric 14468d75effSDimitry Andric AllocatorCache *GetAllocatorCache(MsanThreadLocalMallocStorage *ms) { 14568d75effSDimitry Andric CHECK(ms); 14668d75effSDimitry Andric CHECK_LE(sizeof(AllocatorCache), sizeof(ms->allocator_cache)); 14768d75effSDimitry Andric return reinterpret_cast<AllocatorCache *>(ms->allocator_cache); 14868d75effSDimitry Andric } 14968d75effSDimitry Andric 15068d75effSDimitry Andric void MsanThreadLocalMallocStorage::CommitBack() { 15168d75effSDimitry Andric allocator.SwallowCache(GetAllocatorCache(this)); 15268d75effSDimitry Andric } 15368d75effSDimitry Andric 15468d75effSDimitry Andric static void *MsanAllocate(StackTrace *stack, uptr size, uptr alignment, 15568d75effSDimitry Andric bool zeroise) { 156480093f4SDimitry Andric if (size > max_malloc_size) { 15768d75effSDimitry Andric if (AllocatorMayReturnNull()) { 15868d75effSDimitry Andric Report("WARNING: MemorySanitizer failed to allocate 0x%zx bytes\n", size); 15968d75effSDimitry Andric return nullptr; 16068d75effSDimitry Andric } 161480093f4SDimitry Andric ReportAllocationSizeTooBig(size, max_malloc_size, stack); 16268d75effSDimitry Andric } 16368d75effSDimitry Andric MsanThread *t = GetCurrentThread(); 16468d75effSDimitry Andric void *allocated; 16568d75effSDimitry Andric if (t) { 16668d75effSDimitry Andric AllocatorCache *cache = GetAllocatorCache(&t->malloc_storage()); 16768d75effSDimitry Andric allocated = allocator.Allocate(cache, size, alignment); 16868d75effSDimitry Andric } else { 16968d75effSDimitry Andric SpinMutexLock l(&fallback_mutex); 17068d75effSDimitry Andric AllocatorCache *cache = &fallback_allocator_cache; 17168d75effSDimitry Andric allocated = allocator.Allocate(cache, size, alignment); 17268d75effSDimitry Andric } 17368d75effSDimitry Andric if (UNLIKELY(!allocated)) { 17468d75effSDimitry Andric SetAllocatorOutOfMemory(); 17568d75effSDimitry Andric if (AllocatorMayReturnNull()) 17668d75effSDimitry Andric return nullptr; 17768d75effSDimitry Andric ReportOutOfMemory(size, stack); 17868d75effSDimitry Andric } 17968d75effSDimitry Andric Metadata *meta = 18068d75effSDimitry Andric reinterpret_cast<Metadata *>(allocator.GetMetaData(allocated)); 18168d75effSDimitry Andric meta->requested_size = size; 18268d75effSDimitry Andric if (zeroise) { 18368d75effSDimitry Andric __msan_clear_and_unpoison(allocated, size); 18468d75effSDimitry Andric } else if (flags()->poison_in_malloc) { 18568d75effSDimitry Andric __msan_poison(allocated, size); 18668d75effSDimitry Andric if (__msan_get_track_origins()) { 18768d75effSDimitry Andric stack->tag = StackTrace::TAG_ALLOC; 18868d75effSDimitry Andric Origin o = Origin::CreateHeapOrigin(stack); 18968d75effSDimitry Andric __msan_set_origin(allocated, size, o.raw_id()); 19068d75effSDimitry Andric } 19168d75effSDimitry Andric } 19268d75effSDimitry Andric MSAN_MALLOC_HOOK(allocated, size); 19368d75effSDimitry Andric return allocated; 19468d75effSDimitry Andric } 19568d75effSDimitry Andric 19668d75effSDimitry Andric void MsanDeallocate(StackTrace *stack, void *p) { 19768d75effSDimitry Andric CHECK(p); 19868d75effSDimitry Andric MSAN_FREE_HOOK(p); 19968d75effSDimitry Andric Metadata *meta = reinterpret_cast<Metadata *>(allocator.GetMetaData(p)); 20068d75effSDimitry Andric uptr size = meta->requested_size; 20168d75effSDimitry Andric meta->requested_size = 0; 20268d75effSDimitry Andric // This memory will not be reused by anyone else, so we are free to keep it 20368d75effSDimitry Andric // poisoned. 20468d75effSDimitry Andric if (flags()->poison_in_free) { 20568d75effSDimitry Andric __msan_poison(p, size); 20668d75effSDimitry Andric if (__msan_get_track_origins()) { 20768d75effSDimitry Andric stack->tag = StackTrace::TAG_DEALLOC; 20868d75effSDimitry Andric Origin o = Origin::CreateHeapOrigin(stack); 20968d75effSDimitry Andric __msan_set_origin(p, size, o.raw_id()); 21068d75effSDimitry Andric } 21168d75effSDimitry Andric } 21268d75effSDimitry Andric MsanThread *t = GetCurrentThread(); 21368d75effSDimitry Andric if (t) { 21468d75effSDimitry Andric AllocatorCache *cache = GetAllocatorCache(&t->malloc_storage()); 21568d75effSDimitry Andric allocator.Deallocate(cache, p); 21668d75effSDimitry Andric } else { 21768d75effSDimitry Andric SpinMutexLock l(&fallback_mutex); 21868d75effSDimitry Andric AllocatorCache *cache = &fallback_allocator_cache; 21968d75effSDimitry Andric allocator.Deallocate(cache, p); 22068d75effSDimitry Andric } 22168d75effSDimitry Andric } 22268d75effSDimitry Andric 22368d75effSDimitry Andric void *MsanReallocate(StackTrace *stack, void *old_p, uptr new_size, 22468d75effSDimitry Andric uptr alignment) { 22568d75effSDimitry Andric Metadata *meta = reinterpret_cast<Metadata*>(allocator.GetMetaData(old_p)); 22668d75effSDimitry Andric uptr old_size = meta->requested_size; 22768d75effSDimitry Andric uptr actually_allocated_size = allocator.GetActuallyAllocatedSize(old_p); 22868d75effSDimitry Andric if (new_size <= actually_allocated_size) { 22968d75effSDimitry Andric // We are not reallocating here. 23068d75effSDimitry Andric meta->requested_size = new_size; 23168d75effSDimitry Andric if (new_size > old_size) { 23268d75effSDimitry Andric if (flags()->poison_in_malloc) { 23368d75effSDimitry Andric stack->tag = StackTrace::TAG_ALLOC; 23468d75effSDimitry Andric PoisonMemory((char *)old_p + old_size, new_size - old_size, stack); 23568d75effSDimitry Andric } 23668d75effSDimitry Andric } 23768d75effSDimitry Andric return old_p; 23868d75effSDimitry Andric } 23968d75effSDimitry Andric uptr memcpy_size = Min(new_size, old_size); 24068d75effSDimitry Andric void *new_p = MsanAllocate(stack, new_size, alignment, false /*zeroise*/); 24168d75effSDimitry Andric if (new_p) { 24268d75effSDimitry Andric CopyMemory(new_p, old_p, memcpy_size, stack); 24368d75effSDimitry Andric MsanDeallocate(stack, old_p); 24468d75effSDimitry Andric } 24568d75effSDimitry Andric return new_p; 24668d75effSDimitry Andric } 24768d75effSDimitry Andric 24868d75effSDimitry Andric void *MsanCalloc(StackTrace *stack, uptr nmemb, uptr size) { 24968d75effSDimitry Andric if (UNLIKELY(CheckForCallocOverflow(size, nmemb))) { 25068d75effSDimitry Andric if (AllocatorMayReturnNull()) 25168d75effSDimitry Andric return nullptr; 25268d75effSDimitry Andric ReportCallocOverflow(nmemb, size, stack); 25368d75effSDimitry Andric } 25468d75effSDimitry Andric return MsanAllocate(stack, nmemb * size, sizeof(u64), true); 25568d75effSDimitry Andric } 25668d75effSDimitry Andric 25768d75effSDimitry Andric static uptr AllocationSize(const void *p) { 25868d75effSDimitry Andric if (!p) return 0; 25968d75effSDimitry Andric const void *beg = allocator.GetBlockBegin(p); 26068d75effSDimitry Andric if (beg != p) return 0; 26168d75effSDimitry Andric Metadata *b = (Metadata *)allocator.GetMetaData(p); 26268d75effSDimitry Andric return b->requested_size; 26368d75effSDimitry Andric } 26468d75effSDimitry Andric 26568d75effSDimitry Andric void *msan_malloc(uptr size, StackTrace *stack) { 26668d75effSDimitry Andric return SetErrnoOnNull(MsanAllocate(stack, size, sizeof(u64), false)); 26768d75effSDimitry Andric } 26868d75effSDimitry Andric 26968d75effSDimitry Andric void *msan_calloc(uptr nmemb, uptr size, StackTrace *stack) { 27068d75effSDimitry Andric return SetErrnoOnNull(MsanCalloc(stack, nmemb, size)); 27168d75effSDimitry Andric } 27268d75effSDimitry Andric 27368d75effSDimitry Andric void *msan_realloc(void *ptr, uptr size, StackTrace *stack) { 27468d75effSDimitry Andric if (!ptr) 27568d75effSDimitry Andric return SetErrnoOnNull(MsanAllocate(stack, size, sizeof(u64), false)); 27668d75effSDimitry Andric if (size == 0) { 27768d75effSDimitry Andric MsanDeallocate(stack, ptr); 27868d75effSDimitry Andric return nullptr; 27968d75effSDimitry Andric } 28068d75effSDimitry Andric return SetErrnoOnNull(MsanReallocate(stack, ptr, size, sizeof(u64))); 28168d75effSDimitry Andric } 28268d75effSDimitry Andric 28368d75effSDimitry Andric void *msan_reallocarray(void *ptr, uptr nmemb, uptr size, StackTrace *stack) { 28468d75effSDimitry Andric if (UNLIKELY(CheckForCallocOverflow(size, nmemb))) { 28568d75effSDimitry Andric errno = errno_ENOMEM; 28668d75effSDimitry Andric if (AllocatorMayReturnNull()) 28768d75effSDimitry Andric return nullptr; 28868d75effSDimitry Andric ReportReallocArrayOverflow(nmemb, size, stack); 28968d75effSDimitry Andric } 29068d75effSDimitry Andric return msan_realloc(ptr, nmemb * size, stack); 29168d75effSDimitry Andric } 29268d75effSDimitry Andric 29368d75effSDimitry Andric void *msan_valloc(uptr size, StackTrace *stack) { 29468d75effSDimitry Andric return SetErrnoOnNull(MsanAllocate(stack, size, GetPageSizeCached(), false)); 29568d75effSDimitry Andric } 29668d75effSDimitry Andric 29768d75effSDimitry Andric void *msan_pvalloc(uptr size, StackTrace *stack) { 29868d75effSDimitry Andric uptr PageSize = GetPageSizeCached(); 29968d75effSDimitry Andric if (UNLIKELY(CheckForPvallocOverflow(size, PageSize))) { 30068d75effSDimitry Andric errno = errno_ENOMEM; 30168d75effSDimitry Andric if (AllocatorMayReturnNull()) 30268d75effSDimitry Andric return nullptr; 30368d75effSDimitry Andric ReportPvallocOverflow(size, stack); 30468d75effSDimitry Andric } 30568d75effSDimitry Andric // pvalloc(0) should allocate one page. 30668d75effSDimitry Andric size = size ? RoundUpTo(size, PageSize) : PageSize; 30768d75effSDimitry Andric return SetErrnoOnNull(MsanAllocate(stack, size, PageSize, false)); 30868d75effSDimitry Andric } 30968d75effSDimitry Andric 31068d75effSDimitry Andric void *msan_aligned_alloc(uptr alignment, uptr size, StackTrace *stack) { 31168d75effSDimitry Andric if (UNLIKELY(!CheckAlignedAllocAlignmentAndSize(alignment, size))) { 31268d75effSDimitry Andric errno = errno_EINVAL; 31368d75effSDimitry Andric if (AllocatorMayReturnNull()) 31468d75effSDimitry Andric return nullptr; 31568d75effSDimitry Andric ReportInvalidAlignedAllocAlignment(size, alignment, stack); 31668d75effSDimitry Andric } 31768d75effSDimitry Andric return SetErrnoOnNull(MsanAllocate(stack, size, alignment, false)); 31868d75effSDimitry Andric } 31968d75effSDimitry Andric 32068d75effSDimitry Andric void *msan_memalign(uptr alignment, uptr size, StackTrace *stack) { 32168d75effSDimitry Andric if (UNLIKELY(!IsPowerOfTwo(alignment))) { 32268d75effSDimitry Andric errno = errno_EINVAL; 32368d75effSDimitry Andric if (AllocatorMayReturnNull()) 32468d75effSDimitry Andric return nullptr; 32568d75effSDimitry Andric ReportInvalidAllocationAlignment(alignment, stack); 32668d75effSDimitry Andric } 32768d75effSDimitry Andric return SetErrnoOnNull(MsanAllocate(stack, size, alignment, false)); 32868d75effSDimitry Andric } 32968d75effSDimitry Andric 33068d75effSDimitry Andric int msan_posix_memalign(void **memptr, uptr alignment, uptr size, 33168d75effSDimitry Andric StackTrace *stack) { 33268d75effSDimitry Andric if (UNLIKELY(!CheckPosixMemalignAlignment(alignment))) { 33368d75effSDimitry Andric if (AllocatorMayReturnNull()) 33468d75effSDimitry Andric return errno_EINVAL; 33568d75effSDimitry Andric ReportInvalidPosixMemalignAlignment(alignment, stack); 33668d75effSDimitry Andric } 33768d75effSDimitry Andric void *ptr = MsanAllocate(stack, size, alignment, false); 33868d75effSDimitry Andric if (UNLIKELY(!ptr)) 33968d75effSDimitry Andric // OOM error is already taken care of by MsanAllocate. 34068d75effSDimitry Andric return errno_ENOMEM; 34168d75effSDimitry Andric CHECK(IsAligned((uptr)ptr, alignment)); 34268d75effSDimitry Andric *memptr = ptr; 34368d75effSDimitry Andric return 0; 34468d75effSDimitry Andric } 34568d75effSDimitry Andric 34668d75effSDimitry Andric } // namespace __msan 34768d75effSDimitry Andric 34868d75effSDimitry Andric using namespace __msan; 34968d75effSDimitry Andric 35068d75effSDimitry Andric uptr __sanitizer_get_current_allocated_bytes() { 35168d75effSDimitry Andric uptr stats[AllocatorStatCount]; 35268d75effSDimitry Andric allocator.GetStats(stats); 35368d75effSDimitry Andric return stats[AllocatorStatAllocated]; 35468d75effSDimitry Andric } 35568d75effSDimitry Andric 35668d75effSDimitry Andric uptr __sanitizer_get_heap_size() { 35768d75effSDimitry Andric uptr stats[AllocatorStatCount]; 35868d75effSDimitry Andric allocator.GetStats(stats); 35968d75effSDimitry Andric return stats[AllocatorStatMapped]; 36068d75effSDimitry Andric } 36168d75effSDimitry Andric 36268d75effSDimitry Andric uptr __sanitizer_get_free_bytes() { return 1; } 36368d75effSDimitry Andric 36468d75effSDimitry Andric uptr __sanitizer_get_unmapped_bytes() { return 1; } 36568d75effSDimitry Andric 36668d75effSDimitry Andric uptr __sanitizer_get_estimated_allocated_size(uptr size) { return size; } 36768d75effSDimitry Andric 36868d75effSDimitry Andric int __sanitizer_get_ownership(const void *p) { return AllocationSize(p) != 0; } 36968d75effSDimitry Andric 37068d75effSDimitry Andric uptr __sanitizer_get_allocated_size(const void *p) { return AllocationSize(p); } 371