interceptor: Fix same-transaction detach + re-attach of the same address
When a listener is detached such that a function context becomes empty and
the same address is re-attached within the SAME transaction,
gum_interceptor_attach reported GUM_ATTACH_OK but the hook was silently
dropped (x86_64) or crashed on PAC-enabled arm64.
Root cause: gum_interceptor_detach removed the emptied context from
function_by_address synchronously, while its prologue redirect stays live
until end_transaction. A re-attach in the same transaction then saw
has()==FALSE, so gum_interceptor_resolve followed the still-live redirect
into the outgoing hook's own trampoline and instrumented that address
instead of the real function entry.
Fix: keep the emptied context in function_by_address for the duration of the
transaction. A same-transaction re-attach now finds and revives it (its
trampoline and overwritten_prologue are still intact), and the deferred
deactivate / perform_destroy tasks become no-ops once the context is revived.
The table entry is removed (via steal, to avoid re-triggering the table's
value-destroy) in perform_destroy at end_transaction when no revive occurred.
Adds a regression test exercising the uncovered path: attach, then within one
transaction detach and re-attach the same address, and assert the hook fires
after commit.
interceptor: Fix same-transaction detach + re-attach of the same address
When a listener is detached such that a function context becomes empty and
the same address is re-attached within the SAME transaction,
gum_interceptor_attach reported GUM_ATTACH_OK but the hook was silently
dropped (x86_64) or crashed on PAC-enabled arm64.
Root cause: gum_interceptor_detach removed the emptied context from
function_by_address synchronously, while its prologue redirect stays live
until end_transaction. A re-attach in the same transaction then saw
has()==FALSE, so gum_interceptor_resolve followed the still-live redirect
into the outgoing hook's own trampoline and instrumented that address
instead of the real function entry.
Fix: keep the emptied context in function_by_address for the duration of the
transaction. A same-transaction re-attach now finds and revives it (its
trampoline and overwritten_prologue are still intact), and the deferred
deactivate / perform_destroy tasks become no-ops once the context is revived.
The table entry is removed (via steal, to avoid re-triggering the table's
value-destroy) in perform_destroy at end_transaction when no revive occurred.
Adds a regression test exercising the uncovered path: attach, then within one
transaction detach and re-attach the same address, and assert the hook fires
after commit.