Browse Source

Remove HarmonyProtector and largely useless virtualizer

pull/99/head
DaNike 11 months ago
parent
commit
634d8fe2d1
No known key found for this signature in database GPG Key ID: 40F6F33603F1772D
3 changed files with 0 additions and 287 deletions
  1. +0
    -24
      IPA.Injector/Injector.cs
  2. +0
    -219
      IPA.Injector/Virtualizer.cs
  3. +0
    -44
      IPA.Loader/Loader/HarmonyProtector.cs

+ 0
- 24
IPA.Injector/Injector.cs View File

@ -137,11 +137,6 @@ namespace IPA.Injector
Loader.LibLoader.Configure();
}
private static void InstallHarmonyProtections()
{ // proxy function to delay resolution
HarmonyProtectorProxy.ProtectNull();
}
private static void InstallBootstrapPatch()
{
var sw = Stopwatch.StartNew();
@ -259,9 +254,6 @@ namespace IPA.Injector
endPatchCoreModule:
#endregion Insert patch into UnityEngine.CoreModule.dll
Logging.Logger.Injector.Debug("Ensuring game assemblies are virtualized");
#region Virtualize game assemblies
bool isFirst = true;
foreach (var name in SelfConfig.GameAssemblies_)
{
@ -269,19 +261,6 @@ namespace IPA.Injector
using var execSec = CriticalSection.ExecuteSection();
try
{
Logging.Logger.Injector.Debug($"Virtualizing {name}");
using var ascModule = VirtualizedModule.Load(ascPath);
ascModule.Virtualize(cAsmName, () => bkp?.Add(ascPath));
}
catch (Exception e)
{
Logging.Logger.Injector.Error($"Could not virtualize {ascPath}");
if (SelfConfig.Debug_.ShowHandledErrorStackTraces_)
Logging.Logger.Injector.Error(e);
}
#if BeatSaber
if (isFirst)
{
@ -313,7 +292,6 @@ namespace IPA.Injector
}
#endif
}
#endregion
sw.Stop();
Logging.Logger.Injector.Info($"Installing bootstrapper took {sw.Elapsed}");
@ -338,8 +316,6 @@ namespace IPA.Injector
// need to reinit streams singe Unity seems to redirect stdout
StdoutInterceptor.RedirectConsole();
InstallHarmonyProtections();
var bootstrapper = new GameObject("NonDestructiveBootstrapper").AddComponent<Bootstrapper>();
bootstrapper.Destroyed += Bootstrapper_Destroyed;
}


+ 0
- 219
IPA.Injector/Virtualizer.cs View File

@ -1,219 +0,0 @@
using Mono.Cecil;
using Mono.Cecil.Rocks;
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
namespace IPA.Injector
{
internal class VirtualizedModule : IDisposable
{
private readonly FileInfo file;
private ModuleDefinition module;
public static VirtualizedModule Load(string engineFile)
{
return new VirtualizedModule(engineFile);
}
private VirtualizedModule(string assemblyFile)
{
file = new FileInfo(assemblyFile);
LoadModules();
}
private void LoadModules()
{
module = ModuleDefinition.ReadModule(file.FullName, new ReaderParameters
{
ReadWrite = false,
InMemory = true,
ReadingMode = ReadingMode.Immediate
});
}
public void Virtualize(AssemblyName selfName, Action beforeChangeCallback = null)
{
var changed = false;
var virtualize = true;
foreach (var r in module.AssemblyReferences)
{
if (r.Name == selfName.Name)
{
virtualize = false;
if (r.Version != selfName.Version)
{
r.Version = selfName.Version;
changed = true;
}
}
}
if (virtualize)
{
changed = true;
module.AssemblyReferences.Add(new AssemblyNameReference(selfName.Name, selfName.Version));
foreach (var type in module.Types)
{
VirtualizeType(type);
}
}
if (changed)
{
beforeChangeCallback?.Invoke();
module.Write(file.FullName);
}
}
private TypeReference inModreqRef;
// private TypeReference outModreqRef;
private void VirtualizeType(TypeDefinition type)
{
if(type.IsSealed)
{
// Unseal
type.IsSealed = false;
}
if (type.IsNestedPrivate)
{
type.IsNestedPrivate = false;
type.IsNestedPublic = true;
}
if (type.IsInterface) return;
if (type.IsAbstract) return;
// These two don't seem to work.
if (type.Name == "SceneControl" || type.Name == "ConfigUI") return;
// Take care of sub types
foreach (var subType in type.NestedTypes)
{
VirtualizeType(subType);
}
foreach (var method in type.Methods)
{
if (method.IsManaged
&& method.IsIL
&& !method.IsStatic
&& (!method.IsVirtual || method.IsFinal)
&& !method.IsAbstract
&& !method.IsAddOn
&& !method.IsConstructor
&& !method.IsSpecialName
&& !method.IsGenericInstance
&& !method.HasOverrides)
{
// fix In parameters to have the modreqs required by the compiler
foreach (var param in method.Parameters)
{
if (param.IsIn)
{
inModreqRef ??= module.ImportReference(typeof(System.Runtime.InteropServices.InAttribute));
param.ParameterType = AddModreqIfNotExist(param.ParameterType, inModreqRef);
}
// Breaks override methods if modreq is applied to `out` parameters
//if (param.IsOut)
//{
// outModreqRef ??= module.ImportReference(typeof(System.Runtime.InteropServices.OutAttribute));
// param.ParameterType = AddModreqIfNotExist(param.ParameterType, outModreqRef);
//}
}
method.IsVirtual = true;
method.IsFinal = false;
method.IsPublic = true;
method.IsPrivate = false;
method.IsNewSlot = true;
method.IsHideBySig = true;
}
}
foreach (var field in type.Fields)
{
if (field.IsPrivate) field.IsFamily = true;
}
}
private TypeReference AddModreqIfNotExist(TypeReference type, TypeReference mod)
{
var (element, opt, req) = GetDecomposedModifiers(type);
if (!req.Contains(mod))
{
req.Add(mod);
}
return BuildModifiedType(element, opt, req);
}
private (TypeReference Element, List<TypeReference> ModOpt, List<TypeReference> ModReq) GetDecomposedModifiers(TypeReference type)
{
var opt = new List<TypeReference>();
var req = new List<TypeReference>();
while (type is IModifierType modif)
{
if (type.IsOptionalModifier)
opt.Add(modif.ModifierType);
if (type.IsRequiredModifier)
req.Add(modif.ModifierType);
type = modif.ElementType;
}
return (type, opt, req);
}
private TypeReference BuildModifiedType(TypeReference type, IEnumerable<TypeReference> opt, IEnumerable<TypeReference> req)
{
foreach (var mod in req)
{
type = type.MakeRequiredModifierType(mod);
}
foreach (var mod in opt)
{
type = type.MakeOptionalModifierType(mod);
}
return type;
}
#region IDisposable Support
private bool disposedValue = false; // To detect redundant calls
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
module.Dispose();
}
disposedValue = true;
}
}
~VirtualizedModule()
{
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
Dispose(false);
}
// This code added to correctly implement the disposable pattern.
public void Dispose()
{
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
}
}

+ 0
- 44
IPA.Loader/Loader/HarmonyProtector.cs View File

@ -1,44 +0,0 @@
using HarmonyLib;
using System.Reflection;
namespace IPA.Loader
{
internal static class HarmonyProtectorProxy
{
public static void ProtectNull() => HarmonyProtector.Protect();
}
internal static class HarmonyProtector
{
private static Harmony instance;
private static Assembly selfAssem;
private static Assembly harmonyAssem;
public static void Protect(Harmony inst = null)
{
selfAssem = Assembly.GetExecutingAssembly();
harmonyAssem = typeof(Harmony).Assembly;
if (inst == null)
{
if (instance == null)
instance = new Harmony("BSIPA Safeguard");
inst = instance;
}
var target = typeof(PatchProcessor).GetMethod("Patch");
var patch = typeof(HarmonyProtector).GetMethod(nameof(PatchProcessor_Patch_Prefix), BindingFlags.NonPublic | BindingFlags.Static);
inst.Patch(target, new HarmonyMethod(patch));
}
private static bool PatchProcessor_Patch_Prefix(MethodBase ___original, out MethodInfo __result)
{
var asm = ___original.DeclaringType.Assembly;
__result = ___original as MethodInfo;
return !(asm.Equals(selfAssem) || asm.Equals(harmonyAssem));
}
}
}

Loading…
Cancel
Save