gkms-local/app/src/main/cpp/GakumasLocalify/Il2cppUtils.hpp

248 lines
9.0 KiB
C++

#pragma once
#include "../deps/UnityResolve/UnityResolve.hpp"
#include "Log.h"
#include <memory>
namespace Il2cppUtils {
using namespace GakumasLocal;
struct Il2CppClassHead {
// The following fields are always valid for a Il2CppClass structure
const void* image;
void* gc_desc;
const char* name;
const char* namespaze;
};
struct MethodInfo {
uintptr_t methodPointer;
uintptr_t invoker_method;
const char* name;
uintptr_t klass;
//const Il2CppType* return_type;
//const ParameterInfo* parameters;
const void* return_type;
const void* parameters;
uintptr_t methodDefinition;
uintptr_t genericContainer;
uint32_t token;
uint16_t flags;
uint16_t iflags;
uint16_t slot;
uint8_t parameters_count;
uint8_t is_generic : 1;
uint8_t is_inflated : 1;
uint8_t wrapper_type : 1;
uint8_t is_marshaled_from_native : 1;
};
struct Il2CppObject
{
union
{
void* klass;
void* vtable;
};
void* monitor;
};
enum Il2CppTypeEnum
{
IL2CPP_TYPE_END = 0x00, /* End of List */
IL2CPP_TYPE_VOID = 0x01,
IL2CPP_TYPE_BOOLEAN = 0x02,
IL2CPP_TYPE_CHAR = 0x03,
IL2CPP_TYPE_I1 = 0x04,
IL2CPP_TYPE_U1 = 0x05,
IL2CPP_TYPE_I2 = 0x06,
IL2CPP_TYPE_U2 = 0x07,
IL2CPP_TYPE_I4 = 0x08,
IL2CPP_TYPE_U4 = 0x09,
IL2CPP_TYPE_I8 = 0x0a,
IL2CPP_TYPE_U8 = 0x0b,
IL2CPP_TYPE_R4 = 0x0c,
IL2CPP_TYPE_R8 = 0x0d,
IL2CPP_TYPE_STRING = 0x0e,
IL2CPP_TYPE_PTR = 0x0f,
IL2CPP_TYPE_BYREF = 0x10,
IL2CPP_TYPE_VALUETYPE = 0x11,
IL2CPP_TYPE_CLASS = 0x12,
IL2CPP_TYPE_VAR = 0x13,
IL2CPP_TYPE_ARRAY = 0x14,
IL2CPP_TYPE_GENERICINST = 0x15,
IL2CPP_TYPE_TYPEDBYREF = 0x16,
IL2CPP_TYPE_I = 0x18,
IL2CPP_TYPE_U = 0x19,
IL2CPP_TYPE_FNPTR = 0x1b,
IL2CPP_TYPE_OBJECT = 0x1c,
IL2CPP_TYPE_SZARRAY = 0x1d,
IL2CPP_TYPE_MVAR = 0x1e,
IL2CPP_TYPE_CMOD_REQD = 0x1f,
IL2CPP_TYPE_CMOD_OPT = 0x20,
IL2CPP_TYPE_INTERNAL = 0x21,
IL2CPP_TYPE_MODIFIER = 0x40,
IL2CPP_TYPE_SENTINEL = 0x41,
IL2CPP_TYPE_PINNED = 0x45,
IL2CPP_TYPE_ENUM = 0x55
};
typedef struct Il2CppType
{
void* dummy;
unsigned int attrs : 16;
Il2CppTypeEnum type : 8;
unsigned int num_mods : 6;
unsigned int byref : 1;
unsigned int pinned : 1;
} Il2CppType;
struct Il2CppReflectionType
{
Il2CppObject object;
const Il2CppType* type;
};
struct Resolution_t {
int width;
int height;
int herz;
};
UnityResolve::Class* GetClass(const std::string& assemblyName, const std::string& nameSpaceName,
const std::string& className) {
const auto assembly = UnityResolve::Get(assemblyName);
if (!assembly) {
Log::ErrorFmt("GetMethodPointer error: assembly %s not found.", assemblyName.c_str());
return nullptr;
}
const auto pClass = assembly->Get(className, nameSpaceName);
if (!pClass) {
Log::ErrorFmt("GetMethodPointer error: Class %s::%s not found.", nameSpaceName.c_str(), className.c_str());
return nullptr;
}
return pClass;
}
/*
UnityResolve::Method* GetMethodIl2cpp(const char* assemblyName, const char* nameSpaceName,
const char* className, const char* methodName, const int argsCount) {
auto domain = UnityResolve::Invoke<void*>("il2cpp_domain_get");
UnityResolve::Invoke<void*>("il2cpp_thread_attach", domain);
auto image = UnityResolve::Invoke<void*>("il2cpp_assembly_get_image", domain);
if (!image) {
Log::ErrorFmt("GetMethodIl2cpp error: assembly %s not found.", assemblyName);
return nullptr;
}
Log::Debug("GetMethodIl2cpp 1");
auto klass = UnityResolve::Invoke<void*>("il2cpp_class_from_name", image, nameSpaceName, className);
if (!klass) {
Log::ErrorFmt("GetMethodIl2cpp error: Class %s::%s not found.", nameSpaceName, className);
return nullptr;
}
Log::Debug("GetMethodIl2cpp 2");
auto ret = UnityResolve::Invoke<UnityResolve::Method*>("il2cpp_class_get_method_from_name", klass, methodName, argsCount);
if (!ret) {
Log::ErrorFmt("GetMethodIl2cpp error: method %s::%s.%s not found.", nameSpaceName, className, methodName);
return nullptr;
}
return ret;
}*/
UnityResolve::Method* GetMethod(const std::string& assemblyName, const std::string& nameSpaceName,
const std::string& className, const std::string& methodName, const std::vector<std::string>& args = {}) {
const auto assembly = UnityResolve::Get(assemblyName);
if (!assembly) {
Log::ErrorFmt("GetMethod error: assembly %s not found.", assemblyName.c_str());
return nullptr;
}
const auto pClass = assembly->Get(className, nameSpaceName);
if (!pClass) {
Log::ErrorFmt("GetMethod error: Class %s::%s not found.", nameSpaceName.c_str(), className.c_str());
return nullptr;
}
auto method = pClass->Get<UnityResolve::Method>(methodName, args);
if (!method) {
/*
method = GetMethodIl2cpp(assemblyName.c_str(), nameSpaceName.c_str(), className.c_str(),
methodName.c_str(), args.size() == 0 ? -1 : args.size());
if (!method) {
Log::ErrorFmt("GetMethod error: method %s::%s.%s not found.", nameSpaceName.c_str(), className.c_str(), methodName.c_str());
return nullptr;
}*/
Log::ErrorFmt("GetMethod error: method %s::%s.%s not found.", nameSpaceName.c_str(), className.c_str(), methodName.c_str());
return nullptr;
}
return method;
}
void* GetMethodPointer(const std::string& assemblyName, const std::string& nameSpaceName,
const std::string& className, const std::string& methodName, const std::vector<std::string>& args = {}) {
auto method = GetMethod(assemblyName, nameSpaceName, className, methodName, args);
if (method) {
return method->function;
}
return nullptr;
}
void* il2cpp_resolve_icall(const char* s) {
return UnityResolve::Invoke<void*>("il2cpp_resolve_icall", s);
}
Il2CppClassHead* get_class_from_instance(const void* instance) {
return static_cast<Il2CppClassHead*>(*static_cast<void* const*>(std::assume_aligned<alignof(void*)>(instance)));
}
MethodInfo* il2cpp_class_get_method_from_name(void* klass, const char* name, int argsCount) {
return UnityResolve::Invoke<MethodInfo*>("il2cpp_class_get_method_from_name", klass, name, argsCount);
}
void* find_nested_class(void* klass, std::predicate<void*> auto&& predicate)
{
void* iter{};
while (const auto curNestedClass = UnityResolve::Invoke<void*>("il2cpp_class_get_nested_types", klass, &iter))
{
if (static_cast<decltype(predicate)>(predicate)(curNestedClass))
{
return curNestedClass;
}
}
return nullptr;
}
void* find_nested_class_from_name(void* klass, const char* name)
{
return find_nested_class(klass, [name = std::string_view(name)](void* nestedClass) {
return static_cast<Il2CppClassHead*>(nestedClass)->name == name;
});
}
template <typename RType>
auto ClassGetFieldValue(void* obj, UnityResolve::Field* field) -> RType {
return *reinterpret_cast<RType*>(reinterpret_cast<uintptr_t>(obj) + field->offset);
}
template <typename RType>
auto ClassSetFieldValue(void* obj, UnityResolve::Field* field, RType value) -> void {
*reinterpret_cast<RType*>(reinterpret_cast<uintptr_t>(obj) + field->offset) = value;
}
void* get_system_class_from_reflection_type_str(const char* typeStr, const char* assemblyName = "mscorlib") {
using Il2CppString = UnityResolve::UnityType::String;
static auto assemblyLoad = reinterpret_cast<void* (*)(Il2CppString*)>(
GetMethodPointer("mscorlib.dll", "System.Reflection",
"Assembly", "Load", {"*"})
);
static auto assemblyGetType = reinterpret_cast<Il2CppReflectionType * (*)(void*, Il2CppString*)>(
GetMethodPointer("mscorlib.dll", "System.Reflection",
"Assembly", "GetType", {"*"})
);
static auto reflectionAssembly = assemblyLoad(Il2CppString::New(assemblyName));
auto reflectionType = assemblyGetType(reflectionAssembly, Il2CppString::New(typeStr));
return UnityResolve::Invoke<void*>("il2cpp_class_from_system_type", reflectionType);
}
}