コード例 #1
0
        public MethodBase Rewrite()
        {
            List <Type> parameterTypes = new List <Type>();

            if (!_method.IsStatic)
            {
                if (_method.IsForValueType())
                {
                    parameterTypes.Add(_method.DeclaringType.MakeByRefType());
                }
                else
                {
                    parameterTypes.Add(_method.DeclaringType);
                }
            }

            parameterTypes.AddRange(_method.GetParameters().Select(p => p.ParameterType));
            Type returnType = _method.IsConstructor ? typeof(void) : (_method as MethodInfo).ReturnType;

            DynamicMethod dynamicMethod = new DynamicMethod(
                string.Format("dynamic_{0}_{1}", _method.DeclaringType, _method.Name),
                returnType,
                parameterTypes.ToArray(),
                StubHelper.GetOwningModule(),
                true);

            MethodDisassembler disassembler = new MethodDisassembler(_method);
            MethodBody         methodBody   = _method.GetMethodBody();

            IList <LocalVariableInfo> locals             = methodBody.LocalVariables;
            Dictionary <int, Label>   targetInstructions = new Dictionary <int, Label>();
            List <ExceptionHandler>   handlers           = new List <ExceptionHandler>();

            ILGenerator ilGenerator  = dynamicMethod.GetILGenerator();
            var         instructions = disassembler.GetILInstructions();

            foreach (var clause in methodBody.ExceptionHandlingClauses)
            {
                ExceptionHandler handler = new ExceptionHandler();
                handler.Flag         = clause.Flags.ToString();
                handler.CatchType    = handler.Flag == "Clause" ? clause.CatchType : null;
                handler.TryStart     = clause.TryOffset;
                handler.TryEnd       = (clause.TryOffset + clause.TryLength);
                handler.HandlerStart = clause.HandlerOffset;
                handler.HandlerEnd   = (clause.HandlerOffset + clause.HandlerLength);
                handlers.Add(handler);
            }

            foreach (var local in locals)
            {
                ilGenerator.DeclareLocal(local.LocalType, local.IsPinned);
            }

            var ifTargets = instructions
                            .Where(i => (i.Operand as Instruction) != null)
                            .Where(i => !s_IgnoredOpCodes.Contains(i.OpCode))
                            .Select(i => (i.Operand as Instruction));

            foreach (Instruction instruction in ifTargets)
            {
                targetInstructions.TryAdd(instruction.Offset, ilGenerator.DefineLabel());
            }

            var switchTargets = instructions
                                .Where(i => (i.Operand as Instruction[]) != null)
                                .Select(i => (i.Operand as Instruction[]));

            foreach (Instruction[] _instructions in switchTargets)
            {
                foreach (Instruction _instruction in _instructions)
                {
                    targetInstructions.TryAdd(_instruction.Offset, ilGenerator.DefineLabel());
                }
            }

            foreach (var instruction in instructions)
            {
                EmitILForExceptionHandlers(ilGenerator, instruction, handlers);

                if (s_IgnoredOpCodes.Contains(instruction.OpCode))
                {
                    continue;
                }

                if (targetInstructions.TryGetValue(instruction.Offset, out Label label))
                {
                    ilGenerator.MarkLabel(label);
                }

                switch (instruction.OpCode.OperandType)
                {
                case OperandType.InlineNone:
                    EmitILForInlineNone(ilGenerator, instruction);
                    break;

                case OperandType.InlineI:
                    EmitILForInlineI(ilGenerator, instruction);
                    break;

                case OperandType.InlineI8:
                    EmitILForInlineI8(ilGenerator, instruction);
                    break;

                case OperandType.ShortInlineI:
                    EmitILForShortInlineI(ilGenerator, instruction);
                    break;

                case OperandType.InlineR:
                    EmitILForInlineR(ilGenerator, instruction);
                    break;

                case OperandType.ShortInlineR:
                    EmitILForShortInlineR(ilGenerator, instruction);
                    break;

                case OperandType.InlineString:
                    EmitILForInlineString(ilGenerator, instruction);
                    break;

                case OperandType.ShortInlineBrTarget:
                case OperandType.InlineBrTarget:
                    EmitILForInlineBrTarget(ilGenerator, instruction, targetInstructions);
                    break;

                case OperandType.InlineSwitch:
                    EmitILForInlineSwitch(ilGenerator, instruction, targetInstructions);
                    break;

                case OperandType.ShortInlineVar:
                case OperandType.InlineVar:
                    EmitILForInlineVar(ilGenerator, instruction);
                    break;

                case OperandType.InlineTok:
                case OperandType.InlineType:
                case OperandType.InlineField:
                case OperandType.InlineMethod:
                    EmitILForInlineMember(ilGenerator, instruction);
                    break;

                default:
                    throw new NotSupportedException();
                }
            }

            return(dynamicMethod);
        }
コード例 #2
0
        public MethodBase Rewrite()
        {
            List <Type> parameterTypes = new List <Type>();

            if (!_method.IsStatic)
            {
                if (_method.IsForValueType())
                {
                    parameterTypes.Add(_method.DeclaringType.MakeByRefType());
                }
                else
                {
                    parameterTypes.Add(_method.DeclaringType);
                }
            }

            parameterTypes.AddRange(_method.GetParameters().Select(p => p.ParameterType));
            Type returnType = _method.IsConstructor ? typeof(void) : (_method as MethodInfo).ReturnType;

            DynamicMethod dynamicMethod = new DynamicMethod(
                string.Format("dynamic_{0}_{1}", _method.DeclaringType, _method.Name),
                returnType,
                parameterTypes.ToArray());

            MethodDisassembler        disassembler = new MethodDisassembler(_method);
            IList <LocalVariableInfo> locals       = _method.GetMethodBody().LocalVariables;
            ILGenerator ilGenerator = dynamicMethod.GetILGenerator();

            var instructions = disassembler.GetILInstructions();
            Dictionary <int, Label> targetInstructions = new Dictionary <int, Label>();

            foreach (var local in locals)
            {
                ilGenerator.DeclareLocal(local.LocalType, local.IsPinned);
            }

            var ifTargets = instructions
                            .Where(i => (i.Operand as Instruction) != null)
                            .Select(i => (i.Operand as Instruction));

            foreach (Instruction instruction in ifTargets)
            {
                targetInstructions.TryAdd(instruction.Offset, ilGenerator.DefineLabel());
            }

            var switchTargets = instructions
                                .Where(i => (i.Operand as Instruction[]) != null)
                                .Select(i => (i.Operand as Instruction[]));

            foreach (Instruction[] _instructions in switchTargets)
            {
                foreach (Instruction _instruction in _instructions)
                {
                    targetInstructions.TryAdd(_instruction.Offset, ilGenerator.DefineLabel());
                }
            }

            foreach (var instruction in instructions)
            {
                if (targetInstructions.TryGetValue(instruction.Offset, out Label label))
                {
                    ilGenerator.MarkLabel(label);
                }

                switch (instruction.OpCode.OperandType)
                {
                case OperandType.InlineNone:
                    EmitILForInlineNone(ilGenerator, instruction);
                    break;

                case OperandType.InlineI:
                    EmitILForInlineI(ilGenerator, instruction);
                    break;

                case OperandType.InlineI8:
                    EmitILForInlineI8(ilGenerator, instruction);
                    break;

                case OperandType.ShortInlineI:
                    EmitILForShortInlineI(ilGenerator, instruction);
                    break;

                case OperandType.InlineR:
                    EmitILForInlineR(ilGenerator, instruction);
                    break;

                case OperandType.ShortInlineR:
                    EmitILForShortInlineR(ilGenerator, instruction);
                    break;

                case OperandType.InlineString:
                    EmitILForInlineString(ilGenerator, instruction);
                    break;

                case OperandType.ShortInlineBrTarget:
                case OperandType.InlineBrTarget:
                    EmitILForInlineBrTarget(ilGenerator, instruction, targetInstructions);
                    break;

                case OperandType.InlineSwitch:
                    EmitILForInlineSwitch(ilGenerator, instruction, targetInstructions);
                    break;

                case OperandType.ShortInlineVar:
                case OperandType.InlineVar:
                    EmitILForInlineVar(ilGenerator, instruction);
                    break;

                case OperandType.InlineTok:
                case OperandType.InlineType:
                case OperandType.InlineField:
                case OperandType.InlineMethod:
                    EmitILForInlineMember(ilGenerator, instruction);
                    break;

                default:
                    throw new NotSupportedException();
                }
            }

            return(dynamicMethod);
        }
コード例 #3
0
ファイル: MethodRewriter.cs プロジェクト: mblumenshine/Poise
        public MethodBase Rewrite()
        {
            List <Type> parameterTypes = new List <Type>();

            if (!_method.IsStatic)
            {
                if (_method.IsForValueType())
                {
                    parameterTypes.Add(_method.DeclaringType.MakeByRefType());
                }
                else
                {
                    parameterTypes.Add(_method.DeclaringType);
                }
            }

            parameterTypes.AddRange(_method.GetParameters().Select(p => p.ParameterType));
            Type returnType = _method.IsConstructor ? typeof(void) : (_method as MethodInfo).ReturnType;

            DynamicMethod dynamicMethod = new DynamicMethod(string.Format("dynamic_{0}_{1}", _method.DeclaringType, _method.Name), returnType, parameterTypes.ToArray(), StubHelper.GetOwningModule(), true);


            MethodDisassembler disassembler = new MethodDisassembler(_method);
            MethodBody         methodBody   = _method.GetMethodBody();

            IList <LocalVariableInfo> locals             = methodBody.LocalVariables;
            Dictionary <int, Label>   targetInstructions = new Dictionary <int, Label>();
            List <ExceptionHandler>   handlers           = new List <ExceptionHandler>();

            ILGenerator ilGenerator  = dynamicMethod.GetILGenerator();
            var         instructions = disassembler.GetILInstructions();
            var         code         = _method.GetMethodBody();

            foreach (var clause in methodBody.ExceptionHandlingClauses)
            {
                ExceptionHandler handler = new ExceptionHandler();
                handler.Flag         = clause.Flags.ToString();
                handler.CatchType    = handler.Flag == "Clause" ? clause.CatchType : null;
                handler.TryStart     = clause.TryOffset;
                handler.TryEnd       = (clause.TryOffset + clause.TryLength);
                handler.HandlerStart = clause.HandlerOffset;
                handler.HandlerEnd   = (clause.HandlerOffset + clause.HandlerLength);
                handlers.Add(handler);
            }

            foreach (var local in locals)
            {
                ilGenerator.DeclareLocal(local.LocalType, local.IsPinned);
            }

            var ifTargets = instructions
                            .Where(i => (i.Operand as Instruction) != null)
                            .Where(i => !s_IgnoredOpCodes.Contains(i.OpCode))
                            .Select(i => (i.Operand as Instruction));

            foreach (Instruction instruction in ifTargets)
            {
                targetInstructions.TryAdd(instruction.Offset, ilGenerator.DefineLabel());
            }

            var switchTargets = instructions
                                .Where(i => (i.Operand as Instruction[]) != null)
                                .Select(i => (i.Operand as Instruction[]));

            foreach (Instruction[] _instructions in switchTargets)
            {
                foreach (Instruction _instruction in _instructions)
                {
                    targetInstructions.TryAdd(_instruction.Offset, ilGenerator.DefineLabel());
                }
            }

            foreach (var instruction in instructions)
            {
                EmitILForExceptionHandlers(ilGenerator, instruction, handlers);

                if (s_IgnoredOpCodes.Contains(instruction.OpCode))
                {
                    continue;
                }

                if (targetInstructions.TryGetValue(instruction.Offset, out Label label))
                {
                    ilGenerator.MarkLabel(label);
                }

                // If a constrained instruction is a prefix for an interface, we know any value types
                // must have implemented the interface explicitly, and thus both the constrained and
                // callvirt instructions can be replaced by a simple call instruction.
                // This is necessary as Invoking methods by reflection doesn't seem to work the same way as the CLR which
                // replaces constrained/callvirt pairs to simple calls on the type itself, and the fact that it doesn't do this
                // seems to break Pose and the calls to Method.Invoke
                if (instruction.OpCode == OpCodes.Constrained)
                {
                    _lastInstruction = instruction;
                    _wasLastInstructionConstrained = true;
                    _lastType = instruction.Operand as TypeInfo;

                    continue;
                }
                if (_wasLastInstructionConstrained)
                {
                    _wasLastInstructionConstrained = false;
                    if (instruction.OpCode == OpCodes.Callvirt && ((instruction.Operand as MethodInfo)?.DeclaringType?.IsInterface ?? false))
                    {
                        // emit Nops for constrained call (size is 6)
                        // TODO: Get size from actual offset difference and emit that number of nops... though constrained is always 6 and very unlikely to change
                        EmitILNop(ilGenerator);
                        EmitILNop(ilGenerator);
                        EmitILNop(ilGenerator);
                        EmitILNop(ilGenerator);
                        EmitILNop(ilGenerator);
                        EmitILNop(ilGenerator);

                        // change operand and continue
                        var currentMethodInfo     = instruction.Operand as MethodInfo;
                        var replacementMethodInfo = _lastType.GetMethod(currentMethodInfo.Name);

                        EmitILForMethod(ilGenerator, instruction, replacementMethodInfo, true);

                        continue;
                    }

                    EmitILForInlineMember(ilGenerator, _lastInstruction);

                    _lastInstruction = null;
                    _lastType        = null;
                }
                else
                {
                    _wasLastInstructionConstrained = false;
                }

                switch (instruction.OpCode.OperandType)
                {
                case OperandType.InlineNone:
                    EmitILForInlineNone(ilGenerator, instruction);
                    break;

                case OperandType.InlineI:
                    EmitILForInlineI(ilGenerator, instruction);
                    break;

                case OperandType.InlineI8:
                    EmitILForInlineI8(ilGenerator, instruction);
                    break;

                case OperandType.ShortInlineI:
                    EmitILForShortInlineI(ilGenerator, instruction);
                    break;

                case OperandType.InlineR:
                    EmitILForInlineR(ilGenerator, instruction);
                    break;

                case OperandType.ShortInlineR:
                    EmitILForShortInlineR(ilGenerator, instruction);
                    break;

                case OperandType.InlineString:
                    EmitILForInlineString(ilGenerator, instruction);
                    break;

                case OperandType.ShortInlineBrTarget:
                case OperandType.InlineBrTarget:
                    EmitILForInlineBrTarget(ilGenerator, instruction, targetInstructions);
                    break;

                case OperandType.InlineSwitch:
                    EmitILForInlineSwitch(ilGenerator, instruction, targetInstructions);
                    break;

                case OperandType.ShortInlineVar:
                case OperandType.InlineVar:
                    EmitILForInlineVar(ilGenerator, instruction);
                    break;

                case OperandType.InlineTok:
                case OperandType.InlineType:
                case OperandType.InlineField:
                case OperandType.InlineMethod:
                    EmitILForInlineMember(ilGenerator, instruction);
                    break;

                default:
                    throw new NotSupportedException();
                }
            }

            return(dynamicMethod);
        }