JUUUUUUHUUUUUU works now :

Here the code, maybe somebody else needs the snippeds sometime :-)


---------------------------------
 internal class AssemblyTracing
  {
    /// <nn />
    private readonly string _assemblyPath;

    /// <summary>
    /// Constructor taking initializing parameter.
    /// </summary>
    /// <param name="assemblyPath">The path of the assembly where to inject 
tracing code.</param>
    public AssemblyTracing(string assemblyPath)
    {
      _assemblyPath = assemblyPath;
    }

    /// <summary>
    /// Injects tracing code to the assembly that this class instance has 
been created for.
    /// </summary>
    public void InjectTracingToAssembly()
    {
      var assemblyDefinition = 
AssemblyDefinition.ReadAssembly(_assemblyPath);

      Console.WriteLine("Injecting trace code to assembly \"{0}\"", 
_assemblyPath);
      foreach (var moduleDefinition in assemblyDefinition.Modules)
      {
        foreach (var typeDefinition in moduleDefinition.Types)
        {
          InjectTracingToTypeOfModule(typeDefinition, moduleDefinition);
        }
      }

      assemblyDefinition.Write(_assemblyPath, new WriterParameters { 
WriteSymbols = true });
    }

    /// <nn />
    private void InjectTracingToTypeOfModule(TypeDefinition type, 
ModuleDefinition moduleDefinition)
    {
      if (type.IsInterface || type.IsEnum || !type.IsClass)
      {
        return;
      }

      foreach (var typeDefinition in type.NestedTypes)
      {
        InjectTracingToTypeOfModule(typeDefinition, moduleDefinition);
      }

      FieldDefinition fTraceDomainField = AddFTraceDomainFieldToType(type, 
moduleDefinition);
      MethodDefinition staticConstructor = GetStaticConstructor(type);
      if (staticConstructor == null)
      {
        staticConstructor = AddStaticConstructorForFTraceDomain(type, 
moduleDefinition);
      }

      AddInitialisationOfFTraceDomainFieldToStaticConstructor(
        moduleDefinition, 
        type, 
        staticConstructor, 
        fTraceDomainField);

      foreach (var methodDefinition in type.Methods)
      {
        if (methodDefinition.IsConstructor /*&& methodDefinition.IsStatic*/)
        {
          continue;
        }

        if (methodDefinition.HasBody)
        {         
          EncapsulateMethodBodyWithTryFinallyBlock(moduleDefinition, 
methodDefinition, fTraceDomainField);

        }
      }
    }

    /// <nn />
    private static MethodDefinition GetStaticConstructor(TypeDefinition 
type)
    {
      foreach (var method in type.Methods)
      {
        if (method.IsConstructor && method.IsStatic)
        {
          return method;
        }
      }

      return null;
    }

    /// <nn />
    private static Instruction 
FindFirstInstructionSkipCtor(MethodDefinition med)
    {
      MethodBody body = med.Body;
      if (med.IsConstructor && !med.IsStatic)
      {
        return body.Instructions.Skip(2).First();
      }

      return body.Instructions.First();
    }

    /// <nn />
    private static Instruction FixReturns(MethodDefinition med, 
ModuleDefinition mod)
    {
      MethodBody body = med.Body;

      Instruction formallyLastInstruction = body.Instructions.Last();
      Instruction lastLeaveInstruction = null;
      if (med.ReturnType == mod.TypeSystem.Void)
      {
        var instructions = body.Instructions;
        var lastRet = Instruction.Create(OpCodes.Ret);
        instructions.Add(lastRet);

        for (var index = 0; index < instructions.Count - 1; index++)
        {
          var instruction = instructions[index];
          if (instruction.OpCode == OpCodes.Ret)
          {
            Instruction leaveInstruction = 
Instruction.Create(OpCodes.Leave, lastRet);
            if (instruction == formallyLastInstruction)
            {
              lastLeaveInstruction = leaveInstruction;
            }

            instructions[index] = leaveInstruction;
          }
        }

        FixBranchTargets(lastLeaveInstruction, formallyLastInstruction, 
body);
        return lastRet;
      }
      else
      {
        var instructions = body.Instructions;
        var returnVariable = new VariableDefinition("methodTimerReturn", 
med.ReturnType);
        body.Variables.Add(returnVariable);
        var lastLd = Instruction.Create(OpCodes.Ldloc, returnVariable);
        instructions.Add(lastLd);
        instructions.Add(Instruction.Create(OpCodes.Ret));

        for (var index = 0; index < instructions.Count - 2; index++)
        {
          var instruction = instructions[index];
          if (instruction.OpCode == OpCodes.Ret)
          {
            Instruction leaveInstruction = 
Instruction.Create(OpCodes.Leave, lastLd);
            if (instruction == formallyLastInstruction)
            {
              lastLeaveInstruction = leaveInstruction;
            }

            instructions[index] = leaveInstruction;
            instructions.Insert(index, Instruction.Create(OpCodes.Stloc, 
returnVariable));
            index++;
          }
        }

        FixBranchTargets(lastLeaveInstruction, formallyLastInstruction, 
body);
        return lastLd;
      }
    }

    /// <nn />
    private static void FixBranchTargets(
      Instruction lastLeaveInstruction, 
      Instruction formallyLastRetInstruction,
      MethodBody body)
    {
      for (var index = 0; index < body.Instructions.Count - 2; index++)
      {
        var instruction = body.Instructions[index];
        if (instruction.Operand != null && instruction.Operand == 
formallyLastRetInstruction)
        {
          instruction.Operand = lastLeaveInstruction;
        }
      }
    }

    /// <nn />
    private static void EncapsulateMethodBodyWithTryFinallyBlock(  
      ModuleDefinition mod,
      MethodDefinition med, 
      FieldDefinition fTraceDomainField)
    {

      if (med.Body == null || med.Body.Instructions.Count <= 0)
      {
        Console.WriteLine(med.Name + " has not body or no instructions in 
body");
        return;
      }


      med.Body.SimplifyMacros();

      

      ILProcessor ilProcessor = med.Body.GetILProcessor();

      var firstInstruction = FindFirstInstructionSkipCtor(med);
      Instruction returnInstruction = FixReturns(med, mod);

      var beforeReturn = Instruction.Create(OpCodes.Endfinally);
      ilProcessor.InsertBefore(returnInstruction, beforeReturn);



      var fTraceVar = new VariableDefinition("FTraceVar", 
mod.Import(typeof(syngo.Common.Diagnostics.Tracing.FTrace)));
      med.Body.Variables.Add(fTraceVar);

   
      /////////////// Start of try block  
      Instruction nopInstruction1 = Instruction.Create(OpCodes.Nop);
      ilProcessor.InsertBefore(firstInstruction, nopInstruction1);
    
      Instruction loadDomainInstruction = 
Instruction.Create(OpCodes.Ldsfld, fTraceDomainField);
      ilProcessor.InsertAfter(nopInstruction1 , loadDomainInstruction);

      Instruction loadMethodNameInstr = Instruction.Create(OpCodes.Ldstr, 
med.Name);
      ilProcessor.InsertAfter(loadDomainInstruction, loadMethodNameInstr);

      var constructor = 
        typeof(syngo.Common.Diagnostics.Tracing.FTrace).GetConstructor(
        new[]
        {
          typeof(syngo.Common.Diagnostics.Tracing.FTraceDomain), 
typeof(string)
        });
      var constructorReference = mod.Import(constructor);
      Instruction newConstructorInstruction = 
Instruction.Create(OpCodes.Newobj, constructorReference);
      ilProcessor.InsertAfter(loadMethodNameInstr, 
newConstructorInstruction); // create new instance of person

      Instruction popFTraceVariableInstruction = 
Instruction.Create(OpCodes.Stloc, fTraceVar);
      ////Pop a value from stack and store into local variable at index.
      ilProcessor.InsertAfter(newConstructorInstruction, 
popFTraceVariableInstruction);

 

      //////// Start Finally block
      Instruction nopInstruction2 = Instruction.Create(OpCodes.Nop);
      ilProcessor.InsertBefore(beforeReturn, nopInstruction2);

      Instruction loadFTraceVarInstruction = 
Instruction.Create(OpCodes.Ldloca, fTraceVar);
      ilProcessor.InsertAfter(nopInstruction2, loadFTraceVarInstruction); 
//Loads local variable onto stack

      Instruction callDisposeInstruction = Instruction.Create(OpCodes.Call,
        
mod.Import(typeof(syngo.Common.Diagnostics.Tracing.FTrace).GetMethod("Dispose")));
      ilProcessor.InsertAfter(loadFTraceVarInstruction, 
callDisposeInstruction); // calls dispose
      ///////// End finally block
      

      var handler = new ExceptionHandler(ExceptionHandlerType.Finally)
      {
        TryStart = nopInstruction1,
        TryEnd = nopInstruction2,
        HandlerStart = nopInstruction2,
        HandlerEnd = returnInstruction,
      };


      med.Body.ExceptionHandlers.Add(handler);
      med.Body.InitLocals = true;
      med.Body.OptimizeMacros();

    }



    /// <nn />
    private static FieldDefinition 
AddFTraceDomainFieldToType(TypeDefinition type, ModuleDefinition mod)
    {
      const string FIELDNAME = "FTRACEDOMAIN";

      FieldDefinition fTraceDomain = new FieldDefinition(
        FIELDNAME,
        Mono.Cecil.FieldAttributes.Static | 
Mono.Cecil.FieldAttributes.InitOnly,
        mod.Import(typeof(syngo.Common.Diagnostics.Tracing.FTraceDomain)));

      type.Fields.Add(fTraceDomain);

      return fTraceDomain;

    }

    /// <nn />
    private static MethodDefinition AddStaticConstructorForFTraceDomain(
      TypeDefinition type,
      ModuleDefinition mod)
    {
      var methodAttributes =
        MethodAttributes.Static | 
        MethodAttributes.HideBySig |
        MethodAttributes.SpecialName | 
        MethodAttributes.RTSpecialName;

      var method = new MethodDefinition(".cctor", methodAttributes, 
mod.TypeSystem.Void);
      method.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));
      type.Methods.Add(method);
      return method;
    }

    /// <nn />
    private static void 
AddInitialisationOfFTraceDomainFieldToStaticConstructor(
      ModuleDefinition mod,
      TypeDefinition type,
      MethodDefinition staticConstructor,
      FieldDefinition fTraceDomainField)
    {
      staticConstructor.Body.SimplifyMacros();
      Instruction firstInstruction = 
staticConstructor.Body.Instructions.First();
      ILProcessor ilProcessor = staticConstructor.Body.GetILProcessor();

      var writeLineMethod = typeof(Console).GetMethod("WriteLine", new 
Type[] { typeof(string) });
      var writeLineRef = mod.Import(writeLineMethod);
      Instruction loadInstruction = Instruction.Create(OpCodes.Ldstr, 
"Static Constructor of class " + type.Name);
      ilProcessor.InsertBefore(firstInstruction, loadInstruction);
      Instruction writeInstruction = Instruction.Create(OpCodes.Call, 
writeLineRef);
      ilProcessor.InsertAfter(loadInstruction, writeInstruction);

      Instruction loadClassTypeInstruction = 
Instruction.Create(OpCodes.Ldtoken, type);
      ilProcessor.InsertAfter(writeInstruction, loadClassTypeInstruction);

      Instruction callGetTypeInstruction = Instruction.Create(OpCodes.Call,
      mod.Import(typeof(System.Type).GetMethod("GetTypeFromHandle")));
      ilProcessor.InsertAfter(loadClassTypeInstruction, 
callGetTypeInstruction);

      var domainConstructor = 
        
typeof(syngo.Common.Diagnostics.Tracing.FTraceDomain).GetConstructor(new[] 
{ typeof(Type) });
      var domainConstructorReference = mod.Import(domainConstructor);
      Instruction domainConstructorInstruction = 
Instruction.Create(OpCodes.Newobj, domainConstructorReference);
      ilProcessor.InsertAfter(callGetTypeInstruction, 
domainConstructorInstruction); // create new instance of person
      Instruction popFTraceDomainVariableInstruction = 
Instruction.Create(OpCodes.Stsfld, fTraceDomainField);
      //Pop a value from stack and store into local variable at index.
      ilProcessor.InsertAfter(domainConstructorInstruction, 
popFTraceDomainVariableInstruction);

      staticConstructor.Body.OptimizeMacros();
    }
   
  }
----------------------------------









Am Freitag, 9. Januar 2015 10:00:40 UTC+1 schrieb Reh Gina:
>
> Yes, thats clear for me, but I am so desperate. I found some more help on 
> this page
>
> http://stackoverflow.com/questions/12769699/mono-cecil-injecting-try-finally/12798309#12798309
>
> Everything works fine until I do not add some more custom code and only 
> the try finally block. If adding own variables and calls, the il code is 
> not valid anymore.
>
> I will talk to my Dev Manager because of 'professional help'. Thanks :-)
>
> Am Freitag, 9. Januar 2015 09:37:38 UTC+1 schrieb Jb Evain:
>>
>> Hi, 
>>
>> If this group is all for helping people use Cecil, its purpose is not 
>> to debug other people code. 
>>
>> If you want professional services around Cecil you can contact me 
>> privately. 
>>
>> Thanks! 
>>
>> Jb 
>>
>> On Thu, Jan 8, 2015 at 5:11 PM, Reh Gina <[email protected]> wrote: 
>> > I would like to kill my computer, but for now I will go home and 
>> restart 
>> > tomorrow. Thanks for your help, would it be possible you'll help me a 
>> little 
>> > bit more? 
>> > 
>> > Am Donnerstag, 8. Januar 2015 17:08:27 UTC+1 schrieb Reh Gina: 
>> >> 
>> >> Now I replace the ret instruction by using following code 
>> >> [....] 
>> >> 
>> >> 
>> >>       Instruction popFTraceVariableInstruction = 
>> >> Instruction.Create(OpCodes.Stloc, fTraceVar); 
>> >>       //Pop a value from stack and store into local variable at index. 
>> >>       ilProcessor.InsertAfter(newConstructorInstruction, 
>> >> popFTraceVariableInstruction); 
>> >> 
>> >>       var endFinally = Instruction.Create(OpCodes.Endfinally); 
>> >>       var leave = Instruction.Create(OpCodes.Leave, endFinally); 
>> >>       var ret = Instruction.Create(OpCodes.Ret); 
>> >> 
>> >>       for (int i = 0; i < med.Body.Instructions.Count; i++) 
>> >>       { 
>> >>         Instruction instr = med.Body.Instructions[i]; 
>> >>         //Console.WriteLine(instr.ToString()); 
>> >>         if (instr.OpCode == OpCodes.Ret) 
>> >>         { 
>> >>           Instruction previous = instr.Previous; 
>> >>           ilProcessor.Remove(instr); 
>> >>           ilProcessor.InsertAfter(previous, 
>> >> Instruction.Create(OpCodes.Leave, ret)); 
>> >>         } 
>> >>       } 
>> >> 
>> >> 
>> >>       //////// Start Finally block 
>> >>       Instruction loadFTraceVarInstruction = 
>> >> Instruction.Create(OpCodes.Ldloca, fTraceVar); 
>> >>       ilProcessor.InsertAfter(med.Body.Instructions.Last(), 
>> >> loadFTraceVarInstruction); //Loads local variable onto stack 
>> >>       //ilProcessor.InsertBefore(lastInstruction, 
>> >> loadFTraceVarInstruction); //Loads local variable onto stack 
>> >> 
>> >> [...] 
>> >> [...] 
>> >> 
>> >>   ilProcessor.InsertAfter(callDisposeInstruction, endFinally); 
>> >>       //ilProcessor.InsertAfter(leave, endFinally); 
>> >>       Instruction nopInstruction = Instruction.Create(OpCodes.Nop); 
>> >>       ilProcessor.InsertAfter(endFinally, nopInstruction); 
>> >>       ilProcessor.InsertAfter(nopInstruction, ret); 
>> >> 
>> >>       ///////// End finally block 
>> >> 
>> >>       var handler = new ExceptionHandler(ExceptionHandlerType.Finally) 
>> >>       { 
>> >>         TryStart = med.Body.Instructions.First(), 
>> >>         TryEnd = callDisposeInstruction, 
>> >>         HandlerStart = callDisposeInstruction, 
>> >>         HandlerEnd = nopInstruction, 
>> >>         //CatchType = mod.Import(typeof(Exception)), 
>> >>       }; 
>> >> [...] 
>> >> 
>> >> PEVerify says: 
>> >> [IL]: Error: 
>> >> 
>> [O:\bin\x64\Debug\MeVis.BizLogic.Applications.LiverAnalysis.Viewing.ViewingCP.dll
>>  
>>
>> >> : 
>> >> 
>> MeVis.BizLogic.Applications.LiverAnalysis.Viewing.ViewingCP.AbstractTaskStepBEHandler::Dispose][offset
>>  
>>
>> >> 0x000000A9] Stack underflow. 
>> >> [IL]: Error: 
>> >> 
>> [O:\bin\x64\Debug\MeVis.BizLogic.Applications.LiverAnalysis.Viewing.ViewingCP.dll
>>  
>>
>> >> : 
>> >> 
>> MeVis.BizLogic.Applications.LiverAnalysis.Viewing.ViewingCP.AbstractTaskStepBEHandler::set_IsActive][offset
>>  
>>
>> >> 0x00000027] jmp / exception into the middle of an instruction. 
>> >> [IL]: Error: 
>> >> 
>> [O:\bin\x64\Debug\MeVis.BizLogic.Applications.LiverAnalysis.Viewing.ViewingCP.dll
>>  
>>
>> >> : 
>> >> ..... 
>> >> 
>> >> 
>> >> ARRRRGGGHHHHH 
>> >> 
>> >> Am Donnerstag, 8. Januar 2015 16:35:31 UTC+1 schrieb Jb Evain: 
>> >>> 
>> >>> The error means you can not have a ret instruction inside a protected 
>> >>> block. 
>> >>> 
>> >>> It means that if you're injecting protected blocks, you must make 
>> sure 
>> >>> that rets in them are replaced by into leave opcodes, that are 
>> jumping 
>> >>> outside of the protected block where you'll be able to return. 
>> >>> 
>> >>> I'm afraid there's nothing built-in for this, you'll have to 
>> implement 
>> >>> it. 
>> >>> 
>> >>> Jb 
>> >>> 
>> >>> On Thu, Jan 8, 2015 at 4:27 PM, Reh Gina <[email protected]> wrote: 
>> >>> > Something with a return which ist not correct in try block, but how 
>> to 
>> >>> > I 
>> >>> > remove it. Trying this to get work for almost 2 weeks 
>> >>> > 
>> >>> > Am Donnerstag, 8. Januar 2015 16:25:13 UTC+1 schrieb Reh Gina: 
>> >>> >>> 
>> >>> >>> Now the correct file attached 
>> >>> > 
>> >>> > -- 
>> >>> > -- 
>> >>> > -- 
>> >>> > mono-cecil 
>> >>> > --- 
>> >>> > You received this message because you are subscribed to the Google 
>> >>> > Groups 
>> >>> > "mono-cecil" group. 
>> >>> > To unsubscribe from this group and stop receiving emails from it, 
>> send 
>> >>> > an 
>> >>> > email to [email protected]. 
>> >>> > For more options, visit https://groups.google.com/d/optout. 
>> > 
>> > -- 
>> > -- 
>> > -- 
>> > mono-cecil 
>> > --- 
>> > You received this message because you are subscribed to the Google 
>> Groups 
>> > "mono-cecil" group. 
>> > To unsubscribe from this group and stop receiving emails from it, send 
>> an 
>> > email to [email protected]. 
>> > For more options, visit https://groups.google.com/d/optout. 
>>
>

-- 
-- 
--
mono-cecil
--- 
You received this message because you are subscribed to the Google Groups 
"mono-cecil" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to