[clang][modules] Don't prevent translation of FW_Private includes when explicitly...
[llvm-project.git] / compiler-rt / lib / scudo / standalone / wrappers_c.inc
blobe213da73393b5da6fd35052c81555741514de636
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 //===----------------------------------------------------------------------===//
9 #ifndef SCUDO_PREFIX
10 #error "Define SCUDO_PREFIX prior to including this file!"
11 #endif
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
20 static void reportAllocation(void *ptr, size_t size) {
21   if (SCUDO_ENABLE_HOOKS)
22     if (__scudo_allocate_hook && ptr)
23       __scudo_allocate_hook(ptr, size);
25 static void reportDeallocation(void *ptr) {
26   if (SCUDO_ENABLE_HOOKS)
27     if (__scudo_deallocate_hook)
28       __scudo_deallocate_hook(ptr);
31 extern "C" {
33 INTERFACE WEAK void *SCUDO_PREFIX(calloc)(size_t nmemb, size_t size) {
34   scudo::uptr Product;
35   if (UNLIKELY(scudo::checkForCallocOverflow(size, nmemb, &Product))) {
36     if (SCUDO_ALLOCATOR.canReturnNull()) {
37       errno = ENOMEM;
38       return nullptr;
39     }
40     scudo::reportCallocOverflow(nmemb, size);
41   }
42   void *Ptr = SCUDO_ALLOCATOR.allocate(Product, scudo::Chunk::Origin::Malloc,
43                                        SCUDO_MALLOC_ALIGNMENT, true);
44   reportAllocation(Ptr, Product);
45   return scudo::setErrnoOnNull(Ptr);
48 INTERFACE WEAK void SCUDO_PREFIX(free)(void *ptr) {
49   reportDeallocation(ptr);
50   SCUDO_ALLOCATOR.deallocate(ptr, scudo::Chunk::Origin::Malloc);
53 INTERFACE WEAK struct SCUDO_MALLINFO SCUDO_PREFIX(mallinfo)(void) {
54   struct SCUDO_MALLINFO Info = {};
55   scudo::StatCounters Stats;
56   SCUDO_ALLOCATOR.getStats(Stats);
57   // Space allocated in mmapped regions (bytes)
58   Info.hblkhd = static_cast<__scudo_mallinfo_data_t>(Stats[scudo::StatMapped]);
59   // Maximum total allocated space (bytes)
60   Info.usmblks = Info.hblkhd;
61   // Space in freed fastbin blocks (bytes)
62   Info.fsmblks = static_cast<__scudo_mallinfo_data_t>(Stats[scudo::StatFree]);
63   // Total allocated space (bytes)
64   Info.uordblks =
65       static_cast<__scudo_mallinfo_data_t>(Stats[scudo::StatAllocated]);
66   // Total free space (bytes)
67   Info.fordblks = Info.fsmblks;
68   return Info;
71 // On Android, mallinfo2 is an alias of mallinfo, so don't define both.
72 #if !SCUDO_ANDROID
73 INTERFACE WEAK struct __scudo_mallinfo2 SCUDO_PREFIX(mallinfo2)(void) {
74   struct __scudo_mallinfo2 Info = {};
75   scudo::StatCounters Stats;
76   SCUDO_ALLOCATOR.getStats(Stats);
77   // Space allocated in mmapped regions (bytes)
78   Info.hblkhd = Stats[scudo::StatMapped];
79   // Maximum total allocated space (bytes)
80   Info.usmblks = Info.hblkhd;
81   // Space in freed fastbin blocks (bytes)
82   Info.fsmblks = Stats[scudo::StatFree];
83   // Total allocated space (bytes)
84   Info.uordblks = Stats[scudo::StatAllocated];
85   // Total free space (bytes)
86   Info.fordblks = Info.fsmblks;
87   return Info;
89 #endif
91 INTERFACE WEAK void *SCUDO_PREFIX(malloc)(size_t size) {
92   void *Ptr = SCUDO_ALLOCATOR.allocate(size, scudo::Chunk::Origin::Malloc,
93                                        SCUDO_MALLOC_ALIGNMENT);
94   reportAllocation(Ptr, size);
95   return scudo::setErrnoOnNull(Ptr);
98 #if SCUDO_ANDROID
99 INTERFACE WEAK size_t SCUDO_PREFIX(malloc_usable_size)(const void *ptr) {
100 #else
101 INTERFACE WEAK size_t SCUDO_PREFIX(malloc_usable_size)(void *ptr) {
102 #endif
103   return SCUDO_ALLOCATOR.getUsableSize(ptr);
106 INTERFACE WEAK void *SCUDO_PREFIX(memalign)(size_t alignment, size_t size) {
107   // Android rounds up the alignment to a power of two if it isn't one.
108   if (SCUDO_ANDROID) {
109     if (UNLIKELY(!alignment)) {
110       alignment = 1U;
111     } else {
112       if (UNLIKELY(!scudo::isPowerOfTwo(alignment)))
113         alignment = scudo::roundUpPowerOfTwo(alignment);
114     }
115   } else {
116     if (UNLIKELY(!scudo::isPowerOfTwo(alignment))) {
117       if (SCUDO_ALLOCATOR.canReturnNull()) {
118         errno = EINVAL;
119         return nullptr;
120       }
121       scudo::reportAlignmentNotPowerOfTwo(alignment);
122     }
123   }
124   void *Ptr =
125       SCUDO_ALLOCATOR.allocate(size, scudo::Chunk::Origin::Memalign, alignment);
126   reportAllocation(Ptr, size);
127   return Ptr;
130 INTERFACE WEAK int SCUDO_PREFIX(posix_memalign)(void **memptr, size_t alignment,
131                                                 size_t size) {
132   if (UNLIKELY(scudo::checkPosixMemalignAlignment(alignment))) {
133     if (!SCUDO_ALLOCATOR.canReturnNull())
134       scudo::reportInvalidPosixMemalignAlignment(alignment);
135     return EINVAL;
136   }
137   void *Ptr =
138       SCUDO_ALLOCATOR.allocate(size, scudo::Chunk::Origin::Memalign, alignment);
139   if (UNLIKELY(!Ptr))
140     return ENOMEM;
141   reportAllocation(Ptr, size);
143   *memptr = Ptr;
144   return 0;
147 INTERFACE WEAK void *SCUDO_PREFIX(pvalloc)(size_t size) {
148   const scudo::uptr PageSize = scudo::getPageSizeCached();
149   if (UNLIKELY(scudo::checkForPvallocOverflow(size, PageSize))) {
150     if (SCUDO_ALLOCATOR.canReturnNull()) {
151       errno = ENOMEM;
152       return nullptr;
153     }
154     scudo::reportPvallocOverflow(size);
155   }
156   // pvalloc(0) should allocate one page.
157   void *Ptr =
158       SCUDO_ALLOCATOR.allocate(size ? scudo::roundUp(size, PageSize) : PageSize,
159                                scudo::Chunk::Origin::Memalign, PageSize);
160   reportAllocation(Ptr, scudo::roundUp(size, PageSize));
162   return scudo::setErrnoOnNull(Ptr);
165 INTERFACE WEAK void *SCUDO_PREFIX(realloc)(void *ptr, size_t size) {
166   if (!ptr) {
167     void *Ptr = SCUDO_ALLOCATOR.allocate(size, scudo::Chunk::Origin::Malloc,
168                                          SCUDO_MALLOC_ALIGNMENT);
169     reportAllocation(Ptr, size);
170     return scudo::setErrnoOnNull(Ptr);
171   }
172   if (size == 0) {
173     reportDeallocation(ptr);
174     SCUDO_ALLOCATOR.deallocate(ptr, scudo::Chunk::Origin::Malloc);
175     return nullptr;
176   }
178   void *NewPtr = SCUDO_ALLOCATOR.reallocate(ptr, size, SCUDO_MALLOC_ALIGNMENT);
179   if (NewPtr != ptr) {
180     reportAllocation(NewPtr, size);
181     reportDeallocation(ptr);
182   }
184   return scudo::setErrnoOnNull(NewPtr);
187 INTERFACE WEAK void *SCUDO_PREFIX(valloc)(size_t size) {
188   void *Ptr = SCUDO_ALLOCATOR.allocate(size, scudo::Chunk::Origin::Memalign,
189                                        scudo::getPageSizeCached());
190   reportAllocation(Ptr, size);
192   return scudo::setErrnoOnNull(Ptr);
195 INTERFACE WEAK int SCUDO_PREFIX(malloc_iterate)(
196     uintptr_t base, size_t size,
197     void (*callback)(uintptr_t base, size_t size, void *arg), void *arg) {
198   SCUDO_ALLOCATOR.iterateOverChunks(base, size, callback, arg);
199   return 0;
202 INTERFACE WEAK void SCUDO_PREFIX(malloc_enable)() { SCUDO_ALLOCATOR.enable(); }
204 INTERFACE WEAK void SCUDO_PREFIX(malloc_disable)() {
205   SCUDO_ALLOCATOR.disable();
208 void SCUDO_PREFIX(malloc_postinit)() {
209   SCUDO_ALLOCATOR.initGwpAsan();
210   pthread_atfork(SCUDO_PREFIX(malloc_disable), SCUDO_PREFIX(malloc_enable),
211                  SCUDO_PREFIX(malloc_enable));
214 INTERFACE WEAK int SCUDO_PREFIX(mallopt)(int param, int value) {
215   if (param == M_DECAY_TIME) {
216     if (SCUDO_ANDROID) {
217       if (value == 0) {
218         // Will set the release values to their minimum values.
219         value = INT32_MIN;
220       } else {
221         // Will set the release values to their maximum values.
222         value = INT32_MAX;
223       }
224     }
226     SCUDO_ALLOCATOR.setOption(scudo::Option::ReleaseInterval,
227                               static_cast<scudo::sptr>(value));
228     return 1;
229   } else if (param == M_PURGE) {
230     SCUDO_ALLOCATOR.releaseToOS(scudo::ReleaseToOS::Force);
231     return 1;
232   } else if (param == M_PURGE_ALL) {
233     SCUDO_ALLOCATOR.releaseToOS(scudo::ReleaseToOS::ForceAll);
234     return 1;
235   } else if (param == M_LOG_STATS) {
236     SCUDO_ALLOCATOR.printStats();
237     SCUDO_ALLOCATOR.printFragmentationInfo();
238     return 1;
239   } else {
240     scudo::Option option;
241     switch (param) {
242     case M_MEMTAG_TUNING:
243       option = scudo::Option::MemtagTuning;
244       break;
245     case M_THREAD_DISABLE_MEM_INIT:
246       option = scudo::Option::ThreadDisableMemInit;
247       break;
248     case M_CACHE_COUNT_MAX:
249       option = scudo::Option::MaxCacheEntriesCount;
250       break;
251     case M_CACHE_SIZE_MAX:
252       option = scudo::Option::MaxCacheEntrySize;
253       break;
254     case M_TSDS_COUNT_MAX:
255       option = scudo::Option::MaxTSDsCount;
256       break;
257     default:
258       return 0;
259     }
260     return SCUDO_ALLOCATOR.setOption(option, static_cast<scudo::sptr>(value));
261   }
264 INTERFACE WEAK void *SCUDO_PREFIX(aligned_alloc)(size_t alignment,
265                                                  size_t size) {
266   if (UNLIKELY(scudo::checkAlignedAllocAlignmentAndSize(alignment, size))) {
267     if (SCUDO_ALLOCATOR.canReturnNull()) {
268       errno = EINVAL;
269       return nullptr;
270     }
271     scudo::reportInvalidAlignedAllocAlignment(alignment, size);
272   }
274   void *Ptr =
275       SCUDO_ALLOCATOR.allocate(size, scudo::Chunk::Origin::Malloc, alignment);
276   reportAllocation(Ptr, size);
278   return scudo::setErrnoOnNull(Ptr);
281 INTERFACE WEAK int SCUDO_PREFIX(malloc_info)(UNUSED int options, FILE *stream) {
282   const scudo::uptr max_size =
283       decltype(SCUDO_ALLOCATOR)::PrimaryT::SizeClassMap::MaxSize;
284   auto *sizes = static_cast<scudo::uptr *>(
285       SCUDO_PREFIX(calloc)(max_size, sizeof(scudo::uptr)));
286   auto callback = [](uintptr_t, size_t size, void *arg) {
287     auto *sizes = reinterpret_cast<scudo::uptr *>(arg);
288     if (size < max_size)
289       sizes[size]++;
290   };
292   SCUDO_ALLOCATOR.disable();
293   SCUDO_ALLOCATOR.iterateOverChunks(0, -1ul, callback, sizes);
294   SCUDO_ALLOCATOR.enable();
296   fputs("<malloc version=\"scudo-1\">\n", stream);
297   for (scudo::uptr i = 0; i != max_size; ++i)
298     if (sizes[i])
299       fprintf(stream, "<alloc size=\"%zu\" count=\"%zu\"/>\n", i, sizes[i]);
300   fputs("</malloc>\n", stream);
301   SCUDO_PREFIX(free)(sizes);
302   return 0;
305 // Disable memory tagging for the heap. The caller must disable memory tag
306 // checks globally (e.g. by clearing TCF0 on aarch64) before calling this
307 // function, and may not re-enable them after calling the function.
308 INTERFACE WEAK void SCUDO_PREFIX(malloc_disable_memory_tagging)() {
309   SCUDO_ALLOCATOR.disableMemoryTagging();
312 // Sets whether scudo records stack traces and other metadata for allocations
313 // and deallocations. This function only has an effect if the allocator and
314 // hardware support memory tagging.
315 INTERFACE WEAK void
316 SCUDO_PREFIX(malloc_set_track_allocation_stacks)(int track) {
317   SCUDO_ALLOCATOR.setTrackAllocationStacks(track);
320 // Sets whether scudo zero-initializes all allocated memory.
321 INTERFACE WEAK void SCUDO_PREFIX(malloc_set_zero_contents)(int zero_contents) {
322   SCUDO_ALLOCATOR.setFillContents(zero_contents ? scudo::ZeroFill
323                                                 : scudo::NoFill);
326 // Sets whether scudo pattern-initializes all allocated memory.
327 INTERFACE WEAK void
328 SCUDO_PREFIX(malloc_set_pattern_fill_contents)(int pattern_fill_contents) {
329   SCUDO_ALLOCATOR.setFillContents(
330       pattern_fill_contents ? scudo::PatternOrZeroFill : scudo::NoFill);
333 // Sets whether scudo adds a small amount of slack at the end of large
334 // allocations, before the guard page. This can be enabled to work around buggy
335 // applications that read a few bytes past the end of their allocation.
336 INTERFACE WEAK void
337 SCUDO_PREFIX(malloc_set_add_large_allocation_slack)(int add_slack) {
338   SCUDO_ALLOCATOR.setAddLargeAllocationSlack(add_slack);
341 } // extern "C"