2022-02-16 07:24:35 +08:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <concepts>
|
|
|
|
|
2022-02-19 21:22:09 +08:00
|
|
|
#include "lsplant.hpp"
|
2022-02-19 03:47:26 +08:00
|
|
|
#include "jni_helper.hpp"
|
|
|
|
|
2022-02-16 07:24:35 +08:00
|
|
|
#define CONCATENATE(a, b) a##b
|
|
|
|
|
2022-02-19 03:47:26 +08:00
|
|
|
#define CREATE_HOOK_STUB_ENTRY(SYM, RET, FUNC, PARAMS, DEF) \
|
|
|
|
inline static struct : public lsplant::Hooker<RET PARAMS, decltype(CONCATENATE(SYM, _tstr))>{ \
|
|
|
|
inline static RET replace PARAMS DEF} FUNC
|
2022-02-16 07:24:35 +08:00
|
|
|
|
2022-02-19 03:47:26 +08:00
|
|
|
#define CREATE_MEM_HOOK_STUB_ENTRY(SYM, RET, FUNC, PARAMS, DEF) \
|
|
|
|
inline static struct : public lsplant::MemHooker<RET PARAMS, \
|
|
|
|
decltype(CONCATENATE(SYM, _tstr))>{ \
|
|
|
|
inline static RET replace PARAMS DEF} FUNC
|
2022-02-16 07:24:35 +08:00
|
|
|
|
2022-02-19 03:47:26 +08:00
|
|
|
#define RETRIEVE_FUNC_SYMBOL(name, ...) \
|
|
|
|
(name##Sym = reinterpret_cast<name##Type>(lsplant::Dlsym(handler, __VA_ARGS__)))
|
2022-02-16 07:24:35 +08:00
|
|
|
|
2022-02-19 03:47:26 +08:00
|
|
|
#define RETRIEVE_MEM_FUNC_SYMBOL(name, ...) \
|
|
|
|
(name##Sym = reinterpret_cast<name##Type::FunType>(lsplant::Dlsym(handler, __VA_ARGS__)))
|
2022-02-16 07:24:35 +08:00
|
|
|
|
2022-02-19 03:47:26 +08:00
|
|
|
#define RETRIEVE_FIELD_SYMBOL(name, ...) \
|
|
|
|
(name = reinterpret_cast<decltype(name)>(lsplant::Dlsym(handler, __VA_ARGS__)))
|
2022-02-16 07:24:35 +08:00
|
|
|
|
2022-02-19 03:47:26 +08:00
|
|
|
#define CREATE_FUNC_SYMBOL_ENTRY(ret, func, ...) \
|
|
|
|
typedef ret (*func##Type)(__VA_ARGS__); \
|
|
|
|
inline static ret (*func##Sym)(__VA_ARGS__); \
|
|
|
|
inline static ret func(__VA_ARGS__)
|
2022-02-16 07:24:35 +08:00
|
|
|
|
2022-02-19 03:47:26 +08:00
|
|
|
#define CREATE_MEM_FUNC_SYMBOL_ENTRY(ret, func, thiz, ...) \
|
|
|
|
using func##Type = lsplant::MemberFunction<ret(__VA_ARGS__)>; \
|
|
|
|
inline static func##Type func##Sym; \
|
|
|
|
inline static ret func(thiz, ##__VA_ARGS__)
|
2022-02-16 07:24:35 +08:00
|
|
|
|
|
|
|
namespace lsplant {
|
|
|
|
|
|
|
|
using HookHandler = InitInfo;
|
|
|
|
|
2022-02-19 03:47:26 +08:00
|
|
|
template <char... chars>
|
2022-02-16 07:24:35 +08:00
|
|
|
struct tstring : public std::integer_sequence<char, chars...> {
|
2022-02-19 03:47:26 +08:00
|
|
|
inline constexpr static const char *c_str() { return str_; }
|
2022-02-16 07:24:35 +08:00
|
|
|
|
2022-02-19 03:47:26 +08:00
|
|
|
inline constexpr operator std::string_view() const { return {c_str(), sizeof...(chars)}; }
|
2022-02-16 07:24:35 +08:00
|
|
|
|
|
|
|
private:
|
2022-02-19 03:47:26 +08:00
|
|
|
inline static constexpr char str_[]{chars..., '\0'};
|
2022-02-16 07:24:35 +08:00
|
|
|
};
|
|
|
|
|
2022-02-19 03:47:26 +08:00
|
|
|
template <typename T, T... chars>
|
|
|
|
inline constexpr tstring<chars...> operator""_tstr() {
|
2022-02-16 07:24:35 +08:00
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
2022-02-19 03:47:26 +08:00
|
|
|
template <char... as, char... bs>
|
|
|
|
inline constexpr tstring<as..., bs...> operator+(const tstring<as...> &, const tstring<bs...> &) {
|
2022-02-16 07:24:35 +08:00
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
2022-02-19 03:47:26 +08:00
|
|
|
template <char... as>
|
2022-02-16 07:24:35 +08:00
|
|
|
inline constexpr auto operator+(const std::string &a, const tstring<as...> &) {
|
2022-02-19 03:47:26 +08:00
|
|
|
char b[]{as..., '\0'};
|
2022-02-16 07:24:35 +08:00
|
|
|
return a + b;
|
|
|
|
}
|
|
|
|
|
2022-02-19 03:47:26 +08:00
|
|
|
template <char... as>
|
2022-02-16 07:24:35 +08:00
|
|
|
inline constexpr auto operator+(const tstring<as...> &, const std::string &b) {
|
2022-02-19 03:47:26 +08:00
|
|
|
char a[]{as..., '\0'};
|
2022-02-16 07:24:35 +08:00
|
|
|
return a + b;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void *Dlsym(const HookHandler &handle, const char *name) {
|
|
|
|
return handle.art_symbol_resolver(name);
|
|
|
|
}
|
|
|
|
|
2022-02-19 03:47:26 +08:00
|
|
|
template <typename Class, typename Return, typename T, typename... Args>
|
|
|
|
requires(std::is_same_v<T, void> ||
|
|
|
|
std::is_same_v<Class, T>) inline static auto memfun_cast(Return (*func)(T *, Args...)) {
|
2022-02-16 07:24:35 +08:00
|
|
|
union {
|
|
|
|
Return (Class::*f)(Args...);
|
|
|
|
|
|
|
|
struct {
|
|
|
|
decltype(func) p;
|
|
|
|
std::ptrdiff_t adj;
|
|
|
|
} data;
|
2022-02-19 03:47:26 +08:00
|
|
|
} u{.data = {func, 0}};
|
2022-02-16 07:24:35 +08:00
|
|
|
static_assert(sizeof(u.f) == sizeof(u.data), "Try different T");
|
|
|
|
return u.f;
|
|
|
|
}
|
|
|
|
|
2022-02-19 03:47:26 +08:00
|
|
|
template <std::same_as<void> T, typename Return, typename... Args>
|
2022-02-16 07:24:35 +08:00
|
|
|
inline auto memfun_cast(Return (*func)(T *, Args...)) {
|
|
|
|
return memfun_cast<T>(func);
|
|
|
|
}
|
|
|
|
|
2022-02-19 03:47:26 +08:00
|
|
|
template <typename, typename = void>
|
2022-02-16 07:24:35 +08:00
|
|
|
class MemberFunction;
|
|
|
|
|
2022-02-19 03:47:26 +08:00
|
|
|
template <typename This, typename Return, typename... Args>
|
2022-02-16 07:24:35 +08:00
|
|
|
class MemberFunction<Return(Args...), This> {
|
|
|
|
using SelfType = MemberFunction<Return(This *, Args...), This>;
|
|
|
|
using ThisType = std::conditional_t<std::is_same_v<This, void>, SelfType, This>;
|
2022-02-19 03:47:26 +08:00
|
|
|
using MemFunType = Return (ThisType::*)(Args...);
|
|
|
|
|
2022-02-16 07:24:35 +08:00
|
|
|
public:
|
|
|
|
using FunType = Return (*)(This *, Args...);
|
2022-02-19 03:47:26 +08:00
|
|
|
|
2022-02-16 07:24:35 +08:00
|
|
|
private:
|
|
|
|
MemFunType f_ = nullptr;
|
2022-02-19 03:47:26 +08:00
|
|
|
|
2022-02-16 07:24:35 +08:00
|
|
|
public:
|
|
|
|
MemberFunction() = default;
|
|
|
|
|
|
|
|
MemberFunction(FunType f) : f_(memfun_cast<ThisType>(f)) {}
|
|
|
|
|
|
|
|
MemberFunction(MemFunType f) : f_(f) {}
|
|
|
|
|
|
|
|
Return operator()(This *thiz, Args... args) {
|
|
|
|
return (reinterpret_cast<ThisType *>(thiz)->*f_)(std::forward<Args>(args)...);
|
|
|
|
}
|
|
|
|
|
2022-02-19 03:47:26 +08:00
|
|
|
inline operator bool() { return f_ != nullptr; }
|
2022-02-16 07:24:35 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
// deduction guide
|
2022-02-19 03:47:26 +08:00
|
|
|
template <typename This, typename Return, typename... Args>
|
|
|
|
MemberFunction(Return (*f)(This *, Args...)) -> MemberFunction<Return(Args...), This>;
|
2022-02-16 07:24:35 +08:00
|
|
|
|
2022-02-19 03:47:26 +08:00
|
|
|
template <typename This, typename Return, typename... Args>
|
|
|
|
MemberFunction(Return (This::*f)(Args...)) -> MemberFunction<Return(Args...), This>;
|
2022-02-16 07:24:35 +08:00
|
|
|
|
2022-02-19 03:47:26 +08:00
|
|
|
template <typename, typename>
|
2022-02-16 07:24:35 +08:00
|
|
|
struct Hooker;
|
|
|
|
|
2022-02-19 03:47:26 +08:00
|
|
|
template <typename Ret, typename... Args, char... cs>
|
2022-02-16 07:24:35 +08:00
|
|
|
struct Hooker<Ret(Args...), tstring<cs...>> {
|
|
|
|
inline static Ret (*backup)(Args...) = nullptr;
|
|
|
|
|
|
|
|
inline static constexpr std::string_view sym = tstring<cs...>{};
|
|
|
|
};
|
|
|
|
|
2022-02-19 03:47:26 +08:00
|
|
|
template <typename, typename>
|
2022-02-16 07:24:35 +08:00
|
|
|
struct MemHooker;
|
2022-02-19 03:47:26 +08:00
|
|
|
template <typename Ret, typename This, typename... Args, char... cs>
|
2022-02-16 07:24:35 +08:00
|
|
|
struct MemHooker<Ret(This, Args...), tstring<cs...>> {
|
|
|
|
inline static MemberFunction<Ret(Args...)> backup;
|
|
|
|
inline static constexpr std::string_view sym = tstring<cs...>{};
|
|
|
|
};
|
|
|
|
|
2022-02-19 03:47:26 +08:00
|
|
|
template <typename T>
|
2022-02-16 07:24:35 +08:00
|
|
|
concept HookerType = requires(T a) {
|
|
|
|
a.backup;
|
|
|
|
a.replace;
|
|
|
|
};
|
|
|
|
|
2022-02-19 03:47:26 +08:00
|
|
|
template <HookerType T>
|
2022-02-16 07:24:35 +08:00
|
|
|
inline static bool HookSymNoHandle(const HookHandler &handler, void *original, T &arg) {
|
|
|
|
if (original) {
|
2022-02-19 03:47:26 +08:00
|
|
|
if constexpr (is_instance_v<decltype(arg.backup), MemberFunction>) {
|
2022-02-16 07:24:35 +08:00
|
|
|
void *backup = handler.inline_hooker(original, reinterpret_cast<void *>(arg.replace));
|
|
|
|
arg.backup = reinterpret_cast<typename decltype(arg.backup)::FunType>(backup);
|
|
|
|
} else {
|
2022-02-19 03:47:26 +08:00
|
|
|
arg.backup = reinterpret_cast<decltype(arg.backup)>(
|
|
|
|
handler.inline_hooker(original, reinterpret_cast<void *>(arg.replace)));
|
2022-02-16 07:24:35 +08:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-19 03:47:26 +08:00
|
|
|
template <HookerType T>
|
2022-02-16 07:24:35 +08:00
|
|
|
inline static bool HookSym(const HookHandler &handler, T &arg) {
|
|
|
|
auto original = handler.art_symbol_resolver(arg.sym);
|
|
|
|
return HookSymNoHandle(handler, original, arg);
|
|
|
|
}
|
|
|
|
|
2022-02-19 03:47:26 +08:00
|
|
|
template <HookerType T, HookerType... Args>
|
2022-02-16 07:24:35 +08:00
|
|
|
inline static bool HookSyms(const HookHandler &handle, T &first, Args &...rest) {
|
|
|
|
if (!(HookSym(handle, first) || ... || HookSym(handle, rest))) {
|
2022-02-19 03:59:06 +08:00
|
|
|
__android_log_print(ANDROID_LOG_ERROR,
|
|
|
|
#ifdef LOG_TAG
|
|
|
|
LOG_TAG,
|
|
|
|
#else
|
|
|
|
"HookHelper",
|
|
|
|
#endif
|
|
|
|
"Hook Fails: %*s", static_cast<int>(first.sym.size()),
|
|
|
|
first.sym.data());
|
2022-02-16 07:24:35 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2022-02-19 03:47:26 +08:00
|
|
|
} // namespace lsplant
|