I am using dotPeek and ILSpy to explore some compiled release C# code. Quite a lot of the methods are full of structures like this:
// Within method Class.foo()...
if (condition)
{
label_2:
switch (7)
{
case 0:
goto label_2;
default:
if (false)
{
// ISSUE: method reference
RuntimeMethodHandle runtimeMethodHandle = __methodref (Class.foo);
}
// Do things
switch (3)
{
case 0:
goto label_8;
}
break;
}
}
}
That is from dotPeek. ILSpy translates this as:
if (condition)
{
while (true)
{
switch (7)
{
case 0:
continue;
}
break;
}
if (1 == 0)
{
/*OpCode not supported: LdMemberToken*/;
}
// Do things
while (true)
{
switch (3)
{
case 0:
continue;
}
break;
}
}
So just turning the gotos to a while loop and adding a comment about an unsupported OpCode. The actual IL code of this first switch
is
// start of loop, entry point: IL_002f
// [736 9 - 736 19]
IL_002f: ldc.i4.7
IL_0030: switch (IL_002f)
// end of loop
// [741 13 - 741 23]
IL_0039: ldc.i4.1
IL_003a: brtrue.s IL_0042
// [744 15 - 744 98]
IL_003c: ldtoken method void Class::foo(/* args */)
IL_0041: pop
IL_0042: ...
I believe I have read that while __methodref
is legal in IL code, it is not legal in C#, so I'm assuming this is something added by the compiler or some other post-compilation tool, but I'm wondering why. The code is full of these, references to the method they are in that are unconditionally skipped over using some odd switch structure. I thought the while loop might have been part of some thread-safety check, but that doesn't make sense looking at the IL code. Could the __methodref
s be used for profiling, tracing, or debugging? If so, I'd expect at least one decompiler to recognize them. Are they intentional obfuscation. Can anyone tell me where these come from and what they are for?