Beispiel #1
0
        public override void OnApplicationStart()
        {
            var category = MelonPreferences.CreateCategory(SettingsCategory, "Friends+ Home");

            StartupName = category.CreateEntry(SettingStartupName, nameof(InstanceAccessType.FriendsOfGuests), "Startup instance type");
            ButtonName  = category.CreateEntry(SettingButtonName, nameof(InstanceAccessType.FriendsOfGuests), "\"Go Home\" instance type");

            if (MelonHandler.Mods.Any(it => it.Info.Name == "UI Expansion Kit" && !it.Info.Version.StartsWith("0.1.")))
            {
                RegisterUix2Extension();
            }

            foreach (var methodInfo in typeof(VRCFlowManager).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly))
            {
                if (methodInfo.ReturnType != typeof(void) || methodInfo.GetParameters().Length != 0)
                {
                    continue;
                }

                if (!XrefScanner.XrefScan(methodInfo).Any(it => it.Type == XrefType.Global && it.ReadAsObject()?.ToString() == "Going to Home Location: "))
                {
                    continue;
                }

                MelonLogger.Msg($"Patched {methodInfo.Name}");
                HarmonyInstance.Patch(methodInfo, postfix: new HarmonyMethod(AccessTools.Method(typeof(FriendsPlusHomeMod), nameof(GoHomePatch))));
            }

            DoAfterUiManagerInit(OnUiManagerInit);
        }
Beispiel #2
0
        internal static void XrefDump(this MethodBase methodBase)
        {
            MelonLogger.Msg("Scanning Method: " + methodBase.Name);
            foreach (XrefInstance instance in XrefScanner.XrefScan(methodBase))
            {
                switch (instance.Type)
                {
                case XrefType.Global:
                    MelonLogger.Msg($"\tGlobal Instance: {instance.ReadAsObject()?.ToString()}");
                    break;

                case XrefType.Method:
                    var resolved = instance.TryResolve();
                    if (resolved == null)
                    {
                        MelonLogger.Msg("\tNull Method Instance");
                    }
                    else
                    {
                        MelonLogger.Msg($"\tMethod Instance: {resolved.DeclaringType?.Name} {resolved.Name}");
                    }
                    break;

                default:
                    break;
                }
            }
            MelonLogger.Msg("");
        }
        public static void ReloadAllAvatars(bool excludeSelf)
        {
            // xref yoinked from https://github.com/loukylor/VRC-Mods/commit/11abd2a62caaae5d0f817e20a0f6852d632da6bb#diff-ba8a2891e08655e0e158ea852ef76bbcb1ea58fc831a6817875c5efa21fef610R84 (GPLv3)
            if (ourReloadAllAvatarsDelegate == null)
            {
                var targetMethod = typeof(VRCPlayer).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly)
                                   .Single(it => it.Name.StartsWith("Method_Public_Void_Boolean_") && it.GetParameters().Length == 1 &&
                                           it.GetParameters()[0].IsOptional && XrefScanner.UsedBy(it).Any(jt =>
                {
                    if (jt.Type != XrefType.Method)
                    {
                        return(false);
                    }
                    var m = jt.TryResolve();
                    if (m == null)
                    {
                        return(false);
                    }
                    return(m.DeclaringType == typeof(FeaturePermissionManager) &&
                           m.Name.StartsWith("Method_Public_Void_"));
                }));
                ourReloadAllAvatarsDelegate = (Action <VRCPlayer, bool>)Delegate.CreateDelegate(typeof(Action <VRCPlayer, bool>), targetMethod);
            }

            ourReloadAllAvatarsDelegate(VRCPlayer.field_Internal_Static_VRCPlayer_0, excludeSelf);
        }
        public static bool HasMethodCallWithName(this MethodInfo m, string txt)
        {
            foreach (var instance in XrefScanner.XrefScan(m))
            {
                try
                {
                    if (instance.Type == XrefType.Method && instance.TryResolve() != null)
                    {
                        try
                        {
                            if (instance.TryResolve().Name.Contains(txt))
                            {
                                return(true);
                            }
                        }
                        catch (Exception e)
                        {
                            MelonLogger.Warning(e);
                        }
                    }
                }
                catch
                {
                }
            }

            return(false);
        }
        public static bool SameClassMethodCallCount(this MethodInfo m, int calls)
        {
            var count = 0;

            foreach (var instance in XrefScanner.XrefScan(m))
            {
                try
                {
                    if (instance.Type == XrefType.Method && instance.TryResolve() != null)
                    {
                        try
                        {
                            if (m.DeclaringType == instance.TryResolve().DeclaringType)
                            {
                                count++;
                            }
                        }
                        catch (Exception e)
                        {
                            MelonLogger.Warning(e);
                        }
                    }
                }
                catch
                {
                }
            }

            return(count == calls);
        }
        public static void Refresh(this SimpleAvatarPedestal pedestal, ApiAvatar avatar)
        {
            if (ourPedestalRefreshDelegate == null)
            {
                var target = typeof(SimpleAvatarPedestal)
                             .GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance).Single(
                    it =>
                {
                    if (it.ReturnType != typeof(void))
                    {
                        return(false);
                    }
                    var parameters = it.GetParameters();
                    if (parameters.Length != 1 || parameters[0].ParameterType != typeof(ApiAvatar))
                    {
                        return(false);
                    }

                    return(XrefScanner.XrefScan(it).Any(jt =>
                                                        jt.Type == XrefType.Global && jt.ReadAsObject()?.ToString() == "local"));
                });

                ourPedestalRefreshDelegate =
                    (PedestalRefreshDelegate)Delegate.CreateDelegate(typeof(PedestalRefreshDelegate), target);
            }

            ourPedestalRefreshDelegate(pedestal, avatar);
        }
        public static void DisplayErrorAvatar(this SimpleAvatarPedestal @this)
        {
            if (ourDisplayErrorAvatarDelegate == null)
            {
                var target = typeof(SimpleAvatarPedestal)
                             .GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance).Single(
                    it =>
                {
                    if (it.ReturnType != typeof(void) || it.Name.Contains("_PDM_"))
                    {
                        return(false);
                    }
                    var parameters = it.GetParameters();
                    if (parameters.Length != 0)
                    {
                        return(false);
                    }

                    return(XrefScanner.XrefScan(it).Any(jt =>
                                                        jt.Type == XrefType.Global && jt.ReadAsObject()?.ToString() == "local"));
                });

                ourDisplayErrorAvatarDelegate =
                    (DisplayErrorAvatarDelegate)Delegate.CreateDelegate(typeof(DisplayErrorAvatarDelegate), target);
            }

            ourDisplayErrorAvatarDelegate(@this);
        }
Beispiel #8
0
        internal static void HookFullBodyController(HarmonyInstance harmony)
        {
            var fbbIkInit = typeof(VRCFbbIkController).GetMethod(nameof(VRCFbbIkController.Method_Public_Virtual_Final_New_Boolean_VRC_AnimationController_Animator_VRCPlayer_Boolean_0));

            harmony.Patch(fbbIkInit, new HarmonyMethod(typeof(FullBodyHandling), nameof(FbbIkInitPrefix)),
                          new HarmonyMethod(typeof(FullBodyHandling), nameof(FbbIkInitPostfix)));

            harmony.Patch(AccessTools.Method(typeof(FullBodyBipedIK), nameof(FullBodyBipedIK.LateUpdate)),
                          new HarmonyMethod(typeof(FullBodyHandling), nameof(LateUpdatePrefix)));
            harmony.Patch(AccessTools.Method(typeof(FullBodyBipedIK), nameof(FullBodyBipedIK.Update)),
                          new HarmonyMethod(typeof(FullBodyHandling), nameof(UpdatePrefix)));
            harmony.Patch(AccessTools.Method(typeof(FullBodyBipedIK), nameof(FullBodyBipedIK.FixedUpdate)),
                          new HarmonyMethod(typeof(FullBodyHandling), nameof(FixedUpdatePrefix)));

            harmony.Patch(AccessTools.Method(typeof(VRCTrackingManager), nameof(VRCTrackingManager.Method_Public_Static_Boolean_String_0)),
                          new HarmonyMethod(typeof(FullBodyHandling), nameof(IsCalibratedForAvatarPrefix)));

            var userOfHfts = typeof(VRCFbbIkController)
                             .GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly).Single(it =>
                                                                                                                         XrefScanner.XrefScan(it).Any(jt => jt.Type == XrefType.Global && jt.ReadAsObject()?.ToString() ==
                                                                                                                                                      "Hip+Feet Tracking: 3 trackers found, tracking enabled."));
            var hipAndFeetTrackingSupported = (MethodInfo)XrefScanner.XrefScan(userOfHfts).Single(it =>
            {
                if (it.Type != XrefType.Method)
                {
                    return(false);
                }
                var resolved = it.TryResolve() as MethodInfo;
                return(resolved != null && resolved.DeclaringType == typeof(VRCTrackingManager) && resolved.IsStatic &&
                       resolved.GetParameters().Length == 0 && resolved.ReturnType == typeof(bool));
            }).TryResolve();

            harmony.Patch(hipAndFeetTrackingSupported, new HarmonyMethod(typeof(FullBodyHandling), nameof(PatchHipAndFeetTracking)));
            ourIsFbtSupported = (Func <bool>)Delegate.CreateDelegate(typeof(Func <bool>), hipAndFeetTrackingSupported);
        }
Beispiel #9
0
        public override void OnApplicationStart()
        {
            MelonPrefs.RegisterCategory(SettingsCategory, "Friends+ Home");
            MelonPrefs.RegisterString(SettingsCategory, SettingStartupName, nameof(ApiWorldInstance.AccessType.FriendsOfGuests), "Startup instance type");
            MelonPrefs.RegisterString(SettingsCategory, SettingButtonName, nameof(ApiWorldInstance.AccessType.FriendsOfGuests), "\"Go Home\" instance type");

            if (MelonHandler.Mods.Any(it => it.Info.Name == "UI Expansion Kit" && !it.Info.Version.StartsWith("0.1.")))
            {
                RegisterUix2Extension();
            }

            foreach (var methodInfo in typeof(VRCFlowManagerVRC).GetMethods())
            {
                if (methodInfo.ReturnType != typeof(void) || methodInfo.GetParameters().Length != 0)
                {
                    continue;
                }

                if (!XrefScanner.XrefScan(methodInfo).Any(it => it.Type == XrefType.Global && it.ReadAsObject()?.ToString() == "Going to Home Location: "))
                {
                    continue;
                }

                MelonLogger.Log($"Patched {methodInfo.Name}");
                harmonyInstance.Patch(methodInfo, postfix: new HarmonyMethod(AccessTools.Method(typeof(FriendsPlusHomeMod), nameof(GoHomePatch))));
            }
        }
Beispiel #10
0
        internal static bool PatchMethods()
        {
            try
            {
                // Left room
                MethodInfo onLeftRoomMethod = typeof(NetworkManager).GetMethod(
                    nameof(NetworkManager.OnLeftRoom),
                    BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
                    null,
                    Type.EmptyTypes,
                    null);
                origOnLeftRoom = Patch <OnLeftRoom>(onLeftRoomMethod, GetDetour(nameof(OnLeftRoomPatch)));
            }
            catch (Exception e)
            {
                MelonLogger.Error("Failed to patch OnLeftRoom\n" + e.Message);
                return(false);
            }

            try
            {
                // Faded to and joined and initialized room
                MethodInfo fadeMethod = typeof(VRCUiManager).GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly).First(
                    m => m.Name.StartsWith("Method_Public_Void_String_Single_Action_") &&
                    m.Name.IndexOf("PDM", StringComparison.OrdinalIgnoreCase) == -1 &&
                    m.GetParameters().Length == 3);
                origFadeTo = Patch <FadeTo>(fadeMethod, GetDetour(nameof(FadeToPatch)));
            }
            catch (Exception e)
            {
                MelonLogger.Error("Failed to patch FadeTo\n" + e.Message);
                return(false);
            }

            if (Utilities.IsInVR)
            {
                try
                {
                    // Fixes spinning issue
                    // TL;DR Prevents the tracking manager from applying rotational force
                    MethodInfo applyPlayerMotionMethod = typeof(VRCTrackingManager).GetMethods(BindingFlags.Public | BindingFlags.Static)
                                                         .Where(
                        m => m.Name.StartsWith("Method_Public_Static_Void_Vector3_Quaternion") &&
                        !m.Name.Contains("_PDM_")).First(
                        m => XrefScanner.UsedBy(m).Any(
                            xrefInstance => xrefInstance.Type == XrefType.Method &&
                            xrefInstance.TryResolve()?.ReflectedType
                            ?.Equals(typeof(VRC_StationInternal))
                            == true));
                    origApplyPlayerMotion = Patch <ApplyPlayerMotion>(applyPlayerMotionMethod, GetDetour(nameof(ApplyPlayerMotionPatch)));
                }
                catch (Exception e)
                {
                    MelonLogger.Error("Failed to patch ApplyPlayerMotion\n" + e.Message);
                    return(false);
                }
            }

            return(true);
        }
Beispiel #11
0
        public static void DumpTypesUsedBy(this MethodBase methodBase)
        {
            if (methodBase == null)
            {
                return;
            }

            MelonLogger.Msg("Types used by method: " + methodBase.Name);
            HashSet <string> usedTypes = new HashSet <string>();

            foreach (XrefInstance instance in XrefScanner.UsedBy(methodBase))
            {
                if (instance.Type == XrefType.Method)
                {
                    var resolved = instance.TryResolve();
                    if (resolved == null)
                    {
                        continue;
                    }
                    if (usedTypes.Contains(resolved.DeclaringType?.ToString()))
                    {
                        continue;
                    }
                    usedTypes.Add(resolved.DeclaringType?.ToString());
                    MelonLogger.Msg(resolved.DeclaringType?.ToString());
                }
            }
        }
Beispiel #12
0
        public static void HookVrIkInit(HarmonyInstance harmony)
        {
            var vrikInitMethod = typeof(VRCVrIkController).GetMethod(nameof(VRCVrIkController
                                                                            .Method_Public_Virtual_Final_New_Boolean_VRC_AnimationController_Animator_VRCPlayer_Boolean_0));

            harmony.Patch(vrikInitMethod,
                          postfix: new HarmonyMethod(AccessTools.Method(typeof(VrIkHandling), nameof(VrikInitPatch))));

            var canSupportHipTracking = XrefScanner.XrefScan(typeof(VRCVrIkController)
                                                             .GetMethods(BindingFlags.Public | BindingFlags.Instance |
                                                                         BindingFlags.DeclaredOnly).Single(it =>
                                                                                                           XrefScanner.XrefScan(it).Any(jt =>
                                                                                                                                        jt.Type == XrefType.Global && "Hip Tracking: Hip tracker found. tracking enabled." ==
                                                                                                                                        jt.ReadAsObject()?.ToString()))).Single(it =>
            {
                if (it.Type != XrefType.Method)
                {
                    return(false);
                }
                var resolved = it.TryResolve();
                if (resolved == null || !resolved.IsStatic)
                {
                    return(false);
                }
                return(resolved.DeclaringType == typeof(VRCTrackingManager) && resolved is MethodInfo mi && mi.ReturnType == typeof(bool) && resolved.GetParameters().Length == 0);
            }).TryResolve();

            harmony.Patch(canSupportHipTracking, new HarmonyMethod(AccessTools.Method(typeof(VrIkHandling), nameof(SupportsHipTrackingPatch))));
        }
        public static bool HasMethodWithDeclaringType(this MethodInfo m, Type declaringType)
        {
            foreach (var instance in XrefScanner.XrefScan(m))
            {
                try
                {
                    if (instance.Type == XrefType.Method && instance.TryResolve() != null)
                    {
                        try
                        {
                            if (declaringType == instance.TryResolve().DeclaringType)
                            {
                                return(true);
                            }
                        }
                        catch (Exception e)
                        {
                            MelonLogger.Warning(e);
                        }
                    }
                }
                catch
                {
                }
            }

            return(false);
        }
Beispiel #14
0
 public static bool CheckUsed(MethodInfo method, string methodName)
 {
     try
     {
         return(XrefScanner.UsedBy(method)
                .Where(instance => instance.TryResolve() != null && instance.TryResolve().Name.Contains(methodName)).Any());
     }
     catch { }
     return(false);
 }
Beispiel #15
0
        // Yoinked with love from https://github.com/BenjaminZehowlt/DynamicBonesSafety/blob/master/DynamicBonesSafetyMod.cs
        // or well, the current alternative https://github.com/loukylor/VRC-Mods/blob/main/PlayerList/Utilities/Xref.cs

        public static bool CheckMethod(MethodInfo method, string match)
        {
            try
            {
                return(XrefScanner.XrefScan(method)
                       .Where(instance => instance.Type == XrefType.Global && instance.ReadAsObject().ToString().Contains(match)).Any());
            }
            catch { }
            return(false);
        }
Beispiel #16
0
 /// <summary>
 /// Checks the methods the given method is used by.
 /// Note: the methods passed into the predicate may be false.
 /// </summary>
 /// <param name="method">The method to check</param>
 /// <param name="predicate">The predicate to check the methods against</param>
 /// <returns>true if the predicate returned true any times, otherwise false</returns>
 public static bool CheckUsedBy(MethodBase method, Func <MethodBase, bool> predicate)
 {
     foreach (XrefInstance instance in XrefScanner.UsedBy(method))
     {
         if (instance.Type == XrefType.Method && predicate.Invoke(instance.TryResolve()))
         {
             return(true);
         }
     }
     return(false);
 }
Beispiel #17
0
 /// <summary>
 /// Checks the strings in the given method's body.
 /// </summary>
 /// <param name="method">The method to check</param>
 /// <param name="predicate">The predicate to check the strings against</param>
 /// <returns>true if the predicate returned true any times, otherwise false</returns>
 public static bool CheckStrings(MethodInfo method, Func <string, bool> predicate)
 {
     foreach (XrefInstance instance in XrefScanner.XrefScan(method))
     {
         if (instance.Type == XrefType.Global && predicate.Invoke(instance.ReadAsObject().ToString()))
         {
             return(true);
         }
     }
     return(false);
 }
Beispiel #18
0
        private static bool checkXref(MethodBase m, string match)
        {
            try
            {
                return(XrefScanner.XrefScan(m).Any(
                           instance => instance.Type == XrefType.Global && instance.ReadAsObject() != null && instance.ReadAsObject().ToString()
                           .Equals(match, StringComparison.OrdinalIgnoreCase)));
            }
            catch { } // ignored

            return(false);
        }
Beispiel #19
0
        internal static void Patch(HarmonyInstance harmonyInstance)
        {
            try
            {
                // Left room
                harmonyInstance.Patch(
                    typeof(NetworkManager).GetMethod(nameof(NetworkManager.OnLeftRoom), BindingFlags.Public | BindingFlags.Instance),
                    postfix: GetPatch(nameof(LeftWorldPatch)));
            }
            catch (Exception e)
            {
                MelonLogger.Error("Failed to patch OnLeftRoom\n" + e.Message);
            }

            try
            {
                // Faded to and joined and initialized room
                IEnumerable <MethodInfo> fadeMethods = typeof(VRCUiManager).GetMethods()
                                                       .Where(
                    m => m.Name.StartsWith("Method_Public_Void_String_Single_Action_") &&
                    m.GetParameters().Length == 3);
                foreach (MethodInfo fadeMethod in fadeMethods)
                {
                    harmonyInstance.Patch(fadeMethod, postfix: GetPatch(nameof(JoinedRoomPatch)));
                }
            }
            catch (Exception e)
            {
                MelonLogger.Error("Failed to patch FadeTo Initialized room\n" + e.Message);
            }

            if (Utilities.IsInVR)
            {
                try
                {
                    // Fixes spinning issue
                    // TL;DR Prevents the tracking manager from applying rotational force
                    harmonyInstance.Patch(
                        typeof(VRCTrackingManager).GetMethods(BindingFlags.Public | BindingFlags.Static)
                        .Where(m => m.Name.StartsWith("Method_Public_Static_Void_Vector3_Quaternion") && !m.Name.Contains("_PDM_"))
                        .First(
                            m => XrefScanner.UsedBy(m).Any(
                                xrefInstance => xrefInstance.Type == XrefType.Method &&
                                xrefInstance.TryResolve()?.ReflectedType?.Equals(typeof(VRC_StationInternal))
                                == true)),
                        GetPatch(nameof(ApplyPlayerMotionPatch)));
                }
                catch (Exception e)
                {
                    MelonLogger.Error("Failed to patch ApplyPlayerMotion\n" + e.Message);
                }
            }
        }
Beispiel #20
0
        public static void ScanMethod(MethodInfo m)
        {
            MelonLogger.Msg($"Scanning: {m.FullDescription()}");
            foreach (var instance in XrefScanner.XrefScan(m))
            {
                try
                {
                    if (instance.Type == XrefType.Global && instance.ReadAsObject() != null)
                    {
                        try
                        {
                            MelonLogger.Msg($"   Found String: {instance.ReadAsObject().ToString()}");
                        }
                        catch
                        {
                        }
                    }
                    else if (instance.Type == XrefType.Method && instance.TryResolve() != null)
                    {
                        try
                        {
                            MelonLogger.Msg($"   Found Method: {instance.TryResolve().FullDescription()}");
                        }
                        catch
                        {
                        }
                    }
                }
                catch
                {
                }
            }

            foreach (var instance in XrefScanner.UsedBy(m))
            {
                try
                {
                    if (instance.Type == XrefType.Method && instance.TryResolve() != null)
                    {
                        try
                        {
                            MelonLogger.Msg($"   Found Used By Method: {instance.TryResolve().FullDescription()}");
                        }
                        catch
                        {
                        }
                    }
                }
                catch
                {
                }
            }
        }
Beispiel #21
0
 private static bool CheckUsed(MethodBase methodBase, string methodName)
 {
     if (!string.IsNullOrEmpty(methodName))
     {
         try
         {
             return(XrefScanner.UsedBy(methodBase)
                    .Where(instance => instance.TryResolve() != null && instance.TryResolve().Name.Contains(methodName)).Any());
         }
         catch (Exception e)
         {
             MelonLogger.Error($"Failed to Xref CheckUsed:\n{e}");
         }
     }
     return(false);
 }
Beispiel #22
0
        /// <summary>
        /// Dumps the Xref information on a method.
        /// This is for DEBUG PURPOSES ONLY.
        /// </summary>
        /// <param name="method">The method to dump information on</param>
        public static void DumpXrefInfo(MethodBase method)
        {
            try
            {
                MelonLogger.Msg(ConsoleColor.Yellow, $"Scanning {method.Name}");

                MelonLogger.Msg(ConsoleColor.Yellow, $"Checking UsedBy");
                DumpScan(XrefScanner.UsedBy(method));

                MelonLogger.Msg(ConsoleColor.Green, "Checking Using");
                DumpScan(XrefScanner.XrefScan(method));
            }
            catch (Exception ex)
            {
                MelonLogger.Error($"Failed while dumping {method.Name}:\n{ex}");
            }
        }
Beispiel #23
0
 private static bool checkXrefNoStrings(MethodBase m)
 {
     try
     {
         foreach (XrefInstance instance in XrefScanner.XrefScan(m))
         {
             if (instance.Type != XrefType.Global || instance.ReadAsObject() == null)
             {
                 continue;
             }
             return(false);
         }
         return(true);
     }
     catch (Exception e) { MelonLogger.Log("For loop failed:" + e); }
     return(false);
 }
Beispiel #24
0
 public static bool CheckXrefStrings(MethodBase m, List <string> keywords)
 {
     try
     {
         foreach (string keyword in keywords)
         {
             if (!XrefScanner.XrefScan(m).Any(
                     instance => instance.Type == XrefType.Global && instance.ReadAsObject() != null && instance.ReadAsObject().ToString()
                     .Equals(keyword, StringComparison.OrdinalIgnoreCase)))
             {
                 return(false);
             }
         }
         return(true);
     }
     catch { }
     return(false);
 }
        public static bool HasStringLiterals(this MethodInfo m)
        {
            foreach (var instance in XrefScanner.XrefScan(m))
            {
                try
                {
                    if (instance.Type == XrefType.Global && instance.ReadAsObject() != null)
                    {
                        return(true);
                    }
                }
                catch
                {
                }
            }

            return(false);
        }
        public static bool CheckStringsCount(this MethodInfo m, int count)
        {
            var total = 0;

            foreach (var instance in XrefScanner.XrefScan(m))
            {
                try
                {
                    if (instance.Type == XrefType.Global && instance.ReadAsObject() != null)
                    {
                        total++;
                    }
                }
                catch
                {
                }
            }

            return(total == count);
        }
Beispiel #27
0
 public static bool CheckUsing(MethodInfo method, string match, Type type)
 {
     foreach (XrefInstance instance in XrefScanner.XrefScan(method))
     {
         if (instance.Type == XrefType.Method)
         {
             try
             {
                 if (instance.TryResolve().DeclaringType == type && instance.TryResolve().Name.Contains(match))
                 {
                     return(true);
                 }
             }
             catch
             {
             }
         }
     }
     return(false);
 }
Beispiel #28
0
        private static bool XRefScanForMethod(this MethodBase methodBase, string methodName = null, string reflectedType = null)
        {
            var found = false;

            foreach (XrefInstance xref in XrefScanner.XrefScan(methodBase))
            {
                if (xref.Type != XrefType.Method)
                {
                    continue;
                }

                MethodBase resolved = xref.TryResolve();
                if (resolved == null)
                {
                    continue;
                }

                if (!string.IsNullOrEmpty(methodName))
                {
                    found = !string.IsNullOrEmpty(resolved.Name) && resolved.Name.IndexOf(methodName, StringComparison.OrdinalIgnoreCase) >= 0;
                }


                if (!string.IsNullOrEmpty(reflectedType))
                {
                    found = !string.IsNullOrEmpty(resolved.ReflectedType?.Name) &&
                            resolved.ReflectedType.Name.IndexOf(reflectedType, StringComparison.OrdinalIgnoreCase) >= 0;
                }

                if (found)
                {
                    return(true);
                }
            }

            return(false);
        }
Beispiel #29
0
 //Gracefully taken from Advanced Invites https://github.com/Psychloor/AdvancedInvites/blob/master/AdvancedInvites/Utilities.cs#L356
 public static bool XRefScanFor(this MethodBase methodBase, string searchTerm)
 {
     return(XrefScanner.XrefScan(methodBase).Any(
                xref => xref.Type == XrefType.Global && xref.ReadAsObject()?.ToString().IndexOf(searchTerm, StringComparison.OrdinalIgnoreCase) >= 0));
 }
Beispiel #30
0
        public static void DoPass(RewriteGlobalContext context, UnhollowerOptions options)
        {
            if (string.IsNullOrEmpty(options.GameAssemblyPath))
            {
                Pass15GenerateMemberContexts.HasObfuscatedMethods = false;
                return;
            }

            using var mappedFile = MemoryMappedFile.CreateFromFile(options.GameAssemblyPath, FileMode.Open, null, 0, MemoryMappedFileAccess.Read);
            using var accessor   = mappedFile.CreateViewAccessor(0, 0, MemoryMappedFileAccess.Read);

            IntPtr gameAssemblyPtr;

            unsafe
            {
                byte *fileStartPtr = null;
                accessor.SafeMemoryMappedViewHandle.AcquirePointer(ref fileStartPtr);
                gameAssemblyPtr = (IntPtr)fileStartPtr;
            }

            context.HasGcWbarrierFieldWrite = FindByteSequence(gameAssemblyPtr, accessor.Capacity, nameof(IL2CPP.il2cpp_gc_wbarrier_set_field));

            if (!Pass15GenerateMemberContexts.HasObfuscatedMethods)
            {
                return;
            }

            var methodToCallersMap = new ConcurrentDictionary <long, List <XrefInstance> >();
            var methodToCalleesMap = new ConcurrentDictionary <long, List <long> >();

            context.MethodStartAddresses.Sort();

            // Scan xrefs
            context.Assemblies.SelectMany(it => it.Types).SelectMany(it => it.Methods).AsParallel().ForAll(
                originalTypeMethod =>
            {
                var address = originalTypeMethod.FileOffset;
                if (address == 0)
                {
                    return;
                }

                if (!options.NoXrefCache)
                {
                    var pair = XrefScanMetadataGenerationUtil.FindMetadataInitForMethod(originalTypeMethod, (long)gameAssemblyPtr);
                    originalTypeMethod.MetadataInitFlagRva  = pair.FlagRva;
                    originalTypeMethod.MetadataInitTokenRva = pair.TokenRva;
                }

                var nextMethodStart = context.MethodStartAddresses.BinarySearch(address + 1);
                if (nextMethodStart < 0)
                {
                    nextMethodStart = ~nextMethodStart;
                }
                var length = nextMethodStart >= context.MethodStartAddresses.Count ? 1024 * 1024 : (context.MethodStartAddresses[nextMethodStart] - address);
                foreach (var callTargetGlobal in XrefScanner.XrefScanImpl(XrefScanner.DecoderForAddress(IntPtr.Add(gameAssemblyPtr, (int)address), (int)length), true))
                {
                    var callTarget = callTargetGlobal.RelativeToBase((long)gameAssemblyPtr + originalTypeMethod.FileOffset - originalTypeMethod.Rva);
                    if (callTarget.Type == XrefType.Method)
                    {
                        var targetRelative = (long)callTarget.Pointer;
                        methodToCallersMap.GetOrAdd(targetRelative, _ => new List <XrefInstance>()).AddLocked(new XrefInstance(XrefType.Method, (IntPtr)originalTypeMethod.Rva, callTarget.FoundAt));
                        methodToCalleesMap.GetOrAdd(originalTypeMethod.Rva, _ => new List <long>()).AddLocked(targetRelative);
                    }

                    if (!options.NoXrefCache)
                    {
                        originalTypeMethod.XrefScanResults.Add(callTarget);
                    }
                }
            });

            MapOfCallers = methodToCallersMap;

            void MarkMethodAlive(long address)
            {
                if (!NonDeadMethods.Add(address))
                {
                    return;
                }
                if (!methodToCalleesMap.TryGetValue(address, out var calleeList))
                {
                    return;
                }

                foreach (var callee in calleeList)
                {
                    MarkMethodAlive(callee);
                }
            }

            // Now decided which of them are possible dead code
            foreach (var assemblyRewriteContext in context.Assemblies)
            {
                foreach (var typeRewriteContext in assemblyRewriteContext.Types)
                {
                    foreach (var methodRewriteContext in typeRewriteContext.Methods)
                    {
                        if (methodRewriteContext.FileOffset == 0)
                        {
                            continue;
                        }

                        var originalMethod = methodRewriteContext.OriginalMethod;
                        if (!originalMethod.Name.IsObfuscated(options) || originalMethod.IsVirtual)
                        {
                            MarkMethodAlive(methodRewriteContext.Rva);
                        }
                    }
                }
            }
        }