none
How to pass all arguments to a wrapper function in .NET Profiler with ILRewrite? RRS feed

  • Question

  • Hi ,

    I want to make a profiler like New Relic's .NET agent, but I get some trouble.
    The effect just like the output below.

    a C# method like:
    int Foo(int a, int b, int c)
    {
        Console.Writeline("a={0}, b={1}, c={2}",a, b ,c);
        return (a+b+c);
    }

    when invoke Foo(1,2,3);
    1.before injection output:
    a=1,b=2,c=3

    2.after injection output:
    method(Foo) has three arguments:1,2,3.
     a=1,b=2,c=3
    method(Foo)  return 6.

    I have read 
    https://msdn.microsoft.com/en-us/library/bb384493%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396
    http://www.codeproject.com/Articles/17275/Really-Easy-Logging-using-IL-Rewriting-and-the-NET
    but I don't know how to pass all arguments.

    Thanks a lot!


    Wednesday, April 20, 2016 11:10 AM

Answers

    1. You should only need to write one pop instruction after calling Probe; The arguments will already be removed by the call and only the return value needs to be removed (int). If Probe returned void, then you wouldn't even need to pop that.
    2. If the method contains any exception handlers, then they need to copied too (with adjusted IL offsets). The exception handlers are stored in a data section that appears after the IL (at the first 4-byte aligned address after the last instruction).
    3. Did you write the method header before any IL? the method header contains things like IL length, a reference to the locals signature, max stack depth, weather or not there is a data section after the IL, etc. (see section 25.4 of partition II of ECMA-335)
    4. Did you allocate the memory for the method using the allocator returned by ICorProfilerInfo::GetILFunctionBodyAllocator?
    5. Is Probe an instance member or static? If it's an instance method then you will also need push an instance onto the evaluation stack before any of the arguments?
    6. Is the instrumented method static? if not, then arg0 will be the instance and you will want to start with ldarg.1 rather than ldarg.0.

    When you say "But It's not work" what do you mean? does it throw an exception? (what type/message?) or does the method simply not get called.

    • Marked as answer by IMMark Monday, May 9, 2016 10:18 AM
    Tuesday, April 26, 2016 10:06 PM

All replies

  • Can you clarify what you mean by "I don't know how to pass all arguments."?

    Are you saying you don't know what the required IL for the call looks like? how to emit it? or where to get the required information?

    Wednesday, April 20, 2016 9:56 PM
  • Thanks for your reply.

    When JITCompilationStarted callback, I do these:

    1.Get the number of arguments of the target function "int Foo(int a, int b, int c);"

    2.Get original body by API GetILFunctionBody

    3.Alloc new body size

    4.Write ldarg.0 ldarg.1 ... 

    5.Write call Probe  (Probe is written by C#, "int Probe (int a, int b, int c);" ,the same as the target function)

    6.Write pop pop ...  

    7.Write original body

    8.Set new body by SetILFunctionBody

    But it's  not work, I don't know I was wrong.

    Tuesday, April 26, 2016 11:07 AM
    1. You should only need to write one pop instruction after calling Probe; The arguments will already be removed by the call and only the return value needs to be removed (int). If Probe returned void, then you wouldn't even need to pop that.
    2. If the method contains any exception handlers, then they need to copied too (with adjusted IL offsets). The exception handlers are stored in a data section that appears after the IL (at the first 4-byte aligned address after the last instruction).
    3. Did you write the method header before any IL? the method header contains things like IL length, a reference to the locals signature, max stack depth, weather or not there is a data section after the IL, etc. (see section 25.4 of partition II of ECMA-335)
    4. Did you allocate the memory for the method using the allocator returned by ICorProfilerInfo::GetILFunctionBodyAllocator?
    5. Is Probe an instance member or static? If it's an instance method then you will also need push an instance onto the evaluation stack before any of the arguments?
    6. Is the instrumented method static? if not, then arg0 will be the instance and you will want to start with ldarg.1 rather than ldarg.0.

    When you say "But It's not work" what do you mean? does it throw an exception? (what type/message?) or does the method simply not get called.

    • Marked as answer by IMMark Monday, May 9, 2016 10:18 AM
    Tuesday, April 26, 2016 10:06 PM
  • Thank you very much!

    It works when I remove unnecessary "pop" IL.

    But I have another trouble, please help me.

    I want to write the IL like this in Profiler:   " IL_000e:  box  [mscorlib]System.Int32"

    I know use CEE_BOX to make "box",but how to get "System.Int32"'s mdTypeRef?

    PS:   I write IL to change value type (such as int, float) to object type. Then I found that the value type need to box when I decompile my test code by ildasm.

    Thanks again.


    • Edited by IMMark Monday, May 9, 2016 10:34 AM
    Monday, May 9, 2016 10:18 AM
  • Its usually better to start a new thread for new questions.

    To get the metadata token for "System.Int32" you can get the TypeRef token by using ICorProfilerInfo::GetModuleMetaData to get an IMetaDataImport instance for the module you are instrumenting and then using IMetaDataImport::FindTypeRef or IMetaDataImport::EnumTypeRefs to get the token.

    If you can't rely on the module being rewritten already having the TypeRef, then you can add one. This needs to be done during the ICorProfilerCallback::ModuleLoadFinished callback, by using GetModuleMetaData to request an IMetaDataEmit instance and then using IMetaDataEmit::DefineTypeRefByName.

    Further Reading: creating-an-il-rewriting-profiler

    Monday, May 9, 2016 12:13 PM
  • hi, I start a new thread for my question.  

    https://social.msdn.microsoft.com/Forums/en-US/d36ead29-d813-4cb4-abcf-61fc6e339b0e/how-can-i-change-any-type-from-function-signature-to-object-type-in-il?forum=clr

    Look forward to your reply.

    Saturday, May 14, 2016 11:59 AM