public DynamicMethod ComposePatchedMethod() { DynamicMethod method = AllocatePatchMethod(); var generator = new LoggingIlGenerator(method.GetILGenerator(), PrintMsil ? LogLevel.Info : LogLevel.Trace); List <MsilInstruction> il = EmitPatched((type, pinned) => new MsilLocal(generator.DeclareLocal(type, pinned))).ToList(); if (PrintMsil) { lock (_log) { MethodTranspiler.IntegrityAnalysis(LogLevel.Info, il); } } MethodTranspiler.EmitMethod(il, generator); try { PatchUtilities.Compile(method); } catch { lock (_log) { var ctx = new MethodContext(method); ctx.Read(); MethodTranspiler.IntegrityAnalysis(LogLevel.Warn, ctx.Instructions); } throw; } return(method); }
/// <summary> /// Gets the content of a method as an instruction stream /// </summary> /// <param name="method">Method to examine</param> /// <returns>instruction stream</returns> public static IEnumerable <MsilInstruction> ReadInstructions(MethodBase method) { var context = new MethodContext(method); context.Read(); return(context.Instructions); }
public DynamicMethod ComposePatchedMethod() { DynamicMethod method = AllocatePatchMethod(); var generator = new LoggingIlGenerator(method.GetILGenerator(), PrintMode.HasFlag(PrintModeEnum.EmittedReflection) ? LogLevel.Info : LogLevel.Trace); List <MsilInstruction> il = EmitPatched((type, pinned) => new MsilLocal(generator.DeclareLocal(type, pinned))).ToList(); var dumpTarget = DumpTarget != null?File.CreateText(DumpTarget) : null; try { const string gap = "\n\n\n\n\n"; void LogTarget(PrintModeEnum mode, bool err, string msg) { if (DumpMode.HasFlag(mode)) { dumpTarget?.WriteLine((err ? "ERROR " : "") + msg); } if (!PrintMode.HasFlag(mode)) { return; } if (err) { _log.Error(msg); } else { _log.Info(msg); } } if (PrintMsil || DumpTarget != null) { lock (_log) { var ctx = new MethodContext(_method); ctx.Read(); LogTarget(PrintModeEnum.Original, false, "========== Original method =========="); MethodTranspiler.IntegrityAnalysis((a, b) => LogTarget(PrintModeEnum.Original, a, b), ctx.Instructions, true); LogTarget(PrintModeEnum.Original, false, gap); LogTarget(PrintModeEnum.Emitted, false, "========== Desired method =========="); MethodTranspiler.IntegrityAnalysis((a, b) => LogTarget(PrintModeEnum.Emitted, a, b), il); LogTarget(PrintModeEnum.Emitted, false, gap); } } MethodTranspiler.EmitMethod(il, generator); try { PatchUtilities.Compile(method); } catch { lock (_log) { var ctx = new MethodContext(method); ctx.Read(); MethodTranspiler.IntegrityAnalysis((err, msg) => _log.Warn(msg), ctx.Instructions); } throw; } if (PrintMsil || DumpTarget != null) { lock (_log) { var ctx = new MethodContext(method); ctx.Read(); LogTarget(PrintModeEnum.Patched, false, "========== Patched method =========="); MethodTranspiler.IntegrityAnalysis((a, b) => LogTarget(PrintModeEnum.Patched, a, b), ctx.Instructions, true); LogTarget(PrintModeEnum.Patched, false, gap); } } } finally { dumpTarget?.Close(); } return(method); }