asan_allocator.h 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  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(__sparc__)
  125. const uptr kAllocatorSpace = ~(uptr)0;
  126. const uptr kAllocatorSize = 0x20000000000ULL; // 2T.
  127. typedef DefaultSizeClassMap SizeClassMap;
  128. # elif SANITIZER_WINDOWS
  129. const uptr kAllocatorSpace = ~(uptr)0;
  130. const uptr kAllocatorSize = 0x8000000000ULL; // 500G
  131. typedef DefaultSizeClassMap SizeClassMap;
  132. # else
  133. const uptr kAllocatorSpace = 0x600000000000ULL;
  134. const uptr kAllocatorSize = 0x40000000000ULL; // 4T.
  135. typedef DefaultSizeClassMap SizeClassMap;
  136. # endif
  137. template <typename AddressSpaceViewTy>
  138. struct AP64 { // Allocator64 parameters. Deliberately using a short name.
  139. static const uptr kSpaceBeg = kAllocatorSpace;
  140. static const uptr kSpaceSize = kAllocatorSize;
  141. static const uptr kMetadataSize = 0;
  142. typedef __asan::SizeClassMap SizeClassMap;
  143. typedef AsanMapUnmapCallback MapUnmapCallback;
  144. static const uptr kFlags = 0;
  145. using AddressSpaceView = AddressSpaceViewTy;
  146. };
  147. template <typename AddressSpaceView>
  148. using PrimaryAllocatorASVT = SizeClassAllocator64<AP64<AddressSpaceView>>;
  149. using PrimaryAllocator = PrimaryAllocatorASVT<LocalAddressSpaceView>;
  150. #else // Fallback to SizeClassAllocator32.
  151. typedef CompactSizeClassMap SizeClassMap;
  152. template <typename AddressSpaceViewTy>
  153. struct AP32 {
  154. static const uptr kSpaceBeg = 0;
  155. static const u64 kSpaceSize = SANITIZER_MMAP_RANGE_SIZE;
  156. static const uptr kMetadataSize = 0;
  157. typedef __asan::SizeClassMap SizeClassMap;
  158. static const uptr kRegionSizeLog = 20;
  159. using AddressSpaceView = AddressSpaceViewTy;
  160. typedef AsanMapUnmapCallback MapUnmapCallback;
  161. static const uptr kFlags = 0;
  162. };
  163. template <typename AddressSpaceView>
  164. using PrimaryAllocatorASVT = SizeClassAllocator32<AP32<AddressSpaceView> >;
  165. using PrimaryAllocator = PrimaryAllocatorASVT<LocalAddressSpaceView>;
  166. #endif // SANITIZER_CAN_USE_ALLOCATOR64
  167. static const uptr kNumberOfSizeClasses = SizeClassMap::kNumClasses;
  168. template <typename AddressSpaceView>
  169. using AsanAllocatorASVT =
  170. CombinedAllocator<PrimaryAllocatorASVT<AddressSpaceView>>;
  171. using AsanAllocator = AsanAllocatorASVT<LocalAddressSpaceView>;
  172. using AllocatorCache = AsanAllocator::AllocatorCache;
  173. struct AsanThreadLocalMallocStorage {
  174. uptr quarantine_cache[16];
  175. AllocatorCache allocator_cache;
  176. void CommitBack();
  177. private:
  178. // These objects are allocated via mmap() and are zero-initialized.
  179. AsanThreadLocalMallocStorage() {}
  180. };
  181. void *asan_memalign(uptr alignment, uptr size, BufferedStackTrace *stack,
  182. AllocType alloc_type);
  183. void asan_free(void *ptr, BufferedStackTrace *stack, AllocType alloc_type);
  184. void asan_delete(void *ptr, uptr size, uptr alignment,
  185. BufferedStackTrace *stack, AllocType alloc_type);
  186. void *asan_malloc(uptr size, BufferedStackTrace *stack);
  187. void *asan_calloc(uptr nmemb, uptr size, BufferedStackTrace *stack);
  188. void *asan_realloc(void *p, uptr size, BufferedStackTrace *stack);
  189. void *asan_reallocarray(void *p, uptr nmemb, uptr size,
  190. BufferedStackTrace *stack);
  191. void *asan_valloc(uptr size, BufferedStackTrace *stack);
  192. void *asan_pvalloc(uptr size, BufferedStackTrace *stack);
  193. void *asan_aligned_alloc(uptr alignment, uptr size, BufferedStackTrace *stack);
  194. int asan_posix_memalign(void **memptr, uptr alignment, uptr size,
  195. BufferedStackTrace *stack);
  196. uptr asan_malloc_usable_size(const void *ptr, uptr pc, uptr bp);
  197. uptr asan_mz_size(const void *ptr);
  198. void asan_mz_force_lock();
  199. void asan_mz_force_unlock();
  200. void PrintInternalAllocatorStats();
  201. void AsanSoftRssLimitExceededCallback(bool exceeded);
  202. } // namespace __asan
  203. #endif // ASAN_ALLOCATOR_H