From e2396d202b82cea5c162fdf09a046b3001d3b0e0 Mon Sep 17 00:00:00 2001 From: aldelaro5 Date: Thu, 29 Aug 2024 10:48:50 -0400 Subject: [PATCH] address code review round 3 --- BepInEx.Core/Bootstrap/BaseChainloader.cs | 16 +---- BepInEx.Core/Contract/IPluginLoadContext.cs | 6 ++ BepInEx.Core/Utility.cs | 59 +++++++++++++++++++ .../BepInExPatcherLoadContext.cs | 12 ++++ .../BepInExPatcherProvider.cs | 2 +- .../BepInExPluginLoadContext.cs | 12 ++++ .../BepInExPluginProvider.cs | 2 +- Runtimes/NET/BepInEx.NET.Common/BasePlugin.cs | 2 +- .../Unity/BepInEx.Unity.IL2CPP/BasePlugin.cs | 2 +- .../BepInEx.Unity.Mono/BaseUnityPlugin.cs | 2 +- 10 files changed, 97 insertions(+), 18 deletions(-) diff --git a/BepInEx.Core/Bootstrap/BaseChainloader.cs b/BepInEx.Core/Bootstrap/BaseChainloader.cs index 665535f..c2e7c7e 100644 --- a/BepInEx.Core/Bootstrap/BaseChainloader.cs +++ b/BepInEx.Core/Bootstrap/BaseChainloader.cs @@ -116,18 +116,6 @@ public abstract class BaseChainloader return pluginTarget.Build > CurrentAssemblyVersion.Build; } - /// - /// Obtains the corresponding to its GUID - /// - /// The GUID of the plugin to get the info from - /// When this method returns, contains the - /// associated with the specified GUID, if the plugin was loaded; otherwise, null. This parameter is passed uninitialized. - /// true if the plugin with the GUID was loaded by the chainloader; otherwise, false. - public bool TryGetPluginInfoFromGuid(string pluginGuid, out PluginInfo foundPluginInfo) - { - return Plugins.TryGetValue(pluginGuid, out foundPluginInfo); - } - #region Contract protected virtual string ConsoleTitle => $"BepInEx {Paths.BepInExVersion} - {Paths.ProcessName}"; @@ -409,7 +397,9 @@ public abstract class BaseChainloader } else if (!provider && !loadedAssemblies.TryGetValue(pluginInfo.LoadContext.AssemblyIdentifier, out ass)) { - ass = Assembly.Load(pluginInfo.LoadContext.GetAssemblyData()); + var symbols = pluginInfo.LoadContext.GetAssemblySymbolsData(); + ass = symbols != null ? Assembly.Load(pluginInfo.LoadContext.GetAssemblyData(), symbols) + : Assembly.Load(pluginInfo.LoadContext.GetAssemblyData()); loadedAssemblies[pluginInfo.LoadContext.AssemblyIdentifier] = ass; } diff --git a/BepInEx.Core/Contract/IPluginLoadContext.cs b/BepInEx.Core/Contract/IPluginLoadContext.cs index 715f09c..013b973 100644 --- a/BepInEx.Core/Contract/IPluginLoadContext.cs +++ b/BepInEx.Core/Contract/IPluginLoadContext.cs @@ -26,6 +26,12 @@ public interface IPluginLoadContext : IDisposable /// The assembly's raw data in bytes public byte[] GetAssemblyData(); + /// + /// Obtains the assembly's symbols data which will be loaded by the chainloader alongside the assembly + /// + /// The assembly's symbols data in bytes (either in portable pdb or mdb format). Null if no symbols exists for this assembly + public byte[] GetAssemblySymbolsData(); + /// /// Obtains a file's raw data using a relative path from the plugin assembly /// diff --git a/BepInEx.Core/Utility.cs b/BepInEx.Core/Utility.cs index a6b93bd..b8cd30c 100644 --- a/BepInEx.Core/Utility.cs +++ b/BepInEx.Core/Utility.cs @@ -221,6 +221,55 @@ public static class Utility return false; } + /// + /// Try to resolve the symbols data from an assembly DLL. + /// + /// File path of the DLL assembly. + /// The symbols of the DLL assembly. + /// True, if the symbols were found. Otherwise, false. + public static bool TryResolveDllSymbols(string dllPath, out byte[] symbolsData) + { + symbolsData = null; + + var subDirectory = Path.GetDirectoryName(dllPath); + var filename = Path.GetFileNameWithoutExtension(dllPath); + + var potentialSymbolsFileNames = new[] + { + $"{filename}.mdb", + $"{filename}.pdb" + }; + + foreach (var symbolFileName in potentialSymbolsFileNames) + { + var symbolPath = Path.Combine(subDirectory, symbolFileName); + if (!File.Exists(symbolPath)) + continue; + + try + { + symbolsData = File.ReadAllBytes(symbolPath); + } + catch (Exception) + { + continue; + } + + return true; + } + + return false; + } + + private static Assembly LoadAssemblyWithSymbols(string assemblyFilePath) + { + var assemblyData = File.ReadAllBytes(assemblyFilePath); + + return TryResolveDllSymbols(assemblyFilePath, out byte[] symbolsData) + ? Assembly.Load(assemblyData, symbolsData) + : Assembly.Load(assemblyData); + } + /// /// Checks whether a given cecil type definition is a subtype of a provided type. /// @@ -259,6 +308,16 @@ public static class Utility TryResolveDllAssembly(assemblyName, directory, s => AssemblyDefinition.ReadAssembly(s, readerParameters), out assembly); + /// + /// Try to resolve and load the given assembly DLL including their symbols file. + /// + /// Name of the assembly, of the type . + /// Directory to search the assembly from. + /// The loaded assembly. + /// True, if the assembly was found and loaded. Otherwise, false. + public static bool TryResolveDllAssemblyWithSymbols(AssemblyName assemblyName, string directory, out Assembly assembly) => + TryResolveDllAssembly(assemblyName, directory, LoadAssemblyWithSymbols, out assembly); + /// /// Tries to create a file with the given name /// diff --git a/BepInEx.PatcherProvider/BepInExPatcherLoadContext.cs b/BepInEx.PatcherProvider/BepInExPatcherLoadContext.cs index 9be40a5..63fc627 100644 --- a/BepInEx.PatcherProvider/BepInExPatcherLoadContext.cs +++ b/BepInEx.PatcherProvider/BepInExPatcherLoadContext.cs @@ -8,6 +8,7 @@ public class BepInExPatcherLoadContext : IPluginLoadContext public string AssemblyIdentifier { get; internal set; } public string AssemblyHash { get; internal set; } private byte[] assemblyData; + private byte[] assemblySymbolsData; public byte[] GetAssemblyData() { if (assemblyData == null) @@ -17,6 +18,17 @@ public class BepInExPatcherLoadContext : IPluginLoadContext return assemblyData; } + + public byte[] GetAssemblySymbolsData() + { + if (assemblySymbolsData == null) + { + if (!Utility.TryResolveDllSymbols(AssemblyIdentifier, out assemblySymbolsData)) + assemblySymbolsData = null; + } + + return assemblySymbolsData; + } public byte[] GetFile(string relativePath) { diff --git a/BepInEx.PatcherProvider/BepInExPatcherProvider.cs b/BepInEx.PatcherProvider/BepInExPatcherProvider.cs index 9221ddb..78fa699 100644 --- a/BepInEx.PatcherProvider/BepInExPatcherProvider.cs +++ b/BepInEx.PatcherProvider/BepInExPatcherProvider.cs @@ -40,7 +40,7 @@ public class BepInExPatcherProvider : BasePatcherProvider if (!AssemblyLocationsByFilename.TryGetValue(name, out var location)) return null; - if (!Utility.TryResolveDllAssembly(new(name), location, out var ass)) + if (!Utility.TryResolveDllAssemblyWithSymbols(new(name), location, out var ass)) return null; return ass; diff --git a/BepInEx.PluginProvider/BepInExPluginLoadContext.cs b/BepInEx.PluginProvider/BepInExPluginLoadContext.cs index 9a7cb38..3271a24 100644 --- a/BepInEx.PluginProvider/BepInExPluginLoadContext.cs +++ b/BepInEx.PluginProvider/BepInExPluginLoadContext.cs @@ -8,6 +8,7 @@ public class BepInExPluginLoadContext : IPluginLoadContext public string AssemblyIdentifier { get; internal set; } public string AssemblyHash { get; internal set; } private byte[] assemblyData; + private byte[] assemblySymbolsData; public byte[] GetAssemblyData() { if (assemblyData == null) @@ -18,6 +19,17 @@ public class BepInExPluginLoadContext : IPluginLoadContext return assemblyData; } + public byte[] GetAssemblySymbolsData() + { + if (assemblySymbolsData == null) + { + if (!Utility.TryResolveDllSymbols(AssemblyIdentifier, out assemblySymbolsData)) + assemblySymbolsData = null; + } + + return assemblySymbolsData; + } + public byte[] GetFile(string relativePath) { if (relativePath == null) diff --git a/BepInEx.PluginProvider/BepInExPluginProvider.cs b/BepInEx.PluginProvider/BepInExPluginProvider.cs index 783342a..bae7689 100644 --- a/BepInEx.PluginProvider/BepInExPluginProvider.cs +++ b/BepInEx.PluginProvider/BepInExPluginProvider.cs @@ -39,7 +39,7 @@ public class BepInExPluginProvider : BasePluginProvider if (!AssemblyLocationsByFilename.TryGetValue(name, out var location)) return null; - if (!Utility.TryResolveDllAssembly(new(name), location, out var ass)) + if (!Utility.TryResolveDllAssemblyWithSymbols(new(name), location, out var ass)) return null; return ass; diff --git a/Runtimes/NET/BepInEx.NET.Common/BasePlugin.cs b/Runtimes/NET/BepInEx.NET.Common/BasePlugin.cs index 810dd19..bbd52eb 100644 --- a/Runtimes/NET/BepInEx.NET.Common/BasePlugin.cs +++ b/Runtimes/NET/BepInEx.NET.Common/BasePlugin.cs @@ -15,7 +15,7 @@ namespace BepInEx.NET.Common HarmonyInstance = new Harmony("BepInEx.Plugin." + metadata.GUID); - if (BaseChainloader.Instance.TryGetPluginInfoFromGuid(metadata.GUID, out var pluginInfo)) + if (BaseChainloader.Instance.Plugins.TryGetValue(metadata.GUID, out var pluginInfo)) { Info = pluginInfo; Info.Instance = this; diff --git a/Runtimes/Unity/BepInEx.Unity.IL2CPP/BasePlugin.cs b/Runtimes/Unity/BepInEx.Unity.IL2CPP/BasePlugin.cs index 3ffa16d..e6889da 100644 --- a/Runtimes/Unity/BepInEx.Unity.IL2CPP/BasePlugin.cs +++ b/Runtimes/Unity/BepInEx.Unity.IL2CPP/BasePlugin.cs @@ -13,7 +13,7 @@ public abstract class BasePlugin : IPlugin { var metadata = MetadataHelper.GetPluginMetadata(this); - if (BaseChainloader.Instance.TryGetPluginInfoFromGuid(metadata.GUID, out var pluginInfo)) + if (BaseChainloader.Instance.Plugins.TryGetValue(metadata.GUID, out var pluginInfo)) { Info = pluginInfo; Info.Instance = this; diff --git a/Runtimes/Unity/BepInEx.Unity.Mono/BaseUnityPlugin.cs b/Runtimes/Unity/BepInEx.Unity.Mono/BaseUnityPlugin.cs index 4c0552b..f7ea012 100644 --- a/Runtimes/Unity/BepInEx.Unity.Mono/BaseUnityPlugin.cs +++ b/Runtimes/Unity/BepInEx.Unity.Mono/BaseUnityPlugin.cs @@ -23,7 +23,7 @@ public abstract class BaseUnityPlugin : MonoBehaviour, IPlugin throw new InvalidOperationException("Can't create an instance of " + GetType().FullName + " because it inherits from BaseUnityPlugin and the BepInPlugin attribute is missing."); - if (BaseChainloader.Instance.TryGetPluginInfoFromGuid(metadata.GUID, out var pluginInfo)) + if (BaseChainloader.Instance.Plugins.TryGetValue(metadata.GUID, out var pluginInfo)) { Info = pluginInfo; Info.Instance = this;