asan_allocator.h 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. //===-- asan_allocator.h ----------------------------------------*- 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. // This file is a part of AddressSanitizer, an address sanity checker.
  10. //
  11. // ASan-private header for asan_allocator.cpp.
  12. //===----------------------------------------------------------------------===//
  13. #ifndef ASAN_ALLOCATOR_H
  14. #define ASAN_ALLOCATOR_H
  15. #include "asan_flags.h"
  16. #include "asan_interceptors.h"
  17. #include "asan_internal.h"
  18. #include "sanitizer_common/sanitizer_allocator.h"
  19. #include "sanitizer_common/sanitizer_list.h"
  20. #include "sanitizer_common/sanitizer_platform.h"
  21. namespace __asan {
  22. enum AllocType {
  23. FROM_MALLOC = 1, // Memory block came from malloc, calloc, realloc, etc.
  24. FROM_NEW = 2, // Memory block came from operator new.
  25. FROM_NEW_BR = 3 // Memory block came from operator new [ ]
  26. };
  27. class AsanChunk;
  28. struct AllocatorOptions {
  29. u32 quarantine_size_mb;
  30. u32 thread_local_quarantine_size_kb;
  31. u16 min_redzone;
  32. u16 max_redzone;
  33. u8 may_return_null;
  34. u8 alloc_dealloc_mismatch;
  35. s32 release_to_os_interval_ms;
  36. void SetFrom(const Flags *f, const CommonFlags *cf);
  37. void CopyTo(Flags *f, CommonFlags *cf);
  38. };
  39. void InitializeAllocator(const AllocatorOptions &options);
  40. void ReInitializeAllocator(const AllocatorOptions &options);
  41. void GetAllocatorOptions(AllocatorOptions *options);
  42. class AsanChunkView {
  43. public:
  44. explicit AsanChunkView(AsanChunk *chunk) : chunk_(chunk) {}
  45. bool IsValid() const; // Checks if AsanChunkView points to a valid
  46. // allocated or quarantined chunk.
  47. bool IsAllocated() const; // Checks if the memory is currently allocated.
  48. bool IsQuarantined() const; // Checks if the memory is currently quarantined.
  49. uptr Beg() const; // First byte of user memory.
  50. uptr End() const; // Last byte of user memory.
  51. uptr UsedSize() const; // Size requested by the user.
  52. u32 UserRequestedAlignment() const; // Originally requested alignment.
  53. uptr AllocTid() const;
  54. uptr FreeTid() const;
  55. bool Eq(const AsanChunkView &c) const { return chunk_ == c.chunk_; }
  56. u32 GetAllocStackId() const;
  57. u32 GetFreeStackId() const;
  58. AllocType GetAllocType() const;
  59. bool AddrIsInside(uptr addr, uptr access_size, sptr *offset) const {
  60. if (addr >= Beg() && (addr + access_size) <= End()) {
  61. *offset = addr - Beg();
  62. return true;
  63. }
  64. return false;
  65. }
  66. bool AddrIsAtLeft(uptr addr, uptr access_size, sptr *offset) const {
  67. (void)access_size;
  68. if (addr < Beg()) {
  69. *offset = Beg() - addr;
  70. return true;
  71. }
  72. return false;
  73. }
  74. bool AddrIsAtRight(uptr addr, uptr access_size, sptr *offset) const {
  75. if (addr + access_size > End()) {
  76. *offset = addr - End();
  77. return true;
  78. }
  79. return false;
  80. }
  81. private:
  82. AsanChunk *const chunk_;
  83. };
  84. AsanChunkView FindHeapChunkByAddress(uptr address);
  85. AsanChunkView FindHeapChunkByAllocBeg(uptr address);
  86. // List of AsanChunks with total size.
  87. class AsanChunkFifoList: public IntrusiveList<AsanChunk> {
  88. public:
  89. explicit AsanChunkFifoList(LinkerInitialized) { }
  90. AsanChunkFifoList() { clear(); }
  91. void Push(AsanChunk *n);
  92. void PushList(AsanChunkFifoList *q);
  93. AsanChunk *Pop();
  94. uptr size() { return size_; }
  95. void clear() {
  96. IntrusiveList<AsanChunk>::clear();
  97. size_ = 0;
  98. }
  99. private:
  100. uptr size_;
  101. };
  102. struct AsanMapUnmapCallback {
  103. void OnMap(uptr p, uptr size) const;
  104. void OnUnmap(uptr p, uptr size) const;
  105. };
  106. #if SANITIZER_CAN_USE_ALLOCATOR64
  107. # if SANITIZER_FUCHSIA
  108. const uptr kAllocatorSpace = ~(uptr)0;
  109. const uptr kAllocatorSize = 0x40000000000ULL; // 4T.
  110. typedef DefaultSizeClassMap SizeClassMap;
  111. # elif defined(__powerpc64__)
  112. const uptr kAllocatorSpace = ~(uptr)0;
  113. const uptr kAllocatorSize = 0x20000000000ULL; // 2T.
  114. typedef DefaultSizeClassMap SizeClassMap;
  115. # elif defined(__aarch64__) && SANITIZER_ANDROID
  116. // Android needs to support 39, 42 and 48 bit VMA.
  117. const uptr kAllocatorSpace = ~(uptr)0;
  118. const uptr kAllocatorSize = 0x2000000000ULL; // 128G.
  119. typedef VeryCompactSizeClassMap SizeClassMap;
  120. #elif SANITIZER_RISCV64
  121. const uptr kAllocatorSpace = ~(uptr)0;
  122. const uptr kAllocatorSize = 0x2000000000ULL; // 128G.
  123. typedef VeryDenseSizeClassMap SizeClassMap;
  124. # elif defined(__aarch64__)
  125. // AArch64/SANITIZER_CAN_USE_ALLOCATOR64 is only for 42-bit VMA
  126. // so no need to different values for different VMA.
  127. const uptr kAllocatorSpace = 0x10000000000ULL;
  128. const uptr kAllocatorSize = 0x10000000000ULL; // 3T.
  129. typedef DefaultSizeClassMap SizeClassMap;
  130. #elif defined(__sparc__)
  131. const uptr kAllocatorSpace = ~(uptr)0;
  132. const uptr kAllocatorSize = 0x20000000000ULL; // 2T.
  133. typedef DefaultSizeClassMap SizeClassMap;
  134. # elif SANITIZER_WINDOWS
  135. const uptr kAllocatorSpace = ~(uptr)0;
  136. const uptr kAllocatorSize = 0x8000000000ULL; // 500G
  137. typedef DefaultSizeClassMap SizeClassMap;
  138. # else
  139. const uptr kAllocatorSpace = 0x600000000000ULL;
  140. const uptr kAllocatorSize = 0x40000000000ULL; // 4T.
  141. typedef DefaultSizeClassMap SizeClassMap;
  142. # endif
  143. template <typename AddressSpaceViewTy>
  144. struct AP64 { // Allocator64 parameters. Deliberately using a short name.
  145. static const uptr kSpaceBeg = kAllocatorSpace;
  146. static const uptr kSpaceSize = kAllocatorSize;
  147. static const uptr kMetadataSize = 0;
  148. typedef __asan::SizeClassMap SizeClassMap;
  149. typedef AsanMapUnmapCallback MapUnmapCallback;
  150. static const uptr kFlags = 0;
  151. using AddressSpaceView = AddressSpaceViewTy;
  152. };
  153. template <typename AddressSpaceView>
  154. using PrimaryAllocatorASVT = SizeClassAllocator64<AP64<AddressSpaceView>>;
  155. using PrimaryAllocator = PrimaryAllocatorASVT<LocalAddressSpaceView>;
  156. #else // Fallback to SizeClassAllocator32.
  157. typedef CompactSizeClassMap SizeClassMap;
  158. template <typename AddressSpaceViewTy>
  159. struct AP32 {
  160. static const uptr kSpaceBeg = 0;
  161. static const u64 kSpaceSize = SANITIZER_MMAP_RANGE_SIZE;
  162. static const uptr kMetadataSize = 0;
  163. typedef __asan::SizeClassMap SizeClassMap;
  164. static const uptr kRegionSizeLog = 20;
  165. using AddressSpaceView = AddressSpaceViewTy;
  166. typedef AsanMapUnmapCallback MapUnmapCallback;
  167. static const uptr kFlags = 0;
  168. };
  169. template <typename AddressSpaceView>
  170. using PrimaryAllocatorASVT = SizeClassAllocator32<AP32<AddressSpaceView> >;
  171. using PrimaryAllocator = PrimaryAllocatorASVT<LocalAddressSpaceView>;
  172. #endif // SANITIZER_CAN_USE_ALLOCATOR64
  173. static const uptr kNumberOfSizeClasses = SizeClassMap::kNumClasses;
  174. template <typename AddressSpaceView>
  175. using AsanAllocatorASVT =
  176. CombinedAllocator<PrimaryAllocatorASVT<AddressSpaceView>>;
  177. using AsanAllocator = AsanAllocatorASVT<LocalAddressSpaceView>;
  178. using AllocatorCache = AsanAllocator::AllocatorCache;
  179. struct AsanThreadLocalMallocStorage {
  180. uptr quarantine_cache[16];
  181. AllocatorCache allocator_cache;
  182. void CommitBack();
  183. private:
  184. // These objects are allocated via mmap() and are zero-initialized.
  185. AsanThreadLocalMallocStorage() {}
  186. };
  187. void *asan_memalign(uptr alignment, uptr size, BufferedStackTrace *stack,
  188. AllocType alloc_type);
  189. void asan_free(void *ptr, BufferedStackTrace *stack, AllocType alloc_type);
  190. void asan_delete(void *ptr, uptr size, uptr alignment,
  191. BufferedStackTrace *stack, AllocType alloc_type);
  192. void *asan_malloc(uptr size, BufferedStackTrace *stack);
  193. void *asan_calloc(uptr nmemb, uptr size, BufferedStackTrace *stack);
  194. void *asan_realloc(void *p, uptr size, BufferedStackTrace *stack);
  195. void *asan_reallocarray(void *p, uptr nmemb, uptr size,
  196. BufferedStackTrace *stack);
  197. void *asan_valloc(uptr size, BufferedStackTrace *stack);
  198. void *asan_pvalloc(uptr size, BufferedStackTrace *stack);
  199. void *asan_aligned_alloc(uptr alignment, uptr size, BufferedStackTrace *stack);
  200. int asan_posix_memalign(void **memptr, uptr alignment, uptr size,
  201. BufferedStackTrace *stack);
  202. uptr asan_malloc_usable_size(const void *ptr, uptr pc, uptr bp);
  203. uptr asan_mz_size(const void *ptr);
  204. void asan_mz_force_lock();
  205. void asan_mz_force_unlock();
  206. void PrintInternalAllocatorStats();
  207. void AsanSoftRssLimitExceededCallback(bool exceeded);
  208. } // namespace __asan
  209. #endif // ASAN_ALLOCATOR_H