1 // Copyright 2020 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_ALLOC_HOOKS_H_
6 #define BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_ALLOC_HOOKS_H_
7
8 #include <atomic>
9 #include <cstddef>
10
11 #include "base/allocator/partition_allocator/partition_alloc_base/compiler_specific.h"
12 #include "base/allocator/partition_allocator/partition_alloc_base/component_export.h"
13
14 namespace partition_alloc {
15
16 // PartitionAlloc supports setting hooks to observe allocations/frees as they
17 // occur as well as 'override' hooks that allow overriding those operations.
PA_COMPONENT_EXPORT(PARTITION_ALLOC)18 class PA_COMPONENT_EXPORT(PARTITION_ALLOC) PartitionAllocHooks {
19 public:
20 // Log allocation and free events.
21 typedef void AllocationObserverHook(void* address,
22 size_t size,
23 const char* type_name);
24 typedef void FreeObserverHook(void* address);
25
26 // If it returns true, the allocation has been overridden with the pointer in
27 // *out.
28 typedef bool AllocationOverrideHook(void** out,
29 unsigned int flags,
30 size_t size,
31 const char* type_name);
32 // If it returns true, then the allocation was overridden and has been freed.
33 typedef bool FreeOverrideHook(void* address);
34 // If it returns true, the underlying allocation is overridden and *out holds
35 // the size of the underlying allocation.
36 typedef bool ReallocOverrideHook(size_t* out, void* address);
37
38 // Special hook type, independent of the rest. Triggered when `free()` detects
39 // outstanding references to the allocation.
40 // IMPORTANT: Make sure the hook always overwrites `[address, address + size)`
41 // with a bit pattern that cannot be interpreted as a valid memory address.
42 typedef void QuarantineOverrideHook(void* address, size_t size);
43
44 // To unhook, call Set*Hooks with nullptrs.
45 static void SetObserverHooks(AllocationObserverHook* alloc_hook,
46 FreeObserverHook* free_hook);
47 static void SetOverrideHooks(AllocationOverrideHook* alloc_hook,
48 FreeOverrideHook* free_hook,
49 ReallocOverrideHook realloc_hook);
50
51 // Helper method to check whether hooks are enabled. This is an optimization
52 // so that if a function needs to call observer and override hooks in two
53 // different places this value can be cached and only loaded once.
54 static bool AreHooksEnabled() {
55 return hooks_enabled_.load(std::memory_order_relaxed);
56 }
57
58 static void AllocationObserverHookIfEnabled(void* address,
59 size_t size,
60 const char* type_name);
61 static bool AllocationOverrideHookIfEnabled(void** out,
62 unsigned int flags,
63 size_t size,
64 const char* type_name);
65
66 static void FreeObserverHookIfEnabled(void* address);
67 static bool FreeOverrideHookIfEnabled(void* address);
68
69 static void ReallocObserverHookIfEnabled(void* old_address,
70 void* new_address,
71 size_t size,
72 const char* type_name);
73 static bool ReallocOverrideHookIfEnabled(size_t* out, void* address);
74
75 PA_ALWAYS_INLINE static QuarantineOverrideHook* GetQuarantineOverrideHook() {
76 return quarantine_override_hook_.load(std::memory_order_acquire);
77 }
78
79 static void SetQuarantineOverrideHook(QuarantineOverrideHook* hook);
80
81 private:
82 // Single bool that is used to indicate whether observer or allocation hooks
83 // are set to reduce the numbers of loads required to check whether hooking is
84 // enabled.
85 static std::atomic<bool> hooks_enabled_;
86
87 // Lock used to synchronize Set*Hooks calls.
88 static std::atomic<AllocationObserverHook*> allocation_observer_hook_;
89 static std::atomic<FreeObserverHook*> free_observer_hook_;
90
91 static std::atomic<AllocationOverrideHook*> allocation_override_hook_;
92 static std::atomic<FreeOverrideHook*> free_override_hook_;
93 static std::atomic<ReallocOverrideHook*> realloc_override_hook_;
94
95 static std::atomic<QuarantineOverrideHook*> quarantine_override_hook_;
96 };
97
98 } // namespace partition_alloc
99
100 #endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_ALLOC_HOOKS_H_
101