weixin_39907850
weixin_39907850
2021-01-05 01:54

Request: CodeInstruction generator

It would be really nice to have a function that took a Method and returned a list/enumberable of CodeInstructions for use in Transpilers.

该提问来源于开源项目:pardeike/Harmony

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享
  • 邀请回答

5条回答

  • weixin_39953244 weixin_39953244 4月前

    Part of the api I want to make public in combination with reverse patching

    点赞 评论 复制链接分享
  • weixin_39907850 weixin_39907850 4月前

    Awesome, thanks!

    点赞 评论 复制链接分享
  • weixin_39759182 weixin_39759182 4月前

    Any update on this? Would be amazing to have the CodeInstructions generator available in order to replace methods

    点赞 评论 复制链接分享
  • weixin_39953244 weixin_39953244 4月前

    Just checked it in. The tricky part is that CodeInstructions can have local var references. And those come from registering new variables with the current ILGenerator. So I made this API:

    csharp
    using Harmony;
    using Harmony.ILCopying;
    using System;
    using System.Collections.Generic;
    using System.Reflection;
    using System.Reflection.Emit;
    
    namespace HarmonyConsoleApp
    {
        class Program
        {
            static void Main(string[] args)
            {
                var harmony = HarmonyInstance.Create("com.company.project.product");
                harmony.PatchAll(typeof(Program).Assembly);
    
                var test = new Test();
                test.Call();
                Console.ReadKey();
            }
        }
    
        public class Test
        {
            public void Extra()
            {
                Console.WriteLine("EXTRA");
            }
    
            public void Call()
            {
                Console.WriteLine("ORIGINAL");
            }
        }
    
        [HarmonyPatch(typeof(Test))]
        [HarmonyPatch("Call")]
        static class Patch
        {
            static IEnumerable<codeinstruction> Transpiler(ILGenerator generator, MethodBase method, IEnumerable<codeinstruction> instructions)
            {
                var ils1 = MethodBodyReader.GetInstructions(generator, method);
                foreach (var il in ils1)
                {
                    var instruction = il.GetCodeInstruction();
                    if (instruction.operand as string == "ORIGINAL")
                        instruction.operand = "PATCHED";
                    if (instruction.opcode != OpCodes.Ret)
                        yield return instruction;
                }
    
                var ils2 = MethodBodyReader.GetInstructions(generator, AccessTools.Method(typeof(Test), "Extra"));
                foreach (var il in ils2)
                {
                    var instruction = il.GetCodeInstruction();
                    if (instruction.opcode != OpCodes.Ret)
                        yield return instruction;
                }
    
                yield return new CodeInstruction(OpCodes.Ret);
            }
        }
    }
    </codeinstruction></codeinstruction>

    Note that in order to get the instructions, you will as a side effect generate local vars on your current generator.

    点赞 评论 复制链接分享
  • weixin_39953244 weixin_39953244 4月前

    I am going to make a high level reverse patch operation where you can project the ill codes onto an empty static method you have in your code for easier calling inside your patch functions.

    点赞 评论 复制链接分享

相关推荐