1//===-- wrappers_c.inc ------------------------------------------*- C++ -*-===// 2// 3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4// See https://llvm.org/LICENSE.txt for license information. 5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6// 7//===----------------------------------------------------------------------===// 8 9#ifndef SCUDO_PREFIX 10#error "Define SCUDO_PREFIX prior to including this file!" 11#endif 12 13// malloc-type functions have to be aligned to std::max_align_t. This is 14// distinct from (1U << SCUDO_MIN_ALIGNMENT_LOG), since C++ new-type functions 15// do not have to abide by the same requirement. 16#ifndef SCUDO_MALLOC_ALIGNMENT 17#define SCUDO_MALLOC_ALIGNMENT FIRST_32_SECOND_64(8U, 16U) 18#endif 19 20INTERFACE WEAK void *SCUDO_PREFIX(calloc)(size_t nmemb, size_t size) { 21 scudo::uptr Product; 22 if (UNLIKELY(scudo::checkForCallocOverflow(size, nmemb, &Product))) { 23 if (SCUDO_ALLOCATOR.canReturnNull()) { 24 errno = ENOMEM; 25 return nullptr; 26 } 27 scudo::reportCallocOverflow(nmemb, size); 28 } 29 return scudo::setErrnoOnNull(SCUDO_ALLOCATOR.allocate( 30 Product, scudo::Chunk::Origin::Malloc, SCUDO_MALLOC_ALIGNMENT, true)); 31} 32 33INTERFACE WEAK void SCUDO_PREFIX(free)(void *ptr) { 34 SCUDO_ALLOCATOR.deallocate(ptr, scudo::Chunk::Origin::Malloc); 35} 36 37INTERFACE WEAK struct SCUDO_MALLINFO SCUDO_PREFIX(mallinfo)(void) { 38 struct SCUDO_MALLINFO Info = {}; 39 scudo::StatCounters Stats; 40 SCUDO_ALLOCATOR.getStats(Stats); 41 Info.uordblks = 42 static_cast<__scudo_mallinfo_data_t>(Stats[scudo::StatAllocated]); 43 return Info; 44} 45 46INTERFACE WEAK void *SCUDO_PREFIX(malloc)(size_t size) { 47 return scudo::setErrnoOnNull(SCUDO_ALLOCATOR.allocate( 48 size, scudo::Chunk::Origin::Malloc, SCUDO_MALLOC_ALIGNMENT)); 49} 50 51#if SCUDO_ANDROID 52INTERFACE WEAK size_t SCUDO_PREFIX(malloc_usable_size)(const void *ptr) { 53#else 54INTERFACE WEAK size_t SCUDO_PREFIX(malloc_usable_size)(void *ptr) { 55#endif 56 return SCUDO_ALLOCATOR.getUsableSize(ptr); 57} 58 59INTERFACE WEAK void *SCUDO_PREFIX(memalign)(size_t alignment, size_t size) { 60 // Android rounds up the alignment to a power of two if it isn't one. 61 if (SCUDO_ANDROID) { 62 if (UNLIKELY(!alignment)) { 63 alignment = 1U; 64 } else { 65 if (UNLIKELY(!scudo::isPowerOfTwo(alignment))) 66 alignment = scudo::roundUpToPowerOfTwo(alignment); 67 } 68 } else { 69 if (UNLIKELY(!scudo::isPowerOfTwo(alignment))) { 70 if (SCUDO_ALLOCATOR.canReturnNull()) { 71 errno = EINVAL; 72 return nullptr; 73 } 74 scudo::reportAlignmentNotPowerOfTwo(alignment); 75 } 76 } 77 return SCUDO_ALLOCATOR.allocate(size, scudo::Chunk::Origin::Memalign, 78 alignment); 79} 80 81INTERFACE WEAK int SCUDO_PREFIX(posix_memalign)(void **memptr, size_t alignment, 82 size_t size) { 83 if (UNLIKELY(scudo::checkPosixMemalignAlignment(alignment))) { 84 if (!SCUDO_ALLOCATOR.canReturnNull()) 85 scudo::reportInvalidPosixMemalignAlignment(alignment); 86 return EINVAL; 87 } 88 void *Ptr = 89 SCUDO_ALLOCATOR.allocate(size, scudo::Chunk::Origin::Memalign, alignment); 90 if (UNLIKELY(!Ptr)) 91 return ENOMEM; 92 *memptr = Ptr; 93 return 0; 94} 95 96INTERFACE WEAK void *SCUDO_PREFIX(pvalloc)(size_t size) { 97 const scudo::uptr PageSize = scudo::getPageSizeCached(); 98 if (UNLIKELY(scudo::checkForPvallocOverflow(size, PageSize))) { 99 if (SCUDO_ALLOCATOR.canReturnNull()) { 100 errno = ENOMEM; 101 return nullptr; 102 } 103 scudo::reportPvallocOverflow(size); 104 } 105 // pvalloc(0) should allocate one page. 106 return scudo::setErrnoOnNull(SCUDO_ALLOCATOR.allocate( 107 size ? scudo::roundUpTo(size, PageSize) : PageSize, 108 scudo::Chunk::Origin::Memalign, PageSize)); 109} 110 111INTERFACE WEAK void *SCUDO_PREFIX(realloc)(void *ptr, size_t size) { 112 if (!ptr) 113 return scudo::setErrnoOnNull(SCUDO_ALLOCATOR.allocate( 114 size, scudo::Chunk::Origin::Malloc, SCUDO_MALLOC_ALIGNMENT)); 115 if (size == 0) { 116 SCUDO_ALLOCATOR.deallocate(ptr, scudo::Chunk::Origin::Malloc); 117 return nullptr; 118 } 119 return scudo::setErrnoOnNull( 120 SCUDO_ALLOCATOR.reallocate(ptr, size, SCUDO_MALLOC_ALIGNMENT)); 121} 122 123INTERFACE WEAK void *SCUDO_PREFIX(valloc)(size_t size) { 124 return scudo::setErrnoOnNull(SCUDO_ALLOCATOR.allocate( 125 size, scudo::Chunk::Origin::Memalign, scudo::getPageSizeCached())); 126} 127 128// Bionic wants a function named PREFIX_iterate and not PREFIX_malloc_iterate 129// which is somewhat inconsistent with the rest, workaround that. 130#if SCUDO_ANDROID && _BIONIC 131#define SCUDO_ITERATE iterate 132#else 133#define SCUDO_ITERATE malloc_iterate 134#endif 135 136INTERFACE WEAK int SCUDO_PREFIX(SCUDO_ITERATE)( 137 uintptr_t base, size_t size, 138 void (*callback)(uintptr_t base, size_t size, void *arg), void *arg) { 139 SCUDO_ALLOCATOR.iterateOverChunks(base, size, callback, arg); 140 return 0; 141} 142 143INTERFACE WEAK void SCUDO_PREFIX(malloc_disable)() { 144 SCUDO_ALLOCATOR.disable(); 145} 146 147INTERFACE WEAK void SCUDO_PREFIX(malloc_enable)() { SCUDO_ALLOCATOR.enable(); } 148 149INTERFACE WEAK int SCUDO_PREFIX(mallopt)(int param, UNUSED int value) { 150 if (param == M_DECAY_TIME) { 151 // TODO(kostyak): set release_to_os_interval_ms accordingly. 152 return 1; 153 } else if (param == M_PURGE) { 154 SCUDO_ALLOCATOR.releaseToOS(); 155 return 1; 156 } 157 return 0; 158} 159 160INTERFACE WEAK void *SCUDO_PREFIX(aligned_alloc)(size_t alignment, 161 size_t size) { 162 if (UNLIKELY(scudo::checkAlignedAllocAlignmentAndSize(alignment, size))) { 163 if (SCUDO_ALLOCATOR.canReturnNull()) { 164 errno = EINVAL; 165 return nullptr; 166 } 167 scudo::reportInvalidAlignedAllocAlignment(alignment, size); 168 } 169 return scudo::setErrnoOnNull( 170 SCUDO_ALLOCATOR.allocate(size, scudo::Chunk::Origin::Malloc, alignment)); 171} 172 173INTERFACE WEAK int SCUDO_PREFIX(malloc_info)(int, FILE *) { 174 errno = ENOTSUP; 175 return -1; 176} 177