예제 #1
0
        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);
        }
예제 #2
0
        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);
        }