In C# Harmony patching. how do you compare the labels in CodeInstruction.labels to known label values

256 Views Asked by At

So I have a stream of IL code like this:

    IL_0047: ldarg.0
    IL_0048: ldc.i4.m1
    IL_0049: stfld int32 classname/innerclassname::'<>1__state'
    IL_004e: ldstr ""
    IL_0053: call void classname::set_aProperty(string)
    IL_0058: ldstr ""
    IL_005d: call void classname::set_aProperty(string)
    IL_0062: call int32 classname::get_aProperty()
    IL_0067: ldc.i4.8
    IL_0068: ble.s IL_0076

I want to replace IL_004e with a jump to IL_0067 (for example). The System.Reflection.Emit.Label class is opaque. You can compare equality. But there's no way to specify the label you want to compare it to unless you have already found the label through reflection. So, although I can see there exists a label, I have no idea what label it is. Label.ToString() just returns "System.Reflection.Emit.Label". Is there a way to create a label:

if (instruction.labels.Contains(x => x == Label.FromString("IL_0067")))

or some similar extension method?

1

There are 1 best solutions below

1
On

According to the answers to this question, labels are an abstraction for convenience; in bytecode in the assembly the operand of a jump is an offset relative to the next instruction. As far as I'm aware there is no existing method to generate an instance of System.Reflection.Emit.Label from the label names generated by decompilers.

You can, however, inject an ILGenerator into your transpiler, which you can use to create a new label with ILGenerator.DefineLabel. You can use this label as the operand of the jump and add it to the .labels field of the instruction you want to jump to. You can find that target instruction by looking for some context, for example the first instruction after a call to classname.get_aProperty.

For more information you can check the Harmony documentation: Transpiler - CodeInstruction.