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