-
-
Notifications
You must be signed in to change notification settings - Fork 492
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Request: CodeInstruction generator #42
Comments
Part of the api I want to make public in combination with reverse patching |
Awesome, thanks! |
Any update on this? Would be amazing to have the CodeInstructions generator available in order to replace methods |
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: 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);
}
}
} Note that in order to get the instructions, you will as a side effect generate local vars on your current generator. |
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. |
It would be really nice to have a function that took a Method and returned a list/enumberable of CodeInstructions for use in Transpilers.
The text was updated successfully, but these errors were encountered: