How to determine the arguments that will be passed to a specific IL method call in Mono.Cecil

I use Mono.Cecil to analyze and rewrite the assembly. In some cases, this is quite simple: you can just look right before the call to see where the arguments are loaded:

// Math.Pow(2, 4)
IL_0001:  ldc.r8      00 00 00 00 00 00 00 40 
IL_000A:  ldc.r8      00 00 00 00 00 00 10 40 
IL_0013:  call        System.Math.Pow

However, this is complicated when the function arguments themselves are complex expressions:

// Math.Pow(2, Math.Abs(Math.Max(17, "123".GetHashCode())));
IL_0001:  ldc.r8      00 00 00 00 00 00 00 40 
IL_000A:  ldc.i4.s    11 
IL_000C:  ldstr       "123"
IL_0011:  callvirt    System.Object.GetHashCode
IL_0016:  call        System.Math.Max
IL_001B:  call        System.Math.Abs
IL_0020:  conv.r8     
IL_0021:  call        System.Math.Pow

In this case, a bunch of things happen when the first argument is loaded and when the second argument is loaded. I am wondering: does Mono.Cecil make any tools to find the IL instructions responsible for pressing each argument?

+4
source share
1 answer

ILSpy IL # Cecil, ICSharpCode.Decompiler. IL "IL AST", , , , .

:

var decompiled = new ILAstBuilder().Build(method, true, new DecompilerContext(module));
var block = new ILBlock(decompiled);
new ILInlining(block).InlineAllVariables();

( Release):

static double F()
{
    return Math.Pow(2, Math.Abs(Math.Max(17, "123".GetHashCode())));
}

block :

ret(call(Math::Pow, ldc.r8(2), conv.r8(call(Math::Abs, call(Math::Max, ldc.i4(17), callvirt(object::GetHashCode, ldstr("123")))))));

, ICSharpCode.Decompiler, .

+2

Source: https://habr.com/ru/post/1628637/


All Articles