cecil
cecil copied to clipboard
ILProcessor.Replace bug with branch targets
this will cause some crital issues: IL0001 brtrue.s IL0002 IL0002 nop
Note: the IL0001's operand equals IL0002 but if we replace IL0002 to other instruction by use this method, it will cause the IL0001 link to wrong instruction.
I use a extension method as my workaround:
public static void ReplaceInstruction(this ILProcessor processor, Instruction from, Instruction to)
{
foreach (var item in processor.Body.Instructions)
{
var operInstruction = item.Operand as Instruction;
if (operInstruction != null && operInstruction == from)
{
item.Operand = to;
}
}
processor.Replace(from, to);
}
I hit this too, I think it would be great it Cecil took care of this in ILProcessor.Replace.
@lovettchris I noticed you took the ReplaceInstruction
method from here in the linked PR, but it is incomplete, as switch
operands and exception handlers also need to be modified.
See here for the method I use.
Also, note that you need to update references when removing instructions, but then maybe you intend to reinsert the removed instruction later on, so I'm not sure Cecil can safely do anything smart by itself 😕
Thanks @ltrzesniewski, makes sense. Thanks for the exception handler code, I also have code that fixes up TryStart when I insert code before the existing TryStart and I want that to be the new start of the try/catch. So yeah, I can see that the semantics of all this can be tricky to generalize...