xref: /freebsd-src/contrib/llvm-project/compiler-rt/lib/msan/msan_allocator.cpp (revision 5ffd83dbcc34f10e07f6d3e968ae6365869615f4)
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