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