Decompiled source of UnityDebuggerAssistant v1.4.2

plugins/UnityDebuggerAssistant.dll

Decompiled 4 months ago
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using MonoMod.Cil;
using MonoMod.RuntimeDetour;
using UnityDebuggerAssistant.Components;
using UnityDebuggerAssistant.Filtering;
using UnityDebuggerAssistant.Patches;
using UnityDebuggerAssistant.Processing;
using UnityDebuggerAssistant.Utils;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("LethalCompanyModding")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("A BepinEx plugin that captures Harmony and Monomod (wip) hook information at\r\n      runtime to ease debugging")]
[assembly: AssemblyFileVersion("1.4.2.0")]
[assembly: AssemblyInformationalVersion("1.4.2+79a459d07838d68bc658c4def630236d2d21cdcd")]
[assembly: AssemblyProduct("UnityDebuggerAssistant")]
[assembly: AssemblyTitle("dev.mamallama.lcm.dbgasst")]
[assembly: AssemblyMetadata("RepositoryUrl", "gitgithub.com:RobynLlama/UnityDebuggerAssistant.git")]
[assembly: AssemblyVersion("1.4.2.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class IsReadOnlyAttribute : Attribute
	{
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
[BepInPlugin("dev.mamallama.lcm.dbgasst", "UnityDebuggerAssistant", "1.4.2")]
public class UDAPlugin : BaseUnityPlugin
{
	internal static ManualLogSource? Log;

	internal static PluginConfiguration UDASettings;

	private void Awake()
	{
		//IL_014f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0155: Expected O, but got Unknown
		//IL_018a: Unknown result type (might be due to invalid IL or missing references)
		//IL_018f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0198: Expected O, but got Unknown
		Log = ((BaseUnityPlugin)this).Logger;
		UDASettings = new PluginConfiguration(((BaseUnityPlugin)this).Config);
		UDABlacklist.UpdateLists_Internal();
		StringBuilder stringBuilder = new StringBuilder("\r\n\r\n>------------------------------------------------------------------------<\r\n  Unity Debugger assistant is loaded and receiving exceptions!\r\n\r\n  Note: That UDA will catch ALL exceptions, even harmless ones\r\n  Please ONLY report logs to modders if you have an issue with their mod\r\n\r\n  Config:\r\n");
		stringBuilder.Append("    Using Per-Exception Whitelist: ");
		stringBuilder.AppendLine(UDASettings.EnableWhitelistPerException.Value.ToString());
		stringBuilder.Append("    Using Per-Exception Blacklist: ");
		stringBuilder.AppendLine(UDASettings.EnableBlacklistPerException.Value.ToString());
		stringBuilder.Append("    Using Per-Frame Whitelist: ");
		stringBuilder.AppendLine(UDASettings.EnableWhitelistPerFrame.Value.ToString());
		stringBuilder.Append("    Using Per-Frame Blacklist: ");
		stringBuilder.AppendLine(UDASettings.EnableBlacklistPerFrame.Value.ToString());
		stringBuilder.Append("    Total Filters: ");
		stringBuilder.AppendLine((UDABlacklist.ExceptionBlackList.Count() + UDABlacklist.FrameBlackList.Count()).ToString());
		stringBuilder.AppendLine(">------------------------------------------------------------------------<");
		Log.LogMessage((object)stringBuilder);
		ILHook.OnDetour = (Func<ILHook, MethodBase, Manipulator, bool>)Delegate.Combine(ILHook.OnDetour, new Func<ILHook, MethodBase, Manipulator, bool>(UDAPatchListener.ListenForPatch));
		Harmony val = new Harmony("dev.mamallama.lcm.dbgasst");
		val.PatchAll(typeof(ExceptionConstructorPatch));
		GameObject val2 = new GameObject("UDAMain", new Type[2]
		{
			typeof(UDAExceptionBroker),
			typeof(UDAPostChainloadRunner)
		})
		{
			hideFlags = (HideFlags)61
		};
		Object.DontDestroyOnLoad((Object)(object)val2);
	}
}
internal class PluginConfiguration
{
	public readonly ConfigEntry<bool> EnableWhitelistPerException = Config.Bind<bool>(new ConfigDefinition("ExceptionFilter", "WhitelistEnabled"), true, new ConfigDescription("The per-exception whitelist filters out exceptions that do not originate from common game assemblies or BepinEx plugins.\nDisable this to catch everything. Will increase the log file size.", (AcceptableValueBase)null, Array.Empty<object>()));

	public readonly ConfigEntry<bool> EnableWhitelistPerFrame = Config.Bind<bool>(new ConfigDefinition("FrameFilter", "WhitelistEnabled"), false, new ConfigDescription("The per-frame whitelist will remove frames inside of exceptions that do not originate from common game assemblies.\nEnable this to reduce log file size by cutting out less relevant frames", (AcceptableValueBase)null, Array.Empty<object>()));

	public readonly ConfigEntry<bool> EnableBlacklistPerException = Config.Bind<bool>(new ConfigDefinition("ExceptionFilter", "BlacklistEnabled"), false, new ConfigDescription("The per-exception blacklist filters out exceptions that match the given patterns.\nThis is useful if you know a specific assembly throws errors you can ignore", (AcceptableValueBase)null, Array.Empty<object>()));

	public readonly ConfigEntry<bool> EnableBlacklistPerFrame = Config.Bind<bool>(new ConfigDefinition("FrameFilter", "BlacklistEnabled"), false, new ConfigDescription("The per-frame blacklist filters out exceptions that match the given patterns.\nThis is useful if you know a specific assembly throws errors you can ignore", (AcceptableValueBase)null, Array.Empty<object>()));

	public readonly ConfigEntry<string> ExceptionBlacklist = Config.Bind<string>(new ConfigDefinition("ExceptionFilter", "Blacklist"), "UniverseLib.Mono, UnityExplorer.", new ConfigDescription("A comma-separated list of assembly names to ignore in exception processing\nThis will be matched against the beginning of each assembly name so e.g. `UnityEngine.` will match all UnityEngine assemblies", (AcceptableValueBase)null, Array.Empty<object>()));

	public readonly ConfigEntry<string> FrameBlacklist = Config.Bind<string>(new ConfigDefinition("FrameFilter", "Blacklist"), "mscorlib", new ConfigDescription("A comma-separated list of assembly names to ignore in individual frame processing\nThis will be matched against the beginning of each assembly name so e.g. `UnityEngine.` will match all UnityEngine assemblies", (AcceptableValueBase)null, Array.Empty<object>()));

	public PluginConfiguration(ConfigFile Config)
	{
	}//IL_000c: Unknown result type (might be due to invalid IL or missing references)
	//IL_001d: Unknown result type (might be due to invalid IL or missing references)
	//IL_0027: Expected O, but got Unknown
	//IL_0027: Expected O, but got Unknown
	//IL_0038: Unknown result type (might be due to invalid IL or missing references)
	//IL_0049: Unknown result type (might be due to invalid IL or missing references)
	//IL_0053: Expected O, but got Unknown
	//IL_0053: Expected O, but got Unknown
	//IL_0064: Unknown result type (might be due to invalid IL or missing references)
	//IL_0075: Unknown result type (might be due to invalid IL or missing references)
	//IL_007f: Expected O, but got Unknown
	//IL_007f: Expected O, but got Unknown
	//IL_0090: Unknown result type (might be due to invalid IL or missing references)
	//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
	//IL_00ab: Expected O, but got Unknown
	//IL_00ab: Expected O, but got Unknown
	//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
	//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
	//IL_00db: Expected O, but got Unknown
	//IL_00db: Expected O, but got Unknown
	//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
	//IL_0101: Unknown result type (might be due to invalid IL or missing references)
	//IL_010b: Expected O, but got Unknown
	//IL_010b: Expected O, but got Unknown

}
internal static class LCMPluginInfo
{
	public const string PLUGIN_GUID = "dev.mamallama.lcm.dbgasst";

	public const string PLUGIN_NAME = "UnityDebuggerAssistant";

	public const string PLUGIN_VERSION = "1.4.2";
}
namespace UnityDebuggerAssistant.Utils
{
	internal static class Helpers
	{
		internal static Assembly GetAssemblyByName(string name)
		{
			string name2 = name;
			return AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly assembly) => assembly.GetName().Name.Equals(name2, StringComparison.InvariantCultureIgnoreCase));
		}
	}
	public static class UDAPatchListener
	{
		internal static bool ListenForPatch(ILHook hook, MethodBase @base, Manipulator manipulator)
		{
			if ((object)@base == null || manipulator == null || hook == null || ((Delegate)(object)manipulator).Target == null)
			{
				ManualLogSource? log = UDAPlugin.Log;
				if (log != null)
				{
					log.LogInfo((object)"Skipping a null/empty patch");
				}
				return true;
			}
			UDAPatchStorage.AddPatchInformation(@base, ((Delegate)(object)manipulator).Target.GetType().Assembly);
			return true;
		}
	}
	internal static class UDAPatchStorage
	{
		private static readonly Dictionary<MethodBase, List<Assembly>> Patches = new Dictionary<MethodBase, List<Assembly>>();

		private static readonly Assembly HarmonyAssembly = typeof(Harmony).Assembly;

		internal static bool AddPatchInformation(MethodBase method, Assembly assembly)
		{
			if ((object)assembly == null || assembly == HarmonyAssembly)
			{
				return false;
			}
			if (!Patches.TryGetValue(method, out List<Assembly> value))
			{
				value = (Patches[method] = new List<Assembly>());
			}
			if (value.Contains(assembly))
			{
				return false;
			}
			value.Add(assembly);
			ManualLogSource? log = UDAPlugin.Log;
			if (log != null)
			{
				log.LogInfo((object)("blame " + assembly.GetName().Name + " for " + GeneralExtensions.FullDescription(method)));
			}
			return true;
		}

		internal static List<Assembly> GetPatchInformation(MethodBase method)
		{
			if (!Patches.TryGetValue(method, out List<Assembly> value))
			{
				return new List<Assembly>();
			}
			return value;
		}
	}
	public static class UDAPluginMarshal
	{
		internal static readonly Dictionary<Assembly, PluginInfo> InfoCache = new Dictionary<Assembly, PluginInfo>();

		public static void Run()
		{
			Stopwatch stopwatch = new Stopwatch();
			stopwatch.Start();
			Dictionary<string, PluginInfo>.KeyCollection keys = Chainloader.PluginInfos.Keys;
			foreach (string item in keys)
			{
				Assembly assembly = ((object)Chainloader.PluginInfos[item].Instance).GetType().Assembly;
				PluginInfo val = Chainloader.PluginInfos[item];
				if (val != null)
				{
					AddToInfoCache(assembly, val);
				}
			}
			stopwatch.Stop();
			ManualLogSource? log = UDAPlugin.Log;
			if (log != null)
			{
				log.LogInfo((object)$"BepinEx Plugins Marshaled in {stopwatch.ElapsedMilliseconds}ms");
			}
		}

		internal static bool AddToInfoCache(Assembly assembly, PluginInfo info)
		{
			if (InfoCache.ContainsKey(assembly))
			{
				return false;
			}
			InfoCache.Add(assembly, info);
			return true;
		}
	}
}
namespace UnityDebuggerAssistant.Processing
{
	public static class UDAExceptionHandler
	{
		public static void Handle(Exception ex)
		{
			int num = 0;
			MethodBase targetSite = ex.TargetSite;
			StackTrace stackTrace = new StackTrace(ex, fNeedFileInfo: true);
			Assembly assembly2 = targetSite?.DeclaringType.Assembly;
			bool flag = false;
			if ((object)assembly2 == null)
			{
				flag = true;
				_ = stackTrace.FrameCount;
				StackFrame[] frames = stackTrace.GetFrames();
				foreach (StackFrame stackFrame in frames)
				{
					if (stackFrame.HasMethod())
					{
						assembly2 = stackFrame.GetMethod().DeclaringType.Assembly;
						break;
					}
				}
				if ((object)assembly2 == null)
				{
					return;
				}
			}
			if (!UDAWhitelist.IsOnExceptionWhitelist(assembly2) || UDABlacklist.IsOnExceptionBlacklist(assembly2))
			{
				return;
			}
			StringBuilder stringBuilder = new StringBuilder("\n\n--- Exception Handler ---\n\n");
			stringBuilder.Append("Exception Caught: ");
			stringBuilder.AppendLine(ex.GetType().ToString());
			stringBuilder.Append("Assembly: ");
			stringBuilder.Append(assembly2.GetName().Name);
			if (flag)
			{
				stringBuilder.Append(" (Guess)");
			}
			stringBuilder.AppendLine();
			if (UDAPluginMarshal.InfoCache.TryGetValue(assembly2, out PluginInfo value))
			{
				WritePluginInfo(stringBuilder, value, 1);
			}
			stringBuilder.Append("Message: ");
			stringBuilder.AppendLine(ex.Message);
			if (ex.Source != null)
			{
				stringBuilder.Append("Source: ");
				stringBuilder.AppendLine(ex.Source);
			}
			stringBuilder.AppendLine();
			stringBuilder.Append(Tabs(1));
			stringBuilder.AppendLine("--- Begin Frames ---");
			stringBuilder.AppendLine();
			StackFrame[] frames2 = stackTrace.GetFrames();
			foreach (StackFrame frame2 in frames2)
			{
				StringBuilder stringBuilder2 = new StringBuilder();
				if (DumpFrame(stringBuilder2, frame2, 2))
				{
					stringBuilder.Append(Tabs(1));
					stringBuilder.Append("--FRAME ");
					num++;
					stringBuilder.Append(num);
					stringBuilder.AppendLine(":");
					stringBuilder.Append(stringBuilder2.ToString());
				}
			}
			stringBuilder.Append(Tabs(1));
			stringBuilder.AppendLine("--- End Frames ---");
			stringBuilder.AppendLine("\n--- End Exception Handler ---");
			if (num > 0)
			{
				ManualLogSource? log = UDAPlugin.Log;
				if (log != null)
				{
					log.LogError((object)stringBuilder);
				}
			}
			static void DoHarmonyBlames(StringBuilder sb, ReadOnlyCollection<Patch>? Patches, int Indent)
			{
				if (Patches == null)
				{
					return;
				}
				foreach (Patch Patch in Patches)
				{
					DumpPatch(sb, Patch.PatchMethod.DeclaringType.Assembly, Indent);
				}
			}
			static bool DumpFrame(StringBuilder sb, StackFrame frame, int Indent)
			{
				MethodBase method = frame.GetMethod();
				int iLOffset = frame.GetILOffset();
				bool result = false;
				if ((object)method != null)
				{
					Assembly assembly3 = method.DeclaringType.Assembly;
					if (UDAWhitelist.IsOnFrameWhitelist(assembly3) && !UDABlacklist.IsOnFrameBlacklist(assembly3))
					{
						result = true;
						sb.Append(Tabs(Indent));
						sb.Append("In Assembly: ");
						sb.AppendLine(assembly3.GetName().Name);
						if (frame.GetFileName() != null)
						{
							sb.Append(Tabs(Indent));
							sb.Append("Source: ");
							sb.Append(frame.GetFileName());
							sb.Append(':');
							sb.Append(frame.GetFileLineNumber());
							sb.Append(',');
							sb.AppendLine(frame.GetFileColumnNumber().ToString());
						}
						sb.Append(Tabs(Indent));
						sb.Append("Target Method: ");
						sb.Append(method.DeclaringType.Name);
						sb.Append('.');
						sb.AppendLine(method.Name);
						sb.AppendLine();
						List<Assembly> patchInformation = UDAPatchStorage.GetPatchInformation(method);
						Patches patchInfo = Harmony.GetPatchInfo(method);
						if (patchInformation.Count > 0 || patchInfo != null)
						{
							sb.Append(Tabs(Indent));
							sb.AppendLine("Patched By:");
						}
						foreach (Assembly item in patchInformation)
						{
							DumpPatch(sb, item, Indent + 1);
						}
						if (patchInfo != null)
						{
							DoHarmonyBlames(sb, patchInfo.Prefixes, Indent + 1);
							DoHarmonyBlames(sb, patchInfo.Postfixes, Indent + 1);
							DoHarmonyBlames(sb, patchInfo.Finalizers, Indent + 1);
						}
					}
				}
				return result;
			}
			static void DumpPatch(StringBuilder sb, Assembly assembly, int Indent)
			{
				sb.Append(Tabs(Indent));
				sb.AppendLine(assembly.GetName().Name);
				if (UDAPluginMarshal.InfoCache.TryGetValue(assembly, out PluginInfo value2))
				{
					WritePluginInfo(sb, value2, Indent);
				}
			}
			static string GetPluginDirSandboxed(PluginInfo info)
			{
				int num2 = info.Location.IndexOf($"{Path.DirectorySeparatorChar}plugins{Path.DirectorySeparatorChar}");
				if (num2 < 0)
				{
					return "Unknown";
				}
				int length = info.Location.Length - num2;
				return new string(info.Location.ToCharArray(), num2, length);
			}
			static string Tabs(int n)
			{
				return new string(' ', n * 2);
			}
			static void WritePluginInfo(StringBuilder sb, PluginInfo info, int Indent)
			{
				sb.AppendLine();
				sb.Append(Tabs(Indent));
				sb.AppendLine("Plugin Info");
				sb.Append(Tabs(Indent + 1));
				sb.Append("GUID:     ");
				sb.AppendLine(info.Metadata.GUID);
				sb.Append(Tabs(Indent + 1));
				sb.Append("NAME/VER: ");
				sb.Append(info.Metadata.Name);
				sb.Append("@");
				sb.AppendLine(info.Metadata.Version.ToString());
				sb.Append(Tabs(Indent + 1));
				sb.Append("LOCATION: ");
				sb.AppendLine(GetPluginDirSandboxed(info));
				sb.AppendLine();
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		internal static void DebugThrow()
		{
			throw new Exception("Debug throw");
		}
	}
	internal static class UDAExceptionProcessor
	{
		internal static readonly ConcurrentStack<Exception> Storage = new ConcurrentStack<Exception>();

		internal static readonly int[] LastInExceptions = new int[10];

		internal static int LastInPosition = 0;

		private static bool OperationUnderway = false;

		internal static void PushException(Exception ex)
		{
			int hashCode = ex.GetHashCode();
			int[] lastInExceptions = LastInExceptions;
			foreach (int num in lastInExceptions)
			{
				if (hashCode == num)
				{
					return;
				}
			}
			LastInExceptions[LastInPosition] = hashCode;
			LastInPosition++;
			LastInPosition %= LastInExceptions.Length;
			Storage.Push(ex);
		}

		internal static void Run(Exception __instance)
		{
			if (OperationUnderway)
			{
				ManualLogSource? log = UDAPlugin.Log;
				if (log != null)
				{
					log.LogWarning((object)"Exception processor is busy");
				}
				return;
			}
			OperationUnderway = true;
			try
			{
				UDAExceptionHandler.Handle(__instance);
			}
			catch (Exception ex)
			{
				ManualLogSource? log2 = UDAPlugin.Log;
				if (log2 != null)
				{
					log2.LogError((object)"The exception handler failed while running. Please report the next line to Robyn:");
				}
				ManualLogSource? log3 = UDAPlugin.Log;
				if (log3 != null)
				{
					log3.LogError((object)ex);
				}
			}
			finally
			{
				OperationUnderway = false;
			}
		}
	}
}
namespace UnityDebuggerAssistant.Patches
{
	public static class ExceptionStackGetterPatch
	{
		private static bool LockRoot;

		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		[HarmonyPostfix]
		internal static void ExceptionStackGot(Exception __instance)
		{
			if (!LockRoot)
			{
				LockRoot = true;
				UDAExceptionProcessor.Run(__instance);
				LockRoot = false;
			}
		}
	}
	[HarmonyPatch]
	public static class ExceptionConstructorPatch
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			return typeof(Exception).GetConstructors(BindingFlags.Instance | BindingFlags.Public);
		}

		private static void Postfix(Exception __instance)
		{
			UDAExceptionProcessor.PushException(__instance);
		}
	}
}
namespace UnityDebuggerAssistant.Filtering
{
	internal static class UDABlacklist
	{
		internal static string[] ExceptionBlackList = Array.Empty<string>();

		internal static string[] FrameBlackList = Array.Empty<string>();

		internal static bool IsOnExceptionBlacklist(Assembly assembly)
		{
			if (!UDAPlugin.UDASettings.EnableBlacklistPerException.Value)
			{
				return false;
			}
			return IsOnList_Internal(assembly.GetName().Name, in ExceptionBlackList);
		}

		internal static bool IsOnFrameBlacklist(Assembly assembly)
		{
			if (!UDAPlugin.UDASettings.EnableBlacklistPerException.Value)
			{
				return false;
			}
			return IsOnList_Internal(assembly.GetName().Name, in FrameBlackList);
		}

		internal static bool IsOnList_Internal(string name, in string[] blacklist)
		{
			string[] array = blacklist;
			foreach (string value in array)
			{
				if (name.StartsWith(value))
				{
					return true;
				}
			}
			return false;
		}

		internal static void UpdateLists_Internal()
		{
			ExceptionBlackList = UDAPlugin.UDASettings.ExceptionBlacklist.Value.Split(new char[1] { ',' });
			FrameBlackList = UDAPlugin.UDASettings.FrameBlacklist.Value.Split(new char[1] { ',' });
			for (int i = 0; i < ExceptionBlackList.Length; i++)
			{
				ExceptionBlackList[i] = ExceptionBlackList[i].Trim();
			}
			for (int j = 0; j < FrameBlackList.Length; j++)
			{
				FrameBlackList[j] = FrameBlackList[j].Trim();
			}
		}
	}
	internal static class UDAWhitelist
	{
		internal static readonly List<Assembly> AssemblyWhiteList = new List<Assembly>(2)
		{
			Helpers.GetAssemblyByName("Assembly-CSharp"),
			Helpers.GetAssemblyByName("MMHOOK_Assembly-CSharp")
		};

		internal static bool IsOnExceptionWhitelist(Assembly assembly)
		{
			return Whitelist(UDAPlugin.UDASettings.EnableWhitelistPerException.Value, assembly);
		}

		internal static bool IsOnFrameWhitelist(Assembly assembly)
		{
			return Whitelist(UDAPlugin.UDASettings.EnableWhitelistPerFrame.Value, assembly);
		}

		private static bool Whitelist(bool Setting, Assembly assembly)
		{
			if (UDAPluginMarshal.InfoCache.ContainsKey(assembly))
			{
				return true;
			}
			if (Setting)
			{
				if (Setting)
				{
					return AssemblyWhiteList.Contains(assembly);
				}
				return false;
			}
			return true;
		}
	}
}
namespace UnityDebuggerAssistant.Components
{
	public class UDAExceptionBroker : MonoBehaviour
	{
		private readonly Exception[] popped = new Exception[3];

		private void Awake()
		{
			ManualLogSource? log = UDAPlugin.Log;
			if (log != null)
			{
				log.LogInfo((object)"UDAExceptionBroker active");
			}
		}

		private void Update()
		{
			ConcurrentStack<Exception> storage = UDAExceptionProcessor.Storage;
			int num = storage.TryPopRange(popped);
			if (num > 0)
			{
				for (int i = 0; i < num; i++)
				{
					UDAExceptionProcessor.Run(popped[i]);
				}
			}
		}
	}
	public class UDAPostChainloadRunner : MonoBehaviour
	{
		private void Start()
		{
			ManualLogSource? log = UDAPlugin.Log;
			if (log != null)
			{
				log.LogInfo((object)"UDAPostChainloadRunner Starting");
			}
			UDAPluginMarshal.Run();
		}
	}
}