RMHook/src/core/tinyhook/objcrt.c
2025-10-23 21:41:46 +02:00

66 lines
1.9 KiB
C

#include <objc/runtime.h> // objc_*, ...
#ifndef COMPACT
#include <mach/mach_error.h> // mach_error_string()
#include <printf.h> // fprintf()
#endif
#include "../include/tinyhook.h"
Method ocrt_method(const char *cls, const char *sel, bool type) {
Method oc_method = NULL;
Class oc_class = objc_getClass(cls);
SEL oc_selector = sel_registerName(sel);
if (type == CLASS_METHOD) {
oc_method = class_getClassMethod(oc_class, oc_selector);
} else if (type == INSTANCE_METHOD) {
oc_method = class_getInstanceMethod(oc_class, oc_selector);
}
#ifndef COMPACT
else {
fprintf(stderr, "ocrt_method: invalid method type: %d\n", type);
}
#endif
return oc_method;
}
void *ocrt_impl(const char *cls, const char *sel, bool type) {
return method_getImplementation(ocrt_method(cls, sel, type));
}
static Method ensure_method(const char *cls, const char *sel);
int ocrt_swap(const char *cls1, const char *sel1, const char *cls2, const char *sel2) {
Method oc_method1 = ensure_method(cls1, sel1);
Method oc_method2 = ensure_method(cls2, sel2);
if (oc_method1 == NULL || oc_method2 == NULL) {
return 1;
}
method_exchangeImplementations(oc_method1, oc_method2);
return 0;
}
int ocrt_hook(const char *cls, const char *sel, void *destination, void **origin) {
Method oc_method = ensure_method(cls, sel);
if (oc_method == NULL) {
return 1;
}
void *origin_imp = method_setImplementation(oc_method, destination);
if (origin != NULL) {
*origin = origin_imp;
}
return 0;
}
static Method ensure_method(const char *cls, const char *sel) {
Method oc_method = ocrt_method(cls, sel, CLASS_METHOD);
if (oc_method == NULL) {
oc_method = ocrt_method(cls, sel, INSTANCE_METHOD);
}
#ifndef COMPACT
if (oc_method == NULL) {
fprintf(stderr, "ensure_method: method not found!\n");
}
#endif
return oc_method;
}