• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef PANDA_TOOLING_PT_HOOKS_WRAPPER_H
17 #define PANDA_TOOLING_PT_HOOKS_WRAPPER_H
18 
19 #include <atomic>
20 #include "runtime/include/tooling/debug_interface.h"
21 #include "os/mutex.h"
22 #include "runtime/include/mtmanaged_thread.h"
23 #include "pt_thread_info.h"
24 #include "pt_hook_type_info.h"
25 
26 namespace ark::tooling {
27 
28 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
29 class PtHooksWrapper : public PtHooks {
30 public:
SetHooks(PtHooks * hooks)31     void SetHooks(PtHooks *hooks)
32     {
33         // Atomic with release order reason: data race with hooks_
34         hooks_.store(hooks, std::memory_order_release);
35     }
36 
EnableGlobalHook(PtHookType hookType)37     void EnableGlobalHook(PtHookType hookType)
38     {
39         globalHookTypeInfo_.Enable(hookType);
40     }
41 
DisableGlobalHook(PtHookType hookType)42     void DisableGlobalHook(PtHookType hookType)
43     {
44         globalHookTypeInfo_.Disable(hookType);
45     }
46 
EnableAllGlobalHook()47     void EnableAllGlobalHook()
48     {
49         globalHookTypeInfo_.EnableAll();
50     }
51 
DisableAllGlobalHook()52     void DisableAllGlobalHook()
53     {
54         globalHookTypeInfo_.DisableAll();
55     }
56 
57     // Wrappers for hooks
Breakpoint(PtThread thread,Method * method,const PtLocation & location)58     void Breakpoint(PtThread thread, Method *method, const PtLocation &location) override
59     {
60         // Atomic with acquire order reason: data race with hooks_
61         auto *loadedHooks = hooks_.load(std::memory_order_acquire);
62         if (loadedHooks == nullptr || !HookIsEnabled(PtHookType::PT_HOOK_TYPE_BREAKPOINT)) {
63             return;
64         }
65         // Atomic with acquire order reason: data race with vmdeath_did_not_happen_
66         ASSERT(vmdeathDidNotHappen_.load(std::memory_order_acquire));
67         loadedHooks->Breakpoint(thread, method, location);
68     }
69 
LoadModule(std::string_view pandaFile)70     void LoadModule(std::string_view pandaFile) override
71     {
72         // Atomic with acquire order reason: data race with hooks_
73         auto *loadedHooks = hooks_.load(std::memory_order_acquire);
74         if (loadedHooks == nullptr || !HookIsEnabled(PtHookType::PT_HOOK_TYPE_LOAD_MODULE)) {
75             return;
76         }
77         // Atomic with acquire order reason: data race with vmdeath_did_not_happen_
78         ASSERT(vmdeathDidNotHappen_.load(std::memory_order_acquire));
79         loadedHooks->LoadModule(pandaFile);
80     }
81 
Paused(PauseReason reason)82     void Paused(PauseReason reason) override
83     {
84         // Atomic with acquire order reason: data race with hooks_
85         auto *loadedHooks = hooks_.load(std::memory_order_acquire);
86         if (loadedHooks == nullptr || !HookIsEnabled(PtHookType::PT_HOOK_TYPE_PAUSED)) {
87             return;
88         }
89         // Atomic with acquire order reason: data race with vmdeath_did_not_happen_
90         ASSERT(vmdeathDidNotHappen_.load(std::memory_order_acquire));
91         loadedHooks->Paused(reason);
92     }
93 
Exception(PtThread thread,Method * method,const PtLocation & location,ObjectHeader * exceptionObject,Method * catchMethod,const PtLocation & catchLocation)94     void Exception(PtThread thread, Method *method, const PtLocation &location, ObjectHeader *exceptionObject,
95                    Method *catchMethod, const PtLocation &catchLocation) override
96     {
97         // Atomic with acquire order reason: data race with hooks_
98         auto *loadedHooks = hooks_.load(std::memory_order_acquire);
99         if (loadedHooks == nullptr || !HookIsEnabled(PtHookType::PT_HOOK_TYPE_EXCEPTION)) {
100             return;
101         }
102         // Atomic with acquire order reason: data race with vmdeath_did_not_happen_
103         ASSERT(vmdeathDidNotHappen_.load(std::memory_order_acquire));
104         loadedHooks->Exception(thread, method, location, exceptionObject, catchMethod, catchLocation);
105     }
106 
ExceptionCatch(PtThread thread,Method * method,const PtLocation & location,ObjectHeader * exceptionObject)107     void ExceptionCatch(PtThread thread, Method *method, const PtLocation &location,
108                         ObjectHeader *exceptionObject) override
109     {
110         // Atomic with acquire order reason: data race with hooks_
111         auto *loadedHooks = hooks_.load(std::memory_order_acquire);
112         if (loadedHooks == nullptr || !HookIsEnabled(PtHookType::PT_HOOK_TYPE_EXCEPTION_CATCH)) {
113             return;
114         }
115         // Atomic with acquire order reason: data race with vmdeath_did_not_happen_
116         ASSERT(vmdeathDidNotHappen_.load(std::memory_order_acquire));
117         loadedHooks->ExceptionCatch(thread, method, location, exceptionObject);
118     }
119 
PropertyAccess(PtThread thread,Method * method,const PtLocation & location,ObjectHeader * object,PtProperty property)120     void PropertyAccess(PtThread thread, Method *method, const PtLocation &location, ObjectHeader *object,
121                         PtProperty property) override
122     {
123         // Atomic with acquire order reason: data race with hooks_
124         auto *loadedHooks = hooks_.load(std::memory_order_acquire);
125         if (loadedHooks == nullptr || !HookIsEnabled(PtHookType::PT_HOOK_TYPE_PROPERTY_ACCESS)) {
126             return;
127         }
128         // Atomic with acquire order reason: data race with vmdeath_did_not_happen_
129         ASSERT(vmdeathDidNotHappen_.load(std::memory_order_acquire));
130         loadedHooks->PropertyAccess(thread, method, location, object, property);
131     }
132 
PropertyModification(PtThread thread,Method * method,const PtLocation & location,ObjectHeader * object,PtProperty property,VRegValue newValue)133     void PropertyModification(PtThread thread, Method *method, const PtLocation &location, ObjectHeader *object,
134                               PtProperty property, VRegValue newValue) override
135     {
136         // Atomic with acquire order reason: data race with hooks_
137         auto *loadedHooks = hooks_.load(std::memory_order_acquire);
138         if (loadedHooks == nullptr || !HookIsEnabled(PtHookType::PT_HOOK_TYPE_PROPERTY_MODIFICATION)) {
139             return;
140         }
141         // Atomic with acquire order reason: data race with vmdeath_did_not_happen_
142         ASSERT(vmdeathDidNotHappen_.load(std::memory_order_acquire));
143         loadedHooks->PropertyModification(thread, method, location, object, property, newValue);
144     }
145 
ConsoleCall(PtThread thread,ConsoleCallType type,uint64_t timestamp,const PandaVector<TypedValue> & arguments)146     void ConsoleCall(PtThread thread, ConsoleCallType type, uint64_t timestamp,
147                      const PandaVector<TypedValue> &arguments) override
148     {
149         // Atomic with acquire order reason: data race with hooks_
150         auto *loadedHooks = hooks_.load(std::memory_order_acquire);
151         if (loadedHooks == nullptr || !HookIsEnabled(PtHookType::PT_HOOK_TYPE_CONSOLE_CALL)) {
152             return;
153         }
154         // Atomic with acquire order reason: data race with vmdeath_did_not_happen_
155         ASSERT(vmdeathDidNotHappen_.load(std::memory_order_acquire));
156         loadedHooks->ConsoleCall(thread, type, timestamp, arguments);
157     }
158 
FramePop(PtThread thread,Method * method,bool wasPoppedByException)159     void FramePop(PtThread thread, Method *method, bool wasPoppedByException) override
160     {
161         // Atomic with acquire order reason: data race with hooks_
162         auto *loadedHooks = hooks_.load(std::memory_order_acquire);
163         if (loadedHooks == nullptr || !HookIsEnabled(PtHookType::PT_HOOK_TYPE_FRAME_POP)) {
164             return;
165         }
166         // Atomic with acquire order reason: data race with vmdeath_did_not_happen_
167         ASSERT(vmdeathDidNotHappen_.load(std::memory_order_acquire));
168         loadedHooks->FramePop(thread, method, wasPoppedByException);
169     }
170 
GarbageCollectionFinish()171     void GarbageCollectionFinish() override
172     {
173         // NOTE(dtrubenkov): Add an assertion when 2125 issue is resolved
174         // ASSERT(ManagedThread::GetCurrent() == nullptr)
175         // Atomic with acquire order reason: data race with hooks_
176         auto *loadedHooks = hooks_.load(std::memory_order_acquire);
177         if (loadedHooks == nullptr || !GlobalHookIsEnabled(PtHookType::PT_HOOK_TYPE_GARBAGE_COLLECTION_FINISH)) {
178             return;
179         }
180         // Atomic with acquire order reason: data race with vmdeath_did_not_happen_
181         ASSERT(vmdeathDidNotHappen_.load(std::memory_order_acquire));
182         // Called in an unmanaged thread
183         loadedHooks->GarbageCollectionFinish();
184     }
185 
GarbageCollectionStart()186     void GarbageCollectionStart() override
187     {
188         // NOTE(dtrubenkov): Add an assertion when 2125 issue is resolved
189         // ASSERT(ManagedThread::GetCurrent() == nullptr)
190         // Atomic with acquire order reason: data race with hooks_
191         auto *loadedHooks = hooks_.load(std::memory_order_acquire);
192         if (loadedHooks == nullptr || !GlobalHookIsEnabled(PtHookType::PT_HOOK_TYPE_GARBAGE_COLLECTION_START)) {
193             return;
194         }
195         // Atomic with acquire order reason: data race with vmdeath_did_not_happen_
196         ASSERT(vmdeathDidNotHappen_.load(std::memory_order_acquire));
197         // Called in an unmanaged thread
198         loadedHooks->GarbageCollectionStart();
199     }
200 
MethodEntry(PtThread thread,Method * method)201     void MethodEntry(PtThread thread, Method *method) override
202     {
203         // Atomic with acquire order reason: data race with hooks_
204         auto *loadedHooks = hooks_.load(std::memory_order_acquire);
205         if (loadedHooks == nullptr || !HookIsEnabled(PtHookType::PT_HOOK_TYPE_METHOD_ENTRY)) {
206             return;
207         }
208         // Atomic with acquire order reason: data race with vmdeath_did_not_happen_
209         ASSERT(vmdeathDidNotHappen_.load(std::memory_order_acquire));
210         loadedHooks->MethodEntry(thread, method);
211     }
212 
MethodExit(PtThread thread,Method * method,bool wasPoppedByException,VRegValue returnValue)213     void MethodExit(PtThread thread, Method *method, bool wasPoppedByException, VRegValue returnValue) override
214     {
215         // Atomic with acquire order reason: data race with hooks_
216         auto *loadedHooks = hooks_.load(std::memory_order_acquire);
217         if (loadedHooks == nullptr || !HookIsEnabled(PtHookType::PT_HOOK_TYPE_METHOD_EXIT)) {
218             return;
219         }
220         // Atomic with acquire order reason: data race with vmdeath_did_not_happen_
221         ASSERT(vmdeathDidNotHappen_.load(std::memory_order_acquire));
222         loadedHooks->MethodExit(thread, method, wasPoppedByException, returnValue);
223     }
224 
SingleStep(PtThread thread,Method * method,const PtLocation & location)225     void SingleStep(PtThread thread, Method *method, const PtLocation &location) override
226     {
227         // Atomic with acquire order reason: data race with hooks_
228         auto *loadedHooks = hooks_.load(std::memory_order_acquire);
229         if (loadedHooks == nullptr || !HookIsEnabled(PtHookType::PT_HOOK_TYPE_SINGLE_STEP)) {
230             return;
231         }
232         // Atomic with acquire order reason: data race with vmdeath_did_not_happen_
233         ASSERT(vmdeathDidNotHappen_.load(std::memory_order_acquire));
234         loadedHooks->SingleStep(thread, method, location);
235     }
236 
ThreadStart(PtThread thread)237     void ThreadStart(PtThread thread) override
238     {
239         // Atomic with acquire order reason: data race with hooks_
240         auto *loadedHooks = hooks_.load(std::memory_order_acquire);
241         if (loadedHooks == nullptr || !HookIsEnabled(PtHookType::PT_HOOK_TYPE_THREAD_START)) {
242             return;
243         }
244         // Atomic with acquire order reason: data race with vmdeath_did_not_happen_
245         ASSERT(vmdeathDidNotHappen_.load(std::memory_order_acquire));
246         loadedHooks->ThreadStart(thread);
247     }
248 
ThreadEnd(PtThread thread)249     void ThreadEnd(PtThread thread) override
250     {
251         // Atomic with acquire order reason: data race with hooks_
252         auto *loadedHooks = hooks_.load(std::memory_order_acquire);
253         if (loadedHooks == nullptr || !HookIsEnabled(PtHookType::PT_HOOK_TYPE_THREAD_END)) {
254             return;
255         }
256         // Atomic with acquire order reason: data race with vmdeath_did_not_happen_
257         ASSERT(vmdeathDidNotHappen_.load(std::memory_order_acquire));
258         loadedHooks->ThreadEnd(thread);
259     }
260 
VmStart()261     void VmStart() override
262     {
263         // Atomic with acquire order reason: data race with hooks_
264         auto *loadedHooks = hooks_.load(std::memory_order_acquire);
265         if (loadedHooks == nullptr || !HookIsEnabled(PtHookType::PT_HOOK_TYPE_VM_START)) {
266             return;
267         }
268         // Atomic with acquire order reason: data race with vmdeath_did_not_happen_
269         ASSERT(vmdeathDidNotHappen_.load(std::memory_order_acquire));
270         loadedHooks->VmStart();
271     }
272 
VmInitialization(PtThread thread)273     void VmInitialization(PtThread thread) override
274     {
275         // Atomic with acquire order reason: data race with hooks_
276         auto *loadedHooks = hooks_.load(std::memory_order_acquire);
277         if (loadedHooks == nullptr || !HookIsEnabled(PtHookType::PT_HOOK_TYPE_VM_INITIALIZATION)) {
278             return;
279         }
280         // Atomic with acquire order reason: data race with vmdeath_did_not_happen_
281         ASSERT(vmdeathDidNotHappen_.load(std::memory_order_acquire));
282         loadedHooks->VmInitialization(thread);
283     }
284 
VmDeath()285     void VmDeath() override
286     {
287         // Atomic with acquire order reason: data race with hooks_
288         auto *loadedHooks = hooks_.load(std::memory_order_acquire);
289         if (loadedHooks == nullptr || !HookIsEnabled(PtHookType::PT_HOOK_TYPE_VM_DEATH)) {
290             return;
291         }
292         // Atomic with acquire order reason: data race with vmdeath_did_not_happen_
293         ASSERT(vmdeathDidNotHappen_.load(std::memory_order_acquire));
294 #ifndef NDEBUG
295         // Atomic with release order reason: data race with vmdeath_did_not_happen_
296         vmdeathDidNotHappen_.store(false, std::memory_order_release);
297 #endif
298         loadedHooks->VmDeath();
299         SetHooks(nullptr);
300     }
301 
ExceptionRevoked(ExceptionWrapper reason,ExceptionID exceptionId)302     void ExceptionRevoked(ExceptionWrapper reason, ExceptionID exceptionId) override
303     {
304         // Atomic with acquire order reason: data race with hooks_
305         auto *loadedHooks = hooks_.load(std::memory_order_acquire);
306         if (loadedHooks == nullptr || !HookIsEnabled(PtHookType::PT_HOOK_TYPE_EXCEPTION_REVOKED)) {
307             return;
308         }
309         // Atomic with acquire order reason: data race with vmdeath_did_not_happen_
310         ASSERT(vmdeathDidNotHappen_.load(std::memory_order_acquire));
311         loadedHooks->ExceptionRevoked(reason, exceptionId);
312     }
313 
ExecutionContextCreated(ExecutionContextWrapper context)314     void ExecutionContextCreated(ExecutionContextWrapper context) override
315     {
316         // Atomic with acquire order reason: data race with hooks_
317         auto *loadedHooks = hooks_.load(std::memory_order_acquire);
318         if (loadedHooks == nullptr || !HookIsEnabled(PtHookType::PT_HOOK_TYPE_EXECUTION_CONTEXT_CREATEED)) {
319             return;
320         }
321         // Atomic with acquire order reason: data race with vmdeath_did_not_happen_
322         ASSERT(vmdeathDidNotHappen_.load(std::memory_order_acquire));
323         loadedHooks->ExecutionContextCreated(context);
324     }
325 
ExecutionContextDestroyed(ExecutionContextWrapper context)326     void ExecutionContextDestroyed(ExecutionContextWrapper context) override
327     {
328         // Atomic with acquire order reason: data race with hooks_
329         auto *loadedHooks = hooks_.load(std::memory_order_acquire);
330         if (loadedHooks == nullptr || !HookIsEnabled(PtHookType::PT_HOOK_TYPE_EXECUTION_CONTEXT_DESTROYED)) {
331             return;
332         }
333         // Atomic with acquire order reason: data race with vmdeath_did_not_happen_
334         ASSERT(vmdeathDidNotHappen_.load(std::memory_order_acquire));
335         loadedHooks->ExecutionContextDestroyed(context);
336     }
337 
ExecutionContextsCleared()338     void ExecutionContextsCleared() override
339     {
340         // Atomic with acquire order reason: data race with hooks_
341         auto *loadedHooks = hooks_.load(std::memory_order_acquire);
342         if (loadedHooks == nullptr || !HookIsEnabled(PtHookType::PT_HOOK_TYPE_EXECUTION_CONTEXTS_CLEARED)) {
343             return;
344         }
345         // Atomic with acquire order reason: data race with vmdeath_did_not_happen_
346         ASSERT(vmdeathDidNotHappen_.load(std::memory_order_acquire));
347         loadedHooks->ExecutionContextsCleared();
348     }
349 
InspectRequested(PtObject object,PtObject hints)350     void InspectRequested(PtObject object, PtObject hints) override
351     {
352         // Atomic with acquire order reason: data race with hooks_
353         auto *loadedHooks = hooks_.load(std::memory_order_acquire);
354         if (loadedHooks == nullptr || !HookIsEnabled(PtHookType::PT_HOOK_TYPE_INSPECT_REQUESTED)) {
355             return;
356         }
357         // Atomic with acquire order reason: data race with vmdeath_did_not_happen_
358         ASSERT(vmdeathDidNotHappen_.load(std::memory_order_acquire));
359         loadedHooks->InspectRequested(object, hints);
360     }
361 
ClassLoad(PtThread thread,BaseClass * klass)362     void ClassLoad(PtThread thread, BaseClass *klass) override
363     {
364         // Atomic with acquire order reason: data race with hooks_
365         auto *loadedHooks = hooks_.load(std::memory_order_acquire);
366         if (loadedHooks == nullptr || !HookIsEnabled(PtHookType::PT_HOOK_TYPE_CLASS_LOAD)) {
367             return;
368         }
369         // Atomic with acquire order reason: data race with vmdeath_did_not_happen_
370         ASSERT(vmdeathDidNotHappen_.load(std::memory_order_acquire));
371         loadedHooks->ClassLoad(thread, klass);
372     }
373 
ClassPrepare(PtThread thread,BaseClass * klass)374     void ClassPrepare(PtThread thread, BaseClass *klass) override
375     {
376         // Atomic with acquire order reason: data race with hooks_
377         auto *loadedHooks = hooks_.load(std::memory_order_acquire);
378         if (loadedHooks == nullptr || !HookIsEnabled(PtHookType::PT_HOOK_TYPE_CLASS_PREPARE)) {
379             return;
380         }
381         // Atomic with acquire order reason: data race with vmdeath_did_not_happen_
382         ASSERT(vmdeathDidNotHappen_.load(std::memory_order_acquire));
383         loadedHooks->ClassPrepare(thread, klass);
384     }
385 
MonitorWait(PtThread thread,ObjectHeader * object,int64_t timeout)386     void MonitorWait(PtThread thread, ObjectHeader *object, int64_t timeout) override
387     {
388         // Atomic with acquire order reason: data race with hooks_
389         auto *loadedHooks = hooks_.load(std::memory_order_acquire);
390         if (loadedHooks == nullptr || !HookIsEnabled(PtHookType::PT_HOOK_TYPE_MONITOR_WAIT)) {
391             return;
392         }
393         // Atomic with acquire order reason: data race with vmdeath_did_not_happen_
394         ASSERT(vmdeathDidNotHappen_.load(std::memory_order_acquire));
395         loadedHooks->MonitorWait(thread, object, timeout);
396     }
397 
MonitorWaited(PtThread thread,ObjectHeader * object,bool timedOut)398     void MonitorWaited(PtThread thread, ObjectHeader *object, bool timedOut) override
399     {
400         // Atomic with acquire order reason: data race with hooks_
401         auto *loadedHooks = hooks_.load(std::memory_order_acquire);
402         if (loadedHooks == nullptr || !HookIsEnabled(PtHookType::PT_HOOK_TYPE_MONITOR_WAITED)) {
403             return;
404         }
405         // Atomic with acquire order reason: data race with vmdeath_did_not_happen_
406         ASSERT(vmdeathDidNotHappen_.load(std::memory_order_acquire));
407         loadedHooks->MonitorWaited(thread, object, timedOut);
408     }
409 
MonitorContendedEnter(PtThread thread,ObjectHeader * object)410     void MonitorContendedEnter(PtThread thread, ObjectHeader *object) override
411     {
412         // Atomic with acquire order reason: data race with hooks_
413         auto *loadedHooks = hooks_.load(std::memory_order_acquire);
414         if (loadedHooks == nullptr || !HookIsEnabled(PtHookType::PT_HOOK_TYPE_MONITOR_CONTENDED_ENTER)) {
415             return;
416         }
417         // Atomic with acquire order reason: data race with vmdeath_did_not_happen_
418         ASSERT(vmdeathDidNotHappen_.load(std::memory_order_acquire));
419         loadedHooks->MonitorContendedEnter(thread, object);
420     }
421 
MonitorContendedEntered(PtThread thread,ObjectHeader * object)422     void MonitorContendedEntered(PtThread thread, ObjectHeader *object) override
423     {
424         // Atomic with acquire order reason: data race with hooks_
425         auto *loadedHooks = hooks_.load(std::memory_order_acquire);
426         if (loadedHooks == nullptr || !HookIsEnabled(PtHookType::PT_HOOK_TYPE_MONITOR_CONTENDED_ENTERED)) {
427             return;
428         }
429         // Atomic with acquire order reason: data race with vmdeath_did_not_happen_
430         ASSERT(vmdeathDidNotHappen_.load(std::memory_order_acquire));
431         loadedHooks->MonitorContendedEntered(thread, object);
432     }
433 
ObjectAlloc(BaseClass * klass,ObjectHeader * object,PtThread thread,size_t size)434     void ObjectAlloc(BaseClass *klass, ObjectHeader *object, PtThread thread, size_t size) override
435     {
436         // Atomic with acquire order reason: data race with hooks_
437         auto *loadedHooks = hooks_.load(std::memory_order_acquire);
438         if (loadedHooks == nullptr || !HookIsEnabled(PtHookType::PT_HOOK_TYPE_OBJECT_ALLOC)) {
439             return;
440         }
441         // Atomic with acquire order reason: data race with vmdeath_did_not_happen_
442         ASSERT(vmdeathDidNotHappen_.load(std::memory_order_acquire));
443         loadedHooks->ObjectAlloc(klass, object, thread, size);
444     }
445 
446 private:
GlobalHookIsEnabled(PtHookType type)447     bool GlobalHookIsEnabled(PtHookType type) const
448     {
449         return globalHookTypeInfo_.IsEnabled(type);
450     }
451 
HookIsEnabled(PtHookType type)452     bool HookIsEnabled(PtHookType type) const
453     {
454         if (GlobalHookIsEnabled(type)) {
455             return true;
456         }
457 
458         ManagedThread *managedThread = ManagedThread::GetCurrent();
459         ASSERT(managedThread != nullptr);
460 
461         // Check local value
462         return managedThread->GetPtThreadInfo()->GetHookTypeInfo().IsEnabled(type);
463     }
464 
465     std::atomic<PtHooks *> hooks_ {nullptr};
466 
467     PtHookTypeInfo globalHookTypeInfo_ {true};
468 
469 #ifndef NDEBUG
470     std::atomic_bool vmdeathDidNotHappen_ {true};
471 #endif
472 };
473 }  // namespace ark::tooling
474 
475 #endif  // PANDA_TOOLING_PT_HOOKS_WRAPPER_H
476