• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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