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); }
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); }
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); }
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)))); } }
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); }
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()); } } }
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); }
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); }
// 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); }
/// <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); }
/// <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); }
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); }
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); } } }
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 { } } }
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); }
/// <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}"); } }
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); }
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); }
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); }
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); }
//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)); }
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); } } } } }