public static IntPtr GetIl2CppNestedType(IntPtr enclosingType, string nestedTypeName) { if (enclosingType == IntPtr.Zero) { return(IntPtr.Zero); } IntPtr iter = IntPtr.Zero; IntPtr nestedTypePtr; if (il2cpp_class_is_inflated(enclosingType)) { LogSupport.Trace("Original class was inflated, falling back to reflection"); if (GetNestedTypeViaReflection == null) { // todo: clean up this ugly reflection hack GetNestedTypeViaReflection = AppDomain.CurrentDomain.GetAssemblies() .FirstOrDefault(it => it.GetName().Name == "UnhollowerRuntimeLib") ?.GetType("UnhollowerRuntimeLib.RuntimeReflectionHelper") ?.GetMethod("GetNestedTypeViaReflection", BindingFlags.Static | BindingFlags.Public)?.CreateDelegate(typeof(Func <IntPtr, string, IntPtr>)) as Func <IntPtr, string, IntPtr>; } var result = GetNestedTypeViaReflection?.Invoke(enclosingType, nestedTypeName); if (result != null) { return(result.Value); } } while ((nestedTypePtr = il2cpp_class_get_nested_types(enclosingType, ref iter)) != IntPtr.Zero) { if (Marshal.PtrToStringAnsi(il2cpp_class_get_name(nestedTypePtr)) == nestedTypeName) { return(nestedTypePtr); } } LogSupport.Error($"Nested type {nestedTypeName} on {Marshal.PtrToStringAnsi(il2cpp_class_get_name(enclosingType))} not found!"); return(IntPtr.Zero); }
public static IntPtr GetIl2CppMethod(IntPtr clazz, string methodName, params string[] argTypes) { if (clazz == IntPtr.Zero) { return(NativeStructUtils.GetMethodInfoForMissingMethod(methodName + "(" + string.Join(", ", argTypes) + ")")); } for (var index = 0; index < argTypes.Length; index++) { var argType = argTypes[index]; argTypes[index] = Regex.Replace(argType, "\\`\\d+", "").Replace('/', '.'); } var methodsSeen = 0; var lastMethod = IntPtr.Zero; IntPtr iter = IntPtr.Zero; IntPtr method; while ((method = il2cpp_class_get_methods(clazz, ref iter)) != IntPtr.Zero) { if (Marshal.PtrToStringAnsi(il2cpp_method_get_name(method)) != methodName) { continue; } if (il2cpp_method_get_param_count(method) != argTypes.Length) { continue; } methodsSeen++; lastMethod = method; var badType = false; for (var i = 0; i < argTypes.Length; i++) { var paramType = il2cpp_method_get_param(method, (uint)i); var typeName = Marshal.PtrToStringAnsi(il2cpp_type_get_name(paramType)); if (typeName != argTypes[i]) { badType = true; break; } } if (badType) { continue; } return(method); } var className = Marshal.PtrToStringAnsi(il2cpp_class_get_name(clazz)); LogSupport.Trace($"Method {className}::{methodName} was stubbed with a random matching method of the same name"); if (methodsSeen == 1) { return(lastMethod); } LogSupport.Trace($"Unable to find method {className}::{methodName}; signature follows"); foreach (var argType in argTypes) { LogSupport.Trace($" {argType}"); } LogSupport.Trace("Available methods of this name follow:"); iter = IntPtr.Zero; while ((method = il2cpp_class_get_methods(clazz, ref iter)) != IntPtr.Zero) { if (Marshal.PtrToStringAnsi(il2cpp_method_get_name(method)) != methodName) { continue; } var nParams = il2cpp_method_get_param_count(method); LogSupport.Trace("Method starts"); for (var i = 0; i < nParams; i++) { var paramType = il2cpp_method_get_param(method, (uint)i); var typeName = Marshal.PtrToStringAnsi(il2cpp_type_get_name(paramType)); LogSupport.Trace($" {typeName}"); } return(method); } return(NativeStructUtils.GetMethodInfoForMissingMethod(className + "::" + methodName + "(" + string.Join(", ", argTypes) + ")")); }