GCC Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 87.0% 168 / 0 / 193
Functions: 100.0% 31 / 0 / 31
Branches: 77.1% 91 / 0 / 118

src/internal/hook_backend_visit.hpp
Line Branch Exec Source
1 #ifndef DETOURMODKIT_INTERNAL_HOOK_BACKEND_VISIT_HPP
2 #define DETOURMODKIT_INTERNAL_HOOK_BACKEND_VISIT_HPP
3
4 /**
5 * @file internal/hook_backend_visit.hpp
6 * @brief Nothrow visitation and toggle primitives over the inline/mid backend variant.
7 * @details The hook sibling TUs (src/hook.cpp and src/hook_toggle.cpp) share these helpers, so each visitation and
8 * exception-containment contract is stated exactly once. Every helper is noexcept and contains backend
9 * synchronization or allocation exceptions at this boundary.
10 */
11
12 #include "internal/hook_patch_witness.hpp"
13
14 #include <safetyhook.hpp>
15
16 #include <atomic>
17 #include <cstddef>
18 #include <type_traits>
19 #include <utility>
20 #include <variant>
21
22 namespace DetourModKit::detail
23 {
24 #if defined(DMK_ENABLE_TEST_SEAMS)
25 // Overrides the byte witness Hook::enable() takes after the backend reports a successful patch. The suite can
26 // then drive the negative branch a real backend does not produce on demand.
27 extern bool (*g_hook_enable_witness_override)(bool) noexcept;
28 // Runs after a managed backend disable returns or throws and before DMK witnesses its target bytes.
29 extern void (*g_hook_backend_disable_probe)() noexcept;
30 // Counts managed backend toggle exceptions the containment boundaries below reached and contained.
31 extern std::atomic<std::size_t> g_backend_toggle_exception_catches;
32 #endif
33
34 /**
35 * @brief Returns the inline trampoline pointer for a hook backend, or nullptr for a mid hook / empty backend.
36 * @details The @ref hook::Hook::CallGate publishes this value while an inline hook is armed.
37 */
38 [[nodiscard]] inline void *
39 3940 inline_trampoline(const std::variant<safetyhook::InlineHook, safetyhook::MidHook> &backend) noexcept
40 {
41 3940 const auto *inline_backend = std::get_if<safetyhook::InlineHook>(&backend);
42
5/6
✓ Branch 3 → 4 taken 3881 times.
✓ Branch 3 → 6 taken 59 times.
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 3881 times.
✓ Branch 8 → 9 taken 59 times.
✓ Branch 8 → 10 taken 3881 times.
3940 if (inline_backend == nullptr || !*inline_backend)
43 {
44 59 return nullptr;
45 }
46 3881 return inline_backend->original<void *>();
47 }
48
49 /// Applies a visitor that does not throw, or returns @p fallback when no managed backend is active.
50 template <typename ValueT, typename BackendVariant, typename Visitor>
51 33001 [[nodiscard]] ValueT backend_value_or(BackendVariant &backend, ValueT fallback, Visitor &&visitor) noexcept
52 {
53 using InlineReference = decltype(*std::get_if<safetyhook::InlineHook>(&backend));
54 using MidReference = decltype(*std::get_if<safetyhook::MidHook>(&backend));
55 static_assert(std::is_nothrow_invocable_r_v<ValueT, Visitor, InlineReference>);
56 static_assert(std::is_nothrow_invocable_r_v<ValueT, Visitor, MidReference>);
57
58
22/22
DetourModKit::detail::PatchWitness DetourModKit::detail::backend_value_or<DetourModKit::detail::PatchWitness, std::variant<safetyhook::InlineHook, safetyhook::MidHook>, DetourModKit::detail::witness_of<std::variant<safetyhook::InlineHook, safetyhook::MidHook> >(std::variant<safetyhook::InlineHook, safetyhook::MidHook>&)::{lambda(auto:1&)#1}>(std::variant<safetyhook::InlineHook, safetyhook::MidHook>&, DetourModKit::detail::PatchWitness, DetourModKit::detail::witness_of<std::variant<safetyhook::InlineHook, safetyhook::MidHook> >(std::variant<safetyhook::InlineHook, safetyhook::MidHook>&)::{lambda(auto:1&)#1}&&):
✓ Branch 3 → 4 taken 11399 times.
✓ Branch 3 → 7 taken 538 times.
bool DetourModKit::detail::backend_value_or<bool, std::variant<safetyhook::InlineHook, safetyhook::MidHook>, DetourModKit::hook::Hook::is_enabled() const::{lambda(auto:1&)#1}>(std::variant<safetyhook::InlineHook, safetyhook::MidHook>&, bool, DetourModKit::hook::Hook::is_enabled() const::{lambda(auto:1&)#1}&&):
✓ Branch 3 → 4 taken 1071 times.
✓ Branch 3 → 7 taken 15 times.
bool DetourModKit::detail::backend_value_or<bool, std::variant<safetyhook::InlineHook, safetyhook::MidHook>, DetourModKit::(anonymous namespace)::run_teardown_restore<std::variant<safetyhook::InlineHook, safetyhook::MidHook> >(std::variant<safetyhook::InlineHook, safetyhook::MidHook>&)::{lambda(auto:1&)#1}>(std::variant<safetyhook::InlineHook, safetyhook::MidHook>&, bool, DetourModKit::(anonymous namespace)::run_teardown_restore<std::variant<safetyhook::InlineHook, safetyhook::MidHook> >(std::variant<safetyhook::InlineHook, safetyhook::MidHook>&)::{lambda(auto:1&)#1}&&):
✓ Branch 3 → 4 taken 260 times.
✓ Branch 3 → 7 taken 216 times.
bool DetourModKit::detail::backend_value_or<bool, std::variant<safetyhook::InlineHook, safetyhook::MidHook>, DetourModKit::hook::Hook::enable()::{lambda(auto:1&)#2}>(std::variant<safetyhook::InlineHook, safetyhook::MidHook>&, bool, DetourModKit::hook::Hook::enable()::{lambda(auto:1&)#2}&&):
✓ Branch 3 → 4 taken 3745 times.
✓ Branch 3 → 7 taken 61 times.
bool DetourModKit::detail::backend_value_or<bool, std::variant<safetyhook::InlineHook, safetyhook::MidHook>, DetourModKit::hook::Hook::enable()::{lambda(auto:1&)#3}>(std::variant<safetyhook::InlineHook, safetyhook::MidHook>&, bool, DetourModKit::hook::Hook::enable()::{lambda(auto:1&)#3}&&):
✓ Branch 3 → 4 taken 3745 times.
✓ Branch 3 → 7 taken 61 times.
bool DetourModKit::detail::backend_value_or<bool, std::variant<safetyhook::InlineHook, safetyhook::MidHook>, DetourModKit::hook::Hook::enable()::{lambda(auto:1&)#4}>(std::variant<safetyhook::InlineHook, safetyhook::MidHook>&, bool, DetourModKit::hook::Hook::enable()::{lambda(auto:1&)#4}&&):
✓ Branch 3 → 4 taken 9 times.
✓ Branch 3 → 7 taken 2 times.
bool DetourModKit::detail::backend_value_or<bool, std::variant<safetyhook::InlineHook, safetyhook::MidHook>, DetourModKit::hook::Hook::enable()::{lambda(auto:1&)#6}>(std::variant<safetyhook::InlineHook, safetyhook::MidHook>&, bool, DetourModKit::hook::Hook::enable()::{lambda(auto:1&)#6}&&):
✓ Branch 3 → 4 taken 4 times.
✓ Branch 3 → 7 taken 4 times.
bool DetourModKit::detail::backend_value_or<bool, std::variant<safetyhook::InlineHook, safetyhook::MidHook>, DetourModKit::hook::Hook::enable()::{lambda(auto:1&)#1}>(std::variant<safetyhook::InlineHook, safetyhook::MidHook>&, bool, DetourModKit::hook::Hook::enable()::{lambda(auto:1&)#1}&&):
✓ Branch 3 → 4 taken 3764 times.
✓ Branch 3 → 7 taken 62 times.
bool DetourModKit::detail::backend_value_or<bool, std::variant<safetyhook::InlineHook, safetyhook::MidHook>, DetourModKit::hook::Hook::disable()::{lambda(auto:1&)#2}>(std::variant<safetyhook::InlineHook, safetyhook::MidHook>&, bool, DetourModKit::hook::Hook::disable()::{lambda(auto:1&)#2}&&):
✓ Branch 3 → 4 taken 3538 times.
✓ Branch 3 → 7 taken 14 times.
bool DetourModKit::detail::backend_value_or<bool, std::variant<safetyhook::InlineHook, safetyhook::MidHook>, DetourModKit::hook::Hook::disable()::{lambda(auto:1&)#1}>(std::variant<safetyhook::InlineHook, safetyhook::MidHook>&, bool, DetourModKit::hook::Hook::disable()::{lambda(auto:1&)#1}&&):
✓ Branch 3 → 4 taken 3557 times.
✓ Branch 3 → 7 taken 14 times.
unsigned long long DetourModKit::detail::backend_value_or<unsigned long long, std::variant<safetyhook::InlineHook, safetyhook::MidHook>, DetourModKit::(anonymous namespace)::drain_backend_route<std::variant<safetyhook::InlineHook, safetyhook::MidHook> >(std::variant<safetyhook::InlineHook, safetyhook::MidHook>&)::{lambda()#1}::operator()() const::{lambda(auto:1 const&)#1}>(std::variant<safetyhook::InlineHook, safetyhook::MidHook>&, unsigned long long, DetourModKit::(anonymous namespace)::drain_backend_route<std::variant<safetyhook::InlineHook, safetyhook::MidHook> >(std::variant<safetyhook::InlineHook, safetyhook::MidHook>&)::{lambda()#1}::operator()() const::{lambda(auto:1 const&)#1}&&):
✓ Branch 3 → 4 taken 259 times.
✓ Branch 3 → 8 taken 663 times.
33001 if (auto *inline_backend = std::get_if<safetyhook::InlineHook>(&backend))
59 {
60 31351 return std::forward<Visitor>(visitor)(*inline_backend);
61 }
62
11/22
DetourModKit::detail::PatchWitness DetourModKit::detail::backend_value_or<DetourModKit::detail::PatchWitness, std::variant<safetyhook::InlineHook, safetyhook::MidHook>, DetourModKit::detail::witness_of<std::variant<safetyhook::InlineHook, safetyhook::MidHook> >(std::variant<safetyhook::InlineHook, safetyhook::MidHook>&)::{lambda(auto:1&)#1}>(std::variant<safetyhook::InlineHook, safetyhook::MidHook>&, DetourModKit::detail::PatchWitness, DetourModKit::detail::witness_of<std::variant<safetyhook::InlineHook, safetyhook::MidHook> >(std::variant<safetyhook::InlineHook, safetyhook::MidHook>&)::{lambda(auto:1&)#1}&&):
✓ Branch 8 → 9 taken 538 times.
✗ Branch 8 → 12 not taken.
bool DetourModKit::detail::backend_value_or<bool, std::variant<safetyhook::InlineHook, safetyhook::MidHook>, DetourModKit::hook::Hook::is_enabled() const::{lambda(auto:1&)#1}>(std::variant<safetyhook::InlineHook, safetyhook::MidHook>&, bool, DetourModKit::hook::Hook::is_enabled() const::{lambda(auto:1&)#1}&&):
✓ Branch 8 → 9 taken 15 times.
✗ Branch 8 → 12 not taken.
bool DetourModKit::detail::backend_value_or<bool, std::variant<safetyhook::InlineHook, safetyhook::MidHook>, DetourModKit::(anonymous namespace)::run_teardown_restore<std::variant<safetyhook::InlineHook, safetyhook::MidHook> >(std::variant<safetyhook::InlineHook, safetyhook::MidHook>&)::{lambda(auto:1&)#1}>(std::variant<safetyhook::InlineHook, safetyhook::MidHook>&, bool, DetourModKit::(anonymous namespace)::run_teardown_restore<std::variant<safetyhook::InlineHook, safetyhook::MidHook> >(std::variant<safetyhook::InlineHook, safetyhook::MidHook>&)::{lambda(auto:1&)#1}&&):
✓ Branch 8 → 9 taken 216 times.
✗ Branch 8 → 12 not taken.
bool DetourModKit::detail::backend_value_or<bool, std::variant<safetyhook::InlineHook, safetyhook::MidHook>, DetourModKit::hook::Hook::enable()::{lambda(auto:1&)#2}>(std::variant<safetyhook::InlineHook, safetyhook::MidHook>&, bool, DetourModKit::hook::Hook::enable()::{lambda(auto:1&)#2}&&):
✓ Branch 8 → 9 taken 61 times.
✗ Branch 8 → 12 not taken.
bool DetourModKit::detail::backend_value_or<bool, std::variant<safetyhook::InlineHook, safetyhook::MidHook>, DetourModKit::hook::Hook::enable()::{lambda(auto:1&)#3}>(std::variant<safetyhook::InlineHook, safetyhook::MidHook>&, bool, DetourModKit::hook::Hook::enable()::{lambda(auto:1&)#3}&&):
✓ Branch 8 → 9 taken 61 times.
✗ Branch 8 → 12 not taken.
bool DetourModKit::detail::backend_value_or<bool, std::variant<safetyhook::InlineHook, safetyhook::MidHook>, DetourModKit::hook::Hook::enable()::{lambda(auto:1&)#4}>(std::variant<safetyhook::InlineHook, safetyhook::MidHook>&, bool, DetourModKit::hook::Hook::enable()::{lambda(auto:1&)#4}&&):
✓ Branch 8 → 9 taken 2 times.
✗ Branch 8 → 12 not taken.
bool DetourModKit::detail::backend_value_or<bool, std::variant<safetyhook::InlineHook, safetyhook::MidHook>, DetourModKit::hook::Hook::enable()::{lambda(auto:1&)#6}>(std::variant<safetyhook::InlineHook, safetyhook::MidHook>&, bool, DetourModKit::hook::Hook::enable()::{lambda(auto:1&)#6}&&):
✓ Branch 8 → 9 taken 4 times.
✗ Branch 8 → 12 not taken.
bool DetourModKit::detail::backend_value_or<bool, std::variant<safetyhook::InlineHook, safetyhook::MidHook>, DetourModKit::hook::Hook::enable()::{lambda(auto:1&)#1}>(std::variant<safetyhook::InlineHook, safetyhook::MidHook>&, bool, DetourModKit::hook::Hook::enable()::{lambda(auto:1&)#1}&&):
✓ Branch 8 → 9 taken 62 times.
✗ Branch 8 → 12 not taken.
bool DetourModKit::detail::backend_value_or<bool, std::variant<safetyhook::InlineHook, safetyhook::MidHook>, DetourModKit::hook::Hook::disable()::{lambda(auto:1&)#2}>(std::variant<safetyhook::InlineHook, safetyhook::MidHook>&, bool, DetourModKit::hook::Hook::disable()::{lambda(auto:1&)#2}&&):
✓ Branch 8 → 9 taken 14 times.
✗ Branch 8 → 12 not taken.
bool DetourModKit::detail::backend_value_or<bool, std::variant<safetyhook::InlineHook, safetyhook::MidHook>, DetourModKit::hook::Hook::disable()::{lambda(auto:1&)#1}>(std::variant<safetyhook::InlineHook, safetyhook::MidHook>&, bool, DetourModKit::hook::Hook::disable()::{lambda(auto:1&)#1}&&):
✓ Branch 8 → 9 taken 14 times.
✗ Branch 8 → 12 not taken.
unsigned long long DetourModKit::detail::backend_value_or<unsigned long long, std::variant<safetyhook::InlineHook, safetyhook::MidHook>, DetourModKit::(anonymous namespace)::drain_backend_route<std::variant<safetyhook::InlineHook, safetyhook::MidHook> >(std::variant<safetyhook::InlineHook, safetyhook::MidHook>&)::{lambda()#1}::operator()() const::{lambda(auto:1 const&)#1}>(std::variant<safetyhook::InlineHook, safetyhook::MidHook>&, unsigned long long, DetourModKit::(anonymous namespace)::drain_backend_route<std::variant<safetyhook::InlineHook, safetyhook::MidHook> >(std::variant<safetyhook::InlineHook, safetyhook::MidHook>&)::{lambda()#1}::operator()() const::{lambda(auto:1 const&)#1}&&):
✓ Branch 9 → 10 taken 663 times.
✗ Branch 9 → 14 not taken.
1650 if (auto *mid_backend = std::get_if<safetyhook::MidHook>(&backend))
63 {
64 1650 return std::forward<Visitor>(visitor)(*mid_backend);
65 }
66 return fallback;
67 }
68
69 /// Applies a visitor that does not throw and reports whether a managed backend is active.
70 template <typename BackendVariant, typename Visitor>
71 5014 [[nodiscard]] bool apply_backend(BackendVariant &backend, Visitor &&visitor) noexcept
72 {
73 using InlineReference = decltype(*std::get_if<safetyhook::InlineHook>(&backend));
74 using MidReference = decltype(*std::get_if<safetyhook::MidHook>(&backend));
75 static_assert(std::is_nothrow_invocable_v<Visitor, InlineReference>);
76 static_assert(std::is_nothrow_invocable_v<Visitor, MidReference>);
77
78
19/20
bool DetourModKit::detail::apply_backend<std::variant<safetyhook::InlineHook, safetyhook::MidHook>, DetourModKit::(anonymous namespace)::run_teardown_restore<std::variant<safetyhook::InlineHook, safetyhook::MidHook> >(std::variant<safetyhook::InlineHook, safetyhook::MidHook>&)::{lambda(auto:1&)#2}>(std::variant<safetyhook::InlineHook, safetyhook::MidHook>&, DetourModKit::(anonymous namespace)::run_teardown_restore<std::variant<safetyhook::InlineHook, safetyhook::MidHook> >(std::variant<safetyhook::InlineHook, safetyhook::MidHook>&)::{lambda(auto:1&)#2}&&):
✓ Branch 3 → 4 taken 259 times.
✓ Branch 3 → 8 taken 215 times.
bool DetourModKit::detail::apply_backend<std::variant<safetyhook::InlineHook, safetyhook::MidHook>, DetourModKit::hook::(anonymous namespace)::reconcile_published_state<DetourModKit::hook::Hook::Impl, DetourModKit::hook::Hook::CallGate>(DetourModKit::hook::Hook::Impl&, DetourModKit::hook::Hook::CallGate&, bool)::{lambda(auto:1&)#1}>(DetourModKit::hook::Hook::Impl&, DetourModKit::hook::Hook::CallGate&&):
✓ Branch 3 → 4 taken 2 times.
✗ Branch 3 → 8 not taken.
bool DetourModKit::detail::apply_backend<std::variant<safetyhook::InlineHook, safetyhook::MidHook>, DetourModKit::hook::Hook::enable()::{lambda(auto:1&)#5}>(std::variant<safetyhook::InlineHook, safetyhook::MidHook>&, DetourModKit::hook::Hook::enable()::{lambda(auto:1&)#5}&&):
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 8 taken 1 time.
bool DetourModKit::detail::apply_backend<std::variant<safetyhook::InlineHook, safetyhook::MidHook>, DetourModKit::hook::Hook::enable()::{lambda(auto:1&)#7}>(std::variant<safetyhook::InlineHook, safetyhook::MidHook>&, DetourModKit::hook::Hook::enable()::{lambda(auto:1&)#7}&&):
✓ Branch 3 → 4 taken 2 times.
✓ Branch 3 → 8 taken 2 times.
bool DetourModKit::detail::apply_backend<std::variant<safetyhook::InlineHook, safetyhook::MidHook>, DetourModKit::hook::Hook::enable()::{lambda(auto:1&)#8}>(std::variant<safetyhook::InlineHook, safetyhook::MidHook>&, DetourModKit::hook::Hook::enable()::{lambda(auto:1&)#8}&&):
✓ Branch 3 → 4 taken 4 times.
✓ Branch 3 → 8 taken 2 times.
bool DetourModKit::detail::apply_backend<std::variant<safetyhook::InlineHook, safetyhook::MidHook>, DetourModKit::hook::Hook::disable()::{lambda(auto:1&)#3}>(std::variant<safetyhook::InlineHook, safetyhook::MidHook>&, DetourModKit::hook::Hook::disable()::{lambda(auto:1&)#3}&&):
✓ Branch 3 → 4 taken 3536 times.
✓ Branch 3 → 8 taken 11 times.
bool DetourModKit::detail::apply_backend<std::variant<safetyhook::InlineHook, safetyhook::MidHook>, DetourModKit::hook::Hook::disable()::{lambda(auto:1&)#4}>(std::variant<safetyhook::InlineHook, safetyhook::MidHook>&, DetourModKit::hook::Hook::disable()::{lambda(auto:1&)#4}&&):
✓ Branch 3 → 4 taken 2 times.
✓ Branch 3 → 8 taken 3 times.
bool DetourModKit::detail::apply_backend<std::variant<safetyhook::InlineHook, safetyhook::MidHook>, DetourModKit::hook::Hook::~Hook()::{lambda(auto:1&)#2}>(std::variant<safetyhook::InlineHook, safetyhook::MidHook>&, DetourModKit::hook::Hook::~Hook()::{lambda(auto:1&)#2}&&):
✓ Branch 3 → 4 taken 9 times.
✓ Branch 3 → 8 taken 4 times.
bool DetourModKit::detail::apply_backend<std::variant<safetyhook::InlineHook, safetyhook::MidHook>, DetourModKit::hook::Hook::~Hook()::{lambda(auto:1&)#3}>(std::variant<safetyhook::InlineHook, safetyhook::MidHook>&, DetourModKit::hook::Hook::~Hook()::{lambda(auto:1&)#3}&&):
✓ Branch 3 → 4 taken 259 times.
✓ Branch 3 → 8 taken 215 times.
bool DetourModKit::detail::apply_backend<std::variant<safetyhook::InlineHook, safetyhook::MidHook>, DetourModKit::hook::Hook::~Hook()::{lambda(auto:1&)#1}>(std::variant<safetyhook::InlineHook, safetyhook::MidHook>&, DetourModKit::hook::Hook::~Hook()::{lambda(auto:1&)#1}&&):
✓ Branch 3 → 4 taken 268 times.
✓ Branch 3 → 8 taken 219 times.
5014 if (auto *inline_backend = std::get_if<safetyhook::InlineHook>(&backend))
79 {
80 4342 std::forward<Visitor>(visitor)(*inline_backend);
81 4342 return true;
82 }
83
9/20
bool DetourModKit::detail::apply_backend<std::variant<safetyhook::InlineHook, safetyhook::MidHook>, DetourModKit::(anonymous namespace)::run_teardown_restore<std::variant<safetyhook::InlineHook, safetyhook::MidHook> >(std::variant<safetyhook::InlineHook, safetyhook::MidHook>&)::{lambda(auto:1&)#2}>(std::variant<safetyhook::InlineHook, safetyhook::MidHook>&, DetourModKit::(anonymous namespace)::run_teardown_restore<std::variant<safetyhook::InlineHook, safetyhook::MidHook> >(std::variant<safetyhook::InlineHook, safetyhook::MidHook>&)::{lambda(auto:1&)#2}&&):
✓ Branch 9 → 10 taken 215 times.
✗ Branch 9 → 14 not taken.
bool DetourModKit::detail::apply_backend<std::variant<safetyhook::InlineHook, safetyhook::MidHook>, DetourModKit::hook::(anonymous namespace)::reconcile_published_state<DetourModKit::hook::Hook::Impl, DetourModKit::hook::Hook::CallGate>(DetourModKit::hook::Hook::Impl&, DetourModKit::hook::Hook::CallGate&, bool)::{lambda(auto:1&)#1}>(DetourModKit::hook::Hook::Impl&, DetourModKit::hook::Hook::CallGate&&):
✗ Branch 9 → 10 not taken.
✗ Branch 9 → 14 not taken.
bool DetourModKit::detail::apply_backend<std::variant<safetyhook::InlineHook, safetyhook::MidHook>, DetourModKit::hook::Hook::enable()::{lambda(auto:1&)#5}>(std::variant<safetyhook::InlineHook, safetyhook::MidHook>&, DetourModKit::hook::Hook::enable()::{lambda(auto:1&)#5}&&):
✓ Branch 9 → 10 taken 1 time.
✗ Branch 9 → 14 not taken.
bool DetourModKit::detail::apply_backend<std::variant<safetyhook::InlineHook, safetyhook::MidHook>, DetourModKit::hook::Hook::enable()::{lambda(auto:1&)#7}>(std::variant<safetyhook::InlineHook, safetyhook::MidHook>&, DetourModKit::hook::Hook::enable()::{lambda(auto:1&)#7}&&):
✓ Branch 9 → 10 taken 2 times.
✗ Branch 9 → 14 not taken.
bool DetourModKit::detail::apply_backend<std::variant<safetyhook::InlineHook, safetyhook::MidHook>, DetourModKit::hook::Hook::enable()::{lambda(auto:1&)#8}>(std::variant<safetyhook::InlineHook, safetyhook::MidHook>&, DetourModKit::hook::Hook::enable()::{lambda(auto:1&)#8}&&):
✓ Branch 9 → 10 taken 2 times.
✗ Branch 9 → 14 not taken.
bool DetourModKit::detail::apply_backend<std::variant<safetyhook::InlineHook, safetyhook::MidHook>, DetourModKit::hook::Hook::disable()::{lambda(auto:1&)#3}>(std::variant<safetyhook::InlineHook, safetyhook::MidHook>&, DetourModKit::hook::Hook::disable()::{lambda(auto:1&)#3}&&):
✓ Branch 9 → 10 taken 11 times.
✗ Branch 9 → 14 not taken.
bool DetourModKit::detail::apply_backend<std::variant<safetyhook::InlineHook, safetyhook::MidHook>, DetourModKit::hook::Hook::disable()::{lambda(auto:1&)#4}>(std::variant<safetyhook::InlineHook, safetyhook::MidHook>&, DetourModKit::hook::Hook::disable()::{lambda(auto:1&)#4}&&):
✓ Branch 9 → 10 taken 3 times.
✗ Branch 9 → 14 not taken.
bool DetourModKit::detail::apply_backend<std::variant<safetyhook::InlineHook, safetyhook::MidHook>, DetourModKit::hook::Hook::~Hook()::{lambda(auto:1&)#2}>(std::variant<safetyhook::InlineHook, safetyhook::MidHook>&, DetourModKit::hook::Hook::~Hook()::{lambda(auto:1&)#2}&&):
✓ Branch 9 → 10 taken 4 times.
✗ Branch 9 → 14 not taken.
bool DetourModKit::detail::apply_backend<std::variant<safetyhook::InlineHook, safetyhook::MidHook>, DetourModKit::hook::Hook::~Hook()::{lambda(auto:1&)#3}>(std::variant<safetyhook::InlineHook, safetyhook::MidHook>&, DetourModKit::hook::Hook::~Hook()::{lambda(auto:1&)#3}&&):
✓ Branch 9 → 10 taken 215 times.
✗ Branch 9 → 14 not taken.
bool DetourModKit::detail::apply_backend<std::variant<safetyhook::InlineHook, safetyhook::MidHook>, DetourModKit::hook::Hook::~Hook()::{lambda(auto:1&)#1}>(std::variant<safetyhook::InlineHook, safetyhook::MidHook>&, DetourModKit::hook::Hook::~Hook()::{lambda(auto:1&)#1}&&):
✓ Branch 9 → 10 taken 219 times.
✗ Branch 9 → 14 not taken.
672 if (auto *mid_backend = std::get_if<safetyhook::MidHook>(&backend))
84 {
85 672 std::forward<Visitor>(visitor)(*mid_backend);
86 672 return true;
87 }
88 return false;
89 }
90
91 /**
92 * @brief Reports whether the backend left this hook's own patch armed after a target toggle.
93 * @details enable() publishes Active only for bytes it can attribute to itself.
94 */
95 3806 template <class Backend> [[nodiscard]] bool enable_patch_is_confirmed(const Backend &backend) noexcept
96 {
97
6/8
bool DetourModKit::detail::enable_patch_is_confirmed<safetyhook::InlineHook>(safetyhook::InlineHook const&):
✓ Branch 3 → 4 taken 3744 times.
✓ Branch 3 → 7 taken 1 time.
✓ Branch 5 → 6 taken 3744 times.
✗ Branch 5 → 7 not taken.
bool DetourModKit::detail::enable_patch_is_confirmed<safetyhook::MidHook>(safetyhook::MidHook const&):
✓ Branch 3 → 4 taken 60 times.
✓ Branch 3 → 7 taken 1 time.
✓ Branch 5 → 6 taken 60 times.
✗ Branch 5 → 7 not taken.
3806 const bool confirmed = backend.enabled() && detail::witness_patch(backend) == detail::PatchWitness::OwnedPatch;
98 #if defined(DMK_ENABLE_TEST_SEAMS)
99
4/4
bool DetourModKit::detail::enable_patch_is_confirmed<safetyhook::InlineHook>(safetyhook::InlineHook const&):
✓ Branch 8 → 9 taken 8 times.
✓ Branch 8 → 10 taken 3737 times.
bool DetourModKit::detail::enable_patch_is_confirmed<safetyhook::MidHook>(safetyhook::MidHook const&):
✓ Branch 8 → 9 taken 4 times.
✓ Branch 8 → 10 taken 57 times.
3806 if (auto *override_fn = DetourModKit::detail::g_hook_enable_witness_override)
100 {
101 12 return override_fn(confirmed);
102 }
103 #endif
104 3794 return confirmed;
105 }
106
107 /// Runs a managed backend enable and contains backend synchronization or allocation exceptions.
108 3806 template <class Backend> [[nodiscard]] bool try_backend_enable(Backend &backend) noexcept
109 {
110 try
111 {
112
4/4
bool DetourModKit::detail::try_backend_enable<safetyhook::InlineHook>(safetyhook::InlineHook&):
✓ Branch 2 → 3 taken 3741 times.
✓ Branch 2 → 6 taken 4 times.
bool DetourModKit::detail::try_backend_enable<safetyhook::MidHook>(safetyhook::MidHook&):
✓ Branch 2 → 3 taken 59 times.
✓ Branch 2 → 6 taken 2 times.
3806 return backend.enable().has_value();
113 }
114 6 catch (...)
115 {
116 #if defined(DMK_ENABLE_TEST_SEAMS)
117 DetourModKit::detail::g_backend_toggle_exception_catches.fetch_add(1, std::memory_order_relaxed);
118 #endif
119 6 return false;
120 }
121 }
122
123 /// Runs a managed backend disable and contains backend synchronization or allocation exceptions.
124 4036 template <class Backend> [[nodiscard]] bool try_backend_disable(Backend &backend) noexcept
125 {
126 try
127 {
128
4/4
bool DetourModKit::detail::try_backend_disable<safetyhook::InlineHook>(safetyhook::InlineHook&):
✓ Branch 2 → 3 taken 3793 times.
✓ Branch 2 → 8 taken 9 times.
bool DetourModKit::detail::try_backend_disable<safetyhook::MidHook>(safetyhook::MidHook&):
✓ Branch 2 → 3 taken 227 times.
✓ Branch 2 → 8 taken 7 times.
4036 const bool disabled = backend.disable().has_value();
129 #if defined(DMK_ENABLE_TEST_SEAMS)
130
3/4
bool DetourModKit::detail::try_backend_disable<safetyhook::InlineHook>(safetyhook::InlineHook&):
✓ Branch 4 → 5 taken 1 time.
✓ Branch 4 → 6 taken 3792 times.
bool DetourModKit::detail::try_backend_disable<safetyhook::MidHook>(safetyhook::MidHook&):
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 227 times.
4020 if (auto *probe = DetourModKit::detail::g_hook_backend_disable_probe)
131 {
132 1 probe();
133 }
134 #endif
135 4020 return disabled;
136 }
137 16 catch (...)
138 {
139 #if defined(DMK_ENABLE_TEST_SEAMS)
140 DetourModKit::detail::g_backend_toggle_exception_catches.fetch_add(1, std::memory_order_relaxed);
141
4/4
bool DetourModKit::detail::try_backend_disable<safetyhook::InlineHook>(safetyhook::InlineHook&):
✓ Branch 13 → 14 taken 1 time.
✓ Branch 13 → 15 taken 8 times.
bool DetourModKit::detail::try_backend_disable<safetyhook::MidHook>(safetyhook::MidHook&):
✓ Branch 13 → 14 taken 2 times.
✓ Branch 13 → 15 taken 5 times.
16 if (auto *probe = DetourModKit::detail::g_hook_backend_disable_probe)
142 {
143 3 probe();
144 }
145 #endif
146 16 return false;
147 }
148 }
149
150 /// Returns the current target-byte witness, or Indeterminate when no backend is reachable.
151 11937 template <class BackendVariant> [[nodiscard]] detail::PatchWitness witness_of(BackendVariant &backend) noexcept
152 {
153 11937 return backend_value_or(
154 backend,
155 detail::PatchWitness::Indeterminate,
156 23874 [](auto &one) noexcept { return detail::witness_patch(one); }
157 11937 );
158 }
159 } // namespace DetourModKit::detail
160
161 #endif // DETOURMODKIT_INTERNAL_HOOK_BACKEND_VISIT_HPP
162