mirror of
https://github.com/geode-sdk/geode.git
synced 2025-03-22 02:45:49 -04:00
Add objc hooking utilities
This commit is contained in:
parent
409815acb3
commit
a31d07237f
5 changed files with 103 additions and 4 deletions
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
1.1.1
|
||||
1.2.0
|
|
@ -11,3 +11,4 @@
|
|||
#include "utils/general.hpp"
|
||||
#include "utils/timer.hpp"
|
||||
#include "utils/MiniFunction.hpp"
|
||||
#include "utils/ObjcHook.hpp"
|
||||
|
|
68
loader/include/Geode/utils/ObjcHook.hpp
Normal file
68
loader/include/Geode/utils/ObjcHook.hpp
Normal file
|
@ -0,0 +1,68 @@
|
|||
#pragma once
|
||||
|
||||
#include "../loader/Hook.hpp"
|
||||
#include "Result.hpp"
|
||||
|
||||
namespace geode {
|
||||
namespace hook {
|
||||
/**
|
||||
* Add a new Objective-C method to a class. This method will be created
|
||||
* using the imp provided. If the method already exists, it won't do
|
||||
* anything.
|
||||
* @param className The name of the class to add the method to
|
||||
* @param selectorName The name of the method to add
|
||||
* @param imp The implementation of the method
|
||||
* @returns Ok() if the method was added successfully, or an error.
|
||||
*/
|
||||
Result<> addObjcMethod(std::string const& className, std::string const& selectorName, void* imp);
|
||||
|
||||
/**
|
||||
* Get the implementation of an Objective-C method.
|
||||
* @param className The name of the class whose method to get
|
||||
* @param selectorName The name of the method to get
|
||||
* @returns The implementation of the method, or an error.
|
||||
*/
|
||||
Result<void*> getObjcMethodImp(std::string const& className, std::string const& selectorName);
|
||||
}
|
||||
|
||||
class ObjcHook {
|
||||
public:
|
||||
/**
|
||||
* Create a hook for an Objective-C method
|
||||
* @param className The name of the class whose method to hook
|
||||
* @param selectorName The name of the method to hook
|
||||
* @param function The detour to run when the method is called
|
||||
* @returns The created hook, or an error.
|
||||
*/
|
||||
template <class Func>
|
||||
static Result<Hook*> create(std::string const& className, std::string const& selectorName, Func function, tulip::hook::HookMetadata const& metadata = tulip::hook::HookMetadata()) {
|
||||
GEODE_UNWRAP_INTO(auto imp, geode::hook::getObjcMethodImp(className, selectorName));
|
||||
|
||||
return Ok(Hook::create(
|
||||
getMod(),
|
||||
imp,
|
||||
function,
|
||||
className + "::" + selectorName,
|
||||
tulip::hook::TulipConvention::Default,
|
||||
metadata
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a hook for a new Objective-C method. This method will be
|
||||
* created with a dummy implementation that does nothing.
|
||||
* @param className The name of the class whose method to hook
|
||||
* @param selectorName The name of the method to hook
|
||||
* @param function The detour to run when the method is called
|
||||
* @param empty A function that takes no arguments and returns nothing.
|
||||
* This is used to create a dummy method that can be hooked.
|
||||
* @returns The created hook, or an error.
|
||||
*/
|
||||
template <class Func>
|
||||
static Result<Hook*> create(std::string const& className, std::string const& selectorName, Func function, void(*empty)(), tulip::hook::HookMetadata const& metadata = tulip::hook::HookMetadata()) {
|
||||
GEODE_UNWRAP(geode::hook::addObjcMethod(className, selectorName, (void*)empty));
|
||||
|
||||
return ObjcHook::create(className, selectorName, function, metadata);
|
||||
}
|
||||
};
|
||||
}
|
|
@ -7,9 +7,7 @@ using namespace geode::prelude;
|
|||
|
||||
#include <Geode/loader/Dirs.hpp>
|
||||
#import <AppKit/AppKit.h>
|
||||
#include <Geode/utils/web.hpp>
|
||||
#include <Geode/utils/file.hpp>
|
||||
#include <Geode/utils/cocos.hpp>
|
||||
#include <Geode/Utils.hpp>
|
||||
#include <Geode/binding/GameManager.hpp>
|
||||
|
||||
bool utils::clipboard::write(std::string const& data) {
|
||||
|
@ -235,4 +233,29 @@ void geode::utils::game::restart() {
|
|||
), CCDirector::get()->getRunningScene(), false);
|
||||
}
|
||||
|
||||
Result<> geode::hook::addObjcMethod(std::string const& className, std::string const& selectorName, void* imp) {
|
||||
auto cls = objc_getClass(className.c_str());
|
||||
if (!cls)
|
||||
return Err("Class not found");
|
||||
|
||||
auto sel = sel_registerName(selectorName.c_str());
|
||||
|
||||
class_addMethod(cls, sel, (IMP)imp, "v@:");
|
||||
|
||||
return Ok();
|
||||
}
|
||||
Result<void*> geode::hook::getObjcMethodImp(std::string const& className, std::string const& selectorName) {
|
||||
auto cls = objc_getClass(className.c_str());
|
||||
if (!cls)
|
||||
return Err("Class not found");
|
||||
|
||||
auto sel = sel_registerName(selectorName.c_str());
|
||||
|
||||
auto method = class_getInstanceMethod(cls, sel);
|
||||
if (!method)
|
||||
return Err("Method not found");
|
||||
|
||||
return Ok((void*)method_getImplementation(method));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -184,4 +184,11 @@ void geode::utils::game::restart() {
|
|||
exit(0);
|
||||
}
|
||||
|
||||
Result<> geode::hook::addObjcMethod(std::string const& className, std::string const& selectorName, void* imp) {
|
||||
return Err("Wrong platform");
|
||||
}
|
||||
Result<void*> geode::hook::getObjcMethodImp(std::string const& className, std::string const& selectorName) {
|
||||
return Err("Wrong platform");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue