xref: /freebsd/contrib/llvm-project/compiler-rt/lib/scudo/standalone/wrappers_c.inc (revision 4b50c451720d8b427757a6da1dd2bb4c52cd9e35)
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