#include "utils.hpp" #include #include #include #include #include #include "il2cpp.hpp" struct enum_so_info { const char* name; void* base_addr; }; static int get_so_base_callback(struct dl_phdr_info *info, size_t size, void *data) { auto* enum_info = (enum_so_info *)data; if (info->dlpi_name && strstr(info->dlpi_name, enum_info->name)) { enum_info->base_addr = (void*)info->dlpi_addr; } return 0; } void* Utils::get_so_base_address(const std::string& name) { enum_so_info so_info = {name.c_str(), nullptr}; dl_iterate_phdr(get_so_base_callback, &so_info); if (so_info.base_addr) { SPDLOG_INFO("Found {} at {}", name.c_str(), so_info.base_addr); return so_info.base_addr; } // TODO: throw exception instead of returning nullptr return nullptr; } static LuaScriptMgr_get_Inst get_lua_script_mgr_get_inst() { Il2CppDomain* domain = il2cpp_domain_get(); size_t assembly_count = 0; Il2CppAssembly** assemblies = il2cpp_domain_get_assemblies(domain, &assembly_count); Il2CppClass* cls = nullptr; for (size_t i = 0; i < assembly_count; ++i) { Il2CppImage* image = il2cpp_assembly_get_image(assemblies[i]); Il2CppClass* klass = il2cpp_class_from_name(image, "", "LuaScriptMgr"); if (klass != nullptr) { cls = klass; break; } } if (cls != nullptr) { MethodInfo* method_info = il2cpp_class_get_method_from_name(cls, "get_Inst", 0); if (method_info != nullptr) { auto method = reinterpret_cast(method_info->methodPointer); SPDLOG_INFO("Found LuaScriptMgr.get_Inst at {}", (void*)method_info->methodPointer); return method; } } SPDLOG_ERROR("Failed to get LuaScriptMgr.get_Inst"); throw std::runtime_error("Failed to get LuaScriptMgr.get_Inst"); } lua_State* Utils::get_lua_state() { LuaScriptMgr_get_Inst get_instance = get_lua_script_mgr_get_inst(); struct LuaScriptMgr_o* lua_script_mgr = get_instance(); LuaInterface_LuaState_o* luaState = nullptr; while (luaState == nullptr) { luaState = lua_script_mgr->fields.luaState; std::this_thread::sleep_for(std::chrono::seconds(1)); } SPDLOG_INFO("lua_State: {}", (void*)luaState->fields.L); // std::this_thread::sleep_for(std::chrono::seconds(10)); return (lua_State*)luaState->fields.L; } std::string Utils::Lua::get_type_name(sol::type t) { switch (t) { case sol::type::nil: return "nil"; case sol::type::boolean: return "boolean"; case sol::type::lightuserdata: return "lightuserdata"; case sol::type::number: return "number"; case sol::type::string: return "string"; case sol::type::table: return "table"; case sol::type::function: return "function"; case sol::type::userdata: return "userdata"; case sol::type::thread: return "thread"; case sol::type::poly: return "poly"; default: return "unknown"; } } std::string Utils::Lua::get_type_name(sol::object& o) { return get_type_name(o.get_type()); } void Utils::Lua::print_table_fields_type(sol::table& t) { for (auto& p : t) { if (p.first.get_type() == sol::type::string) { if (p.second.get_type() == sol::type::number) { SPDLOG_INFO("[{}] = {}", p.first.as(), p.second.as()); } else if (p.second.get_type() == sol::type::boolean) { SPDLOG_INFO("[{}] = {}", p.first.as(), p.second.as()); } else if (p.second.get_type() == sol::type::string) { SPDLOG_INFO("[{}] = {}", p.first.as(), p.second.as()); } else { SPDLOG_INFO("[{}] -> {}", p.first.as(), Utils::Lua::get_type_name(p.second)); } } else { if (p.second.get_type() == sol::type::number) { SPDLOG_INFO("[{}] = {}", p.first.as(), p.second.as()); } else if (p.second.get_type() == sol::type::boolean) { SPDLOG_INFO("[{}] = {}", p.first.as(), p.second.as()); } else if (p.second.get_type() == sol::type::string) { SPDLOG_INFO("[{}] = {}", p.first.as(), p.second.as()); } else { SPDLOG_INFO("[{}] -> {}", p.first.as(), Utils::Lua::get_type_name(p.second)); } } } } void Utils::Lua::print_traceback(sol::this_state& L) { sol::state_view state(L); sol::function trace = state["debug"]["traceback"]; std::string trace_str = trace(); SPDLOG_INFO("trace: {}", trace_str); } void Utils::Lua::print_object(sol::object& obj) { auto type = obj.get_type(); if (type == sol::type::nil) { SPDLOG_INFO("[nil]"); } else if (type == sol::type::boolean) { bool b = obj.as(); SPDLOG_INFO("[boolean] = {}", b); } else if (type == sol::type::number){ double number = obj.as(); SPDLOG_INFO("[number] = {}", number); } else if (type == sol::type::string) { std::string str = obj.as(); SPDLOG_INFO("[string] = {}", str); } else if (type == sol::type::table) { SPDLOG_INFO("[table]"); sol::table table = obj; print_table_fields_type(table); } else if (type == sol::type::function) { SPDLOG_INFO("[function]"); } else if (type == sol::type::userdata) { SPDLOG_INFO("[userdata]"); } else if (type == sol::type::thread) { SPDLOG_INFO("[thread]"); } else if (type == sol::type::poly) { SPDLOG_INFO("[poly]"); } else { SPDLOG_INFO("Unknown type: {}", static_cast(type)); } }