xref: /aosp_15_r20/external/scudo/standalone/wrappers_c.inc (revision 76559068c068bd27e82aff38fac3bfc865233bca)
1*76559068SAndroid Build Coastguard Worker//===-- wrappers_c.inc ------------------------------------------*- C++ -*-===//
2*76559068SAndroid Build Coastguard Worker//
3*76559068SAndroid Build Coastguard Worker// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*76559068SAndroid Build Coastguard Worker// See https://llvm.org/LICENSE.txt for license information.
5*76559068SAndroid Build Coastguard Worker// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*76559068SAndroid Build Coastguard Worker//
7*76559068SAndroid Build Coastguard Worker//===----------------------------------------------------------------------===//
8*76559068SAndroid Build Coastguard Worker
9*76559068SAndroid Build Coastguard Worker#ifndef SCUDO_PREFIX
10*76559068SAndroid Build Coastguard Worker#error "Define SCUDO_PREFIX prior to including this file!"
11*76559068SAndroid Build Coastguard Worker#endif
12*76559068SAndroid Build Coastguard Worker
13*76559068SAndroid Build Coastguard Worker// malloc-type functions have to be aligned to std::max_align_t. This is
14*76559068SAndroid Build Coastguard Worker// distinct from (1U << SCUDO_MIN_ALIGNMENT_LOG), since C++ new-type functions
15*76559068SAndroid Build Coastguard Worker// do not have to abide by the same requirement.
16*76559068SAndroid Build Coastguard Worker#ifndef SCUDO_MALLOC_ALIGNMENT
17*76559068SAndroid Build Coastguard Worker#define SCUDO_MALLOC_ALIGNMENT FIRST_32_SECOND_64(8U, 16U)
18*76559068SAndroid Build Coastguard Worker#endif
19*76559068SAndroid Build Coastguard Worker
20*76559068SAndroid Build Coastguard Workerstatic void reportAllocation(void *ptr, size_t size) {
21*76559068SAndroid Build Coastguard Worker  if (SCUDO_ENABLE_HOOKS)
22*76559068SAndroid Build Coastguard Worker    if (__scudo_allocate_hook && ptr)
23*76559068SAndroid Build Coastguard Worker      __scudo_allocate_hook(ptr, size);
24*76559068SAndroid Build Coastguard Worker}
25*76559068SAndroid Build Coastguard Workerstatic void reportDeallocation(void *ptr) {
26*76559068SAndroid Build Coastguard Worker  if (SCUDO_ENABLE_HOOKS)
27*76559068SAndroid Build Coastguard Worker    if (__scudo_deallocate_hook)
28*76559068SAndroid Build Coastguard Worker      __scudo_deallocate_hook(ptr);
29*76559068SAndroid Build Coastguard Worker}
30*76559068SAndroid Build Coastguard Workerstatic void reportReallocAllocation(void *old_ptr, void *new_ptr, size_t size) {
31*76559068SAndroid Build Coastguard Worker  DCHECK_NE(new_ptr, nullptr);
32*76559068SAndroid Build Coastguard Worker
33*76559068SAndroid Build Coastguard Worker  if (SCUDO_ENABLE_HOOKS) {
34*76559068SAndroid Build Coastguard Worker    if (__scudo_realloc_allocate_hook)
35*76559068SAndroid Build Coastguard Worker      __scudo_realloc_allocate_hook(old_ptr, new_ptr, size);
36*76559068SAndroid Build Coastguard Worker    else if (__scudo_allocate_hook)
37*76559068SAndroid Build Coastguard Worker      __scudo_allocate_hook(new_ptr, size);
38*76559068SAndroid Build Coastguard Worker  }
39*76559068SAndroid Build Coastguard Worker}
40*76559068SAndroid Build Coastguard Workerstatic void reportReallocDeallocation(void *old_ptr) {
41*76559068SAndroid Build Coastguard Worker  if (SCUDO_ENABLE_HOOKS) {
42*76559068SAndroid Build Coastguard Worker    if (__scudo_realloc_deallocate_hook)
43*76559068SAndroid Build Coastguard Worker      __scudo_realloc_deallocate_hook(old_ptr);
44*76559068SAndroid Build Coastguard Worker    else if (__scudo_deallocate_hook)
45*76559068SAndroid Build Coastguard Worker      __scudo_deallocate_hook(old_ptr);
46*76559068SAndroid Build Coastguard Worker  }
47*76559068SAndroid Build Coastguard Worker}
48*76559068SAndroid Build Coastguard Worker
49*76559068SAndroid Build Coastguard Workerextern "C" {
50*76559068SAndroid Build Coastguard Worker
51*76559068SAndroid Build Coastguard WorkerINTERFACE WEAK void *SCUDO_PREFIX(calloc)(size_t nmemb, size_t size) {
52*76559068SAndroid Build Coastguard Worker  scudo::uptr Product;
53*76559068SAndroid Build Coastguard Worker  if (UNLIKELY(scudo::checkForCallocOverflow(size, nmemb, &Product))) {
54*76559068SAndroid Build Coastguard Worker    if (SCUDO_ALLOCATOR.canReturnNull()) {
55*76559068SAndroid Build Coastguard Worker      errno = ENOMEM;
56*76559068SAndroid Build Coastguard Worker      return nullptr;
57*76559068SAndroid Build Coastguard Worker    }
58*76559068SAndroid Build Coastguard Worker    scudo::reportCallocOverflow(nmemb, size);
59*76559068SAndroid Build Coastguard Worker  }
60*76559068SAndroid Build Coastguard Worker  void *Ptr = SCUDO_ALLOCATOR.allocate(Product, scudo::Chunk::Origin::Malloc,
61*76559068SAndroid Build Coastguard Worker                                       SCUDO_MALLOC_ALIGNMENT, true);
62*76559068SAndroid Build Coastguard Worker  reportAllocation(Ptr, Product);
63*76559068SAndroid Build Coastguard Worker  return scudo::setErrnoOnNull(Ptr);
64*76559068SAndroid Build Coastguard Worker}
65*76559068SAndroid Build Coastguard Worker
66*76559068SAndroid Build Coastguard WorkerINTERFACE WEAK void SCUDO_PREFIX(free)(void *ptr) {
67*76559068SAndroid Build Coastguard Worker  reportDeallocation(ptr);
68*76559068SAndroid Build Coastguard Worker  SCUDO_ALLOCATOR.deallocate(ptr, scudo::Chunk::Origin::Malloc);
69*76559068SAndroid Build Coastguard Worker}
70*76559068SAndroid Build Coastguard Worker
71*76559068SAndroid Build Coastguard WorkerINTERFACE WEAK struct SCUDO_MALLINFO SCUDO_PREFIX(mallinfo)(void) {
72*76559068SAndroid Build Coastguard Worker  struct SCUDO_MALLINFO Info = {};
73*76559068SAndroid Build Coastguard Worker  scudo::StatCounters Stats;
74*76559068SAndroid Build Coastguard Worker  SCUDO_ALLOCATOR.getStats(Stats);
75*76559068SAndroid Build Coastguard Worker  // Space allocated in mmapped regions (bytes)
76*76559068SAndroid Build Coastguard Worker  Info.hblkhd = static_cast<__scudo_mallinfo_data_t>(Stats[scudo::StatMapped]);
77*76559068SAndroid Build Coastguard Worker  // Maximum total allocated space (bytes)
78*76559068SAndroid Build Coastguard Worker  Info.usmblks = Info.hblkhd;
79*76559068SAndroid Build Coastguard Worker  // Space in freed fastbin blocks (bytes)
80*76559068SAndroid Build Coastguard Worker  Info.fsmblks = static_cast<__scudo_mallinfo_data_t>(Stats[scudo::StatFree]);
81*76559068SAndroid Build Coastguard Worker  // Total allocated space (bytes)
82*76559068SAndroid Build Coastguard Worker  Info.uordblks =
83*76559068SAndroid Build Coastguard Worker      static_cast<__scudo_mallinfo_data_t>(Stats[scudo::StatAllocated]);
84*76559068SAndroid Build Coastguard Worker  // Total free space (bytes)
85*76559068SAndroid Build Coastguard Worker  Info.fordblks = Info.fsmblks;
86*76559068SAndroid Build Coastguard Worker  return Info;
87*76559068SAndroid Build Coastguard Worker}
88*76559068SAndroid Build Coastguard Worker
89*76559068SAndroid Build Coastguard Worker// On Android, mallinfo2 is an alias of mallinfo, so don't define both.
90*76559068SAndroid Build Coastguard Worker#if !SCUDO_ANDROID
91*76559068SAndroid Build Coastguard WorkerINTERFACE WEAK struct __scudo_mallinfo2 SCUDO_PREFIX(mallinfo2)(void) {
92*76559068SAndroid Build Coastguard Worker  struct __scudo_mallinfo2 Info = {};
93*76559068SAndroid Build Coastguard Worker  scudo::StatCounters Stats;
94*76559068SAndroid Build Coastguard Worker  SCUDO_ALLOCATOR.getStats(Stats);
95*76559068SAndroid Build Coastguard Worker  // Space allocated in mmapped regions (bytes)
96*76559068SAndroid Build Coastguard Worker  Info.hblkhd = Stats[scudo::StatMapped];
97*76559068SAndroid Build Coastguard Worker  // Maximum total allocated space (bytes)
98*76559068SAndroid Build Coastguard Worker  Info.usmblks = Info.hblkhd;
99*76559068SAndroid Build Coastguard Worker  // Space in freed fastbin blocks (bytes)
100*76559068SAndroid Build Coastguard Worker  Info.fsmblks = Stats[scudo::StatFree];
101*76559068SAndroid Build Coastguard Worker  // Total allocated space (bytes)
102*76559068SAndroid Build Coastguard Worker  Info.uordblks = Stats[scudo::StatAllocated];
103*76559068SAndroid Build Coastguard Worker  // Total free space (bytes)
104*76559068SAndroid Build Coastguard Worker  Info.fordblks = Info.fsmblks;
105*76559068SAndroid Build Coastguard Worker  return Info;
106*76559068SAndroid Build Coastguard Worker}
107*76559068SAndroid Build Coastguard Worker#endif
108*76559068SAndroid Build Coastguard Worker
109*76559068SAndroid Build Coastguard WorkerINTERFACE WEAK void *SCUDO_PREFIX(malloc)(size_t size) {
110*76559068SAndroid Build Coastguard Worker  void *Ptr = SCUDO_ALLOCATOR.allocate(size, scudo::Chunk::Origin::Malloc,
111*76559068SAndroid Build Coastguard Worker                                       SCUDO_MALLOC_ALIGNMENT);
112*76559068SAndroid Build Coastguard Worker  reportAllocation(Ptr, size);
113*76559068SAndroid Build Coastguard Worker  return scudo::setErrnoOnNull(Ptr);
114*76559068SAndroid Build Coastguard Worker}
115*76559068SAndroid Build Coastguard Worker
116*76559068SAndroid Build Coastguard Worker#if SCUDO_ANDROID
117*76559068SAndroid Build Coastguard WorkerINTERFACE WEAK size_t SCUDO_PREFIX(malloc_usable_size)(const void *ptr) {
118*76559068SAndroid Build Coastguard Worker#else
119*76559068SAndroid Build Coastguard WorkerINTERFACE WEAK size_t SCUDO_PREFIX(malloc_usable_size)(void *ptr) {
120*76559068SAndroid Build Coastguard Worker#endif
121*76559068SAndroid Build Coastguard Worker  return SCUDO_ALLOCATOR.getUsableSize(ptr);
122*76559068SAndroid Build Coastguard Worker}
123*76559068SAndroid Build Coastguard Worker
124*76559068SAndroid Build Coastguard WorkerINTERFACE WEAK void *SCUDO_PREFIX(memalign)(size_t alignment, size_t size) {
125*76559068SAndroid Build Coastguard Worker  // Android rounds up the alignment to a power of two if it isn't one.
126*76559068SAndroid Build Coastguard Worker  if (SCUDO_ANDROID) {
127*76559068SAndroid Build Coastguard Worker    if (UNLIKELY(!alignment)) {
128*76559068SAndroid Build Coastguard Worker      alignment = 1U;
129*76559068SAndroid Build Coastguard Worker    } else {
130*76559068SAndroid Build Coastguard Worker      if (UNLIKELY(!scudo::isPowerOfTwo(alignment)))
131*76559068SAndroid Build Coastguard Worker        alignment = scudo::roundUpPowerOfTwo(alignment);
132*76559068SAndroid Build Coastguard Worker    }
133*76559068SAndroid Build Coastguard Worker  } else {
134*76559068SAndroid Build Coastguard Worker    if (UNLIKELY(!scudo::isPowerOfTwo(alignment))) {
135*76559068SAndroid Build Coastguard Worker      if (SCUDO_ALLOCATOR.canReturnNull()) {
136*76559068SAndroid Build Coastguard Worker        errno = EINVAL;
137*76559068SAndroid Build Coastguard Worker        return nullptr;
138*76559068SAndroid Build Coastguard Worker      }
139*76559068SAndroid Build Coastguard Worker      scudo::reportAlignmentNotPowerOfTwo(alignment);
140*76559068SAndroid Build Coastguard Worker    }
141*76559068SAndroid Build Coastguard Worker  }
142*76559068SAndroid Build Coastguard Worker  void *Ptr =
143*76559068SAndroid Build Coastguard Worker      SCUDO_ALLOCATOR.allocate(size, scudo::Chunk::Origin::Memalign, alignment);
144*76559068SAndroid Build Coastguard Worker  reportAllocation(Ptr, size);
145*76559068SAndroid Build Coastguard Worker  return Ptr;
146*76559068SAndroid Build Coastguard Worker}
147*76559068SAndroid Build Coastguard Worker
148*76559068SAndroid Build Coastguard WorkerINTERFACE WEAK int SCUDO_PREFIX(posix_memalign)(void **memptr, size_t alignment,
149*76559068SAndroid Build Coastguard Worker                                                size_t size) {
150*76559068SAndroid Build Coastguard Worker  if (UNLIKELY(scudo::checkPosixMemalignAlignment(alignment))) {
151*76559068SAndroid Build Coastguard Worker    if (!SCUDO_ALLOCATOR.canReturnNull())
152*76559068SAndroid Build Coastguard Worker      scudo::reportInvalidPosixMemalignAlignment(alignment);
153*76559068SAndroid Build Coastguard Worker    return EINVAL;
154*76559068SAndroid Build Coastguard Worker  }
155*76559068SAndroid Build Coastguard Worker  void *Ptr =
156*76559068SAndroid Build Coastguard Worker      SCUDO_ALLOCATOR.allocate(size, scudo::Chunk::Origin::Memalign, alignment);
157*76559068SAndroid Build Coastguard Worker  if (UNLIKELY(!Ptr))
158*76559068SAndroid Build Coastguard Worker    return ENOMEM;
159*76559068SAndroid Build Coastguard Worker  reportAllocation(Ptr, size);
160*76559068SAndroid Build Coastguard Worker
161*76559068SAndroid Build Coastguard Worker  *memptr = Ptr;
162*76559068SAndroid Build Coastguard Worker  return 0;
163*76559068SAndroid Build Coastguard Worker}
164*76559068SAndroid Build Coastguard Worker
165*76559068SAndroid Build Coastguard WorkerINTERFACE WEAK void *SCUDO_PREFIX(pvalloc)(size_t size) {
166*76559068SAndroid Build Coastguard Worker  const scudo::uptr PageSize = scudo::getPageSizeCached();
167*76559068SAndroid Build Coastguard Worker  if (UNLIKELY(scudo::checkForPvallocOverflow(size, PageSize))) {
168*76559068SAndroid Build Coastguard Worker    if (SCUDO_ALLOCATOR.canReturnNull()) {
169*76559068SAndroid Build Coastguard Worker      errno = ENOMEM;
170*76559068SAndroid Build Coastguard Worker      return nullptr;
171*76559068SAndroid Build Coastguard Worker    }
172*76559068SAndroid Build Coastguard Worker    scudo::reportPvallocOverflow(size);
173*76559068SAndroid Build Coastguard Worker  }
174*76559068SAndroid Build Coastguard Worker  // pvalloc(0) should allocate one page.
175*76559068SAndroid Build Coastguard Worker  void *Ptr =
176*76559068SAndroid Build Coastguard Worker      SCUDO_ALLOCATOR.allocate(size ? scudo::roundUp(size, PageSize) : PageSize,
177*76559068SAndroid Build Coastguard Worker                               scudo::Chunk::Origin::Memalign, PageSize);
178*76559068SAndroid Build Coastguard Worker  reportAllocation(Ptr, scudo::roundUp(size, PageSize));
179*76559068SAndroid Build Coastguard Worker
180*76559068SAndroid Build Coastguard Worker  return scudo::setErrnoOnNull(Ptr);
181*76559068SAndroid Build Coastguard Worker}
182*76559068SAndroid Build Coastguard Worker
183*76559068SAndroid Build Coastguard WorkerINTERFACE WEAK void *SCUDO_PREFIX(realloc)(void *ptr, size_t size) {
184*76559068SAndroid Build Coastguard Worker  if (!ptr) {
185*76559068SAndroid Build Coastguard Worker    void *Ptr = SCUDO_ALLOCATOR.allocate(size, scudo::Chunk::Origin::Malloc,
186*76559068SAndroid Build Coastguard Worker                                         SCUDO_MALLOC_ALIGNMENT);
187*76559068SAndroid Build Coastguard Worker    reportAllocation(Ptr, size);
188*76559068SAndroid Build Coastguard Worker    return scudo::setErrnoOnNull(Ptr);
189*76559068SAndroid Build Coastguard Worker  }
190*76559068SAndroid Build Coastguard Worker  if (size == 0) {
191*76559068SAndroid Build Coastguard Worker    reportDeallocation(ptr);
192*76559068SAndroid Build Coastguard Worker    SCUDO_ALLOCATOR.deallocate(ptr, scudo::Chunk::Origin::Malloc);
193*76559068SAndroid Build Coastguard Worker    return nullptr;
194*76559068SAndroid Build Coastguard Worker  }
195*76559068SAndroid Build Coastguard Worker
196*76559068SAndroid Build Coastguard Worker  // Given that the reporting of deallocation and allocation are not atomic, we
197*76559068SAndroid Build Coastguard Worker  // always pretend the old pointer will be released so that the user doesn't
198*76559068SAndroid Build Coastguard Worker  // need to worry about the false double-use case from the view of hooks.
199*76559068SAndroid Build Coastguard Worker  //
200*76559068SAndroid Build Coastguard Worker  // For example, assume that `realloc` releases the old pointer and allocates a
201*76559068SAndroid Build Coastguard Worker  // new pointer. Before the reporting of both operations has been done, another
202*76559068SAndroid Build Coastguard Worker  // thread may get the old pointer from `malloc`. It may be misinterpreted as
203*76559068SAndroid Build Coastguard Worker  // double-use if it's not handled properly on the hook side.
204*76559068SAndroid Build Coastguard Worker  reportReallocDeallocation(ptr);
205*76559068SAndroid Build Coastguard Worker  void *NewPtr = SCUDO_ALLOCATOR.reallocate(ptr, size, SCUDO_MALLOC_ALIGNMENT);
206*76559068SAndroid Build Coastguard Worker  if (NewPtr != nullptr) {
207*76559068SAndroid Build Coastguard Worker    // Note that even if NewPtr == ptr, the size has changed. We still need to
208*76559068SAndroid Build Coastguard Worker    // report the new size.
209*76559068SAndroid Build Coastguard Worker    reportReallocAllocation(/*OldPtr=*/ptr, NewPtr, size);
210*76559068SAndroid Build Coastguard Worker  } else {
211*76559068SAndroid Build Coastguard Worker    // If `realloc` fails, the old pointer is not released. Report the old
212*76559068SAndroid Build Coastguard Worker    // pointer as allocated again.
213*76559068SAndroid Build Coastguard Worker    reportReallocAllocation(/*OldPtr=*/ptr, /*NewPtr=*/ptr,
214*76559068SAndroid Build Coastguard Worker                            SCUDO_ALLOCATOR.getAllocSize(ptr));
215*76559068SAndroid Build Coastguard Worker  }
216*76559068SAndroid Build Coastguard Worker
217*76559068SAndroid Build Coastguard Worker  return scudo::setErrnoOnNull(NewPtr);
218*76559068SAndroid Build Coastguard Worker}
219*76559068SAndroid Build Coastguard Worker
220*76559068SAndroid Build Coastguard WorkerINTERFACE WEAK void *SCUDO_PREFIX(valloc)(size_t size) {
221*76559068SAndroid Build Coastguard Worker  void *Ptr = SCUDO_ALLOCATOR.allocate(size, scudo::Chunk::Origin::Memalign,
222*76559068SAndroid Build Coastguard Worker                                       scudo::getPageSizeCached());
223*76559068SAndroid Build Coastguard Worker  reportAllocation(Ptr, size);
224*76559068SAndroid Build Coastguard Worker
225*76559068SAndroid Build Coastguard Worker  return scudo::setErrnoOnNull(Ptr);
226*76559068SAndroid Build Coastguard Worker}
227*76559068SAndroid Build Coastguard Worker
228*76559068SAndroid Build Coastguard WorkerINTERFACE WEAK int SCUDO_PREFIX(malloc_iterate)(
229*76559068SAndroid Build Coastguard Worker    uintptr_t base, size_t size,
230*76559068SAndroid Build Coastguard Worker    void (*callback)(uintptr_t base, size_t size, void *arg), void *arg) {
231*76559068SAndroid Build Coastguard Worker  SCUDO_ALLOCATOR.iterateOverChunks(base, size, callback, arg);
232*76559068SAndroid Build Coastguard Worker  return 0;
233*76559068SAndroid Build Coastguard Worker}
234*76559068SAndroid Build Coastguard Worker
235*76559068SAndroid Build Coastguard WorkerINTERFACE WEAK void SCUDO_PREFIX(malloc_enable)() { SCUDO_ALLOCATOR.enable(); }
236*76559068SAndroid Build Coastguard Worker
237*76559068SAndroid Build Coastguard WorkerINTERFACE WEAK void SCUDO_PREFIX(malloc_disable)() {
238*76559068SAndroid Build Coastguard Worker  SCUDO_ALLOCATOR.disable();
239*76559068SAndroid Build Coastguard Worker}
240*76559068SAndroid Build Coastguard Worker
241*76559068SAndroid Build Coastguard Workervoid SCUDO_PREFIX(malloc_postinit)() {
242*76559068SAndroid Build Coastguard Worker  SCUDO_ALLOCATOR.initGwpAsan();
243*76559068SAndroid Build Coastguard Worker  pthread_atfork(SCUDO_PREFIX(malloc_disable), SCUDO_PREFIX(malloc_enable),
244*76559068SAndroid Build Coastguard Worker                 SCUDO_PREFIX(malloc_enable));
245*76559068SAndroid Build Coastguard Worker}
246*76559068SAndroid Build Coastguard Worker
247*76559068SAndroid Build Coastguard WorkerINTERFACE WEAK int SCUDO_PREFIX(mallopt)(int param, int value) {
248*76559068SAndroid Build Coastguard Worker  if (param == M_DECAY_TIME) {
249*76559068SAndroid Build Coastguard Worker    if (SCUDO_ANDROID) {
250*76559068SAndroid Build Coastguard Worker      // Before changing the interval, reset the memory usage status by doing a
251*76559068SAndroid Build Coastguard Worker      // M_PURGE call so that we can minimize the impact of any unreleased pages
252*76559068SAndroid Build Coastguard Worker      // introduced by interval transition.
253*76559068SAndroid Build Coastguard Worker      SCUDO_ALLOCATOR.releaseToOS(scudo::ReleaseToOS::Force);
254*76559068SAndroid Build Coastguard Worker
255*76559068SAndroid Build Coastguard Worker      // The values allowed on Android are {-1, 0, 1}. "1" means the longest
256*76559068SAndroid Build Coastguard Worker      // interval.
257*76559068SAndroid Build Coastguard Worker      CHECK(value >= -1 && value <= 1);
258*76559068SAndroid Build Coastguard Worker      if (value == 1)
259*76559068SAndroid Build Coastguard Worker        value = INT32_MAX;
260*76559068SAndroid Build Coastguard Worker    }
261*76559068SAndroid Build Coastguard Worker
262*76559068SAndroid Build Coastguard Worker    SCUDO_ALLOCATOR.setOption(scudo::Option::ReleaseInterval,
263*76559068SAndroid Build Coastguard Worker                              static_cast<scudo::sptr>(value));
264*76559068SAndroid Build Coastguard Worker    return 1;
265*76559068SAndroid Build Coastguard Worker  } else if (param == M_PURGE) {
266*76559068SAndroid Build Coastguard Worker    SCUDO_ALLOCATOR.releaseToOS(scudo::ReleaseToOS::Force);
267*76559068SAndroid Build Coastguard Worker    return 1;
268*76559068SAndroid Build Coastguard Worker  } else if (param == M_PURGE_ALL) {
269*76559068SAndroid Build Coastguard Worker    SCUDO_ALLOCATOR.releaseToOS(scudo::ReleaseToOS::ForceAll);
270*76559068SAndroid Build Coastguard Worker    return 1;
271*76559068SAndroid Build Coastguard Worker  } else if (param == M_LOG_STATS) {
272*76559068SAndroid Build Coastguard Worker    SCUDO_ALLOCATOR.printStats();
273*76559068SAndroid Build Coastguard Worker    SCUDO_ALLOCATOR.printFragmentationInfo();
274*76559068SAndroid Build Coastguard Worker    return 1;
275*76559068SAndroid Build Coastguard Worker  } else {
276*76559068SAndroid Build Coastguard Worker    scudo::Option option;
277*76559068SAndroid Build Coastguard Worker    switch (param) {
278*76559068SAndroid Build Coastguard Worker    case M_MEMTAG_TUNING:
279*76559068SAndroid Build Coastguard Worker      option = scudo::Option::MemtagTuning;
280*76559068SAndroid Build Coastguard Worker      break;
281*76559068SAndroid Build Coastguard Worker    case M_THREAD_DISABLE_MEM_INIT:
282*76559068SAndroid Build Coastguard Worker      option = scudo::Option::ThreadDisableMemInit;
283*76559068SAndroid Build Coastguard Worker      break;
284*76559068SAndroid Build Coastguard Worker    case M_CACHE_COUNT_MAX:
285*76559068SAndroid Build Coastguard Worker      option = scudo::Option::MaxCacheEntriesCount;
286*76559068SAndroid Build Coastguard Worker      break;
287*76559068SAndroid Build Coastguard Worker    case M_CACHE_SIZE_MAX:
288*76559068SAndroid Build Coastguard Worker      option = scudo::Option::MaxCacheEntrySize;
289*76559068SAndroid Build Coastguard Worker      break;
290*76559068SAndroid Build Coastguard Worker    case M_TSDS_COUNT_MAX:
291*76559068SAndroid Build Coastguard Worker      option = scudo::Option::MaxTSDsCount;
292*76559068SAndroid Build Coastguard Worker      break;
293*76559068SAndroid Build Coastguard Worker    default:
294*76559068SAndroid Build Coastguard Worker      return 0;
295*76559068SAndroid Build Coastguard Worker    }
296*76559068SAndroid Build Coastguard Worker    return SCUDO_ALLOCATOR.setOption(option, static_cast<scudo::sptr>(value));
297*76559068SAndroid Build Coastguard Worker  }
298*76559068SAndroid Build Coastguard Worker}
299*76559068SAndroid Build Coastguard Worker
300*76559068SAndroid Build Coastguard WorkerINTERFACE WEAK void *SCUDO_PREFIX(aligned_alloc)(size_t alignment,
301*76559068SAndroid Build Coastguard Worker                                                 size_t size) {
302*76559068SAndroid Build Coastguard Worker  if (UNLIKELY(scudo::checkAlignedAllocAlignmentAndSize(alignment, size))) {
303*76559068SAndroid Build Coastguard Worker    if (SCUDO_ALLOCATOR.canReturnNull()) {
304*76559068SAndroid Build Coastguard Worker      errno = EINVAL;
305*76559068SAndroid Build Coastguard Worker      return nullptr;
306*76559068SAndroid Build Coastguard Worker    }
307*76559068SAndroid Build Coastguard Worker    scudo::reportInvalidAlignedAllocAlignment(alignment, size);
308*76559068SAndroid Build Coastguard Worker  }
309*76559068SAndroid Build Coastguard Worker
310*76559068SAndroid Build Coastguard Worker  void *Ptr =
311*76559068SAndroid Build Coastguard Worker      SCUDO_ALLOCATOR.allocate(size, scudo::Chunk::Origin::Malloc, alignment);
312*76559068SAndroid Build Coastguard Worker  reportAllocation(Ptr, size);
313*76559068SAndroid Build Coastguard Worker
314*76559068SAndroid Build Coastguard Worker  return scudo::setErrnoOnNull(Ptr);
315*76559068SAndroid Build Coastguard Worker}
316*76559068SAndroid Build Coastguard Worker
317*76559068SAndroid Build Coastguard WorkerINTERFACE WEAK int SCUDO_PREFIX(malloc_info)(UNUSED int options, FILE *stream) {
318*76559068SAndroid Build Coastguard Worker  const scudo::uptr max_size =
319*76559068SAndroid Build Coastguard Worker      decltype(SCUDO_ALLOCATOR)::PrimaryT::SizeClassMap::MaxSize;
320*76559068SAndroid Build Coastguard Worker  auto *sizes = static_cast<scudo::uptr *>(
321*76559068SAndroid Build Coastguard Worker      SCUDO_PREFIX(calloc)(max_size, sizeof(scudo::uptr)));
322*76559068SAndroid Build Coastguard Worker  auto callback = [](uintptr_t, size_t size, void *arg) {
323*76559068SAndroid Build Coastguard Worker    auto *sizes = reinterpret_cast<scudo::uptr *>(arg);
324*76559068SAndroid Build Coastguard Worker    if (size < max_size)
325*76559068SAndroid Build Coastguard Worker      sizes[size]++;
326*76559068SAndroid Build Coastguard Worker  };
327*76559068SAndroid Build Coastguard Worker
328*76559068SAndroid Build Coastguard Worker  SCUDO_ALLOCATOR.disable();
329*76559068SAndroid Build Coastguard Worker  SCUDO_ALLOCATOR.iterateOverChunks(0, -1ul, callback, sizes);
330*76559068SAndroid Build Coastguard Worker  SCUDO_ALLOCATOR.enable();
331*76559068SAndroid Build Coastguard Worker
332*76559068SAndroid Build Coastguard Worker  fputs("<malloc version=\"scudo-1\">\n", stream);
333*76559068SAndroid Build Coastguard Worker  for (scudo::uptr i = 0; i != max_size; ++i)
334*76559068SAndroid Build Coastguard Worker    if (sizes[i])
335*76559068SAndroid Build Coastguard Worker      fprintf(stream, "<alloc size=\"%zu\" count=\"%zu\"/>\n", i, sizes[i]);
336*76559068SAndroid Build Coastguard Worker  fputs("</malloc>\n", stream);
337*76559068SAndroid Build Coastguard Worker  SCUDO_PREFIX(free)(sizes);
338*76559068SAndroid Build Coastguard Worker  return 0;
339*76559068SAndroid Build Coastguard Worker}
340*76559068SAndroid Build Coastguard Worker
341*76559068SAndroid Build Coastguard Worker// Disable memory tagging for the heap. The caller must disable memory tag
342*76559068SAndroid Build Coastguard Worker// checks globally (e.g. by clearing TCF0 on aarch64) before calling this
343*76559068SAndroid Build Coastguard Worker// function, and may not re-enable them after calling the function.
344*76559068SAndroid Build Coastguard WorkerINTERFACE WEAK void SCUDO_PREFIX(malloc_disable_memory_tagging)() {
345*76559068SAndroid Build Coastguard Worker  SCUDO_ALLOCATOR.disableMemoryTagging();
346*76559068SAndroid Build Coastguard Worker}
347*76559068SAndroid Build Coastguard Worker
348*76559068SAndroid Build Coastguard Worker// Sets whether scudo records stack traces and other metadata for allocations
349*76559068SAndroid Build Coastguard Worker// and deallocations. This function only has an effect if the allocator and
350*76559068SAndroid Build Coastguard Worker// hardware support memory tagging.
351*76559068SAndroid Build Coastguard WorkerINTERFACE WEAK void
352*76559068SAndroid Build Coastguard WorkerSCUDO_PREFIX(malloc_set_track_allocation_stacks)(int track) {
353*76559068SAndroid Build Coastguard Worker  SCUDO_ALLOCATOR.setTrackAllocationStacks(track);
354*76559068SAndroid Build Coastguard Worker}
355*76559068SAndroid Build Coastguard Worker
356*76559068SAndroid Build Coastguard Worker// Sets whether scudo zero-initializes all allocated memory.
357*76559068SAndroid Build Coastguard WorkerINTERFACE WEAK void SCUDO_PREFIX(malloc_set_zero_contents)(int zero_contents) {
358*76559068SAndroid Build Coastguard Worker  SCUDO_ALLOCATOR.setFillContents(zero_contents ? scudo::ZeroFill
359*76559068SAndroid Build Coastguard Worker                                                : scudo::NoFill);
360*76559068SAndroid Build Coastguard Worker}
361*76559068SAndroid Build Coastguard Worker
362*76559068SAndroid Build Coastguard Worker// Sets whether scudo pattern-initializes all allocated memory.
363*76559068SAndroid Build Coastguard WorkerINTERFACE WEAK void
364*76559068SAndroid Build Coastguard WorkerSCUDO_PREFIX(malloc_set_pattern_fill_contents)(int pattern_fill_contents) {
365*76559068SAndroid Build Coastguard Worker  SCUDO_ALLOCATOR.setFillContents(
366*76559068SAndroid Build Coastguard Worker      pattern_fill_contents ? scudo::PatternOrZeroFill : scudo::NoFill);
367*76559068SAndroid Build Coastguard Worker}
368*76559068SAndroid Build Coastguard Worker
369*76559068SAndroid Build Coastguard Worker// Sets whether scudo adds a small amount of slack at the end of large
370*76559068SAndroid Build Coastguard Worker// allocations, before the guard page. This can be enabled to work around buggy
371*76559068SAndroid Build Coastguard Worker// applications that read a few bytes past the end of their allocation.
372*76559068SAndroid Build Coastguard WorkerINTERFACE WEAK void
373*76559068SAndroid Build Coastguard WorkerSCUDO_PREFIX(malloc_set_add_large_allocation_slack)(int add_slack) {
374*76559068SAndroid Build Coastguard Worker  SCUDO_ALLOCATOR.setAddLargeAllocationSlack(add_slack);
375*76559068SAndroid Build Coastguard Worker}
376*76559068SAndroid Build Coastguard Worker
377*76559068SAndroid Build Coastguard Worker} // extern "C"
378