Esempio n. 1
0
        public void Invoke(ILManipulator manip)
        {
            foreach (Instruction instr in Instrs)
            {
                if (instr.Operand is Instruction target)
                {
                    instr.Operand = new HookILLabel(this, target);
                }
                else if (instr.Operand is Instruction[] targets)
                {
                    instr.Operand = targets.Select(t => new HookILLabel(this, t)).ToArray();
                }
            }

            manip(this);

            foreach (Instruction instr in Instrs)
            {
                if (instr.Operand is HookILLabel label)
                {
                    instr.Operand = label.Target;
                }
                else if (instr.Operand is HookILLabel[] targets)
                {
                    instr.Operand = targets.Select(l => l.Target).ToArray();
                }
            }

            Method.ConvertShortLongOps();
        }
Esempio n. 2
0
        internal static Exception Create(Exception ex, MethodBody body)
        {
            var match = Regex.Match(ex.Message.TrimEnd(), "Reason: Invalid IL code in.+: IL_(\\d{4}): (.+)$");

            if (match.Success is false)
            {
                return(new HarmonyException("IL Compile Error (unknown location)", ex));
            }

            var finalInstructions = ILManipulator.GetInstructions(body) ?? new Dictionary <int, CodeInstruction>();

            var offset = int.Parse(match.Groups[1].Value, System.Globalization.NumberStyles.HexNumber);

            _ = Regex.Replace(match.Groups[2].Value, " {2,}", " ");
            if (ex is HarmonyException hEx)
            {
                if (finalInstructions.Count != 0)
                {
                    hEx.instructions = finalInstructions;
                    hEx.errorOffset  = offset;
                }
                return(hEx);
            }
            return(new HarmonyException(ex, finalInstructions, offset));
        }
Esempio n. 3
0
        private void ApplyReversePatch(ILContext ctx)
        {
            // Make a cecil copy of the original method for convenience sake
            var dmd = new DynamicMethodDefinition(original);

            var manipulator = new ILManipulator(dmd.Definition.Body);

            // Copy over variables from the original code
            ctx.Body.Variables.Clear();
            foreach (var variableDefinition in dmd.Definition.Body.Variables)
            {
                ctx.Body.Variables.Add(new VariableDefinition(ctx.Module.ImportReference(variableDefinition.VariableType)));
            }

            var transpiler = GetTranspiler(standin);

            if (transpiler != null)
            {
                manipulator.AddTranspiler(transpiler);
            }

            manipulator.WriteTo(ctx.Body, standin);

            // Write a ret in case it got removed (wrt. HarmonyManipulator)
            ctx.IL.Emit(OpCodes.Ret);
        }
Esempio n. 4
0
 internal void Invoke(ILManipulator manip)
 {
     manip(this);
     foreach (HookILLabel label in Labels)
     {
         IL.ReplaceOperands(label, label.Instr);
     }
 }
Esempio n. 5
0
		/// <summary>Returns the methods unmodified list of CodeInstructions</summary>
		/// <param name="original">The original method</param>
		/// <param name="generator">A new generator that now contains all local variables and labels contained in the result</param>
		/// <returns>A list containing all the original CodeInstructions</returns>
		public static List<CodeInstruction> GetOriginalInstructions(MethodBase original, out ILGenerator generator)
		{
			// Create a copy
			var dmd = new DynamicMethodDefinition(original);
			// Create a manipulator to obtain the instructions
			var manipulator = new ILManipulator(dmd.Definition.Body);
			generator = new CecilILGenerator(dmd.GetILProcessor()).GetProxy();
			return manipulator.GetInstructions(generator);
		}
Esempio n. 6
0
 public void Invoke(ILManipulator manip)
 {
     manip(this);
     foreach (HookILLabel label in Labels)
     {
         IL.ReplaceOperands(label, label.Instr);
     }
     Method.RecalculateILOffsets();
     Method.ConvertShortLongOps();
 }
Esempio n. 7
0
        /// <summary>A low level way to read the body of a method. Used for quick searching in methods</summary>
        /// <param name="method">The original method</param>
        /// <param name="generator">An existing generator that will be used to create all local variables and labels contained in the result</param>
        /// <returns>All instructions as opcode/operand pairs</returns>
        ///
        public static IEnumerable <KeyValuePair <OpCode, object> > ReadMethodBody(MethodBase method, ILGenerator generator)
        {
            var original = method.GetMethodPatcher().CopyOriginal();

            if (original == null)
            {
                return(null);
            }
            var manipulator = new ILManipulator(original.Definition.Body);

            // Force label generation
            _ = manipulator.GetInstructions(generator);
            return(manipulator.GetRawInstructions());
        }
Esempio n. 8
0
        public void Invoke(ILManipulator manip)
        {
            foreach (Instruction instr in Instrs)
            {
                if (instr.Operand is Instruction target)
                {
                    instr.Operand = new HookILLabel(this, target);
                }
            }

            manip(this);

            foreach (Instruction instr in Instrs)
            {
                if (instr.Operand is HookILLabel label)
                {
                    instr.Operand = label.Target;
                }
            }
        }
Esempio n. 9
0
        internal static MethodInfo ReversePatch(HarmonyMethod standin, MethodBase original, MethodInfo postTranspiler, MethodInfo postManipulator)
        {
            if (standin is null)
            {
                throw new ArgumentNullException(nameof(standin));
            }
            if (standin.method is null)
            {
                throw new ArgumentNullException($"{nameof(standin)}.{nameof(standin.method)}");
            }

            var transpilers    = new List <MethodInfo>();
            var ilmanipulators = new List <MethodInfo>();

            if (standin.reversePatchType == HarmonyReversePatchType.Snapshot)
            {
                var info = Harmony.GetPatchInfo(original);
                transpilers.AddRange(GetSortedPatchMethods(original, info.Transpilers.ToArray()));
                ilmanipulators.AddRange(GetSortedPatchMethods(original, info.ILManipulators.ToArray()));
            }
            if (postTranspiler is object)
            {
                transpilers.Add(postTranspiler);
            }
            if (postManipulator is object)
            {
                ilmanipulators.Add(postManipulator);
            }

            MethodBody patchBody = null;
            var        hook      = new ILHook(standin.method, ctx =>
            {
                if (!(original is MethodInfo mi))
                {
                    return;
                }

                patchBody = ctx.Body;

                var patcher = mi.GetMethodPatcher();
                var dmd     = patcher.CopyOriginal();

                if (dmd == null)
                {
                    throw new NullReferenceException($"Cannot reverse patch {mi.FullDescription()}: method patcher ({patcher.GetType().FullDescription()}) can't copy original method body");
                }

                var manipulator = new ILManipulator(dmd.Definition.Body);

                // Copy over variables from the original code
                ctx.Body.Variables.Clear();
                foreach (var variableDefinition in manipulator.Body.Variables)
                {
                    ctx.Body.Variables.Add(new VariableDefinition(ctx.Module.ImportReference(variableDefinition.VariableType)));
                }

                foreach (var methodInfo in transpilers)
                {
                    manipulator.AddTranspiler(methodInfo);
                }

                manipulator.WriteTo(ctx.Body, standin.method);

                HarmonyManipulator.ApplyILManipulators(ctx, original, ilmanipulators, null);

                // Write a ret in case it got removed (wrt. HarmonyManipulator)
                ctx.IL.Emit(OpCodes.Ret);
            }, new ILHookConfig {