using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using ILUtils.HarmonyXtensions;
using Microsoft.CodeAnalysis;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("AmazingAssets.TerrainToMesh")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: IgnoresAccessChecksTo("ClientNetworkTransform")]
[assembly: IgnoresAccessChecksTo("DissonanceVoip")]
[assembly: IgnoresAccessChecksTo("Facepunch Transport for Netcode for GameObjects")]
[assembly: IgnoresAccessChecksTo("Facepunch.Steamworks.Win64")]
[assembly: IgnoresAccessChecksTo("Unity.AI.Navigation")]
[assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging")]
[assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging.DocCodeExamples")]
[assembly: IgnoresAccessChecksTo("Unity.Burst")]
[assembly: IgnoresAccessChecksTo("Unity.Burst.Unsafe")]
[assembly: IgnoresAccessChecksTo("Unity.Collections")]
[assembly: IgnoresAccessChecksTo("Unity.Collections.LowLevel.ILSupport")]
[assembly: IgnoresAccessChecksTo("Unity.InputSystem")]
[assembly: IgnoresAccessChecksTo("Unity.InputSystem.ForUI")]
[assembly: IgnoresAccessChecksTo("Unity.Jobs")]
[assembly: IgnoresAccessChecksTo("Unity.Mathematics")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.Common")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.MetricTypes")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStats")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Component")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Configuration")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Implementation")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsReporting")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkProfiler.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkSolutionInterface")]
[assembly: IgnoresAccessChecksTo("Unity.Netcode.Components")]
[assembly: IgnoresAccessChecksTo("Unity.Netcode.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.Networking.Transport")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Csg")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.KdTree")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Poly2Tri")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Stl")]
[assembly: IgnoresAccessChecksTo("Unity.Profiling.Core")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.ShaderLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Config.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.ShaderGraph.ShaderGraphLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Authentication")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Analytics")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Configuration")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Device")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments.Internal")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Internal")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Networking")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Registration")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Scheduler")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Telemetry")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Threading")]
[assembly: IgnoresAccessChecksTo("Unity.Services.QoS")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Relay")]
[assembly: IgnoresAccessChecksTo("Unity.TextMeshPro")]
[assembly: IgnoresAccessChecksTo("Unity.Timeline")]
[assembly: IgnoresAccessChecksTo("Unity.VisualEffectGraph.Runtime")]
[assembly: IgnoresAccessChecksTo("UnityEngine.ARModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.NVIDIAModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.UI")]
[assembly: AssemblyCompany("DBJ")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("BepInEx Transpiler Tools")]
[assembly: AssemblyFileVersion("1.0.4.0")]
[assembly: AssemblyInformationalVersion("1.0.4+d27649a62bda6708d5643ed084212d173d522337")]
[assembly: AssemblyProduct("ILUtils")]
[assembly: AssemblyTitle("com.github.decibillyjoel.ILUtils")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/DecibillyJoel/ILUtils")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.4.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[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;
}
}
}
internal static class BepPluginInfo
{
public const string PLUGIN_GUID = "com.github.decibillyjoel.ILUtils";
public const string PLUGIN_NAME = "ILUtils";
public const string PLUGIN_TS_TEAM = "DBJ";
public const string PLUGIN_VERSION = "1.0.4";
}
namespace ILUtils
{
public static class ILPatterns
{
public static int? StackSizeDelta(StackBehaviour stackBehaviour)
{
switch (stackBehaviour)
{
case StackBehaviour.Pop0:
return 0;
case StackBehaviour.Pop1:
return -1;
case StackBehaviour.Pop1_pop1:
return -2;
case StackBehaviour.Popi:
return -1;
case StackBehaviour.Popi_pop1:
return -2;
case StackBehaviour.Popi_popi:
return -2;
case StackBehaviour.Popi_popi8:
return -2;
case StackBehaviour.Popi_popi_popi:
return -3;
case StackBehaviour.Popi_popr4:
return -2;
case StackBehaviour.Popi_popr8:
return -2;
case StackBehaviour.Popref:
return -1;
case StackBehaviour.Popref_pop1:
return -2;
case StackBehaviour.Popref_popi:
return -2;
case StackBehaviour.Popref_popi_popi:
return -3;
case StackBehaviour.Popref_popi_popi8:
return -3;
case StackBehaviour.Popref_popi_popr4:
return -3;
case StackBehaviour.Popref_popi_popr8:
return -3;
case StackBehaviour.Popref_popi_popref:
return -3;
case StackBehaviour.Push0:
return 0;
case StackBehaviour.Push1:
return 1;
case StackBehaviour.Push1_push1:
return 2;
case StackBehaviour.Pushi:
return 1;
case StackBehaviour.Pushi8:
return 1;
case StackBehaviour.Pushr4:
return 1;
case StackBehaviour.Pushr8:
return 1;
case StackBehaviour.Pushref:
return 1;
case StackBehaviour.Popref_popi_pop1:
return -3;
case StackBehaviour.Varpop:
case StackBehaviour.Varpush:
return null;
default:
throw new ArgumentOutOfRangeException($"stackBehaviour {stackBehaviour} is an invalid value");
}
}
public static int? StackSizeDelta(OpCode opCode, object operand)
{
if (opCode == OpCodes.Calli)
{
return null;
}
if (opCode.FlowControl == FlowControl.Call)
{
MethodInfo methodInfo = operand as MethodInfo;
if (methodInfo == null)
{
return null;
}
int num = -methodInfo.GetParameters().Count();
if (opCode != OpCodes.Newobj && methodInfo.CallingConvention.HasFlag(CallingConventions.HasThis) && !methodInfo.CallingConvention.HasFlag(CallingConventions.ExplicitThis))
{
num--;
}
if (opCode == OpCodes.Newobj || methodInfo.ReturnType != typeof(void))
{
num++;
}
return num;
}
int? num2 = StackSizeDelta(opCode.StackBehaviourPush);
int? num3 = StackSizeDelta(opCode.StackBehaviourPop);
if (!num2.HasValue || !num3.HasValue)
{
return null;
}
return num2 + num3;
}
public static int? StackSizeDelta(CodeInstruction code)
{
return StackSizeDelta(code.opcode, code.operand);
}
public static bool EmptiesStack(OpCode opcode)
{
FlowControl flowControl = opcode.FlowControl;
if (flowControl == FlowControl.Branch || (uint)(flowControl - 7) <= 1u)
{
return true;
}
return false;
}
public static bool EmptiesStack(CodeInstruction code)
{
return EmptiesStack(code.opcode);
}
public static Func<CodeInstruction, int, bool> NextEmptyStack(int startSize = 0)
{
return delegate(CodeInstruction code, int index)
{
if (EmptiesStack(code))
{
return true;
}
int num = StackSizeDelta(code) ?? throw new ArgumentException($"[ILStepper.ILPatterns.NextEmptyStack] Encountered uncountable instruction [{index}] {code}");
return (startSize += num) == 0;
};
}
}
public class ILStepper
{
public readonly List<CodeInstruction> Instructions;
public int CurrentIndex;
public readonly ILGenerator Generator;
public readonly Dictionary<int, LocalVariableInfo> Locals;
public readonly Dictionary<int, Label> Labels;
public CodeInstruction CurrentInstruction => Instructions[CurrentIndex];
public OpCode CurrentOpCode => CurrentInstruction.opcode;
public object? CurrentOperand => CurrentInstruction.operand;
public ILStepper(IEnumerable<CodeInstruction> codes, ILGenerator generator, MethodBase original, int index = 0)
{
Instructions = codes.ToList();
CurrentIndex = index;
Generator = generator;
Locals = (from code in Instructions
select code.operand as LocalVariableInfo into local
where local != null
select local).Distinct().ToDictionary((LocalVariableInfo local) => local.LocalIndex, (LocalVariableInfo local) => local);
Labels = Instructions.SelectMany((CodeInstruction code) => code.labels).Distinct().ToDictionary((Label label) => label.GetHashCode(), (Label label) => label);
CollectionExtensions.DoIf<LocalVariableInfo>((IEnumerable<LocalVariableInfo>)original.GetMethodBody().LocalVariables, (Func<LocalVariableInfo, bool>)((LocalVariableInfo local) => !Locals.ContainsKey(local.LocalIndex)), (Action<LocalVariableInfo>)delegate(LocalVariableInfo local)
{
Locals.Add(local.LocalIndex, local);
});
Instructions.ForEach(delegate(CodeInstruction code)
{
TrySetLocal(code, code);
});
}
public Label DeclareLabel()
{
Label label = Generator.DefineLabel();
Labels.Add(label.GetHashCode(), label);
return label;
}
public LocalVariableInfo DeclareLocal(Type type, bool pinned = false)
{
LocalVariableInfo localVariableInfo = Generator.DeclareLocal(type, pinned);
Locals.Add(localVariableInfo.LocalIndex, localVariableInfo);
return localVariableInfo;
}
public LocalVariableInfo? TryGetLocal(int localIndex)
{
if (!Locals.TryGetValue(localIndex, out LocalVariableInfo value))
{
return null;
}
return value;
}
public LocalVariableInfo? TryGetLocal(CodeInstruction codeWithLocal)
{
if (!CodeInstructionExtensions.IsLdloc(codeWithLocal, (LocalBuilder)null) && !CodeInstructionExtensions.IsStloc(codeWithLocal, (LocalBuilder)null))
{
return null;
}
return TryGetLocal(codeWithLocal.LocalIndex());
}
public LocalVariableInfo GetLocal(int localIndex, string errorMessage = "No such local variable!")
{
return TryGetLocal(localIndex) ?? throw new Exception($"[ILStepper.ILStepper.GetLocal] [{localIndex}] | {errorMessage}");
}
public LocalVariableInfo GetLocal(CodeInstruction codeWithLocal, string errorMessage = "No such local variable!")
{
return TryGetLocal(codeWithLocal) ?? throw new Exception($"[ILStepper.ILStepper.GetLocal] [{codeWithLocal}] | {errorMessage}");
}
public LocalVariableInfo? TrySetLocal(CodeInstruction code, LocalVariableInfo local)
{
CodeInstruction val;
if (CodeInstructionExtensions.IsLdloc(code, (LocalBuilder)null))
{
val = CodeInstructionPolyfills.LoadLocal(local, code.opcode == OpCodes.Ldloca || code.opcode == OpCodes.Ldloca_S);
}
else
{
if (!CodeInstructionExtensions.IsStloc(code, (LocalBuilder)null))
{
return null;
}
val = CodeInstructionPolyfills.StoreLocal(local);
}
code.opcode = val.opcode;
code.operand = val.operand;
return local;
}
public LocalVariableInfo? TrySetLocal(CodeInstruction code, int localIndex)
{
LocalVariableInfo localVariableInfo = TryGetLocal(localIndex);
if (localVariableInfo == null)
{
return null;
}
return TrySetLocal(code, localVariableInfo);
}
public LocalVariableInfo? TrySetLocal(CodeInstruction code, CodeInstruction codeWithLocal)
{
LocalVariableInfo localVariableInfo = TryGetLocal(codeWithLocal);
if (localVariableInfo == null)
{
return null;
}
return TrySetLocal(code, localVariableInfo);
}
public LocalVariableInfo SetLocal(CodeInstruction code, LocalVariableInfo local, string errorMessage = "Could not set local!")
{
return TrySetLocal(code, local) ?? throw new Exception($"[ILStepper.ILStepper.SetLocal] [{code}, {local}] | {errorMessage}");
}
public LocalVariableInfo SetLocal(CodeInstruction code, int localIndex, string errorMessage = "Could not set local!")
{
return TrySetLocal(code, localIndex) ?? throw new Exception($"[ILStepper.ILStepperSetLocal] [{code}, {localIndex}] | {errorMessage}");
}
public LocalVariableInfo SetLocal(CodeInstruction code, CodeInstruction codeWithLocal, string errorMessage = "Could not set local!")
{
return TrySetLocal(code, codeWithLocal) ?? throw new Exception($"[ILStepper.ILStepperSetLocal] [{code}, {codeWithLocal}] | {errorMessage}");
}
public int? TryFindIL(Func<CodeInstruction, int, bool> searchCondition, int? index = null, int offset = 0, bool reverse = false)
{
index = (index ?? CurrentIndex) + offset + (reverse ? (-1) : 0);
while (index >= 0 && index < Instructions.Count)
{
if (searchCondition(Instructions[index.Value], index.Value))
{
return index;
}
index += ((!reverse) ? 1 : (-1));
}
return null;
}
public int? TryFindIL(Func<CodeInstruction, bool> searchCondition, int? index = null, int offset = 0, bool reverse = false)
{
Func<CodeInstruction, bool> searchCondition2 = searchCondition;
return TryFindIL((CodeInstruction code, int index) => searchCondition2(code), index, offset, reverse);
}
public int FindIL(Func<CodeInstruction, int, bool> searchCondition, int? index = null, int offset = 0, bool reverse = false, string errorMessage = "Not found!")
{
int valueOrDefault = index.GetValueOrDefault();
if (!index.HasValue)
{
valueOrDefault = CurrentIndex;
index = valueOrDefault;
}
return TryFindIL(searchCondition, index, offset, reverse) ?? throw new Exception(string.Format("[ILStepper.ILStepperFindIL] [{0}, {1}, {2} ({3})] | {4}", searchCondition, index, reverse, reverse ? "reverse" : "forward", errorMessage));
}
public int FindIL(Func<CodeInstruction, bool> searchCondition, int? index = null, int offset = 0, bool reverse = false, string errorMessage = "Not found!")
{
int valueOrDefault = index.GetValueOrDefault();
if (!index.HasValue)
{
valueOrDefault = CurrentIndex;
index = valueOrDefault;
}
return TryFindIL(searchCondition, index, offset, reverse) ?? throw new Exception(string.Format("[ILStepper.ILStepperFindIL] [{0}, {1}, {2} ({3})] | {4}", searchCondition, index, reverse, reverse ? "reverse" : "forward", errorMessage));
}
public int? TryGotoIL(Func<CodeInstruction, bool> searchCondition, int? index = null, int offset = 0, bool reverse = false)
{
index = TryFindIL(searchCondition, index, offset, reverse);
CurrentIndex = index ?? CurrentIndex;
return index;
}
public int? TryGotoIL(Func<CodeInstruction, int, bool> searchCondition, int? index = null, int offset = 0, bool reverse = false)
{
index = TryFindIL(searchCondition, index, offset, reverse);
CurrentIndex = index ?? CurrentIndex;
return index;
}
public int GotoIL(Func<CodeInstruction, bool> searchCondition, int? index = null, int offset = 0, bool reverse = false, string errorMessage = "Not found!")
{
int valueOrDefault = index.GetValueOrDefault();
if (!index.HasValue)
{
valueOrDefault = CurrentIndex;
index = valueOrDefault;
}
return CurrentIndex = TryFindIL(searchCondition, index, offset, reverse) ?? throw new Exception(string.Format("[ILStepper.ILStepper.GotoIL] [{0}, {1}, {2} ({3})] | {4}", searchCondition, index, reverse, reverse ? "reverse" : "forward", errorMessage));
}
public int GotoIL(Func<CodeInstruction, int, bool> searchCondition, int? index = null, int offset = 0, bool reverse = false, string errorMessage = "Not found!")
{
int valueOrDefault = index.GetValueOrDefault();
if (!index.HasValue)
{
valueOrDefault = CurrentIndex;
index = valueOrDefault;
}
return CurrentIndex = TryFindIL(searchCondition, index, offset, reverse) ?? throw new Exception(string.Format("[ILStepper.ILStepper.GotoIL] [{0}, {1}, {2} ({3})] | {4}", searchCondition, index, reverse, reverse ? "reverse" : "forward", errorMessage));
}
public int? TryFindIndex(int? index = null, int offset = 0, int leftBoundOffset = 0, int rightBoundOffset = 1)
{
index = (index ?? CurrentIndex) + offset;
if (index < leftBoundOffset || index > Instructions.Count - 1 + rightBoundOffset)
{
return null;
}
return index;
}
public int FindIndex(int? index = null, int offset = 0, int leftBoundOffset = 0, int rightBoundOffset = 1, string errorMessage = "Out of bounds!")
{
int valueOrDefault = index.GetValueOrDefault();
if (!index.HasValue)
{
valueOrDefault = CurrentIndex;
index = valueOrDefault;
}
return TryFindIndex(index, offset, leftBoundOffset, rightBoundOffset) ?? throw new Exception($"[ILStepper.ILStepper.FindIndex] [{index + offset} ({index} + {offset}), {leftBoundOffset} (0 + {leftBoundOffset}), {Instructions.Count - 1 + rightBoundOffset} ({Instructions.Count - 1} + {rightBoundOffset})] | {errorMessage}");
}
public int? TryGotoIndex(int? index = null, int offset = 0, int leftBoundOffset = 0, int rightBoundOffset = 1)
{
index = TryFindIndex(index, offset, leftBoundOffset, rightBoundOffset);
CurrentIndex = index ?? CurrentIndex;
return index;
}
public int GotoIndex(int? index = null, int offset = 0, int leftBoundOffset = 0, int rightBoundOffset = 1, string errorMessage = "Out of bounds!")
{
int valueOrDefault = index.GetValueOrDefault();
if (!index.HasValue)
{
valueOrDefault = CurrentIndex;
index = valueOrDefault;
}
return CurrentIndex = TryFindIndex(index, offset, leftBoundOffset, rightBoundOffset) ?? throw new Exception($"[ILStepper.ILStepper.GotoIndex] [{index + offset} ({index} + {offset}), {leftBoundOffset} (0 + {leftBoundOffset}), {Instructions.Count - 1 + rightBoundOffset} ({Instructions.Count - 1} + {rightBoundOffset})] | {errorMessage}");
}
public List<CodeInstruction>? TryInsertIL(List<CodeInstruction> codeRange, int? index = null, bool shiftCurrentIndex = true, bool pinLabels = true, bool pinBlocks = true)
{
index = TryFindIndex(index);
if (!index.HasValue)
{
return null;
}
codeRange = ((IEnumerable<CodeInstruction>)codeRange).Select((Func<CodeInstruction, CodeInstruction>)((CodeInstruction code) => new CodeInstruction(code))).ToList();
if (index < Instructions.Count && codeRange.Count > 0)
{
if (pinLabels)
{
CodeInstructionExtensions.MoveLabelsTo(Instructions[index.Value], codeRange[0]);
}
if (pinBlocks)
{
CodeInstructionExtensions.MoveBlocksTo(Instructions[index.Value], codeRange[0]);
}
}
Instructions.InsertRange(index.Value, codeRange);
if (shiftCurrentIndex && CurrentIndex >= index)
{
CurrentIndex += codeRange.Count;
}
return codeRange;
}
public List<CodeInstruction>? TryInsertIL(CodeInstruction? code, int? index = null, bool shiftCurrentIndex = true, bool pinLabels = true, bool pinBlocks = true)
{
return TryInsertIL((code != null) ? new List<CodeInstruction>(1) { code } : new List<CodeInstruction>(), index, shiftCurrentIndex, pinLabels, pinBlocks);
}
public List<CodeInstruction> InsertIL(List<CodeInstruction> codeRange, int? index = null, bool shiftCurrentIndex = true, bool pinLabels = true, bool pinBlocks = true, string errorMessage = "Out of bounds!")
{
int valueOrDefault = index.GetValueOrDefault();
if (!index.HasValue)
{
valueOrDefault = CurrentIndex;
index = valueOrDefault;
}
return TryInsertIL(codeRange, index, shiftCurrentIndex, pinLabels, pinBlocks) ?? throw new Exception(string.Format("[ILStepper.ILStepper.InsertIL] [{0}, {1}, {2} ({3})] | {4}", codeRange, index, shiftCurrentIndex, shiftCurrentIndex ? "shift current index" : "dont shift current index", errorMessage));
}
public List<CodeInstruction> InsertIL(CodeInstruction? code, int? index = null, bool shiftCurrentIndex = true, bool pinLabels = true, bool pinBlocks = true, string errorMessage = "Out of bounds!")
{
int valueOrDefault = index.GetValueOrDefault();
if (!index.HasValue)
{
valueOrDefault = CurrentIndex;
index = valueOrDefault;
}
return TryInsertIL((code != null) ? new List<CodeInstruction>(1) { code } : new List<CodeInstruction>(), index, shiftCurrentIndex, pinLabels, pinBlocks) ?? throw new Exception(string.Format("[ILStepper.ILStepper.InsertIL] [{0}, {1}, {2} ({3})] | {4}", code, index, shiftCurrentIndex, shiftCurrentIndex ? "shift current index" : "dont shift current index", errorMessage));
}
public List<CodeInstruction>? TryRemoveIL(int? startIndex = null, int? endIndex = null, bool shiftCurrentIndex = true, bool pinLabels = true, bool pinBlocks = true)
{
startIndex = TryFindIndex(startIndex);
endIndex = TryFindIndex(endIndex);
if (!startIndex.HasValue || !endIndex.HasValue)
{
return null;
}
if (startIndex > endIndex)
{
int? num = endIndex;
endIndex = startIndex;
startIndex = num;
}
if (endIndex >= Instructions.Count)
{
return null;
}
int num2 = endIndex.Value - startIndex.Value;
List<CodeInstruction> range = Instructions.GetRange(startIndex.Value, num2);
Instructions.RemoveRange(startIndex.Value, num2);
if (startIndex < Instructions.Count)
{
range.ForEach(delegate(CodeInstruction code)
{
if (pinLabels)
{
CodeInstructionExtensions.MoveLabelsFrom(Instructions[startIndex.Value], code);
}
if (pinBlocks)
{
CodeInstructionExtensions.MoveBlocksFrom(Instructions[startIndex.Value], code);
}
});
}
if (shiftCurrentIndex && CurrentIndex > startIndex)
{
CurrentIndex = Math.Max(startIndex.Value, CurrentIndex - num2);
}
return range;
}
public List<CodeInstruction> RemoveIL(int? startIndex = null, int? endIndex = null, bool shiftCurrentIndex = true, bool pinLabels = true, bool pinBlocks = true, string errorMessage = "Out of bounds!")
{
int valueOrDefault = startIndex.GetValueOrDefault();
if (!startIndex.HasValue)
{
valueOrDefault = CurrentIndex;
startIndex = valueOrDefault;
}
valueOrDefault = endIndex.GetValueOrDefault();
if (!endIndex.HasValue)
{
valueOrDefault = CurrentIndex;
endIndex = valueOrDefault;
}
return TryRemoveIL(startIndex, endIndex, shiftCurrentIndex, pinLabels, pinBlocks) ?? throw new Exception(string.Format("[ILStepper.ILStepper.RemoveIL] [{0}, {1}, {2} ({3})] | {4}", startIndex, endIndex, shiftCurrentIndex, shiftCurrentIndex ? "shift current index" : "dont shift current index", errorMessage));
}
public List<CodeInstruction>? TryGetIL(int? startIndex = null, int? endIndex = null)
{
startIndex = TryFindIndex(startIndex);
endIndex = TryFindIndex(endIndex);
if (!startIndex.HasValue || !endIndex.HasValue)
{
return null;
}
if (startIndex > endIndex)
{
int? num = endIndex;
endIndex = startIndex;
startIndex = num;
}
if (endIndex >= Instructions.Count)
{
return null;
}
int count = endIndex.Value - startIndex.Value;
return Instructions.GetRange(startIndex.Value, count);
}
public List<CodeInstruction> GetIL(int? startIndex = null, int? endIndex = null, string errorMessage = "Out of bounds!")
{
int valueOrDefault = startIndex.GetValueOrDefault();
if (!startIndex.HasValue)
{
valueOrDefault = CurrentIndex;
startIndex = valueOrDefault;
}
valueOrDefault = endIndex.GetValueOrDefault();
if (!endIndex.HasValue)
{
valueOrDefault = CurrentIndex;
endIndex = valueOrDefault;
}
return TryGetIL(startIndex, endIndex) ?? throw new Exception($"[ILStepper.ILStepper.GetIL] [{startIndex}, {endIndex}] | {errorMessage}");
}
public List<Label>? TryMoveAllLabels(List<CodeInstruction> sourceCodeRange, List<CodeInstruction> destinationCodeRange)
{
List<CodeInstruction> destinationCodeRange2 = destinationCodeRange;
if (sourceCodeRange.Count != destinationCodeRange2.Count)
{
return null;
}
return sourceCodeRange.SelectMany(delegate(CodeInstruction sourceCode, int sourceCodeIndex)
{
List<Label> list = CodeInstructionExtensions.ExtractLabels(sourceCode);
destinationCodeRange2[sourceCodeIndex].labels.AddRange(list);
return list;
}).ToList();
}
public List<Label>? TryMoveAllLabels(List<CodeInstruction> sourceCodeRange, CodeInstruction destinationCode)
{
return TryMoveAllLabels(sourceCodeRange, Enumerable.Repeat<CodeInstruction>(destinationCode, sourceCodeRange.Count).ToList());
}
public List<Label> MoveAllLabels(List<CodeInstruction> sourceCodeRange, List<CodeInstruction> destinationCodeRange, string errorMessage = "Source and destination instruction count don't match!")
{
return TryMoveAllLabels(sourceCodeRange, destinationCodeRange) ?? throw new Exception($"[ILStepper.ILStepper.MoveAllLabels] [{sourceCodeRange}, {destinationCodeRange}] | {errorMessage}");
}
public List<Label> MoveAllLabels(List<CodeInstruction> sourceCodeRange, CodeInstruction destinationCode, string errorMessage = "Source and destination instruction count don't match!")
{
return TryMoveAllLabels(sourceCodeRange, Enumerable.Repeat<CodeInstruction>(destinationCode, sourceCodeRange.Count).ToList()) ?? throw new Exception($"[ILStepper.ILStepper.MoveAllLabels] [{sourceCodeRange}, {{{destinationCode}, ...}}] | {errorMessage}");
}
public List<Label>? TryShiftAllLabels(int? startIndex = null, int? endIndex = null, int shiftBy = 1)
{
List<CodeInstruction> list = TryGetIL(startIndex, endIndex);
if (list == null)
{
return null;
}
int? startIndex2 = TryFindIndex(startIndex, shiftBy);
int? endIndex2 = TryFindIndex(endIndex, shiftBy);
if (!startIndex2.HasValue || !endIndex2.HasValue)
{
return null;
}
List<CodeInstruction> list2 = TryGetIL(startIndex2, endIndex2);
if (list2 == null)
{
return null;
}
return TryMoveAllLabels(list, list2);
}
public List<Label> ShiftAllLabels(int? startIndex = null, int? endIndex = null, int shiftBy = 1, string errorMessage = "Source and/or destination instructions out of bounds!")
{
int valueOrDefault = startIndex.GetValueOrDefault();
if (!startIndex.HasValue)
{
valueOrDefault = CurrentIndex;
startIndex = valueOrDefault;
}
valueOrDefault = endIndex.GetValueOrDefault();
if (!endIndex.HasValue)
{
valueOrDefault = CurrentIndex;
endIndex = valueOrDefault;
}
return TryShiftAllLabels(startIndex, endIndex) ?? throw new Exception($"[ILStepper.ILStepper.ShiftAllLabels] [{startIndex}, {endIndex}, {startIndex + shiftBy} ({startIndex} + {shiftBy}), {endIndex + shiftBy} ({endIndex} + {shiftBy})] | {errorMessage}");
}
public List<ExceptionBlock>? TryMoveAllBlocks(List<CodeInstruction> sourceCodeRange, List<CodeInstruction> destinationCodeRange)
{
List<CodeInstruction> destinationCodeRange2 = destinationCodeRange;
if (sourceCodeRange.Count != destinationCodeRange2.Count)
{
return null;
}
return sourceCodeRange.SelectMany(delegate(CodeInstruction sourceCode, int sourceCodeIndex)
{
List<ExceptionBlock> list = CodeInstructionExtensions.ExtractBlocks(sourceCode);
destinationCodeRange2[sourceCodeIndex].blocks.AddRange(list);
return list;
}).ToList();
}
public List<ExceptionBlock>? TryMoveAllBlocks(List<CodeInstruction> sourceCodeRange, CodeInstruction destinationCode)
{
return TryMoveAllBlocks(sourceCodeRange, Enumerable.Repeat<CodeInstruction>(destinationCode, sourceCodeRange.Count).ToList());
}
public List<ExceptionBlock> MoveAllBlocks(List<CodeInstruction> sourceCodeRange, List<CodeInstruction> destinationCodeRange, string errorMessage = "Source and destination instruction count don't match!")
{
return TryMoveAllBlocks(sourceCodeRange, destinationCodeRange) ?? throw new Exception($"[ILStepper.ILStepper.MoveAllBlocks] [{sourceCodeRange}, {destinationCodeRange}] | {errorMessage}");
}
public List<ExceptionBlock> MoveAllBlocks(List<CodeInstruction> sourceCodeRange, CodeInstruction destinationCode, string errorMessage = "Source and destination instruction count don't match!")
{
return TryMoveAllBlocks(sourceCodeRange, Enumerable.Repeat<CodeInstruction>(destinationCode, sourceCodeRange.Count).ToList()) ?? throw new Exception($"[ILStepper.ILStepper.MoveAllBlocks] [{sourceCodeRange}, {{{destinationCode}, ...}}] | {errorMessage}");
}
public List<ExceptionBlock>? TryShiftAllBlocks(int? startIndex = null, int? endIndex = null, int shiftBy = 1)
{
List<CodeInstruction> list = TryGetIL(startIndex, endIndex);
if (list == null)
{
return null;
}
int? startIndex2 = TryFindIndex(startIndex, shiftBy);
int? endIndex2 = TryFindIndex(endIndex, shiftBy);
if (!startIndex2.HasValue || !endIndex2.HasValue)
{
return null;
}
List<CodeInstruction> list2 = TryGetIL(startIndex2, endIndex2);
if (list2 == null)
{
return null;
}
return TryMoveAllBlocks(list, list2);
}
public List<ExceptionBlock> ShiftAllBlocks(int? startIndex = null, int? endIndex = null, int shiftBy = 1, string errorMessage = "Source and/or destination instructions out of bounds!")
{
int valueOrDefault = startIndex.GetValueOrDefault();
if (!startIndex.HasValue)
{
valueOrDefault = CurrentIndex;
startIndex = valueOrDefault;
}
valueOrDefault = endIndex.GetValueOrDefault();
if (!endIndex.HasValue)
{
valueOrDefault = CurrentIndex;
endIndex = valueOrDefault;
}
return TryShiftAllBlocks(startIndex, endIndex) ?? throw new Exception($"[ILStepper.ILStepper.ShiftAllBlocks] [{startIndex}, {endIndex}, {startIndex + shiftBy} ({startIndex} + {shiftBy}), {endIndex + shiftBy} ({endIndex} + {shiftBy})] | {errorMessage}");
}
public List<Label> ExtractAllLabels(List<CodeInstruction> codeRange)
{
return codeRange.SelectMany((CodeInstruction code) => CodeInstructionExtensions.ExtractLabels(code)).ToList();
}
public List<Label>? TryExtractAllLabels(int? startIndex = null, int? endIndex = null)
{
List<CodeInstruction> list = TryGetIL(startIndex, endIndex);
if (list == null)
{
return null;
}
return ExtractAllLabels(list);
}
public List<Label> ExtractAllLabels(int? startIndex = null, int? endIndex = null, string errorMessage = "Out of bounds!")
{
int valueOrDefault = startIndex.GetValueOrDefault();
if (!startIndex.HasValue)
{
valueOrDefault = CurrentIndex;
startIndex = valueOrDefault;
}
return TryExtractAllLabels(startIndex, endIndex) ?? throw new Exception($"[ILStepper.ILStepper.ExtractAllLabels] [{startIndex}, {endIndex}] | {errorMessage}");
}
public List<Label> ExtractAllBlocks(List<CodeInstruction> codeRange)
{
return codeRange.SelectMany((CodeInstruction code) => CodeInstructionExtensions.ExtractLabels(code)).ToList();
}
public List<Label>? TryExtractAllBlocks(int? startIndex = null, int? endIndex = null)
{
List<CodeInstruction> list = TryGetIL(startIndex, endIndex);
if (list == null)
{
return null;
}
return ExtractAllBlocks(list);
}
public List<Label> ExtractAllBlocks(int? startIndex = null, int? endIndex = null, string errorMessage = "Out of bounds!")
{
int valueOrDefault = startIndex.GetValueOrDefault();
if (!startIndex.HasValue)
{
valueOrDefault = CurrentIndex;
startIndex = valueOrDefault;
}
valueOrDefault = endIndex.GetValueOrDefault();
if (!endIndex.HasValue)
{
valueOrDefault = CurrentIndex;
endIndex = valueOrDefault;
}
return TryExtractAllBlocks(startIndex, endIndex) ?? throw new Exception($"[ILStepper.ILStepper.ExtractAllBlocks] [{startIndex}, {endIndex}] | {errorMessage}");
}
public List<CodeInstruction>? TryShiftIL(int? startIndex = null, int? endIndex = null, int shiftBy = 1, bool shiftCurrentIndex = true)
{
startIndex = TryFindIndex(startIndex);
endIndex = TryFindIndex(endIndex);
if (!startIndex.HasValue || !endIndex.HasValue)
{
return null;
}
if (startIndex > endIndex)
{
int? num = endIndex;
endIndex = startIndex;
startIndex = num;
}
if (endIndex >= Instructions.Count)
{
return null;
}
int num2 = endIndex.Value - startIndex.Value;
int? index = TryFindIndex(startIndex, shiftBy, 0, -num2 + 1);
if (!index.HasValue)
{
return null;
}
if (shiftCurrentIndex && CurrentIndex >= startIndex && CurrentIndex < endIndex)
{
CurrentIndex += shiftBy;
shiftCurrentIndex = false;
}
string errorMessage = $"[ILStepper.ILStepper.TryShiftIL] [{startIndex}, {endIndex}, {startIndex + shiftBy} ({startIndex} + {shiftBy}), {endIndex + shiftBy} ({endIndex} + {shiftBy})] Somehow calculated invalid parameters. This should never happen!";
List<CodeInstruction> codeRange = RemoveIL(startIndex, endIndex, shiftCurrentIndex, pinLabels: false, pinBlocks: false, errorMessage);
return InsertIL(codeRange, index, shiftCurrentIndex, pinLabels: false, pinBlocks: false, errorMessage);
}
public List<CodeInstruction> ShiftIL(int? startIndex = null, int? endIndex = null, int shiftBy = 1, bool shiftCurrentIndex = true, string errorMessage = "Source and/or destination instructions out of bounds!")
{
int valueOrDefault = startIndex.GetValueOrDefault();
if (!startIndex.HasValue)
{
valueOrDefault = CurrentIndex;
startIndex = valueOrDefault;
}
valueOrDefault = endIndex.GetValueOrDefault();
if (!endIndex.HasValue)
{
valueOrDefault = CurrentIndex;
endIndex = valueOrDefault;
}
return TryShiftIL(startIndex, endIndex, shiftBy, shiftCurrentIndex) ?? throw new Exception($"[ILStepper.ILStepper.ShiftIL] [{startIndex}, {endIndex}, {startIndex + shiftBy} ({startIndex} + {shiftBy}), {endIndex + shiftBy} ({endIndex} + {shiftBy})] | {errorMessage}");
}
public List<CodeInstruction>? TryOverwriteIL(List<CodeInstruction> codeRange, int? index = null, bool pinLabels = true, bool pinBlocks = true)
{
int valueOrDefault = index.GetValueOrDefault();
if (!index.HasValue)
{
valueOrDefault = CurrentIndex;
index = valueOrDefault;
}
List<CodeInstruction> removedIL = TryRemoveIL(index, index + codeRange.Count(), shiftCurrentIndex: false, pinLabels: false, pinBlocks: false);
if (removedIL == null)
{
return null;
}
codeRange = codeRange.Select(delegate(CodeInstruction code, int i)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Expected O, but got Unknown
code = new CodeInstruction(code);
if (pinLabels)
{
CodeInstructionExtensions.MoveLabelsTo(removedIL[i], code);
}
if (pinBlocks)
{
CodeInstructionExtensions.MoveBlocksTo(removedIL[i], code);
}
return code;
}).ToList();
return TryInsertIL(codeRange, index, shiftCurrentIndex: false, pinLabels: false, pinBlocks: false);
}
public List<CodeInstruction>? TryOverwriteIL(CodeInstruction? code, int? index = null, bool pinLabels = true, bool pinBlocks = true)
{
return TryOverwriteIL((code != null) ? new List<CodeInstruction>(1) { code } : new List<CodeInstruction>(), index, pinLabels, pinBlocks);
}
public List<CodeInstruction> OverwriteIL(List<CodeInstruction> codeRange, int? index = null, bool pinLabels = true, bool pinBlocks = true, string errorMessage = "Out of bounds!")
{
int valueOrDefault = index.GetValueOrDefault();
if (!index.HasValue)
{
valueOrDefault = CurrentIndex;
index = valueOrDefault;
}
return TryOverwriteIL(codeRange, index, pinLabels, pinBlocks) ?? throw new Exception($"[ILStepper.ILStepper.OverwriteIL] [{codeRange}, {index}, {index + codeRange.Count()} ({index} + {codeRange.Count()})] | {errorMessage}");
}
public List<CodeInstruction> OverwriteIL(CodeInstruction? code, int? index = null, bool pinLabels = true, bool pinBlocks = true, string errorMessage = "Out of bounds!")
{
int valueOrDefault = index.GetValueOrDefault();
if (!index.HasValue)
{
valueOrDefault = CurrentIndex;
index = valueOrDefault;
}
return TryOverwriteIL((code != null) ? new List<CodeInstruction>(1) { code } : new List<CodeInstruction>(), index, pinLabels, pinBlocks) ?? throw new Exception($"[ILStepper.ILStepper.OverwriteIL] [{code}, {index}, {index + ((code != null) ? 1 : 0)} ({index} + {((code != null) ? 1 : 0)})] | {errorMessage}");
}
}
[BepInPlugin("com.github.decibillyjoel.ILUtils", "DBJ.ILUtils", "1.0.4")]
public class Plugin : BaseUnityPlugin
{
public const string PLUGIN_GUID = "com.github.decibillyjoel.ILUtils";
public const string PLUGIN_NAME = "ILUtils";
public const string PLUGIN_VERSION = "1.0.4";
public const string PLUGIN_TS_TEAM = "DBJ";
public static ManualLogSource PluginLogger;
public static void Log(LogLevel logLevel, string logMessage)
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
PluginLogger.Log(logLevel, (object)(logMessage ?? ""));
}
public static void Log(string logMessage)
{
Log((LogLevel)16, logMessage);
}
private void Awake()
{
PluginLogger = ((BaseUnityPlugin)this).Logger;
Log("[v1.0.4] Finished loading!");
}
}
}
namespace ILUtils.HarmonyXtensions
{
public static class CodeInstructionPolyfills
{
public static readonly OpCode[] ARGUMENTED_LOCAL_INSTRUCTS = new OpCode[6]
{
OpCodes.Ldloc,
OpCodes.Stloc,
OpCodes.Ldloca,
OpCodes.Ldloc_S,
OpCodes.Stloc_S,
OpCodes.Ldloca_S
};
public static readonly OpCode[] LOAD_FIELD_INSTRUCTS = new OpCode[4]
{
OpCodes.Ldfld,
OpCodes.Ldsfld,
OpCodes.Ldflda,
OpCodes.Ldsflda
};
public static readonly OpCode[] STORE_FIELD_INSTRUCTS = new OpCode[2]
{
OpCodes.Stfld,
OpCodes.Stsfld
};
public static bool IsValid(this OpCode code)
{
return code.Size > 0;
}
public static CodeInstruction Call(Type type, string name, Type[]? parameters = null, Type[]? generics = null)
{
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_004a: Expected O, but got Unknown
MethodInfo methodInfo = AccessTools.Method(type, name, parameters, generics) ?? throw new ArgumentException($"No method found for type={type}, name={name}, parameters={GeneralExtensions.Description(parameters)}, generics={GeneralExtensions.Description(generics)}");
return new CodeInstruction(OpCodes.Call, (object)methodInfo);
}
public static bool Calls(this CodeInstruction codeInstruction, Type type, string name, Type[]? parameters = null, Type[]? generics = null)
{
MethodInfo methodInfo = AccessTools.Method(type, name, parameters, generics) ?? throw new ArgumentException($"No method found for type={type}, name={name}, parameters={GeneralExtensions.Description(parameters)}, generics={GeneralExtensions.Description(generics)}");
return CodeInstructionExtensions.Calls(codeInstruction, methodInfo);
}
public static CodeInstruction Call(string typeColonMethodname, Type[]? parameters = null, Type[]? generics = null)
{
//IL_0052: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: Expected O, but got Unknown
MethodInfo methodInfo = AccessTools.Method(typeColonMethodname, parameters, generics) ?? throw new ArgumentException("No method found for " + typeColonMethodname + ", parameters=" + GeneralExtensions.Description(parameters) + ", generics=" + GeneralExtensions.Description(generics));
return new CodeInstruction(OpCodes.Call, (object)methodInfo);
}
public static bool Calls(this CodeInstruction codeInstruction, string typeColonMethodname, Type[]? parameters = null, Type[]? generics = null)
{
MethodInfo methodInfo = AccessTools.Method(typeColonMethodname, parameters, generics) ?? throw new ArgumentException("No method found for " + typeColonMethodname + ", parameters=" + GeneralExtensions.Description(parameters) + ", generics=" + GeneralExtensions.Description(generics));
return CodeInstructionExtensions.Calls(codeInstruction, methodInfo);
}
public static CodeInstruction Call(Expression<Action> expression)
{
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Expected O, but got Unknown
return new CodeInstruction(OpCodes.Call, (object)SymbolExtensions.GetMethodInfo(expression));
}
public static CodeInstruction Call<T>(Expression<Action<T>> expression)
{
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Expected O, but got Unknown
return new CodeInstruction(OpCodes.Call, (object)SymbolExtensions.GetMethodInfo<T>(expression));
}
public static CodeInstruction Call<T, TResult>(Expression<Func<T, TResult>> expression)
{
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Expected O, but got Unknown
return new CodeInstruction(OpCodes.Call, (object)SymbolExtensions.GetMethodInfo<T, TResult>(expression));
}
public static CodeInstruction Call(LambdaExpression expression)
{
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Expected O, but got Unknown
return new CodeInstruction(OpCodes.Call, (object)SymbolExtensions.GetMethodInfo(expression));
}
public static CodeInstruction CallClosure<T>(T closure) where T : Delegate
{
return Transpilers.EmitDelegate<T>(closure);
}
public static CodeInstruction CallConstructor(Type type, Type[]? parameters = null, bool searchForStatic = false)
{
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: Expected O, but got Unknown
ConstructorInfo constructorInfo = AccessTools.Constructor(type, parameters, searchForStatic) ?? throw new ArgumentException($"No constructor found for type={type}, parameters={GeneralExtensions.Description(parameters)}, searchForStatic={searchForStatic}");
return new CodeInstruction(OpCodes.Newobj, (object)constructorInfo);
}
public static CodeInstruction LoadField(Type type, string name, bool useAddress = false)
{
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
//IL_0052: Expected O, but got Unknown
FieldInfo fieldInfo = AccessTools.Field(type, name) ?? throw new ArgumentException($"No field found for {type} and {name}");
return new CodeInstruction((!useAddress) ? (fieldInfo.IsStatic ? OpCodes.Ldsfld : OpCodes.Ldfld) : (fieldInfo.IsStatic ? OpCodes.Ldsflda : OpCodes.Ldflda), (object)fieldInfo);
}
public static CodeInstruction StoreField(Type type, string name)
{
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_0039: Expected O, but got Unknown
FieldInfo fieldInfo = AccessTools.Field(type, name) ?? throw new ArgumentException($"No field found for {type} and {name}");
return new CodeInstruction(fieldInfo.IsStatic ? OpCodes.Stsfld : OpCodes.Stfld, (object)fieldInfo);
}
public static bool LoadsField(this CodeInstruction codeInstruction, Type type, string name, bool byAddress = false)
{
FieldInfo fieldInfo = AccessTools.DeclaredField(type, name);
if (fieldInfo != null)
{
return CodeInstructionExtensions.LoadsField(codeInstruction, fieldInfo, byAddress);
}
return false;
}
public static bool StoresField(this CodeInstruction codeInstruction, Type type, string name)
{
FieldInfo fieldInfo = AccessTools.DeclaredField(type, name);
if (fieldInfo != null)
{
return CodeInstructionExtensions.StoresField(codeInstruction, fieldInfo);
}
return false;
}
public static int LocalIndex(this CodeInstruction code)
{
if (code.opcode == OpCodes.Ldloc_0 || code.opcode == OpCodes.Stloc_0)
{
return 0;
}
if (code.opcode == OpCodes.Ldloc_1 || code.opcode == OpCodes.Stloc_1)
{
return 1;
}
if (code.opcode == OpCodes.Ldloc_2 || code.opcode == OpCodes.Stloc_2)
{
return 2;
}
if (code.opcode == OpCodes.Ldloc_3 || code.opcode == OpCodes.Stloc_3)
{
return 3;
}
if (ARGUMENTED_LOCAL_INSTRUCTS.Contains(code.opcode))
{
int? num = (code.operand as LocalVariableInfo)?.LocalIndex;
return Convert.ToInt32(num.HasValue ? ((object)num.GetValueOrDefault()) : code.operand);
}
throw new ArgumentException("Instruction is not a load or store", "code");
}
public static CodeInstruction LoadLocal(int index, bool useAddress = false)
{
//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
//IL_00b7: Expected O, but got Unknown
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Expected O, but got Unknown
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Expected O, but got Unknown
//IL_005c: Unknown result type (might be due to invalid IL or missing references)
//IL_0062: Expected O, but got Unknown
//IL_006a: Unknown result type (might be due to invalid IL or missing references)
//IL_0070: Expected O, but got Unknown
//IL_0078: Unknown result type (might be due to invalid IL or missing references)
//IL_007e: Expected O, but got Unknown
//IL_0086: Unknown result type (might be due to invalid IL or missing references)
//IL_008c: Expected O, but got Unknown
//IL_009e: Unknown result type (might be due to invalid IL or missing references)
//IL_00a4: Expected O, but got Unknown
if (useAddress)
{
if (index < 256)
{
return new CodeInstruction(OpCodes.Ldloca_S, (object)Convert.ToByte(index));
}
return new CodeInstruction(OpCodes.Ldloca, (object)index);
}
if (index < 256)
{
return (CodeInstruction)(index switch
{
0 => (object)new CodeInstruction(OpCodes.Ldloc_0, (object)null),
1 => (object)new CodeInstruction(OpCodes.Ldloc_1, (object)null),
2 => (object)new CodeInstruction(OpCodes.Ldloc_2, (object)null),
3 => (object)new CodeInstruction(OpCodes.Ldloc_3, (object)null),
_ => (object)new CodeInstruction(OpCodes.Ldloc_S, (object)Convert.ToByte(index)),
});
}
return new CodeInstruction(OpCodes.Ldloc, (object)index);
}
public static CodeInstruction LoadLocal(LocalVariableInfo local, bool useAddress = false)
{
return LoadLocal(local.LocalIndex, useAddress);
}
public static CodeInstruction StoreLocal(int index)
{
//IL_007b: Unknown result type (might be due to invalid IL or missing references)
//IL_0081: Expected O, but got Unknown
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_002c: Expected O, but got Unknown
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: Expected O, but got Unknown
//IL_0042: Unknown result type (might be due to invalid IL or missing references)
//IL_0048: Expected O, but got Unknown
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
//IL_0056: Expected O, but got Unknown
//IL_0068: Unknown result type (might be due to invalid IL or missing references)
//IL_006e: Expected O, but got Unknown
if (index < 256)
{
return (CodeInstruction)(index switch
{
0 => (object)new CodeInstruction(OpCodes.Stloc_0, (object)null),
1 => (object)new CodeInstruction(OpCodes.Stloc_1, (object)null),
2 => (object)new CodeInstruction(OpCodes.Stloc_2, (object)null),
3 => (object)new CodeInstruction(OpCodes.Stloc_3, (object)null),
_ => (object)new CodeInstruction(OpCodes.Stloc_S, (object)Convert.ToByte(index)),
});
}
return new CodeInstruction(OpCodes.Stloc, (object)index);
}
public static CodeInstruction StoreLocal(LocalVariableInfo local)
{
return StoreLocal(local.LocalIndex);
}
public static bool LoadsLocal(this CodeInstruction code, LocalVariableInfo? local = null)
{
if (CodeInstructionExtensions.IsLdloc(code, (LocalBuilder)null))
{
if (local != null)
{
return code.LocalIndex() == local.LocalIndex;
}
return true;
}
return false;
}
public static bool LoadsLocal(this CodeInstruction code, int index)
{
if (CodeInstructionExtensions.IsLdloc(code, (LocalBuilder)null))
{
return code.LocalIndex() == index;
}
return false;
}
public static bool StoresLocal(this CodeInstruction code, LocalVariableInfo? local = null)
{
if (CodeInstructionExtensions.IsStloc(code, (LocalBuilder)null))
{
if (local != null)
{
return code.LocalIndex() == local.LocalIndex;
}
return true;
}
return false;
}
public static bool StoresLocal(this CodeInstruction code, int index)
{
if (CodeInstructionExtensions.IsStloc(code, (LocalBuilder)null))
{
return code.LocalIndex() == index;
}
return false;
}
public static CodeInstruction LoadArgument(int index, bool useAddress = false)
{
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: Expected O, but got Unknown
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Expected O, but got Unknown
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Expected O, but got Unknown
//IL_004b: Unknown result type (might be due to invalid IL or missing references)
//IL_0051: Expected O, but got Unknown
//IL_005b: Unknown result type (might be due to invalid IL or missing references)
//IL_0061: Expected O, but got Unknown
//IL_006b: Unknown result type (might be due to invalid IL or missing references)
//IL_0071: Expected O, but got Unknown
//IL_009a: Unknown result type (might be due to invalid IL or missing references)
//IL_00a0: Expected O, but got Unknown
//IL_0089: Unknown result type (might be due to invalid IL or missing references)
//IL_008f: Expected O, but got Unknown
if (useAddress)
{
if (index >= 256)
{
return new CodeInstruction(OpCodes.Ldarga, (object)index);
}
return new CodeInstruction(OpCodes.Ldarga_S, (object)Convert.ToByte(index));
}
if (index != 0)
{
if (index != 1)
{
if (index != 2)
{
if (index != 3)
{
if (index >= 256)
{
return new CodeInstruction(OpCodes.Ldarg, (object)index);
}
return new CodeInstruction(OpCodes.Ldarg_S, (object)Convert.ToByte(index));
}
return new CodeInstruction(OpCodes.Ldarg_3, (object)null);
}
return new CodeInstruction(OpCodes.Ldarg_2, (object)null);
}
return new CodeInstruction(OpCodes.Ldarg_1, (object)null);
}
return new CodeInstruction(OpCodes.Ldarg_0, (object)null);
}
public static int ArgumentIndex(this CodeInstruction code)
{
if (code.opcode == OpCodes.Ldarg_0)
{
return 0;
}
if (code.opcode == OpCodes.Ldarg_1)
{
return 1;
}
if (code.opcode == OpCodes.Ldarg_2)
{
return 2;
}
if (code.opcode == OpCodes.Ldarg_3)
{
return 3;
}
if (code.opcode == OpCodes.Ldarg_S || code.opcode == OpCodes.Ldarg)
{
return Convert.ToInt32(code.operand);
}
if (code.opcode == OpCodes.Starg_S || code.opcode == OpCodes.Starg)
{
return Convert.ToInt32(code.operand);
}
if (code.opcode == OpCodes.Ldarga_S || code.opcode == OpCodes.Ldarga)
{
return Convert.ToInt32(code.operand);
}
throw new ArgumentException("Instruction is not a load or store", "code");
}
public static CodeInstruction StoreArgument(int index)
{
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
//IL_002f: Expected O, but got Unknown
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Expected O, but got Unknown
if (index >= 256)
{
return new CodeInstruction(OpCodes.Starg, (object)index);
}
return new CodeInstruction(OpCodes.Starg_S, (object)Convert.ToByte(index));
}
public static bool LoadsString(this CodeInstruction code, string str)
{
if (code.opcode != OpCodes.Ldstr)
{
return false;
}
string text = Convert.ToString(code.operand);
return text == str;
}
public static CodeInstruction LoadConstant(sbyte number)
{
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: Expected O, but got Unknown
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
//IL_0052: Expected O, but got Unknown
//IL_005d: Unknown result type (might be due to invalid IL or missing references)
//IL_0063: Expected O, but got Unknown
//IL_006b: Unknown result type (might be due to invalid IL or missing references)
//IL_0071: Expected O, but got Unknown
//IL_0079: Unknown result type (might be due to invalid IL or missing references)
//IL_007f: Expected O, but got Unknown
//IL_0087: Unknown result type (might be due to invalid IL or missing references)
//IL_008d: Expected O, but got Unknown
//IL_0095: Unknown result type (might be due to invalid IL or missing references)
//IL_009b: Expected O, but got Unknown
//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
//IL_00a9: Expected O, but got Unknown
//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
//IL_00b7: Expected O, but got Unknown
//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
//IL_00c5: Expected O, but got Unknown
//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
//IL_00d8: Expected O, but got Unknown
return (CodeInstruction)(number switch
{
-1 => (object)new CodeInstruction(OpCodes.Ldc_I4_M1, (object)null),
0 => (object)new CodeInstruction(OpCodes.Ldc_I4_0, (object)null),
1 => (object)new CodeInstruction(OpCodes.Ldc_I4_1, (object)null),
2 => (object)new CodeInstruction(OpCodes.Ldc_I4_2, (object)null),
3 => (object)new CodeInstruction(OpCodes.Ldc_I4_3, (object)null),
4 => (object)new CodeInstruction(OpCodes.Ldc_I4_4, (object)null),
5 => (object)new CodeInstruction(OpCodes.Ldc_I4_5, (object)null),
6 => (object)new CodeInstruction(OpCodes.Ldc_I4_6, (object)null),
7 => (object)new CodeInstruction(OpCodes.Ldc_I4_7, (object)null),
8 => (object)new CodeInstruction(OpCodes.Ldc_I4_8, (object)null),
_ => (object)new CodeInstruction(OpCodes.Ldc_I4_S, (object)number),
});
}
public static CodeInstruction LoadConstant(int number)
{
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Expected O, but got Unknown
if (number >= -128 && number <= 127)
{
return LoadConstant(Convert.ToSByte(number));
}
return new CodeInstruction(OpCodes.Ldc_I4, (object)number);
}
public static CodeInstruction LoadConstant(long number)
{
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Expected O, but got Unknown
return new CodeInstruction(OpCodes.Ldc_I8, (object)number);
}
public static CodeInstruction LoadConstant(Enum e)
{
return (CodeInstruction)(e.GetTypeCode() switch
{
TypeCode.Int64 => LoadConstant(Convert.ToInt64(e)),
TypeCode.SByte => LoadConstant(Convert.ToSByte(e)),
_ => LoadConstant(Convert.ToInt32(e)),
});
}
public static CodeInstruction[] LoadLongOptimally(long number)
{
//IL_0063: Unknown result type (might be due to invalid IL or missing references)
//IL_0069: Expected O, but got Unknown
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Expected O, but got Unknown
//IL_007f: Unknown result type (might be due to invalid IL or missing references)
//IL_0085: Expected O, but got Unknown
if (number >= -128)
{
if (number <= 127)
{
return (CodeInstruction[])(object)new CodeInstruction[2]
{
LoadConstant(Convert.ToSByte(number)),
new CodeInstruction(OpCodes.Conv_I8, (object)null)
};
}
if (number <= int.MaxValue)
{
goto IL_0047;
}
}
else if (number >= int.MinValue)
{
goto IL_0047;
}
return (CodeInstruction[])(object)new CodeInstruction[1]
{
new CodeInstruction(OpCodes.Ldc_I8, (object)number)
};
IL_0047:
return (CodeInstruction[])(object)new CodeInstruction[2]
{
LoadConstant(Convert.ToInt32(number)),
new CodeInstruction(OpCodes.Conv_I8, (object)null)
};
}
public static CodeInstruction[] LoadEnumOptimally(Enum e)
{
return e.GetTypeCode() switch
{
TypeCode.Int64 => LoadLongOptimally(Convert.ToInt64(e)),
TypeCode.SByte => (CodeInstruction[])(object)new CodeInstruction[1] { LoadConstant(Convert.ToSByte(e)) },
_ => (CodeInstruction[])(object)new CodeInstruction[1] { LoadConstant(Convert.ToInt32(e)) },
};
}
public static CodeInstruction LoadString(string str)
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Expected O, but got Unknown
return new CodeInstruction(OpCodes.Ldstr, (object)str);
}
public static CodeInstruction LoadNull()
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Expected O, but got Unknown
return new CodeInstruction(OpCodes.Ldnull, (object)null);
}
public static bool LoadsNull(this CodeInstruction code)
{
return object.Equals(code.opcode, OpCodes.Ldnull);
}
public static bool LoadsProperty(this CodeInstruction code, PropertyInfo property)
{
return CodeInstructionExtensions.Calls(code, property.GetGetMethod(nonPublic: true));
}
public static bool LoadsProperty(this CodeInstruction code, Type type, string name)
{
PropertyInfo propertyInfo = AccessTools.DeclaredProperty(type, name);
if (propertyInfo != null)
{
return code.LoadsProperty(propertyInfo);
}
return false;
}
public static bool StoresProperty(this CodeInstruction code, PropertyInfo property)
{
return CodeInstructionExtensions.Calls(code, property.GetSetMethod(nonPublic: true));
}
public static bool StoresProperty(this CodeInstruction code, Type type, string name)
{
PropertyInfo propertyInfo = AccessTools.DeclaredProperty(type, name);
if (propertyInfo != null)
{
return code.StoresProperty(propertyInfo);
}
return false;
}
public static CodeInstruction LoadProperty(PropertyInfo property)
{
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: Expected O, but got Unknown
return new CodeInstruction(OpCodes.Call, (object)property.GetGetMethod(nonPublic: true));
}
public static CodeInstruction LoadProperty(Type type, string name)
{
PropertyInfo property = AccessTools.Property(type, name) ?? throw new ArgumentException($"No property found for type={type}, name={name}");
return LoadProperty(property);
}
public static CodeInstruction StoreProperty(PropertyInfo property)
{
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: Expected O, but got Unknown
return new CodeInstruction(OpCodes.Call, (object)property.GetSetMethod(nonPublic: true));
}
public static CodeInstruction StoreProperty(Type type, string name)
{
PropertyInfo property = AccessTools.Property(type, name) ?? throw new ArgumentException($"No property found for type={type}, name={name}");
return StoreProperty(property);
}
}
}
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
internal sealed class IgnoresAccessChecksToAttribute : Attribute
{
public IgnoresAccessChecksToAttribute(string assemblyName)
{
}
}
}