Instruction Injection issue

26 views
Skip to first unread message

marti...@dotnetsharp.com

unread,
Mar 17, 2009, 7:13:34 PM3/17/09
to mono-cecil
//A method with try … catch (MSIL) whose Assembly is loaded by
Mono.Cecil and instructions injected in catch{ … } block
.method private hidebysig instance void TestMethod (object A,
class [mscorlib]
System.EventArgs a) cil managed
{
// Code size 544 (0x220)
.maxstack 5
.locals init (int32 V_0,
int32 V_1,
class [mscorlib]System.Exception V_2,
int32[] V_3,
string V_4)
.try
{
IL_0000: ldc.i4.2
IL_0001: stloc.0
IL_0002: ldc.i4.3
IL_0003: stloc.1
IL_0004: leave.s IL_001f /*** should be IL_021f ***/
} // end .try
catch [mscorlib]System.Exception
{
IL_0006: stloc.2
IL_0007: ldarg.0

// The original instruction is a “ldstr” has been replaced with a
list of instructions that I dreamed up 
//…………………..

IL_0207: ldloc.2
IL_0208: callvirt instance string [mscorlib]
System.Object::ToString()
IL_020d: call string [mscorlib]System.String::Concat
(string,

string)
IL_0212: ldc.i4.0
IL_0213: newarr [mscorlib]System.Object
IL_0218: call instance void FormBase::ShowInfo(string,
object[])
IL_021d: leave.s IL_021f
} // end handler
IL_021f: ret
} // end of method TestClass::TestMethod

Instructions are injected using Mono.Cecil’s method.Body.CilWorker.
As you can see from the above /* ... */ line, after the instruction
injection, the short form (_s) OpCode with
OperandType.ShortInlineBrTarget will be insufficient since it is only
8 unsigned bit long and it will get overflow. I managed to replace the
short form OpCode with non-short form one. But that is more like a
"hack" as it replaces every single one of them. Nonetheless, that did
the trick and rendered a valid program and my small test application
succeeded. But it failed in much more complex projects.

I wonder if I am still missing something? Thanks for any insights.

cygin

unread,
Mar 18, 2009, 6:03:16 AM3/18/09
to mono-cecil
MethodBody.Simplify() simplifies the body by turning short
instructions into normal ones (e.g. leave_s to leave)
After that, you can inject instructions without overflowing the
offsets.
Finally, you can use MethodBody.Optimize() to turn all into short form
when possible.

On Mar 18, 12:13 am, "martin....@dotnetsharp.com"
<martin....@dotnetsharp.com> wrote:
> //A method with try ... catch (MSIL) whose Assembly is loaded by
> Mono.Cecil and instructions injected in catch{ ... } block
> .method private hidebysig instance void TestMethod (object A,
> class [mscorlib]
> System.EventArgs a) cil managed
> {
> // Code size 544 (0x220)
> .maxstack 5
> .locals init (int32 V_0,
> int32 V_1,
> class [mscorlib]System.Exception V_2,
> int32[] V_3,
> string V_4)
> .try
> {
> IL_0000: ldc.i4.2
> IL_0001: stloc.0
> IL_0002: ldc.i4.3
> IL_0003: stloc.1
> IL_0004: leave.s IL_001f /*** should be IL_021f ***/
> } // end .try
> catch [mscorlib]System.Exception
> {
> IL_0006: stloc.2
> IL_0007: ldarg.0
>
> // The original instruction is a "ldstr" has been replaced with a
> list of instructions that I dreamed up 
> //.......................

Mar7in

unread,
Mar 18, 2009, 10:04:39 AM3/18/09
to mono-cecil
Great stuff! cannot believe I missed that "Simplify()" beauty. Thanks
a bunch!
> > I wonder if I am still missing something? Thanks for any insights.- Hide quoted text -
>
> - Show quoted text -
Reply all
Reply to author
Forward
0 new messages