hwasan_allocator.h 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. //===-- hwasan_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 HWAddressSanitizer.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #ifndef HWASAN_ALLOCATOR_H
  13. #define HWASAN_ALLOCATOR_H
  14. #include "hwasan.h"
  15. #include "hwasan_interface_internal.h"
  16. #include "hwasan_mapping.h"
  17. #include "hwasan_poisoning.h"
  18. #include "sanitizer_common/sanitizer_allocator.h"
  19. #include "sanitizer_common/sanitizer_allocator_checks.h"
  20. #include "sanitizer_common/sanitizer_allocator_interface.h"
  21. #include "sanitizer_common/sanitizer_allocator_report.h"
  22. #include "sanitizer_common/sanitizer_common.h"
  23. #include "sanitizer_common/sanitizer_ring_buffer.h"
  24. #if !defined(__aarch64__) && !defined(__x86_64__)
  25. #error Unsupported platform
  26. #endif
  27. namespace __hwasan {
  28. struct Metadata {
  29. u32 requested_size_low;
  30. u32 requested_size_high : 31;
  31. u32 right_aligned : 1;
  32. u32 alloc_context_id;
  33. u64 get_requested_size() {
  34. return (static_cast<u64>(requested_size_high) << 32) + requested_size_low;
  35. }
  36. void set_requested_size(u64 size) {
  37. requested_size_low = size & ((1ul << 32) - 1);
  38. requested_size_high = size >> 32;
  39. }
  40. };
  41. struct HwasanMapUnmapCallback {
  42. void OnMap(uptr p, uptr size) const { UpdateMemoryUsage(); }
  43. void OnUnmap(uptr p, uptr size) const {
  44. // We are about to unmap a chunk of user memory.
  45. // It can return as user-requested mmap() or another thread stack.
  46. // Make it accessible with zero-tagged pointer.
  47. TagMemory(p, size, 0);
  48. }
  49. };
  50. static const uptr kMaxAllowedMallocSize = 1UL << 40; // 1T
  51. struct AP64 {
  52. static const uptr kSpaceBeg = ~0ULL;
  53. #if defined(HWASAN_ALIASING_MODE)
  54. static const uptr kSpaceSize = 1ULL << kAddressTagShift;
  55. #else
  56. static const uptr kSpaceSize = 0x2000000000ULL;
  57. #endif
  58. static const uptr kMetadataSize = sizeof(Metadata);
  59. typedef __sanitizer::VeryDenseSizeClassMap SizeClassMap;
  60. using AddressSpaceView = LocalAddressSpaceView;
  61. typedef HwasanMapUnmapCallback MapUnmapCallback;
  62. static const uptr kFlags = 0;
  63. };
  64. typedef SizeClassAllocator64<AP64> PrimaryAllocator;
  65. typedef CombinedAllocator<PrimaryAllocator> Allocator;
  66. typedef Allocator::AllocatorCache AllocatorCache;
  67. void AllocatorSwallowThreadLocalCache(AllocatorCache *cache);
  68. class HwasanChunkView {
  69. public:
  70. HwasanChunkView() : block_(0), metadata_(nullptr) {}
  71. HwasanChunkView(uptr block, Metadata *metadata)
  72. : block_(block), metadata_(metadata) {}
  73. bool IsAllocated() const; // Checks if the memory is currently allocated
  74. uptr Beg() const; // First byte of user memory
  75. uptr End() const; // Last byte of user memory
  76. uptr UsedSize() const; // Size requested by the user
  77. uptr ActualSize() const; // Size allocated by the allocator.
  78. u32 GetAllocStackId() const;
  79. bool FromSmallHeap() const;
  80. private:
  81. uptr block_;
  82. Metadata *const metadata_;
  83. };
  84. HwasanChunkView FindHeapChunkByAddress(uptr address);
  85. // Information about one (de)allocation that happened in the past.
  86. // These are recorded in a thread-local ring buffer.
  87. // TODO: this is currently 24 bytes (20 bytes + alignment).
  88. // Compress it to 16 bytes or extend it to be more useful.
  89. struct HeapAllocationRecord {
  90. uptr tagged_addr;
  91. u32 alloc_context_id;
  92. u32 free_context_id;
  93. u32 requested_size;
  94. };
  95. typedef RingBuffer<HeapAllocationRecord> HeapAllocationsRingBuffer;
  96. void GetAllocatorStats(AllocatorStatCounters s);
  97. inline bool InTaggableRegion(uptr addr) {
  98. #if defined(HWASAN_ALIASING_MODE)
  99. // Aliases are mapped next to shadow so that the upper bits match the shadow
  100. // base.
  101. return (addr >> kTaggableRegionCheckShift) ==
  102. (GetShadowOffset() >> kTaggableRegionCheckShift);
  103. #endif
  104. return true;
  105. }
  106. } // namespace __hwasan
  107. #endif // HWASAN_ALLOCATOR_H