void WriteInstr(Instruction instr)
        {
            var opcode = ConvertOpCode(instr.OpCode);

            switch (instr.OpCode.OperandType)
            {
            case OperandType.InlineNone:
                ilg.Emit(opcode);
                break;

            case OperandType.InlineBrTarget:
            case OperandType.ShortInlineBrTarget:
                ilg.Emit(opcode, GetLabel((Instruction)instr.Operand));
                break;

            case OperandType.InlineSwitch:
                ilg.Emit(opcode, GetLabels((Instruction[])instr.Operand));
                break;

            case OperandType.ShortInlineI:
                if (instr.OpCode.Code == Code.Ldc_I4_S)
                {
                    ilg.Emit(opcode, (sbyte)instr.Operand);
                }
                else
                {
                    ilg.Emit(opcode, (byte)instr.Operand);
                }
                break;

            case OperandType.InlineI:
                ilg.Emit(opcode, (int)instr.Operand);
                break;

            case OperandType.InlineI8:
                ilg.Emit(opcode, (long)instr.Operand);
                break;

            case OperandType.InlineR:
                ilg.Emit(opcode, (double)instr.Operand);
                break;

            case OperandType.ShortInlineR:
                ilg.Emit(opcode, (float)instr.Operand);
                break;

            case OperandType.InlineString:
                ilg.Emit(opcode, (string)instr.Operand);
                break;

            case OperandType.InlineTok:
            case OperandType.InlineType:
            case OperandType.InlineMethod:
            case OperandType.InlineField:
                var obj = Resolver.GetRtObject((ITokenOperand)instr.Operand);
                if (obj is ConstructorInfo)
                {
                    ilg.Emit(opcode, (ConstructorInfo)obj);
                }
                else if (obj is MethodInfo)
                {
                    ilg.Emit(opcode, (MethodInfo)obj);
                }
                else if (obj is FieldInfo)
                {
                    ilg.Emit(opcode, (FieldInfo)obj);
                }
                else if (obj is Type)
                {
                    ilg.Emit(opcode, (Type)obj);
                }
                else
                {
                    throw new ApplicationException(string.Format("Unknown type: {0}", (obj == null ? obj : obj.GetType())));
                }
                break;

            case OperandType.InlineVar:
                ilg.Emit(opcode, checked ((short)((IVariable)instr.Operand).Index));
                break;

            case OperandType.ShortInlineVar:
                ilg.Emit(opcode, checked ((byte)((IVariable)instr.Operand).Index));
                break;

            case OperandType.InlineSig:                 //TODO:
            default:
                throw new ApplicationException(string.Format("Unknown OperandType {0}", instr.OpCode.OperandType));
            }
        }
Beispiel #2
0
        void Update(Block block, NewMethodInfo currentMethodInfo)
        {
            var instrs = block.Instructions;

            for (int i = 0; i < instrs.Count; i++)
            {
                var instr = instrs[i];
                if (instr.OpCode == OpCodes.Newobj)
                {
                    var ctor             = (IMethod)instr.Operand;
                    var ctorTypeFullName = ctor.DeclaringType.FullName;
                    if (ctorTypeFullName == "System.Diagnostics.StackTrace")
                    {
                        InsertLoadThis(block, i + 1);
                        InsertCallOurMethod(block, i + 2, "static_RtFixStackTrace");
                        i += 2;
                        continue;
                    }
                    else if (ctorTypeFullName == "System.Diagnostics.StackFrame")
                    {
                        InsertLoadThis(block, i + 1);
                        InsertCallOurMethod(block, i + 2, "static_RtFixStackFrame");
                        i += 2;
                        continue;
                    }
                }

                if (instr.OpCode == OpCodes.Call || instr.OpCode == OpCodes.Callvirt)
                {
                    var calledMethod = (IMethod)instr.Operand;
                    if (calledMethod.DeclaringType.DefinitionAssembly.IsCorLib())
                    {
                        var calledMethodFullName = calledMethod.FullName;
                        if (calledMethodFullName == "System.Reflection.Assembly System.Reflection.Assembly::GetAssembly(System.Type)")
                        {
                            block.Replace(i, 1, OpCodes.Nop.ToInstruction());
                            InsertLoadThis(block, i + 1);
                            InsertCallOurMethod(block, i + 2, "static_RtGetAssembly_TypeArg");
                            i += 2;
                            continue;
                        }
                        else if (calledMethodFullName == "System.Reflection.Assembly System.Reflection.Assembly::GetCallingAssembly()" ||
                                 calledMethodFullName == "System.Reflection.Assembly System.Reflection.Assembly::GetEntryAssembly()" ||
                                 calledMethodFullName == "System.Reflection.Assembly System.Reflection.Assembly::GetExecutingAssembly()")
                        {
                            block.Replace(i, 1, OpCodes.Nop.ToInstruction());
                            InsertLoadThis(block, i + 1);
                            block.Insert(i + 2, OpCodes.Ldc_I4.ToInstruction(currentMethodInfo.delegateIndex));
                            InsertCallOurMethod(block, i + 3, "RtGetAssembly");
                            i += 3;
                            continue;
                        }
                    }

                    var method = Resolver.GetMethod((IMethod)instr.Operand);
                    if (method != null)
                    {
                        CreateMethod(method.methodBase);
                        var newMethodInfo = realMethodToNewMethod[method.methodBase];

                        block.Replace(i, 1, OpCodes.Nop.ToInstruction());
                        int n = i + 1;

                        // Pop all pushed args to a temp array
                        var mparams = GetParameters(method.methodDef);
                        if (mparams.Count > 0)
                        {
                            block.Insert(n++, OpCodes.Ldc_I4.ToInstruction(mparams.Count));
                            var objectType = method.methodDef.DeclaringType.Module.CorLibTypes.Object;
                            block.Insert(n++, OpCodes.Newarr.ToInstruction(objectType));
                            block.Insert(n++, Create(OpCodes.Stloc, new Operand(Operand.Type.TempObjArray)));

                            for (int j = mparams.Count - 1; j >= 0; j--)
                            {
                                var argType = mparams[j];
                                if (argType.RemovePinnedAndModifiers().IsValueType)
                                {
                                    block.Insert(n++, OpCodes.Box.ToInstruction(((TypeDefOrRefSig)argType).TypeDefOrRef));
                                }
                                block.Insert(n++, Create(OpCodes.Stloc, new Operand(Operand.Type.TempObj)));
                                block.Insert(n++, Create(OpCodes.Ldloc, new Operand(Operand.Type.TempObjArray)));
                                block.Insert(n++, OpCodes.Ldc_I4.ToInstruction(j));
                                block.Insert(n++, Create(OpCodes.Ldloc, new Operand(Operand.Type.TempObj)));
                                block.Insert(n++, OpCodes.Stelem_Ref.ToInstruction());
                            }
                        }

                        // Push delegate instance
                        InsertLoadThis(block, n++);
                        block.Insert(n++, OpCodes.Ldc_I4.ToInstruction(newMethodInfo.delegateIndex));
                        InsertCallOurMethod(block, n++, "RtGetDelegateInstance");
                        block.Insert(n++, Create(OpCodes.Castclass, new Operand(Operand.Type.ReflectionType, newMethodInfo.delegateType)));

                        // Push all popped args
                        if (mparams.Count > 0)
                        {
                            for (int j = 0; j < mparams.Count; j++)
                            {
                                block.Insert(n++, Create(OpCodes.Ldloc, new Operand(Operand.Type.TempObjArray)));
                                block.Insert(n++, OpCodes.Ldc_I4.ToInstruction(j));
                                block.Insert(n++, OpCodes.Ldelem_Ref.ToInstruction());
                                var argType = mparams[j];
                                if (argType.RemovePinnedAndModifiers().IsValueType)
                                {
                                    block.Insert(n++, OpCodes.Unbox_Any.ToInstruction(((TypeDefOrRefSig)argType).TypeDefOrRef));
                                }
                                else
                                {
                                    // Don't cast it to its correct type. This will sometimes cause
                                    // an exception in some EF obfuscated assembly since we'll be
                                    // trying to cast a System.Reflection.AssemblyName type to some
                                    // other type.
                                    // block.insert(n++, Instruction.Create(OpCodes.Castclass, argType.ToTypeDefOrRef()));
                                }
                            }
                        }

                        InsertLoadThis(block, n++);
                        block.Insert(n++, Create(OpCodes.Call, new Operand(Operand.Type.NewMethod, method.methodBase)));
                        i = n - 1;
                        continue;
                    }
                }
            }
        }