detour_transaction_abort
This commit is contained in:
parent
b78bf27449
commit
b1eb0ad995
3 changed files with 62 additions and 1 deletions
|
|
@ -11,6 +11,7 @@
|
|||
typedef void* detour_func_t;
|
||||
|
||||
#define detour_err_in_progress (err_local | 1)
|
||||
#define detour_err_wrong_thread (err_local | 2)
|
||||
|
||||
mach_error_t detour_transaction_begin();
|
||||
mach_error_t detour_transaction_abort();
|
||||
|
|
|
|||
|
|
@ -9,11 +9,19 @@
|
|||
#if DETOUR_DEBUG
|
||||
#define DETOUR_TRACE(x) printf x
|
||||
#define DETOUR_BREAK() raise(SIGTRAP)
|
||||
#define DETOUR_CHECK(x) \
|
||||
{ \
|
||||
kern_return_t check_error = (x); \
|
||||
if (check_error != err_none) { \
|
||||
DETOUR_BREAK(); \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#define DETOUR_TRACE(x)
|
||||
#define DETOUR_BREAK()
|
||||
#define DETOUR_CHECK(x) (x)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -8,8 +8,9 @@
|
|||
|
||||
#include <stdatomic.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <mach/mach_init.h>
|
||||
#include <mach/mach.h>
|
||||
#include <mach/mach_vm.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -53,6 +54,15 @@ static void internal_detour_runnable_trampoline_regions()
|
|||
}
|
||||
}
|
||||
|
||||
static void internal_detour_free_trampoline(detour_trampoline* trampoline)
|
||||
{
|
||||
detour_region* region = (detour_region*)((uintptr_t)trampoline & ~(uintptr_t)0xffff);
|
||||
|
||||
memset(trampoline, 0, sizeof(*trampoline));
|
||||
trampoline->ptr_remain = (uint8_t*)region->free_list_head;
|
||||
region->free_list_head = trampoline;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Transactions
|
||||
|
||||
|
|
@ -102,3 +112,45 @@ mach_error_t detour_transaction_begin()
|
|||
|
||||
return s_pending_error;
|
||||
}
|
||||
|
||||
mach_error_t detour_transaction_abort()
|
||||
{
|
||||
if (s_transaction_thread != mach_thread_self()) {
|
||||
return detour_err_wrong_thread;
|
||||
}
|
||||
|
||||
// Restore all the page permissions.
|
||||
const mach_port_t port = mach_task_self();
|
||||
for (detour_operation* operation = s_pending_operations_head; operation != nullptr;) {
|
||||
DETOUR_CHECK(mach_vm_protect(port, (mach_vm_address_t)operation->target, operation->trampoline->restore_code_size, false, operation->perm));
|
||||
|
||||
if (operation->kind == detour_operation_kind_attach) {
|
||||
if (operation->trampoline) {
|
||||
internal_detour_free_trampoline(operation->trampoline);
|
||||
operation->trampoline = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
detour_operation* next = operation->next;
|
||||
free(operation);
|
||||
operation = next;
|
||||
}
|
||||
s_pending_operations_head = nullptr;
|
||||
|
||||
// Make sure the trampoline pages are no longer writable.
|
||||
internal_detour_runnable_trampoline_regions();
|
||||
|
||||
// Resume any suspended threads.
|
||||
for (detour_pending_thread* thread = s_pending_threads_head; thread != nullptr;) {
|
||||
// There is nothing we can do if this fails.
|
||||
DETOUR_CHECK(thread_resume(thread->thread));
|
||||
|
||||
detour_pending_thread* next = thread->next;
|
||||
free(thread);
|
||||
thread = next;
|
||||
}
|
||||
s_pending_threads_head = nullptr;
|
||||
s_transaction_thread = THREAD_NULL;
|
||||
|
||||
return err_none;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue