wrappers_c.inc 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  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. #ifndef SCUDO_PREFIX
  9. #error "Define SCUDO_PREFIX prior to including this file!"
  10. #endif
  11. // malloc-type functions have to be aligned to std::max_align_t. This is
  12. // distinct from (1U << SCUDO_MIN_ALIGNMENT_LOG), since C++ new-type functions
  13. // do not have to abide by the same requirement.
  14. #ifndef SCUDO_MALLOC_ALIGNMENT
  15. #define SCUDO_MALLOC_ALIGNMENT FIRST_32_SECOND_64(8U, 16U)
  16. #endif
  17. extern "C" {
  18. INTERFACE WEAK void *SCUDO_PREFIX(calloc)(size_t nmemb, size_t size) {
  19. scudo::uptr Product;
  20. if (UNLIKELY(scudo::checkForCallocOverflow(size, nmemb, &Product))) {
  21. if (SCUDO_ALLOCATOR.canReturnNull()) {
  22. errno = ENOMEM;
  23. return nullptr;
  24. }
  25. scudo::reportCallocOverflow(nmemb, size);
  26. }
  27. return scudo::setErrnoOnNull(SCUDO_ALLOCATOR.allocate(
  28. Product, scudo::Chunk::Origin::Malloc, SCUDO_MALLOC_ALIGNMENT, true));
  29. }
  30. INTERFACE WEAK void SCUDO_PREFIX(free)(void *ptr) {
  31. SCUDO_ALLOCATOR.deallocate(ptr, scudo::Chunk::Origin::Malloc);
  32. }
  33. INTERFACE WEAK struct SCUDO_MALLINFO SCUDO_PREFIX(mallinfo)(void) {
  34. struct SCUDO_MALLINFO Info = {};
  35. scudo::StatCounters Stats;
  36. SCUDO_ALLOCATOR.getStats(Stats);
  37. // Space allocated in mmapped regions (bytes)
  38. Info.hblkhd = static_cast<__scudo_mallinfo_data_t>(Stats[scudo::StatMapped]);
  39. // Maximum total allocated space (bytes)
  40. Info.usmblks = Info.hblkhd;
  41. // Space in freed fastbin blocks (bytes)
  42. Info.fsmblks = static_cast<__scudo_mallinfo_data_t>(Stats[scudo::StatFree]);
  43. // Total allocated space (bytes)
  44. Info.uordblks =
  45. static_cast<__scudo_mallinfo_data_t>(Stats[scudo::StatAllocated]);
  46. // Total free space (bytes)
  47. Info.fordblks = Info.fsmblks;
  48. return Info;
  49. }
  50. INTERFACE WEAK struct __scudo_mallinfo2 SCUDO_PREFIX(mallinfo2)(void) {
  51. struct __scudo_mallinfo2 Info = {};
  52. scudo::StatCounters Stats;
  53. SCUDO_ALLOCATOR.getStats(Stats);
  54. // Space allocated in mmapped regions (bytes)
  55. Info.hblkhd = Stats[scudo::StatMapped];
  56. // Maximum total allocated space (bytes)
  57. Info.usmblks = Info.hblkhd;
  58. // Space in freed fastbin blocks (bytes)
  59. Info.fsmblks = Stats[scudo::StatFree];
  60. // Total allocated space (bytes)
  61. Info.uordblks = Stats[scudo::StatAllocated];
  62. // Total free space (bytes)
  63. Info.fordblks = Info.fsmblks;
  64. return Info;
  65. }
  66. INTERFACE WEAK void *SCUDO_PREFIX(malloc)(size_t size) {
  67. return scudo::setErrnoOnNull(SCUDO_ALLOCATOR.allocate(
  68. size, scudo::Chunk::Origin::Malloc, SCUDO_MALLOC_ALIGNMENT));
  69. }
  70. #if SCUDO_ANDROID
  71. INTERFACE WEAK size_t SCUDO_PREFIX(malloc_usable_size)(const void *ptr) {
  72. #else
  73. INTERFACE WEAK size_t SCUDO_PREFIX(malloc_usable_size)(void *ptr) {
  74. #endif
  75. return SCUDO_ALLOCATOR.getUsableSize(ptr);
  76. }
  77. INTERFACE WEAK void *SCUDO_PREFIX(memalign)(size_t alignment, size_t size) {
  78. // Android rounds up the alignment to a power of two if it isn't one.
  79. if (SCUDO_ANDROID) {
  80. if (UNLIKELY(!alignment)) {
  81. alignment = 1U;
  82. } else {
  83. if (UNLIKELY(!scudo::isPowerOfTwo(alignment)))
  84. alignment = scudo::roundUpToPowerOfTwo(alignment);
  85. }
  86. } else {
  87. if (UNLIKELY(!scudo::isPowerOfTwo(alignment))) {
  88. if (SCUDO_ALLOCATOR.canReturnNull()) {
  89. errno = EINVAL;
  90. return nullptr;
  91. }
  92. scudo::reportAlignmentNotPowerOfTwo(alignment);
  93. }
  94. }
  95. return SCUDO_ALLOCATOR.allocate(size, scudo::Chunk::Origin::Memalign,
  96. alignment);
  97. }
  98. INTERFACE WEAK int SCUDO_PREFIX(posix_memalign)(void **memptr, size_t alignment,
  99. size_t size) {
  100. if (UNLIKELY(scudo::checkPosixMemalignAlignment(alignment))) {
  101. if (!SCUDO_ALLOCATOR.canReturnNull())
  102. scudo::reportInvalidPosixMemalignAlignment(alignment);
  103. return EINVAL;
  104. }
  105. void *Ptr =
  106. SCUDO_ALLOCATOR.allocate(size, scudo::Chunk::Origin::Memalign, alignment);
  107. if (UNLIKELY(!Ptr))
  108. return ENOMEM;
  109. *memptr = Ptr;
  110. return 0;
  111. }
  112. INTERFACE WEAK void *SCUDO_PREFIX(pvalloc)(size_t size) {
  113. const scudo::uptr PageSize = scudo::getPageSizeCached();
  114. if (UNLIKELY(scudo::checkForPvallocOverflow(size, PageSize))) {
  115. if (SCUDO_ALLOCATOR.canReturnNull()) {
  116. errno = ENOMEM;
  117. return nullptr;
  118. }
  119. scudo::reportPvallocOverflow(size);
  120. }
  121. // pvalloc(0) should allocate one page.
  122. return scudo::setErrnoOnNull(SCUDO_ALLOCATOR.allocate(
  123. size ? scudo::roundUpTo(size, PageSize) : PageSize,
  124. scudo::Chunk::Origin::Memalign, PageSize));
  125. }
  126. INTERFACE WEAK void *SCUDO_PREFIX(realloc)(void *ptr, size_t size) {
  127. if (!ptr)
  128. return scudo::setErrnoOnNull(SCUDO_ALLOCATOR.allocate(
  129. size, scudo::Chunk::Origin::Malloc, SCUDO_MALLOC_ALIGNMENT));
  130. if (size == 0) {
  131. SCUDO_ALLOCATOR.deallocate(ptr, scudo::Chunk::Origin::Malloc);
  132. return nullptr;
  133. }
  134. return scudo::setErrnoOnNull(
  135. SCUDO_ALLOCATOR.reallocate(ptr, size, SCUDO_MALLOC_ALIGNMENT));
  136. }
  137. INTERFACE WEAK void *SCUDO_PREFIX(valloc)(size_t size) {
  138. return scudo::setErrnoOnNull(SCUDO_ALLOCATOR.allocate(
  139. size, scudo::Chunk::Origin::Memalign, scudo::getPageSizeCached()));
  140. }
  141. INTERFACE WEAK int SCUDO_PREFIX(malloc_iterate)(
  142. uintptr_t base, size_t size,
  143. void (*callback)(uintptr_t base, size_t size, void *arg), void *arg) {
  144. SCUDO_ALLOCATOR.iterateOverChunks(base, size, callback, arg);
  145. return 0;
  146. }
  147. INTERFACE WEAK void SCUDO_PREFIX(malloc_enable)() { SCUDO_ALLOCATOR.enable(); }
  148. INTERFACE WEAK void SCUDO_PREFIX(malloc_disable)() {
  149. SCUDO_ALLOCATOR.disable();
  150. }
  151. void SCUDO_PREFIX(malloc_postinit)() {
  152. SCUDO_ALLOCATOR.initGwpAsan();
  153. pthread_atfork(SCUDO_PREFIX(malloc_disable), SCUDO_PREFIX(malloc_enable),
  154. SCUDO_PREFIX(malloc_enable));
  155. }
  156. INTERFACE WEAK int SCUDO_PREFIX(mallopt)(int param, int value) {
  157. if (param == M_DECAY_TIME) {
  158. if (SCUDO_ANDROID) {
  159. if (value == 0) {
  160. // Will set the release values to their minimum values.
  161. value = INT32_MIN;
  162. } else {
  163. // Will set the release values to their maximum values.
  164. value = INT32_MAX;
  165. }
  166. }
  167. SCUDO_ALLOCATOR.setOption(scudo::Option::ReleaseInterval,
  168. static_cast<scudo::sptr>(value));
  169. return 1;
  170. } else if (param == M_PURGE) {
  171. SCUDO_ALLOCATOR.releaseToOS();
  172. return 1;
  173. } else {
  174. scudo::Option option;
  175. switch (param) {
  176. case M_MEMTAG_TUNING:
  177. option = scudo::Option::MemtagTuning;
  178. break;
  179. case M_THREAD_DISABLE_MEM_INIT:
  180. option = scudo::Option::ThreadDisableMemInit;
  181. break;
  182. case M_CACHE_COUNT_MAX:
  183. option = scudo::Option::MaxCacheEntriesCount;
  184. break;
  185. case M_CACHE_SIZE_MAX:
  186. option = scudo::Option::MaxCacheEntrySize;
  187. break;
  188. case M_TSDS_COUNT_MAX:
  189. option = scudo::Option::MaxTSDsCount;
  190. break;
  191. default:
  192. return 0;
  193. }
  194. return SCUDO_ALLOCATOR.setOption(option, static_cast<scudo::sptr>(value));
  195. }
  196. }
  197. INTERFACE WEAK void *SCUDO_PREFIX(aligned_alloc)(size_t alignment,
  198. size_t size) {
  199. if (UNLIKELY(scudo::checkAlignedAllocAlignmentAndSize(alignment, size))) {
  200. if (SCUDO_ALLOCATOR.canReturnNull()) {
  201. errno = EINVAL;
  202. return nullptr;
  203. }
  204. scudo::reportInvalidAlignedAllocAlignment(alignment, size);
  205. }
  206. return scudo::setErrnoOnNull(
  207. SCUDO_ALLOCATOR.allocate(size, scudo::Chunk::Origin::Malloc, alignment));
  208. }
  209. INTERFACE WEAK int SCUDO_PREFIX(malloc_info)(UNUSED int options, FILE *stream) {
  210. const scudo::uptr max_size =
  211. decltype(SCUDO_ALLOCATOR)::PrimaryT::SizeClassMap::MaxSize;
  212. auto *sizes = static_cast<scudo::uptr *>(
  213. SCUDO_PREFIX(calloc)(max_size, sizeof(scudo::uptr)));
  214. auto callback = [](uintptr_t, size_t size, void *arg) {
  215. auto *sizes = reinterpret_cast<scudo::uptr *>(arg);
  216. if (size < max_size)
  217. sizes[size]++;
  218. };
  219. SCUDO_ALLOCATOR.iterateOverChunks(0, -1ul, callback, sizes);
  220. fputs("<malloc version=\"scudo-1\">\n", stream);
  221. for (scudo::uptr i = 0; i != max_size; ++i)
  222. if (sizes[i])
  223. fprintf(stream, "<alloc size=\"%zu\" count=\"%zu\"/>\n", i, sizes[i]);
  224. fputs("</malloc>\n", stream);
  225. SCUDO_PREFIX(free)(sizes);
  226. return 0;
  227. }
  228. // Disable memory tagging for the heap. The caller must disable memory tag
  229. // checks globally (e.g. by clearing TCF0 on aarch64) before calling this
  230. // function, and may not re-enable them after calling the function.
  231. INTERFACE WEAK void SCUDO_PREFIX(malloc_disable_memory_tagging)() {
  232. SCUDO_ALLOCATOR.disableMemoryTagging();
  233. }
  234. // Sets whether scudo records stack traces and other metadata for allocations
  235. // and deallocations. This function only has an effect if the allocator and
  236. // hardware support memory tagging.
  237. INTERFACE WEAK void
  238. SCUDO_PREFIX(malloc_set_track_allocation_stacks)(int track) {
  239. SCUDO_ALLOCATOR.setTrackAllocationStacks(track);
  240. }
  241. // Sets whether scudo zero-initializes all allocated memory.
  242. INTERFACE WEAK void SCUDO_PREFIX(malloc_set_zero_contents)(int zero_contents) {
  243. SCUDO_ALLOCATOR.setFillContents(zero_contents ? scudo::ZeroFill
  244. : scudo::NoFill);
  245. }
  246. // Sets whether scudo pattern-initializes all allocated memory.
  247. INTERFACE WEAK void
  248. SCUDO_PREFIX(malloc_set_pattern_fill_contents)(int pattern_fill_contents) {
  249. SCUDO_ALLOCATOR.setFillContents(
  250. pattern_fill_contents ? scudo::PatternOrZeroFill : scudo::NoFill);
  251. }
  252. // Sets whether scudo adds a small amount of slack at the end of large
  253. // allocations, before the guard page. This can be enabled to work around buggy
  254. // applications that read a few bytes past the end of their allocation.
  255. INTERFACE WEAK void
  256. SCUDO_PREFIX(malloc_set_add_large_allocation_slack)(int add_slack) {
  257. SCUDO_ALLOCATOR.setAddLargeAllocationSlack(add_slack);
  258. }
  259. } // extern "C"