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
1406c3fb27SDimitry Andric #include "msan_allocator.h"
1506c3fb27SDimitry Andric
1606c3fb27SDimitry Andric #include "msan.h"
1706c3fb27SDimitry Andric #include "msan_interface_internal.h"
1806c3fb27SDimitry Andric #include "msan_origin.h"
1906c3fb27SDimitry Andric #include "msan_poisoning.h"
2006c3fb27SDimitry Andric #include "msan_thread.h"
2168d75effSDimitry Andric #include "sanitizer_common/sanitizer_allocator.h"
2268d75effSDimitry Andric #include "sanitizer_common/sanitizer_allocator_checks.h"
2368d75effSDimitry Andric #include "sanitizer_common/sanitizer_allocator_interface.h"
2468d75effSDimitry Andric #include "sanitizer_common/sanitizer_allocator_report.h"
2568d75effSDimitry Andric #include "sanitizer_common/sanitizer_errno.h"
2668d75effSDimitry Andric
2768d75effSDimitry Andric namespace __msan {
2868d75effSDimitry Andric
2968d75effSDimitry Andric struct Metadata {
3068d75effSDimitry Andric uptr requested_size;
3168d75effSDimitry Andric };
3268d75effSDimitry Andric
3368d75effSDimitry Andric struct MsanMapUnmapCallback {
OnMap__msan::MsanMapUnmapCallback3468d75effSDimitry Andric void OnMap(uptr p, uptr size) const {}
OnMapSecondary__msan::MsanMapUnmapCallback3506c3fb27SDimitry Andric void OnMapSecondary(uptr p, uptr size, uptr user_begin,
3606c3fb27SDimitry Andric uptr user_size) const {}
OnUnmap__msan::MsanMapUnmapCallback3768d75effSDimitry Andric void OnUnmap(uptr p, uptr size) const {
3868d75effSDimitry Andric __msan_unpoison((void *)p, size);
3968d75effSDimitry Andric
4068d75effSDimitry Andric // We are about to unmap a chunk of user memory.
4168d75effSDimitry Andric // Mark the corresponding shadow memory as not needed.
4268d75effSDimitry Andric uptr shadow_p = MEM_TO_SHADOW(p);
4368d75effSDimitry Andric ReleaseMemoryPagesToOS(shadow_p, shadow_p + size);
4468d75effSDimitry Andric if (__msan_get_track_origins()) {
4568d75effSDimitry Andric uptr origin_p = MEM_TO_ORIGIN(p);
4668d75effSDimitry Andric ReleaseMemoryPagesToOS(origin_p, origin_p + size);
4768d75effSDimitry Andric }
4868d75effSDimitry Andric }
4968d75effSDimitry Andric };
5068d75effSDimitry Andric
51439352acSDimitry Andric // Note: to ensure that the allocator is compatible with the application memory
52439352acSDimitry Andric // layout (especially with high-entropy ASLR), kSpaceBeg and kSpaceSize must be
53439352acSDimitry Andric // duplicated as MappingDesc::ALLOCATOR in msan.h.
5468d75effSDimitry Andric #if defined(__mips64)
5568d75effSDimitry Andric static const uptr kMaxAllowedMallocSize = 2UL << 30;
5668d75effSDimitry Andric
5768d75effSDimitry Andric struct AP32 {
5868d75effSDimitry Andric static const uptr kSpaceBeg = 0;
5968d75effSDimitry Andric static const u64 kSpaceSize = SANITIZER_MMAP_RANGE_SIZE;
6068d75effSDimitry Andric static const uptr kMetadataSize = sizeof(Metadata);
6168d75effSDimitry Andric typedef __sanitizer::CompactSizeClassMap SizeClassMap;
6268d75effSDimitry Andric static const uptr kRegionSizeLog = 20;
6368d75effSDimitry Andric using AddressSpaceView = LocalAddressSpaceView;
6468d75effSDimitry Andric typedef MsanMapUnmapCallback MapUnmapCallback;
6568d75effSDimitry Andric static const uptr kFlags = 0;
6668d75effSDimitry Andric };
6768d75effSDimitry Andric typedef SizeClassAllocator32<AP32> PrimaryAllocator;
6868d75effSDimitry Andric #elif defined(__x86_64__)
69bdd1243dSDimitry Andric #if SANITIZER_NETBSD || SANITIZER_LINUX
7068d75effSDimitry Andric static const uptr kAllocatorSpace = 0x700000000000ULL;
7168d75effSDimitry Andric #else
7268d75effSDimitry Andric static const uptr kAllocatorSpace = 0x600000000000ULL;
7368d75effSDimitry Andric #endif
74*0fca6ea1SDimitry Andric static const uptr kMaxAllowedMallocSize = 1ULL << 40;
7568d75effSDimitry Andric
7668d75effSDimitry Andric struct AP64 { // Allocator64 parameters. Deliberately using a short name.
7768d75effSDimitry Andric static const uptr kSpaceBeg = kAllocatorSpace;
7868d75effSDimitry Andric static const uptr kSpaceSize = 0x40000000000; // 4T.
7968d75effSDimitry Andric static const uptr kMetadataSize = sizeof(Metadata);
8068d75effSDimitry Andric typedef DefaultSizeClassMap SizeClassMap;
8168d75effSDimitry Andric typedef MsanMapUnmapCallback MapUnmapCallback;
8268d75effSDimitry Andric static const uptr kFlags = 0;
8368d75effSDimitry Andric using AddressSpaceView = LocalAddressSpaceView;
8468d75effSDimitry Andric };
8568d75effSDimitry Andric
8668d75effSDimitry Andric typedef SizeClassAllocator64<AP64> PrimaryAllocator;
8768d75effSDimitry Andric
8806c3fb27SDimitry Andric #elif defined(__loongarch_lp64)
8906c3fb27SDimitry Andric const uptr kAllocatorSpace = 0x700000000000ULL;
9006c3fb27SDimitry Andric const uptr kMaxAllowedMallocSize = 8UL << 30;
9106c3fb27SDimitry Andric
9206c3fb27SDimitry Andric struct AP64 { // Allocator64 parameters. Deliberately using a short name.
9306c3fb27SDimitry Andric static const uptr kSpaceBeg = kAllocatorSpace;
9406c3fb27SDimitry Andric static const uptr kSpaceSize = 0x40000000000; // 4T.
9506c3fb27SDimitry Andric static const uptr kMetadataSize = sizeof(Metadata);
9606c3fb27SDimitry Andric typedef DefaultSizeClassMap SizeClassMap;
9706c3fb27SDimitry Andric typedef MsanMapUnmapCallback MapUnmapCallback;
9806c3fb27SDimitry Andric static const uptr kFlags = 0;
9906c3fb27SDimitry Andric using AddressSpaceView = LocalAddressSpaceView;
10006c3fb27SDimitry Andric };
10106c3fb27SDimitry Andric
10206c3fb27SDimitry Andric typedef SizeClassAllocator64<AP64> PrimaryAllocator;
10306c3fb27SDimitry Andric
10468d75effSDimitry Andric #elif defined(__powerpc64__)
10568d75effSDimitry Andric static const uptr kMaxAllowedMallocSize = 2UL << 30; // 2G
10668d75effSDimitry Andric
10768d75effSDimitry Andric struct AP64 { // Allocator64 parameters. Deliberately using a short name.
10868d75effSDimitry Andric static const uptr kSpaceBeg = 0x300000000000;
10968d75effSDimitry Andric static const uptr kSpaceSize = 0x020000000000; // 2T.
11068d75effSDimitry Andric static const uptr kMetadataSize = sizeof(Metadata);
11168d75effSDimitry Andric typedef DefaultSizeClassMap SizeClassMap;
11268d75effSDimitry Andric typedef MsanMapUnmapCallback MapUnmapCallback;
11368d75effSDimitry Andric static const uptr kFlags = 0;
11468d75effSDimitry Andric using AddressSpaceView = LocalAddressSpaceView;
11568d75effSDimitry Andric };
11668d75effSDimitry Andric
11768d75effSDimitry Andric typedef SizeClassAllocator64<AP64> PrimaryAllocator;
1185ffd83dbSDimitry Andric #elif defined(__s390x__)
1195ffd83dbSDimitry Andric static const uptr kMaxAllowedMallocSize = 2UL << 30; // 2G
1205ffd83dbSDimitry Andric
1215ffd83dbSDimitry Andric struct AP64 { // Allocator64 parameters. Deliberately using a short name.
1225ffd83dbSDimitry Andric static const uptr kSpaceBeg = 0x440000000000;
1235ffd83dbSDimitry Andric static const uptr kSpaceSize = 0x020000000000; // 2T.
1245ffd83dbSDimitry Andric static const uptr kMetadataSize = sizeof(Metadata);
1255ffd83dbSDimitry Andric typedef DefaultSizeClassMap SizeClassMap;
1265ffd83dbSDimitry Andric typedef MsanMapUnmapCallback MapUnmapCallback;
1275ffd83dbSDimitry Andric static const uptr kFlags = 0;
1285ffd83dbSDimitry Andric using AddressSpaceView = LocalAddressSpaceView;
1295ffd83dbSDimitry Andric };
1305ffd83dbSDimitry Andric
1315ffd83dbSDimitry Andric typedef SizeClassAllocator64<AP64> PrimaryAllocator;
13268d75effSDimitry Andric #elif defined(__aarch64__)
133bdd1243dSDimitry Andric static const uptr kMaxAllowedMallocSize = 8UL << 30;
13468d75effSDimitry Andric
135bdd1243dSDimitry Andric struct AP64 {
136bdd1243dSDimitry Andric static const uptr kSpaceBeg = 0xE00000000000ULL;
137bdd1243dSDimitry Andric static const uptr kSpaceSize = 0x40000000000; // 4T.
13868d75effSDimitry Andric static const uptr kMetadataSize = sizeof(Metadata);
139bdd1243dSDimitry Andric typedef DefaultSizeClassMap SizeClassMap;
14068d75effSDimitry Andric typedef MsanMapUnmapCallback MapUnmapCallback;
14168d75effSDimitry Andric static const uptr kFlags = 0;
142bdd1243dSDimitry Andric using AddressSpaceView = LocalAddressSpaceView;
14368d75effSDimitry Andric };
144bdd1243dSDimitry Andric typedef SizeClassAllocator64<AP64> PrimaryAllocator;
14568d75effSDimitry Andric #endif
14668d75effSDimitry Andric typedef CombinedAllocator<PrimaryAllocator> Allocator;
14768d75effSDimitry Andric typedef Allocator::AllocatorCache AllocatorCache;
14868d75effSDimitry Andric
14968d75effSDimitry Andric static Allocator allocator;
15068d75effSDimitry Andric static AllocatorCache fallback_allocator_cache;
15168d75effSDimitry Andric static StaticSpinMutex fallback_mutex;
15268d75effSDimitry Andric
153480093f4SDimitry Andric static uptr max_malloc_size;
154480093f4SDimitry Andric
MsanAllocatorInit()15568d75effSDimitry Andric void MsanAllocatorInit() {
15668d75effSDimitry Andric SetAllocatorMayReturnNull(common_flags()->allocator_may_return_null);
15768d75effSDimitry Andric allocator.Init(common_flags()->allocator_release_to_os_interval_ms);
158480093f4SDimitry Andric if (common_flags()->max_allocation_size_mb)
159480093f4SDimitry Andric max_malloc_size = Min(common_flags()->max_allocation_size_mb << 20,
160480093f4SDimitry Andric kMaxAllowedMallocSize);
161480093f4SDimitry Andric else
162480093f4SDimitry Andric max_malloc_size = kMaxAllowedMallocSize;
16368d75effSDimitry Andric }
16468d75effSDimitry Andric
LockAllocator()1655f757f3fSDimitry Andric void LockAllocator() { allocator.ForceLock(); }
1665f757f3fSDimitry Andric
UnlockAllocator()1675f757f3fSDimitry Andric void UnlockAllocator() { allocator.ForceUnlock(); }
1685f757f3fSDimitry Andric
GetAllocatorCache(MsanThreadLocalMallocStorage * ms)16968d75effSDimitry Andric AllocatorCache *GetAllocatorCache(MsanThreadLocalMallocStorage *ms) {
17068d75effSDimitry Andric CHECK(ms);
17168d75effSDimitry Andric CHECK_LE(sizeof(AllocatorCache), sizeof(ms->allocator_cache));
17268d75effSDimitry Andric return reinterpret_cast<AllocatorCache *>(ms->allocator_cache);
17368d75effSDimitry Andric }
17468d75effSDimitry Andric
Init()17506c3fb27SDimitry Andric void MsanThreadLocalMallocStorage::Init() {
17606c3fb27SDimitry Andric allocator.InitCache(GetAllocatorCache(this));
17706c3fb27SDimitry Andric }
17806c3fb27SDimitry Andric
CommitBack()17968d75effSDimitry Andric void MsanThreadLocalMallocStorage::CommitBack() {
18068d75effSDimitry Andric allocator.SwallowCache(GetAllocatorCache(this));
18106c3fb27SDimitry Andric allocator.DestroyCache(GetAllocatorCache(this));
18268d75effSDimitry Andric }
18368d75effSDimitry Andric
MsanAllocate(BufferedStackTrace * stack,uptr size,uptr alignment,bool zeroise)1841db9f3b2SDimitry Andric static void *MsanAllocate(BufferedStackTrace *stack, uptr size, uptr alignment,
18568d75effSDimitry Andric bool zeroise) {
1861db9f3b2SDimitry Andric if (UNLIKELY(size > max_malloc_size)) {
18768d75effSDimitry Andric if (AllocatorMayReturnNull()) {
18868d75effSDimitry Andric Report("WARNING: MemorySanitizer failed to allocate 0x%zx bytes\n", size);
18968d75effSDimitry Andric return nullptr;
19068d75effSDimitry Andric }
1911db9f3b2SDimitry Andric GET_FATAL_STACK_TRACE_IF_EMPTY(stack);
192480093f4SDimitry Andric ReportAllocationSizeTooBig(size, max_malloc_size, stack);
19368d75effSDimitry Andric }
1940eae32dcSDimitry Andric if (UNLIKELY(IsRssLimitExceeded())) {
1950eae32dcSDimitry Andric if (AllocatorMayReturnNull())
1960eae32dcSDimitry Andric return nullptr;
1971db9f3b2SDimitry Andric GET_FATAL_STACK_TRACE_IF_EMPTY(stack);
1980eae32dcSDimitry Andric ReportRssLimitExceeded(stack);
1990eae32dcSDimitry Andric }
20068d75effSDimitry Andric MsanThread *t = GetCurrentThread();
20168d75effSDimitry Andric void *allocated;
20268d75effSDimitry Andric if (t) {
20368d75effSDimitry Andric AllocatorCache *cache = GetAllocatorCache(&t->malloc_storage());
20468d75effSDimitry Andric allocated = allocator.Allocate(cache, size, alignment);
20568d75effSDimitry Andric } else {
20668d75effSDimitry Andric SpinMutexLock l(&fallback_mutex);
20768d75effSDimitry Andric AllocatorCache *cache = &fallback_allocator_cache;
20868d75effSDimitry Andric allocated = allocator.Allocate(cache, size, alignment);
20968d75effSDimitry Andric }
21068d75effSDimitry Andric if (UNLIKELY(!allocated)) {
21168d75effSDimitry Andric SetAllocatorOutOfMemory();
21268d75effSDimitry Andric if (AllocatorMayReturnNull())
21368d75effSDimitry Andric return nullptr;
2141db9f3b2SDimitry Andric GET_FATAL_STACK_TRACE_IF_EMPTY(stack);
21568d75effSDimitry Andric ReportOutOfMemory(size, stack);
21668d75effSDimitry Andric }
21768d75effSDimitry Andric Metadata *meta =
21868d75effSDimitry Andric reinterpret_cast<Metadata *>(allocator.GetMetaData(allocated));
21968d75effSDimitry Andric meta->requested_size = size;
22068d75effSDimitry Andric if (zeroise) {
22106c3fb27SDimitry Andric if (allocator.FromPrimary(allocated))
22268d75effSDimitry Andric __msan_clear_and_unpoison(allocated, size);
22306c3fb27SDimitry Andric else
22406c3fb27SDimitry Andric __msan_unpoison(allocated, size); // Mem is already zeroed.
22568d75effSDimitry Andric } else if (flags()->poison_in_malloc) {
22668d75effSDimitry Andric __msan_poison(allocated, size);
22768d75effSDimitry Andric if (__msan_get_track_origins()) {
22868d75effSDimitry Andric stack->tag = StackTrace::TAG_ALLOC;
22968d75effSDimitry Andric Origin o = Origin::CreateHeapOrigin(stack);
23068d75effSDimitry Andric __msan_set_origin(allocated, size, o.raw_id());
23168d75effSDimitry Andric }
23268d75effSDimitry Andric }
23381ad6265SDimitry Andric UnpoisonParam(2);
23481ad6265SDimitry Andric RunMallocHooks(allocated, size);
23568d75effSDimitry Andric return allocated;
23668d75effSDimitry Andric }
23768d75effSDimitry Andric
MsanDeallocate(BufferedStackTrace * stack,void * p)2381db9f3b2SDimitry Andric void MsanDeallocate(BufferedStackTrace *stack, void *p) {
23968d75effSDimitry Andric CHECK(p);
24081ad6265SDimitry Andric UnpoisonParam(1);
24181ad6265SDimitry Andric RunFreeHooks(p);
24281ad6265SDimitry Andric
24368d75effSDimitry Andric Metadata *meta = reinterpret_cast<Metadata *>(allocator.GetMetaData(p));
24468d75effSDimitry Andric uptr size = meta->requested_size;
24568d75effSDimitry Andric meta->requested_size = 0;
24668d75effSDimitry Andric // This memory will not be reused by anyone else, so we are free to keep it
24706c3fb27SDimitry Andric // poisoned. The secondary allocator will unmap and unpoison by
24806c3fb27SDimitry Andric // MsanMapUnmapCallback, no need to poison it here.
24906c3fb27SDimitry Andric if (flags()->poison_in_free && allocator.FromPrimary(p)) {
25068d75effSDimitry Andric __msan_poison(p, size);
25168d75effSDimitry Andric if (__msan_get_track_origins()) {
25268d75effSDimitry Andric stack->tag = StackTrace::TAG_DEALLOC;
25368d75effSDimitry Andric Origin o = Origin::CreateHeapOrigin(stack);
25468d75effSDimitry Andric __msan_set_origin(p, size, o.raw_id());
25568d75effSDimitry Andric }
25668d75effSDimitry Andric }
25768d75effSDimitry Andric MsanThread *t = GetCurrentThread();
25868d75effSDimitry Andric if (t) {
25968d75effSDimitry Andric AllocatorCache *cache = GetAllocatorCache(&t->malloc_storage());
26068d75effSDimitry Andric allocator.Deallocate(cache, p);
26168d75effSDimitry Andric } else {
26268d75effSDimitry Andric SpinMutexLock l(&fallback_mutex);
26368d75effSDimitry Andric AllocatorCache *cache = &fallback_allocator_cache;
26468d75effSDimitry Andric allocator.Deallocate(cache, p);
26568d75effSDimitry Andric }
26668d75effSDimitry Andric }
26768d75effSDimitry Andric
MsanReallocate(BufferedStackTrace * stack,void * old_p,uptr new_size,uptr alignment)2681db9f3b2SDimitry Andric static void *MsanReallocate(BufferedStackTrace *stack, void *old_p,
2691db9f3b2SDimitry Andric uptr new_size, uptr alignment) {
27068d75effSDimitry Andric Metadata *meta = reinterpret_cast<Metadata*>(allocator.GetMetaData(old_p));
27168d75effSDimitry Andric uptr old_size = meta->requested_size;
27268d75effSDimitry Andric uptr actually_allocated_size = allocator.GetActuallyAllocatedSize(old_p);
27368d75effSDimitry Andric if (new_size <= actually_allocated_size) {
27468d75effSDimitry Andric // We are not reallocating here.
27568d75effSDimitry Andric meta->requested_size = new_size;
27668d75effSDimitry Andric if (new_size > old_size) {
27768d75effSDimitry Andric if (flags()->poison_in_malloc) {
27868d75effSDimitry Andric stack->tag = StackTrace::TAG_ALLOC;
27968d75effSDimitry Andric PoisonMemory((char *)old_p + old_size, new_size - old_size, stack);
28068d75effSDimitry Andric }
28168d75effSDimitry Andric }
28268d75effSDimitry Andric return old_p;
28368d75effSDimitry Andric }
28468d75effSDimitry Andric uptr memcpy_size = Min(new_size, old_size);
28568d75effSDimitry Andric void *new_p = MsanAllocate(stack, new_size, alignment, false /*zeroise*/);
28668d75effSDimitry Andric if (new_p) {
28768d75effSDimitry Andric CopyMemory(new_p, old_p, memcpy_size, stack);
28868d75effSDimitry Andric MsanDeallocate(stack, old_p);
28968d75effSDimitry Andric }
29068d75effSDimitry Andric return new_p;
29168d75effSDimitry Andric }
29268d75effSDimitry Andric
MsanCalloc(BufferedStackTrace * stack,uptr nmemb,uptr size)2931db9f3b2SDimitry Andric static void *MsanCalloc(BufferedStackTrace *stack, uptr nmemb, uptr size) {
29468d75effSDimitry Andric if (UNLIKELY(CheckForCallocOverflow(size, nmemb))) {
29568d75effSDimitry Andric if (AllocatorMayReturnNull())
29668d75effSDimitry Andric return nullptr;
2971db9f3b2SDimitry Andric GET_FATAL_STACK_TRACE_IF_EMPTY(stack);
29868d75effSDimitry Andric ReportCallocOverflow(nmemb, size, stack);
29968d75effSDimitry Andric }
30068d75effSDimitry Andric return MsanAllocate(stack, nmemb * size, sizeof(u64), true);
30168d75effSDimitry Andric }
30268d75effSDimitry Andric
AllocationBegin(const void * p)30306c3fb27SDimitry Andric static const void *AllocationBegin(const void *p) {
30406c3fb27SDimitry Andric if (!p)
30506c3fb27SDimitry Andric return nullptr;
30606c3fb27SDimitry Andric void *beg = allocator.GetBlockBegin(p);
30706c3fb27SDimitry Andric if (!beg)
30806c3fb27SDimitry Andric return nullptr;
30906c3fb27SDimitry Andric Metadata *b = (Metadata *)allocator.GetMetaData(beg);
31006c3fb27SDimitry Andric if (!b)
31106c3fb27SDimitry Andric return nullptr;
31206c3fb27SDimitry Andric if (b->requested_size == 0)
31306c3fb27SDimitry Andric return nullptr;
31406c3fb27SDimitry Andric
31506c3fb27SDimitry Andric return (const void *)beg;
31606c3fb27SDimitry Andric }
31706c3fb27SDimitry Andric
AllocationSize(const void * p)31868d75effSDimitry Andric static uptr AllocationSize(const void *p) {
31968d75effSDimitry Andric if (!p) return 0;
32068d75effSDimitry Andric const void *beg = allocator.GetBlockBegin(p);
32168d75effSDimitry Andric if (beg != p) return 0;
32268d75effSDimitry Andric Metadata *b = (Metadata *)allocator.GetMetaData(p);
32368d75effSDimitry Andric return b->requested_size;
32468d75effSDimitry Andric }
32568d75effSDimitry Andric
AllocationSizeFast(const void * p)32606c3fb27SDimitry Andric static uptr AllocationSizeFast(const void *p) {
32706c3fb27SDimitry Andric return reinterpret_cast<Metadata *>(allocator.GetMetaData(p))->requested_size;
32806c3fb27SDimitry Andric }
32906c3fb27SDimitry Andric
msan_malloc(uptr size,BufferedStackTrace * stack)3301db9f3b2SDimitry Andric void *msan_malloc(uptr size, BufferedStackTrace *stack) {
33168d75effSDimitry Andric return SetErrnoOnNull(MsanAllocate(stack, size, sizeof(u64), false));
33268d75effSDimitry Andric }
33368d75effSDimitry Andric
msan_calloc(uptr nmemb,uptr size,BufferedStackTrace * stack)3341db9f3b2SDimitry Andric void *msan_calloc(uptr nmemb, uptr size, BufferedStackTrace *stack) {
33568d75effSDimitry Andric return SetErrnoOnNull(MsanCalloc(stack, nmemb, size));
33668d75effSDimitry Andric }
33768d75effSDimitry Andric
msan_realloc(void * ptr,uptr size,BufferedStackTrace * stack)3381db9f3b2SDimitry Andric void *msan_realloc(void *ptr, uptr size, BufferedStackTrace *stack) {
33968d75effSDimitry Andric if (!ptr)
34068d75effSDimitry Andric return SetErrnoOnNull(MsanAllocate(stack, size, sizeof(u64), false));
34168d75effSDimitry Andric if (size == 0) {
34268d75effSDimitry Andric MsanDeallocate(stack, ptr);
34368d75effSDimitry Andric return nullptr;
34468d75effSDimitry Andric }
34568d75effSDimitry Andric return SetErrnoOnNull(MsanReallocate(stack, ptr, size, sizeof(u64)));
34668d75effSDimitry Andric }
34768d75effSDimitry Andric
msan_reallocarray(void * ptr,uptr nmemb,uptr size,BufferedStackTrace * stack)3481db9f3b2SDimitry Andric void *msan_reallocarray(void *ptr, uptr nmemb, uptr size,
3491db9f3b2SDimitry Andric BufferedStackTrace *stack) {
35068d75effSDimitry Andric if (UNLIKELY(CheckForCallocOverflow(size, nmemb))) {
35168d75effSDimitry Andric errno = errno_ENOMEM;
35268d75effSDimitry Andric if (AllocatorMayReturnNull())
35368d75effSDimitry Andric return nullptr;
3541db9f3b2SDimitry Andric GET_FATAL_STACK_TRACE_IF_EMPTY(stack);
35568d75effSDimitry Andric ReportReallocArrayOverflow(nmemb, size, stack);
35668d75effSDimitry Andric }
35768d75effSDimitry Andric return msan_realloc(ptr, nmemb * size, stack);
35868d75effSDimitry Andric }
35968d75effSDimitry Andric
msan_valloc(uptr size,BufferedStackTrace * stack)3601db9f3b2SDimitry Andric void *msan_valloc(uptr size, BufferedStackTrace *stack) {
36168d75effSDimitry Andric return SetErrnoOnNull(MsanAllocate(stack, size, GetPageSizeCached(), false));
36268d75effSDimitry Andric }
36368d75effSDimitry Andric
msan_pvalloc(uptr size,BufferedStackTrace * stack)3641db9f3b2SDimitry Andric void *msan_pvalloc(uptr size, BufferedStackTrace *stack) {
36568d75effSDimitry Andric uptr PageSize = GetPageSizeCached();
36668d75effSDimitry Andric if (UNLIKELY(CheckForPvallocOverflow(size, PageSize))) {
36768d75effSDimitry Andric errno = errno_ENOMEM;
36868d75effSDimitry Andric if (AllocatorMayReturnNull())
36968d75effSDimitry Andric return nullptr;
3701db9f3b2SDimitry Andric GET_FATAL_STACK_TRACE_IF_EMPTY(stack);
37168d75effSDimitry Andric ReportPvallocOverflow(size, stack);
37268d75effSDimitry Andric }
37368d75effSDimitry Andric // pvalloc(0) should allocate one page.
37468d75effSDimitry Andric size = size ? RoundUpTo(size, PageSize) : PageSize;
37568d75effSDimitry Andric return SetErrnoOnNull(MsanAllocate(stack, size, PageSize, false));
37668d75effSDimitry Andric }
37768d75effSDimitry Andric
msan_aligned_alloc(uptr alignment,uptr size,BufferedStackTrace * stack)3781db9f3b2SDimitry Andric void *msan_aligned_alloc(uptr alignment, uptr size, BufferedStackTrace *stack) {
37968d75effSDimitry Andric if (UNLIKELY(!CheckAlignedAllocAlignmentAndSize(alignment, size))) {
38068d75effSDimitry Andric errno = errno_EINVAL;
38168d75effSDimitry Andric if (AllocatorMayReturnNull())
38268d75effSDimitry Andric return nullptr;
3831db9f3b2SDimitry Andric GET_FATAL_STACK_TRACE_IF_EMPTY(stack);
38468d75effSDimitry Andric ReportInvalidAlignedAllocAlignment(size, alignment, stack);
38568d75effSDimitry Andric }
38668d75effSDimitry Andric return SetErrnoOnNull(MsanAllocate(stack, size, alignment, false));
38768d75effSDimitry Andric }
38868d75effSDimitry Andric
msan_memalign(uptr alignment,uptr size,BufferedStackTrace * stack)3891db9f3b2SDimitry Andric void *msan_memalign(uptr alignment, uptr size, BufferedStackTrace *stack) {
39068d75effSDimitry Andric if (UNLIKELY(!IsPowerOfTwo(alignment))) {
39168d75effSDimitry Andric errno = errno_EINVAL;
39268d75effSDimitry Andric if (AllocatorMayReturnNull())
39368d75effSDimitry Andric return nullptr;
3941db9f3b2SDimitry Andric GET_FATAL_STACK_TRACE_IF_EMPTY(stack);
39568d75effSDimitry Andric ReportInvalidAllocationAlignment(alignment, stack);
39668d75effSDimitry Andric }
39768d75effSDimitry Andric return SetErrnoOnNull(MsanAllocate(stack, size, alignment, false));
39868d75effSDimitry Andric }
39968d75effSDimitry Andric
msan_posix_memalign(void ** memptr,uptr alignment,uptr size,BufferedStackTrace * stack)40068d75effSDimitry Andric int msan_posix_memalign(void **memptr, uptr alignment, uptr size,
4011db9f3b2SDimitry Andric BufferedStackTrace *stack) {
40268d75effSDimitry Andric if (UNLIKELY(!CheckPosixMemalignAlignment(alignment))) {
40368d75effSDimitry Andric if (AllocatorMayReturnNull())
40468d75effSDimitry Andric return errno_EINVAL;
4051db9f3b2SDimitry Andric GET_FATAL_STACK_TRACE_IF_EMPTY(stack);
40668d75effSDimitry Andric ReportInvalidPosixMemalignAlignment(alignment, stack);
40768d75effSDimitry Andric }
40868d75effSDimitry Andric void *ptr = MsanAllocate(stack, size, alignment, false);
40968d75effSDimitry Andric if (UNLIKELY(!ptr))
41068d75effSDimitry Andric // OOM error is already taken care of by MsanAllocate.
41168d75effSDimitry Andric return errno_ENOMEM;
41268d75effSDimitry Andric CHECK(IsAligned((uptr)ptr, alignment));
41368d75effSDimitry Andric *memptr = ptr;
41468d75effSDimitry Andric return 0;
41568d75effSDimitry Andric }
41668d75effSDimitry Andric
41768d75effSDimitry Andric } // namespace __msan
41868d75effSDimitry Andric
41968d75effSDimitry Andric using namespace __msan;
42068d75effSDimitry Andric
__sanitizer_get_current_allocated_bytes()42168d75effSDimitry Andric uptr __sanitizer_get_current_allocated_bytes() {
42268d75effSDimitry Andric uptr stats[AllocatorStatCount];
42368d75effSDimitry Andric allocator.GetStats(stats);
42468d75effSDimitry Andric return stats[AllocatorStatAllocated];
42568d75effSDimitry Andric }
42668d75effSDimitry Andric
__sanitizer_get_heap_size()42768d75effSDimitry Andric uptr __sanitizer_get_heap_size() {
42868d75effSDimitry Andric uptr stats[AllocatorStatCount];
42968d75effSDimitry Andric allocator.GetStats(stats);
43068d75effSDimitry Andric return stats[AllocatorStatMapped];
43168d75effSDimitry Andric }
43268d75effSDimitry Andric
__sanitizer_get_free_bytes()43368d75effSDimitry Andric uptr __sanitizer_get_free_bytes() { return 1; }
43468d75effSDimitry Andric
__sanitizer_get_unmapped_bytes()43568d75effSDimitry Andric uptr __sanitizer_get_unmapped_bytes() { return 1; }
43668d75effSDimitry Andric
__sanitizer_get_estimated_allocated_size(uptr size)43768d75effSDimitry Andric uptr __sanitizer_get_estimated_allocated_size(uptr size) { return size; }
43868d75effSDimitry Andric
__sanitizer_get_ownership(const void * p)43968d75effSDimitry Andric int __sanitizer_get_ownership(const void *p) { return AllocationSize(p) != 0; }
44068d75effSDimitry Andric
__sanitizer_get_allocated_begin(const void * p)44106c3fb27SDimitry Andric const void *__sanitizer_get_allocated_begin(const void *p) {
44206c3fb27SDimitry Andric return AllocationBegin(p);
44306c3fb27SDimitry Andric }
44406c3fb27SDimitry Andric
__sanitizer_get_allocated_size(const void * p)44568d75effSDimitry Andric uptr __sanitizer_get_allocated_size(const void *p) { return AllocationSize(p); }
44606c3fb27SDimitry Andric
__sanitizer_get_allocated_size_fast(const void * p)44706c3fb27SDimitry Andric uptr __sanitizer_get_allocated_size_fast(const void *p) {
44806c3fb27SDimitry Andric DCHECK_EQ(p, __sanitizer_get_allocated_begin(p));
44906c3fb27SDimitry Andric uptr ret = AllocationSizeFast(p);
45006c3fb27SDimitry Andric DCHECK_EQ(ret, __sanitizer_get_allocated_size(p));
45106c3fb27SDimitry Andric return ret;
45206c3fb27SDimitry Andric }
45306c3fb27SDimitry Andric
__sanitizer_purge_allocator()45406c3fb27SDimitry Andric void __sanitizer_purge_allocator() { allocator.ForceReleaseToOS(); }
455