GetILProcessor() публичный Метод

public GetILProcessor ( ) : Mono.Cecil.Cil.ILProcessor
Результат Mono.Cecil.Cil.ILProcessor
Пример #1
0
        private static void InsertInvalidIl(MethodBody methodBody)
        {
            //Get the instructions and cil worker
            var instructions = methodBody.Instructions;

            if (instructions.Count <= 0)
            {
                return; //We can only do this if we have instructions to work with
            }
            ILProcessor il = methodBody.GetILProcessor();

            //First create an invalid il instruction
            OpCode      fakeOpCode      = CreateInvalidOpCode();
            Instruction invalidIlInstr1 = il.Create(fakeOpCode);
            Instruction invalidIlInstr2 = il.Create(fakeOpCode);
            Instruction originalFirst   = instructions[0];

            //Insert invalid il at the start
            il.InsertBefore(originalFirst, invalidIlInstr1);
            il.InsertBefore(invalidIlInstr1, invalidIlInstr2);

            //Create the branch statement
            Instruction branchStatement = il.Create(OpCodes.Br_S, originalFirst);

            //Add the branch to the start
            il.InsertBefore(invalidIlInstr2, branchStatement);

            //Readjust the offsets
            il.AdjustOffsets(methodBody, 4);
        }
Пример #2
0
        /// <summary>
        /// Create a new method in the declaring type of the given implicit implementation with the given name.
        /// This method will call the implicit implementation.
        /// </summary>
        internal static MethodDefinition CreateExplicitStub(MethodDefinition implicitImpl, string name, MethodDefinition iMethod, bool avoidGenericParam)
        {
            // Create method
            var newMethod = new MethodDefinition(name, implicitImpl.Attributes, implicitImpl.ReturnType);
            newMethod.IsVirtual = false;
            newMethod.IsAbstract = false;
            newMethod.IsFinal = true;

            // Clone generic parameters
            foreach (var gp in implicitImpl.GenericParameters)
            {
                newMethod.GenericParameters.Add(new GenericParameter(gp.Name, newMethod));
            }

            // Update according to new context
            var cloner = new TypeCloner(avoidGenericParam, implicitImpl.Module.TypeSystem);
            newMethod.ReturnType = cloner.Get(implicitImpl.ReturnType, newMethod);

            // Clone parameters
            foreach (var p in iMethod.Parameters)
            {
                newMethod.Parameters.Add(new ParameterDefinition(p.Name, p.Attributes, cloner.Get(p.ParameterType, newMethod)));
            }

            // Add the method
            var targetType = implicitImpl.DeclaringType;
            targetType.Methods.Add(newMethod);


            // Add override
            newMethod.Overrides.Add(iMethod);

            // Create method body
            var body = new MethodBody(newMethod);
            newMethod.Body = body;
            var worker = body.GetILProcessor();

            // Push this 
            worker.Emit(OpCodes.Ldarg, body.ThisParameter);
            for (var i = 0; i < implicitImpl.Parameters.Count; i++)
            {
                var p = iMethod.Parameters[i];
                var newMethodParam = newMethod.Parameters[i];
                worker.Emit(OpCodes.Ldarg, newMethodParam);
                if (/*avoidGenericParam &&*/ p.ParameterType.ContainsGenericParameter)
                {
                    worker.Emit(OpCodes.Box, implicitImpl.Parameters[i].ParameterType);
                }
            }
            worker.Emit(implicitImpl.IsVirtual ? OpCodes.Callvirt : OpCodes.Call, implicitImpl);
            worker.Emit(OpCodes.Ret);

            // Mark method reachable
            if (implicitImpl.IsReachable)
            {
                newMethod.SetReachable(null);
            }

            return newMethod;
        }
Пример #3
0
        private void WeaveDependencyProperty(MethodBody staticCtorBody, FieldReference field, PropertyDefinition property)
        {
            var assembly          = property.DeclaringType.Module.Assembly;
            var propertyType      = assembly.ImportType(Type.GetType(property.PropertyType.FullName));
            var getTypeFromHandle = assembly.ImportMethod(typeof(Type).GetMethod("GetTypeFromHandle"));
            var register          = assembly.ImportMethod(typeof(DependencyProperty).GetMethod("Register", new[] { typeof(string), typeof(Type), typeof(Type) }));

            // ignore previously weaved DPs
            if (staticCtorBody.Instructions.Any(i => i.Operand != null && i.Operand.ToString() == field.ToString()))
            {
                return;
            }

            var ret = staticCtorBody.Instructions.Last();

            if (ret.OpCode != OpCodes.Ret)
            {
                throw new InvalidOperationException("The last instruction should be OpCode.Ret");
            }

            HasChanges = true;

            var proc = staticCtorBody.GetILProcessor();

            proc.InsertBefore(ret, proc.Create(OpCodes.Ldstr, property.Name));
            proc.InsertBefore(ret, proc.Create(OpCodes.Ldtoken, propertyType));
            proc.InsertBefore(ret, proc.Create(OpCodes.Call, getTypeFromHandle));
            proc.InsertBefore(ret, proc.Create(OpCodes.Ldtoken, property.DeclaringType));
            proc.InsertBefore(ret, proc.Create(OpCodes.Call, getTypeFromHandle));
            proc.InsertBefore(ret, proc.Create(OpCodes.Call, register));
            proc.InsertBefore(ret, proc.Create(OpCodes.Stsfld, field));
        }
Пример #4
0
        public static void RewriteCilCodeBlock(Mono.Cecil.Cil.MethodBody body)
        {
            List <Instruction> result = new List <Instruction>();

            for (int j = 0; j < body.Instructions.Count; ++j)
            {
                Instruction i = body.Instructions[j];

                var inst_to_insert = i;

                if (i.OpCode.FlowControl == FlowControl.Call)
                {
                    object method = i.Operand;

                    if (method as Mono.Cecil.MethodReference == null)
                    {
                        throw new Exception();
                    }

                    var           method_reference = method as Mono.Cecil.MethodReference;
                    TypeReference mr_dt            = method_reference.DeclaringType;

                    var bcl_substitute = SubstituteMethod(method_reference);
                    if (bcl_substitute != null)
                    {
                        CallSite cs = new CallSite(typeof(void).ToMonoTypeReference());
                        body.Instructions.RemoveAt(j);
                        var         worker   = body.GetILProcessor();
                        Instruction new_inst = worker.Create(i.OpCode, bcl_substitute);
                        new_inst.Offset = i.Offset;
                        body.Instructions.Insert(j, new_inst);
                    }
                }
            }
        }
Пример #5
0
        private void InsertEventHandler(bool before, Assembly asm, AssemblyDefinition asmDef, InjectionMethod im, string eventType, Type[] eventArgumentTypes)
        {
            ModuleDefinition module        = asmDef.MainModule;
            MethodReference  mrHandleEvent = module.ImportReference(asm.GetType("TSML.Event.EventHandler").GetMethod("OnEvent", new Type[] { asm.GetType("TSML.Event.Event") }));

            MethodReference eventCtor = module.ImportReference(asm.GetType(eventType).GetConstructor(eventArgumentTypes));

            Mono.Cecil.Cil.MethodBody body = im.MethodDef.Body;
            ILProcessor proc = body.GetILProcessor();

            Instruction        target = body.Instructions[before ? 0 : body.Instructions.Count - 1];
            List <Instruction> insns  = new List <Instruction>();

            // Load arguments, index 0 being the object itself
            for (int i = 0; i < eventArgumentTypes.Length; i++)
            {
                insns.Add(proc.Create(OpCodes.Ldarg, i));
            }

            insns.Add(proc.Create(OpCodes.Newobj, eventCtor));
            insns.Add(proc.Create(OpCodes.Call, mrHandleEvent));

            foreach (Instruction insn in insns)
            {
                proc.InsertBefore(target, insn);
            }
        }
Пример #6
0
    static void FillArgs(MethodDefinition target, Instruction endPoint, Action <MethodDefinition, Instruction, int> parseReferenceProcess)
    {
        MethodBody  targetBody = target.Body;
        ILProcessor il         = targetBody.GetILProcessor();
        int         paramCount = target.Parameters.Count + (target.HasThis ? 1 : 0);

        for (int i = 0; i < paramCount; ++i)
        {
            if (i < ldargs.Length)
            {
                il.InsertBefore(endPoint, il.Create(ldargs[i]));
            }
            else if (i <= byte.MaxValue)
            {
                il.InsertBefore(endPoint, il.Create(OpCodes.Ldarg_S, (byte)i));
            }
            else
            {
                il.InsertBefore(endPoint, il.Create(OpCodes.Ldarg, (short)i));
            }

            if (parseReferenceProcess != null)
            {
                parseReferenceProcess(target, endPoint, i);
            }
        }
    }
Пример #7
0
        public static void FillMMILProxy(ModuleDefinition proxyMod, TypeDefinition proxy, MethodInfo stub)
        {
            MethodDefinition method = new MethodDefinition(
                stub.Name,
                MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Static,
                proxyMod.ImportReference(stub.ReturnType)
                );

            ParameterInfo[] args      = stub.GetParameters();
            int             argsCount = args.Length;

            for (int i = 1; i < argsCount; i++)
            {
                method.Parameters.Add(
                    new ParameterDefinition(args[i].Name, (ParameterAttributes)args[i].Attributes, proxyMod.ImportReference(args[i].ParameterType))
                    );
            }
            --argsCount; // MMILRT contains self as first parameter

            MethodBody  body = method.Body = new MethodBody(method);
            ILProcessor il   = body.GetILProcessor();

            // Always required to get the MonoModder instance.
            il.Emit(OpCodes.Call, proxyMod.ImportReference(m_get_Self));

            // Load arguments to stack.
            // TODO: What about generic arguments in MMILProxy?
            if (argsCount > 0)
            {
                il.Emit(OpCodes.Ldarg_0);
            }
            if (argsCount > 1)
            {
                il.Emit(OpCodes.Ldarg_1);
            }
            if (argsCount > 2)
            {
                il.Emit(OpCodes.Ldarg_2);
            }
            if (argsCount > 3)
            {
                il.Emit(OpCodes.Ldarg_3);
            }
            for (int i = 4; i < argsCount && i < 256; i++)
            {
                il.Emit(OpCodes.Ldarg_S, (byte)i);
            }
            for (int i = 256; i < argsCount; i++)
            {
                il.Emit(OpCodes.Ldarg, i);
            }

            // Call the actual method.
            il.Emit(OpCodes.Call, proxyMod.ImportReference(stub));

            // Finish it off with a ret.
            il.Emit(OpCodes.Ret);

            proxy.Methods.Add(method);
        }
Пример #8
0
        public virtual void PatchTrampoline(MethodDefinition targetMethod, MethodDefinition method)
        {
            method.IsManaged      = true;
            method.IsIL           = true;
            method.IsNative       = false;
            method.PInvokeInfo    = null;
            method.IsInternalCall = false;
            method.IsPInvokeImpl  = false;
            method.NoInlining     = true;

            MethodBody  body = method.Body = new MethodBody(method);
            ILProcessor il   = body.GetILProcessor();

            for (int i = 64; i > -1; --i)
            {
                il.Emit(OpCodes.Nop);
            }
            if (method.ReturnType.MetadataType != MetadataType.Void)
            {
                il.Emit(OpCodes.Ldnull);
                if (method.ReturnType.IsValueType)
                {
                    il.Emit(OpCodes.Box, method.ReturnType);
                }
            }
            il.Emit(OpCodes.Ret);

            RegisterTrampoline(targetMethod, method);
        }
Пример #9
0
    private void ProcessMethodDefinition(MethodDefinition method)
    {
        MethodBody body = method.Body;

        body.SimplifyMacros();
        ILProcessor ilProcessor = body.GetILProcessor();

        if (body.HasExceptionHandlers)
        {
            for (int i = 0; i < body.ExceptionHandlers.Count; i++)
            {
                //This doesn't rethrow per se, but it might be the path to more fine grained control
                //var exceptionType = typeof(Exception);
                //var exceptionCtor = exceptionType.GetConstructor(new Type[] {});
                //var constructorReference = ModuleDefinition.ImportReference(exceptionCtor);
                //ilProcessor.InsertBefore(body.ExceptionHandlers[i].HandlerEnd.Previous, Instruction.Create(OpCodes.Newobj, constructorReference));
                //ilProcessor.InsertBefore(body.ExceptionHandlers[i].HandlerEnd.Previous, Instruction.Create(OpCodes.Throw));

                ilProcessor.Replace(body.ExceptionHandlers[i].HandlerEnd.Previous, Instruction.Create(OpCodes.Rethrow));
            }
        }

        body.InitLocals = true;
        body.OptimizeMacros();
    }
Пример #10
0
    static void FillCoroutineState(MethodDefinition coroutineCarrier)
    {
        MethodBody  targetBody = coroutineCarrier.Body;
        ILProcessor il         = targetBody.GetILProcessor();

        il.InsertBefore(cursor, il.Create(OpCodes.Ldarg_0));
        var stateField = coroutineCarrier.DeclaringType.Fields.Single(field => field.Name == "$PC");

        il.InsertBefore(cursor, il.Create(OpCodes.Ldfld, stateField));
    }
Пример #11
0
        public static void PatchMethodThatUsedDisplayClassToTreatItAsAStruct(MethodBody body, VariableDefinition displayClassVariable)
        {
            var displayClassTypeReference = displayClassVariable.VariableType;
            var instructions = body.Instructions.ToArray();
            var ilProcessor  = body.GetILProcessor();

            foreach (var instruction in instructions)
            {
                // We will replace all LdLoc of our displayclass to LdLoca of our displayclass variable that now lives on the stack.
                // Except in the case where we are storing a nested DisplayClass!
                if ((instruction.IsLoadLocal(out int loadIndex) && displayClassVariable.Index == loadIndex) &&
                    !(instruction.Next != null && instruction.Next.OpCode == OpCodes.Stfld && (instruction.Next.Operand as FieldReference).IsNestedDisplayClassField()))
                {
                    instruction.OpCode  = OpCodes.Ldloca;
                    instruction.Operand = body.Variables[loadIndex];
                }

                // We also need to replace and ldfld a nested DisplayClass that we turned into a struct with ldflda
                if (instruction.OpCode == OpCodes.Ldfld && ((FieldReference)instruction.Operand).IsNestedDisplayClassField())
                {
                    instruction.OpCode = OpCodes.Ldflda;
                }

                // Roselyn should never double assign the DisplayClass to a variable, throw if we somehow detect this.
                if (instruction.IsStoreLocal(out int storeIndex) && displayClassVariable.Index == storeIndex)
                {
                    InternalCompilerError.DCICE003(body.Method, instruction).Throw();
                }

                bool IsInstructionNewObjOfDisplayClass(Instruction thisInstruction)
                {
                    return(thisInstruction.OpCode.Code == Code.Newobj && ((MethodReference)thisInstruction.Operand).DeclaringType.TypeReferenceEquals(displayClassTypeReference));
                }

                // We need to replace the creation of the displayclass object on the heap, with a initobj of the displayclass on the stack.
                // The final sequence will be ldloca, initobj (which will replace newobj, stloc.1.
                if (IsInstructionNewObjOfDisplayClass(instruction))
                {
                    // Remove next stloc.1 instruction so that we can replace both of these with the instructions below
                    if (!instruction.Next.IsStoreLocal(out _))
                    {
                        InternalCompilerError.DCICE004(body.Method, instruction).Throw();
                    }
                    instruction.Next.MakeNOP();
                    ilProcessor.Replace(instruction, new[]
                    {
                        Instruction.Create(OpCodes.Ldloca, displayClassVariable),
                        Instruction.Create(OpCodes.Initobj, displayClassTypeReference),
                    });
                }
            }
        }
Пример #12
0
    static void FillJumpInfo(MethodDefinition target, bool bConfirmPopReturnValue)
    {
        MethodBody  targetBody = target.Body;
        ILProcessor il         = targetBody.GetILProcessor();

        if (!bConfirmPopReturnValue)
        {
            Instruction retIns = il.Create(OpCodes.Ret);
            if (!injectType.HasFlag(InjectType.Before))
            {
                if (cursor.Previous.OpCode == OpCodes.Nop)
                {
                    cursor.Previous.OpCode  = retIns.OpCode;
                    cursor.Previous.Operand = retIns.Operand;
                    retIns = cursor.Previous;
                }
                else
                {
                    il.InsertBefore(cursor, retIns);
                }
            }
            else
            {
                Instruction start = il.Create(OpCodes.Ldloc, flagDef);
                if (cursor.Previous.OpCode == OpCodes.Nop)
                {
                    cursor.Previous.OpCode  = start.OpCode;
                    cursor.Previous.Operand = start.Operand;
                    il.InsertAfter(cursor.Previous, retIns);
                }
                else
                {
                    il.InsertBefore(cursor, retIns);
                    il.InsertBefore(retIns, start);
                }

                Instruction popIns          = il.Create(OpCodes.Pop);
                bool        bGotReturnValue = !target.ReturnVoid();
                if (bGotReturnValue)
                {
                    il.InsertBefore(cursor, popIns);
                }
                il.InsertBefore(retIns, il.Create(ldcI4s[(int)InjectType.Before / 2]));
                il.InsertBefore(retIns, il.Create(OpCodes.Ble_Un, bGotReturnValue ? popIns : cursor));
            }
        }
        else if (cursor.Previous.OpCode == OpCodes.Nop)
        {
            targetBody.Instructions.Remove(cursor.Previous);
        }
    }
Пример #13
0
 /// <summary>
 /// Create a clone of the given method body
 /// </summary>
 public static MethodBody Clone(this MethodBody source, MethodDefinition target)
 {
     var result = new MethodBody(target) { InitLocals = source.InitLocals, MaxStackSize = source.MaxStackSize };
     var worker = result.GetILProcessor();
     foreach (var i in source.Instructions)
     {
         // Poor mans clone, but sufficient for our needs
         var clone = Instruction.Create(OpCodes.Nop);
         clone.OpCode = i.OpCode;
         clone.Operand = i.Operand;
         worker.Append(clone);
     }
     return result;
 }
Пример #14
0
        public static void ILMethodIntrument(MethodDefinition md, long methodID, MethodReference startMR, MethodReference endMR)
        {
            Mono.Cecil.Cil.MethodBody mb = md.Body;

            Instruction        startInst;
            List <Instruction> endInst = new List <Instruction>();

            Console.WriteLine(" -- StartMSpan");
            foreach (Instruction inst in mb.Instructions)
            {
                switch (inst.OpCode.Code)
                {
                case Code.Ret:
                case Code.Throw:
                case Code.Rethrow:
                    endInst.Add(inst);
                    Console.WriteLine(" -- EndMSpan");
                    break;
                }
                Console.WriteLine(inst.OpCode.Name);
            }

            mb.InitLocals = true;
            VariableDefinition vd = new VariableDefinition(startMR.ReturnType);

            mb.Variables.Add(vd);

            ILProcessor ilp = mb.GetILProcessor();

            startInst = mb.Instructions[0];
            if (startInst.OpCode.Code != Code.Nop)
            {
                ilp.InsertBefore(startInst, ilp.Create(OpCodes.Nop));
                startInst = mb.Instructions[0];
            }

            ilp.InsertBefore(startInst, ilp.Create(OpCodes.Nop));
            ilp.InsertBefore(startInst, ilp.Create(OpCodes.Ldc_I8, methodID));
            ilp.InsertBefore(startInst, ilp.Create(OpCodes.Call, startMR));
            ilp.InsertBefore(startInst, ilp.Create(OpCodes.Stloc, vd));

            foreach (Instruction inst in endInst)
            {
                ilp.InsertBefore(inst, ilp.Create(OpCodes.Ldloc, vd));
                ilp.InsertBefore(inst, ilp.Create(OpCodes.Call, endMR));
            }
            ilp.Body.OptimizeMacros();
        }
        public MethodBodyPatcher(string methodName, MethodDefinition method)
        {
            _methodName = methodName;
            _methodBody = method.Body;
            _processor = _methodBody.GetILProcessor();

            _realBodyStart = _methodBody.Instructions.First();
            _realBodyEnd = _methodBody.Instructions.Last();

            _markStart1BeforeCreateArgumentsArray = _processor.Create(OpCodes.Nop);
            _markStart2BeforeCreateMethodExecutionArgs = _processor.Create(OpCodes.Nop);
            _markStart3BeforeOnEntryCall = _processor.Create(OpCodes.Nop);
            _markStart4BeforeRealBodyStartExceptionHandler = _processor.Create(OpCodes.Nop);
            _markEnd1NewRealBodyEnd = _processor.Create(OpCodes.Nop);
            _markEnd2BeforeOnExitCall = _processor.Create(OpCodes.Nop);
            _markRetNew = EndsWithThrow ? _processor.Create(OpCodes.Throw) : _processor.Create(OpCodes.Ret);
        }
Пример #16
0
        public void AddInstruction()
        {
            var object_ref = new TypeReference ("System", "Object", null, null, false);
            var method = new MethodDefinition ("foo", MethodAttributes.Static, object_ref);
            var body = new MethodBody (method);

            var il = body.GetILProcessor ();

            var first = il.Create (OpCodes.Nop);
            var second = il.Create (OpCodes.Nop);

            body.Instructions.Add (first);
            body.Instructions.Add (second);

            Assert.IsNull (first.Previous);
            Assert.AreEqual (second, first.Next);
            Assert.AreEqual (first, second.Previous);
            Assert.IsNull (second.Next);
        }
Пример #17
0
    static Action <MethodDefinition, InjectType> GetCoroutineInjectInfoFiller(MethodDefinition coroutineCreator, FieldDefinition hostRef)
    {
        return((coroutineCarrier, runtimeInjectType) =>
        {
            MethodBody targetBody = coroutineCarrier.Body;
            ILProcessor il = targetBody.GetILProcessor();

            il.InsertBefore(cursor, il.Create(OpCodes.Ldloc, funcDef));
            if (coroutineCreator.HasThis)
            {
                il.InsertBefore(cursor, il.Create(OpCodes.Ldarg_0));
                il.InsertBefore(cursor, il.Create(OpCodes.Ldfld, hostRef));
            }
            CopyCarrierFieldsToArg(coroutineCreator, coroutineCarrier);
            FillCoroutineState(coroutineCarrier);

            il.InsertBefore(cursor, il.Create(OpCodes.Call, GetLuaMethodInvoker(coroutineCreator, true, true)));
        });
    }
Пример #18
0
    static void FillBaseCall(MethodDefinition target, InjectType runtimeInjectType, bool preCall)
    {
        MethodBody  targetBody        = target.Body;
        ILProcessor il                = targetBody.GetILProcessor();
        InjectType  curBaseInjectType = preCall ? InjectType.ReplaceWithPreInvokeBase : InjectType.ReplaceWithPostInvokeBase;

        if (runtimeInjectType.HasFlag(curBaseInjectType))
        {
            Instruction end = il.Create(OpCodes.Nop);
            il.InsertBefore(cursor, end);
            il.InsertBefore(end, il.Create(OpCodes.Ldloc, flagDef));
            il.InsertBefore(end, il.Create(OpCodes.Ldc_I4, (int)curBaseInjectType));
            il.InsertBefore(end, il.Create(OpCodes.Bne_Un, end));

            FillArgs(target, end, PostProcessBaseMethodArg);
            il.InsertBefore(end, il.Create(OpCodes.Call, target.GetBaseMethodInstance()));
            if (!target.ReturnVoid())
            {
                il.InsertBefore(end, il.Create(OpCodes.Pop));
            }
        }
    }
        private MsilBodyGenerator(MethodDefinition method)
        {
            _module    = method.Module;
            _method    = method;
            _body      = method.Body = new MethodBody(method);
            _processor = _body.GetILProcessor();

            _elementTypes = new[]
            {
                _module.TypeSystem.Void.Resolve(),
                    _module.TypeSystem.Boolean.Resolve(),
                    _module.TypeSystem.Char.Resolve(),
                    _module.TypeSystem.String.Resolve(),
                    _module.TypeSystem.Byte.Resolve(),
                    _module.TypeSystem.SByte.Resolve(),
                    _module.TypeSystem.UInt16.Resolve(),
                    _module.TypeSystem.Int16.Resolve(),
                    _module.TypeSystem.UInt32.Resolve(),
                    _module.TypeSystem.Int32.Resolve(),
                    _module.TypeSystem.UInt64.Resolve(),
                    _module.TypeSystem.Int64.Resolve(),
            };
        }
Пример #20
0
    static void FillBegin(MethodDefinition target, int methodIndex)
    {
        MethodBody  targetBody = target.Body;
        ILProcessor il         = targetBody.GetILProcessor();

        targetBody.InitLocals = true;
        flagDef = new VariableDefinition(injectFlagTypeRef);
        funcDef = new VariableDefinition(luaFunctionTypeDef);
        targetBody.Variables.Add(flagDef);
        targetBody.Variables.Add(funcDef);

        Instruction startInsertPos = targetBody.Instructions[0];

        il.InsertBefore(startInsertPos, il.Create(OpCodes.Ldc_I4, methodIndex));
        il.InsertBefore(startInsertPos, il.Create(OpCodes.Call, injectFlagGetter));
        il.InsertBefore(startInsertPos, il.Create(OpCodes.Stloc, flagDef));
        il.InsertBefore(startInsertPos, il.Create(OpCodes.Ldloc, flagDef));
        il.InsertBefore(startInsertPos, il.Create(OpCodes.Brfalse, startInsertPos));
        il.InsertBefore(startInsertPos, il.Create(OpCodes.Ldc_I4, methodIndex));
        il.InsertBefore(startInsertPos, il.Create(OpCodes.Call, injectedFuncGetter));
        il.InsertBefore(startInsertPos, il.Create(OpCodes.Stloc, funcDef));
        offset = targetBody.Instructions.IndexOf(startInsertPos);
    }
Пример #21
0
        #pragma warning restore xUnit1019
        public void CorrectBranchSizes_CorrectsOpCodeFromShortOne_IfOffsetDoesNotFitSByte(OpCode opCode)
        {
            var body = new MethodBody(new MethodDefinition("", 0, new TypeReference("", "", null, null)));
            var il   = body.GetILProcessor();

            var target = il.Create(OpCodes.Ret);

            il.Emit(opCode, target);
            for (var i = 0; i < 129; i++)
            {
                il.Emit(OpCodes.Nop);
            }
            il.InsertAfter(body.Instructions.Last(), target);

            il.CorrectAllAfterChanges();

            var corrected = body.Instructions.First();

            Assert.Equal(
                Regex.Replace(opCode.Code.ToString(), "_S$", ""),
                corrected.OpCode.Code.ToString()
                );
        }
Пример #22
0
    static void FillInjectMethod(MethodDefinition target, Action <MethodDefinition, InjectType> fillInjectInfo, InjectType runtimeInjectType)
    {
        if (runtimeInjectType == InjectType.None)
        {
            return;
        }

        MethodBody  targetBody = target.Body;
        ILProcessor il         = targetBody.GetILProcessor();

        cursor = GetMethodNextInsertPosition(target, null, runtimeInjectType.HasFlag(InjectType.After));

        while (cursor != null)
        {
            bool        bAfterInject = runtimeInjectType == InjectType.After;
            Instruction startPos     = il.Create(OpCodes.Ldloc, flagDef);
            if (bAfterInject)
            {
                /// Replace instruction with references reserved
                Instruction endPos       = il.Create(OpCodes.Ret);
                int         replaceIndex = targetBody.Instructions.IndexOf(cursor);
                cursor.OpCode  = startPos.OpCode;
                cursor.Operand = startPos.Operand;
                il.InsertAfter(targetBody.Instructions[replaceIndex], endPos);
                cursor = targetBody.Instructions[replaceIndex + 1];
            }
            else
            {
                il.InsertBefore(cursor, startPos);
            }
            il.InsertBefore(cursor, il.Create(ldcI4s[(int)InjectType.After / 2]));
            il.InsertBefore(cursor, il.Create(bAfterInject ? OpCodes.Bne_Un : OpCodes.Ble_Un, cursor));

            fillInjectInfo(target, runtimeInjectType);
            cursor = GetMethodNextInsertPosition(target, cursor, runtimeInjectType.HasFlag(InjectType.After));
        }
    }
Пример #23
0
    static void FillReplaceCoroutine(MethodDefinition target, InjectType runtimeInjectType)
    {
        if (runtimeInjectType == InjectType.None)
        {
            return;
        }

        MethodBody  targetBody = target.Body;
        ILProcessor il         = targetBody.GetILProcessor();

        cursor = GetMethodNextInsertPosition(target, null, false);

        if (cursor != null)
        {
            il.InsertBefore(cursor, il.Create(OpCodes.Ldloc, flagDef));
            il.InsertBefore(cursor, il.Create(ldcI4s[(int)InjectType.Replace / 2]));
            il.InsertBefore(cursor, il.Create(OpCodes.Bne_Un, cursor));

            il.InsertBefore(cursor, il.Create(OpCodes.Ldloc, funcDef));
            FillArgs(target, cursor, null);
            il.InsertBefore(cursor, il.Create(OpCodes.Call, GetLuaMethodInvoker(target, false, false)));
            il.InsertBefore(cursor, il.Create(OpCodes.Ret));
        }
    }
 public override void VisitMethodBody(MethodBody body)
 {
     _body = body;
       _il = body.GetILProcessor();
 }
        public override void ProcessType(TypeDefinition type)
        {
            if (!type.Is ("System.Net.Http", "HttpClient"))
                return;

            MethodDefinition default_ctor = null;
            MethodDefinition full_ctor = null;
            foreach (var m in type.Methods) {
                if (m.IsStatic || !m.IsConstructor)
                    continue;
                if (!m.HasParameters) {
                    default_ctor = m;
                } else if (m.Parameters.Count == 2) {
                    full_ctor = m;
                }
            }

            if (default_ctor == null || full_ctor == null)
                throw new Exception ("Could not set the default HttpMessageHandler");

            var handler = RuntimeOptions.GetHttpMessageHandler (Options.RuntimeOptions, type.Module);

            MethodDefinition handler_ctor = null;
            foreach (var m in handler.Methods) {
                if (m.IsStatic || !m.IsConstructor || m.HasParameters)
                    continue;
                handler_ctor = m;
                break;
            }
            // re-write default ctor
            var body = new MethodBody (default_ctor);
            var il = body.GetILProcessor ();
            il.Emit (OpCodes.Ldarg_0);
            il.Emit (OpCodes.Newobj, handler_ctor);
            il.Emit (OpCodes.Ldc_I4_1);
            il.Emit (OpCodes.Call, full_ctor);
            il.Emit (OpCodes.Ret);
            default_ctor.Body = body;
        }
Пример #26
0
        private MethodBody GenerateDelegateMethod(MethodDefinition method, Class declaringClass)
        {
            // Delegate type
            var delegateType = corlib.MainModule.GetType(typeof(Delegate).FullName);

            // Delegate fields
            var targetField = delegateType.Fields.First(x => x.Name == "_target");
            var methodPtrField = delegateType.Fields.First(x => x.Name == "_methodPtr");
            var methodPtrAuxField = delegateType.Fields.First(x => x.Name == "_methodPtrAux");

            var body = new MethodBody(method);
            var il = body.GetILProcessor();

            if (method.Name == ".ctor")
            {
                // Mark
                //GenerateMulticastInvokeThunk(declaringClass);

                // Two main cases:
                // - Instance method:
                //    this._methodPtr = fnptr;
                //    this._target = target;
                //    Result: this._methodPtr(this._target, arg1, ..) will directly work
                // - Static method:
                //    this._target = this;
                //    this._methodPtrAux = fnptr;
                //    this._methodPtr = (delegate, arg1, ...) => { delegate->_methodPtrAux(arg1, ...); }
                //    Result: this._methodPtr(this._target, arg1, ...) will call thunk,
                //            which will call fnptr (from this._target._methodPtr) without the first argument
                var target = Instruction.Create(OpCodes.Ldarg_0);

                // if (target == null)
                // {
                il.Append(Instruction.Create(OpCodes.Ldarg, method.Parameters[0]));
                il.Append(Instruction.Create(OpCodes.Brtrue, target));

                //     Generate thunk (for now, done using direct LLVM, not sure weither LLVM or IL is better)
                //      this._methodPtr = (delegate, arg1, ...) => { delegate->_methodPtrAux(arg1, ...); }
                var invokeMethodHelper = GenerateStaticInvokeThunk(declaringClass);

                //      Fake Nop to push this thunk on stack (TODO: Better way to do this? i.e. store it in some static field?)
                il.Append(Instruction.Create(OpCodes.Ldarg_0));
                var loadFunctionPointerInstruction = Instruction.Create(OpCodes.Nop);
                InstructionActions.Add(loadFunctionPointerInstruction, (stack) =>
                {
                    // Push the generated method pointer on the stack
                    stack.Add(new StackValue(StackValueType.NativeInt, intPtr,
                        LLVM.BuildPointerCast(builder, invokeMethodHelper, intPtrLLVM, string.Empty)));
                });
                il.Append(loadFunctionPointerInstruction);
                il.Append(Instruction.Create(OpCodes.Stfld, methodPtrField));

                //     this._methodPtrAux = method;
                il.Append(Instruction.Create(OpCodes.Ldarg_0));
                il.Append(Instruction.Create(OpCodes.Ldarg, method.Parameters[1]));
                il.Append(Instruction.Create(OpCodes.Stfld, methodPtrAuxField));

                //     this._target = this;
                il.Append(Instruction.Create(OpCodes.Ldarg_0));
                il.Append(Instruction.Create(OpCodes.Ldarg_0));
                il.Append(Instruction.Create(OpCodes.Stfld, targetField));

                //     return;
                // }
                il.Append(Instruction.Create(OpCodes.Ret));


                // this._target = target;
                il.Append(target);
                il.Append(Instruction.Create(OpCodes.Ldarg, method.Parameters[0]));
                il.Append(Instruction.Create(OpCodes.Stfld, targetField));

                // this._methodPtr = method;
                il.Append(Instruction.Create(OpCodes.Ldarg_0));
                il.Append(Instruction.Create(OpCodes.Ldarg, method.Parameters[1]));
                il.Append(Instruction.Create(OpCodes.Stfld, methodPtrField));

                // return;
                il.Append(Instruction.Create(OpCodes.Ret));
            }
            else if (method.Name == "GetMulticastDispatchMethod")
            {
                var invokeMethodHelper = GenerateMulticastInvokeThunk(declaringClass);

                var loadFunctionPointerInstruction = Instruction.Create(OpCodes.Nop);
                InstructionActions.Add(loadFunctionPointerInstruction, (stack) =>
                {
                    // Push the generated method pointer on the stack
                    stack.Add(new StackValue(StackValueType.NativeInt, intPtr,
                        LLVM.BuildPointerCast(builder, invokeMethodHelper, intPtrLLVM, string.Empty)));
                });
                il.Append(loadFunctionPointerInstruction);

                il.Append(Instruction.Create(OpCodes.Ret));
            }
            else if (method.Name == "Invoke")
            {
                // For now, generate IL
                // Note that we could probably optimize at callsite too,
                // but probably not necessary if LLVM and sealed class are optimized/inlined well enough

                // ldarg_0
                // ldfld _target
                il.Append(Instruction.Create(OpCodes.Ldarg_0));
                il.Append(Instruction.Create(OpCodes.Ldfld, targetField));

                var callsite = new CallSite(method.ReturnType);
                callsite.Parameters.Add(new ParameterDefinition(targetField.FieldType));

                foreach (var parameter in method.Parameters)
                {
                    callsite.Parameters.Add(new ParameterDefinition(parameter.Name, parameter.Attributes, parameter.ParameterType));

                    // ldarg
                    il.Append(Instruction.Create(OpCodes.Ldarg, parameter));
                }

                // ldarg_0
                // ldfld _methodPtr
                il.Append(Instruction.Create(OpCodes.Ldarg_0));
                il.Append(Instruction.Create(OpCodes.Ldfld, methodPtrField));

                // calli
                il.Append(Instruction.Create(OpCodes.Calli, callsite));

                // ret
                il.Append(Instruction.Create(OpCodes.Ret));
            }
            else
            {
                LLVM.BuildUnreachable(builder);
                return null;
            }
            return body;
        }
Пример #27
0
 public static void Emit(this MethodBody body, Action <ILProcessor> il)
 {
     il(body.GetILProcessor());
 }
Пример #28
0
        private void InnerProcess(MethodDefinition method, bool returnVoid, ReferenceContainer references)
        {
            body = method.Body;
            body.SimplifyMacros();

            if (body.Instructions.Count <= 3)
                return; // nothing to do (empty method)

            HandleReturnType(method, returnVoid, references);

            var ilProcessor = body.GetILProcessor();

            var firstInstruction = FirstInstructionSkipCtor(method);

            firstInstruction = RejigFirstInstruction(ilProcessor, firstInstruction);

            InjectContext(ilProcessor, firstInstruction, method, references);
            var returnInstruction = FixReturns();

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

            // exclude try-catch from constructors (lot's of pain otherwise)
            if (!method.IsConstructor)
            {
                var beginCatch = InjectIlForCatch(ilProcessor, beforeReturn, references);
                var beginFinally = InjectIlForFinaly(ilProcessor, beforeReturn, references);

                var catchHandler = new ExceptionHandler(ExceptionHandlerType.Catch)
                    {
                        TryStart = firstInstruction,
                        TryEnd = beginCatch,
                        CatchType = references.ExceptionType,
                        HandlerStart = beginCatch,
                        HandlerEnd = beginFinally,
                    };

                body.ExceptionHandlers.Add(catchHandler);

                var finallyHandler = new ExceptionHandler(ExceptionHandlerType.Finally)
                    {
                        TryStart = firstInstruction,
                        TryEnd = beginFinally,
                        HandlerStart = beginFinally,
                        HandlerEnd = beforeReturn,
                    };

                body.ExceptionHandlers.Add(finallyHandler);
            }
            else
            {
                InjectIlForDispose(ilProcessor, returnInstruction, references);
            }

            body.InitLocals = true;
            body.OptimizeMacros();
        }
    private void Inject()
    {
        body = Method.Body;

        body.SimplifyMacros();

        var ilProcessor = body.GetILProcessor();

        var returnFixer = new ReturnFixer
        {
            Method = Method
        };

        returnFixer.MakeLastStatementReturn();

        var methodBodyFirstInstruction = GetMethodBodyFirstInstruction();

        var startInstructions = new List <Instruction>();

        startInstructions.AddRange(GetStartInstructions());

        foreach (var instruction in startInstructions)
        {
            ilProcessor.InsertBefore(methodBodyFirstInstruction, instruction);
        }

        var paramInstructions = GetParamInstructions();

        paramInstructions.Reverse();

        if (paramInstructions.Any())
        {
            foreach (var instruction in paramInstructions)
            {
                ilProcessor.InsertAfter(startInstructions.Last(), instruction);
            }
        }

        ilProcessor.InsertBefore(returnFixer.NopBeforeReturn, GetReturnValueInstructions(returnFixer.ReturnVariable));

        var tryCatchLeaveInstructions = Instruction.Create(OpCodes.Leave, returnFixer.NopBeforeReturn);
        var catchInstructions         = new List <Instruction>();

        catchInstructions.AddRange(GetCatchInstructions());
        ilProcessor.InsertBefore(returnFixer.NopBeforeReturn, tryCatchLeaveInstructions);
        ilProcessor.InsertBefore(returnFixer.NopBeforeReturn, catchInstructions);

        var endInstructions = new List <Instruction>();

        endInstructions.AddRange(GetEndInstructions());
        var finallyInstruction = Instruction.Create(OpCodes.Endfinally);

        endInstructions.Add(finallyInstruction);
        endInstructions.Reverse();

        foreach (var instruction in endInstructions)
        {
            ilProcessor.InsertAfter(catchInstructions.Last(), instruction);
        }

        var handler = new ExceptionHandler(ExceptionHandlerType.Catch)
        {
            CatchType    = ExceptionType,
            TryStart     = methodBodyFirstInstruction,
            TryEnd       = tryCatchLeaveInstructions.Next,
            HandlerStart = catchInstructions.First(),
            HandlerEnd   = catchInstructions.Last().Next
        };

        body.ExceptionHandlers.Add(handler);

        handler = new ExceptionHandler(ExceptionHandlerType.Finally)
        {
            TryStart     = methodBodyFirstInstruction,
            TryEnd       = catchInstructions.Last().Next,
            HandlerStart = catchInstructions.Last().Next,
            HandlerEnd   = finallyInstruction.Next
        };

        body.ExceptionHandlers.Add(handler);

        var         instructions         = body.Instructions;
        Instruction doubleDupInstruction = null;

        for (var index = 0; index < instructions.Count; index++)
        {
            var instruction = instructions[index];

            if (instruction.OpCode == OpCodes.Dup && instructions[index + 1].OpCode == OpCodes.Dup)
            {
                doubleDupInstruction = instructions[index + 1];
            }

            if (instruction.OpCode == OpCodes.Pop && doubleDupInstruction != null)
            {
                var extraPopInstruction = instructions[index];
                ilProcessor.Remove(extraPopInstruction);
                ilProcessor.InsertAfter(doubleDupInstruction, extraPopInstruction);
                doubleDupInstruction = null;
            }
        }

        body.InitLocals = true;
        body.OptimizeMacros();
    }
Пример #30
0
        /// <summary>
        /// Processes the instructions replacing all strings being loaded with an encrypted version.
        /// </summary>
        /// <param name="assemblyDef">The assembly definition.</param>
        /// <param name="body">The body.</param>
        /// <param name="decryptMethod">The decrypt method.</param>
        private void ProcessInstructions(AssemblyDefinition assemblyDef, MethodBody body, MethodReference decryptMethod)
        {
            var instructions = body.Instructions;
            var il = body.GetILProcessor();

            List<Instruction> instructionsToExpand = new List<Instruction>();
            List<int> offsets = new List<int>();
            foreach (Instruction instruction in instructions)
            {
                //Find the call statement
                switch (instruction.OpCode.Name)
                {
                    case "ldstr":
                        //We've found a string load message - we need to replace this instruction
                        if (instruction.Operand is string) //Only do the direct strings for now
                            instructionsToExpand.Add(instruction);
                        break;
                }
            }
            //Fix each ldstr instruction found
            foreach (Instruction instruction in instructionsToExpand)
            {
                //What we do is replace the ldstr "bla" with:
                //ldstr bytearray encrypted_array
                //ldc.i4 random_integer
                //call string class Decrypt(string, int32)

                //First get the original value
                string originalValue = instruction.Operand.ToString();
                offsets.Add(instruction.Offset);

                //Secondly generate a random integer as a salt
                int salt = random.Next(5000, 10000);

                //Now we need to work out what the encrypted value is and set the operand
                OutputHelper.WriteLine("Encrypting string \"{0}\"", originalValue);
                string byteArray = EncryptString(originalValue, salt);
                Instruction loadString = il.Create(OpCodes.Ldstr, byteArray);
                il.Replace(instruction, loadString);

                //Now load the salt
                Instruction loadSalt = il.Create(OpCodes.Ldc_I4, salt);
                il.InsertAfter(loadString, loadSalt);

                //Process the decryption
                Instruction call = il.Create(OpCodes.Call, decryptMethod);
                il.InsertAfter(loadSalt, call);
            }

            //Unfortunately one thing Mono.Cecil doesn't do is adjust instruction offsets for branch statements
            //and exception handling start points. We need to fix these manually
            if (offsets.Count == 0)
                return;

            //Do the adjustments
            il.AdjustOffsets(body, offsets, 6 + assemblyDef.GetAddressSize());
        }
        private void _CopyMethodToDefinition()
        {
            MethodBase method     = OriginalMethod;
            Module     moduleFrom = method.Module;

            System.Reflection.MethodBody bodyFrom = method.GetMethodBody();
            byte[] data = bodyFrom?.GetILAsByteArray();
            if (data == null)
            {
                throw new NotSupportedException("Body-less method");
            }

            MethodDefinition def      = Definition;
            ModuleDefinition moduleTo = def.Module;

            Mono.Cecil.Cil.MethodBody bodyTo = def.Body;
            ILProcessor processor            = bodyTo.GetILProcessor();

            Type[] typeArguments = null;
            if (method.DeclaringType.IsGenericType)
            {
                typeArguments = method.DeclaringType.GetGenericArguments();
            }

            Type[] methodArguments = null;
            if (method.IsGenericMethod)
            {
                methodArguments = method.GetGenericArguments();
            }

            foreach (LocalVariableInfo info in bodyFrom.LocalVariables)
            {
                TypeReference type = moduleTo.ImportReference(info.LocalType);
                if (info.IsPinned)
                {
                    type = new PinnedType(type);
                }
                bodyTo.Variables.Add(new VariableDefinition(type));
            }

            using (BinaryReader reader = new BinaryReader(new MemoryStream(data))) {
                while (reader.BaseStream.Position < reader.BaseStream.Length)
                {
                    int         offset = (int)reader.BaseStream.Position;
                    Instruction instr  = Instruction.Create(OpCodes.Nop);
                    byte        op     = reader.ReadByte();
                    instr.OpCode = op != 0xfe ? _CecilOpCodes1X[op] : _CecilOpCodes2X[reader.ReadByte()];
                    instr.Offset = offset;
                    ReadOperand(reader, instr);
                    bodyTo.Instructions.Add(instr);
                }
            }

            foreach (Instruction instr in bodyTo.Instructions)
            {
                switch (instr.OpCode.OperandType)
                {
                case OperandType.ShortInlineBrTarget:
                case OperandType.InlineBrTarget:
                    instr.Operand = GetInstruction((int)instr.Operand);
                    break;

                case OperandType.InlineSwitch:
                    int[]         offsets = (int[])instr.Operand;
                    Instruction[] targets = new Instruction[offsets.Length];
                    for (int i = 0; i < offsets.Length; i++)
                    {
                        targets[i] = GetInstruction(offsets[i]);
                    }
                    instr.Operand = targets;
                    break;
                }
            }

            foreach (ExceptionHandlingClause clause in bodyFrom.ExceptionHandlingClauses)
            {
                ExceptionHandler handler = new ExceptionHandler((ExceptionHandlerType)clause.Flags);
                bodyTo.ExceptionHandlers.Add(handler);

                handler.TryStart = GetInstruction(clause.TryOffset);
                handler.TryEnd   = GetInstruction(clause.TryOffset + clause.TryLength);

                handler.FilterStart  = handler.HandlerType != ExceptionHandlerType.Filter ? null : GetInstruction(clause.FilterOffset);
                handler.HandlerStart = GetInstruction(clause.HandlerOffset);
                handler.HandlerEnd   = GetInstruction(clause.HandlerOffset + clause.HandlerLength);

                handler.CatchType = handler.HandlerType != ExceptionHandlerType.Catch ? null : clause.CatchType == null ? null : moduleTo.ImportReference(clause.CatchType);
            }

            void ReadOperand(BinaryReader reader, Instruction instr)
            {
                int index, offs, length;

                switch (instr.OpCode.OperandType)
                {
                case OperandType.InlineNone:
                    instr.Operand = null;
                    break;

                case OperandType.InlineSwitch:
                    length = reader.ReadInt32();
                    offs   = (int)reader.BaseStream.Position + (4 * length);
                    int[] targets = new int[length];
                    for (int i = 0; i < length; i++)
                    {
                        targets[i] = reader.ReadInt32() + offs;
                    }
                    instr.Operand = targets;
                    break;

                case OperandType.ShortInlineBrTarget:
                    offs          = reader.ReadSByte();
                    instr.Operand = (int)reader.BaseStream.Position + offs;
                    break;

                case OperandType.InlineBrTarget:
                    offs          = reader.ReadInt32();
                    instr.Operand = (int)reader.BaseStream.Position + offs;
                    break;

                case OperandType.ShortInlineI:
                    instr.Operand = instr.OpCode == OpCodes.Ldc_I4_S ? reader.ReadSByte() : (object)reader.ReadByte();
                    break;

                case OperandType.InlineI:
                    instr.Operand = reader.ReadInt32();
                    break;

                case OperandType.ShortInlineR:
                    instr.Operand = reader.ReadSingle();
                    break;

                case OperandType.InlineR:
                    instr.Operand = reader.ReadDouble();
                    break;

                case OperandType.InlineI8:
                    instr.Operand = reader.ReadInt64();
                    break;

                case OperandType.InlineSig:
                    throw new NotSupportedException("Parsing CallSites at runtime currently not supported");

                case OperandType.InlineString:
                    instr.Operand = moduleFrom.ResolveString(reader.ReadInt32());
                    break;

                case OperandType.InlineTok:
                    switch (moduleFrom.ResolveMember(reader.ReadInt32(), typeArguments, methodArguments))
                    {
                    case Type i:
                        instr.Operand = moduleTo.ImportReference(i);
                        break;

                    case FieldInfo i:
                        instr.Operand = moduleTo.ImportReference(i);
                        break;

                    case MethodBase i:
                        instr.Operand = moduleTo.ImportReference(i);
                        break;
                    }
                    break;

                case OperandType.InlineType:
                    instr.Operand = moduleTo.ImportReference(moduleFrom.ResolveType(reader.ReadInt32(), typeArguments, methodArguments));
                    break;

                case OperandType.InlineMethod:
                    instr.Operand = moduleTo.ImportReference(moduleFrom.ResolveMethod(reader.ReadInt32(), typeArguments, methodArguments));
                    break;

                case OperandType.InlineField:
                    instr.Operand = moduleTo.ImportReference(moduleFrom.ResolveField(reader.ReadInt32(), typeArguments, methodArguments));
                    break;

                case OperandType.ShortInlineVar:
                case OperandType.InlineVar:
                    index         = instr.OpCode.OperandType == OperandType.ShortInlineVar ? reader.ReadByte() : reader.ReadInt16();
                    instr.Operand = bodyTo.Variables[index];
                    break;

                case OperandType.InlineArg:
                case OperandType.ShortInlineArg:
                    index         = instr.OpCode.OperandType == OperandType.ShortInlineArg ? reader.ReadByte() : reader.ReadInt16();
                    instr.Operand = def.Parameters[index];
                    break;

                case OperandType.InlinePhi:     // No opcode seems to use this
                default:
                    throw new NotSupportedException($"Unsupported opcode ${instr.OpCode.Name}");
                }
            }

            Instruction GetInstruction(int offset)
            {
                int last = bodyTo.Instructions.Count - 1;

                if (offset < 0 || offset > bodyTo.Instructions[last].Offset)
                {
                    return(null);
                }

                int min = 0;
                int max = last;

                while (min <= max)
                {
                    int         mid   = min + ((max - min) / 2);
                    Instruction instr = bodyTo.Instructions[mid];

                    if (offset == instr.Offset)
                    {
                        return(instr);
                    }

                    if (offset < instr.Offset)
                    {
                        max = mid - 1;
                    }
                    else
                    {
                        min = mid + 1;
                    }
                }

                return(null);
            }
        }
Пример #32
0
		public bool Compile()
		{
			LogLine(1, "Compiling Xaml");
			LogLine(1, "\nAssembly: {0}", Assembly);
			if (!string.IsNullOrEmpty(DependencyPaths))
				LogLine(1, "DependencyPaths: \t{0}", DependencyPaths);
			if (!string.IsNullOrEmpty(ReferencePath))
				LogLine(1, "ReferencePath: \t{0}", ReferencePath.Replace("//", "/"));
			LogLine(3, "DebugSymbols:\"{0}\"", DebugSymbols);
			var skipassembly = true; //change this to false to enable XamlC by default
			bool success = true;

			if (!File.Exists(Assembly))
			{
				LogLine(1, "Assembly file not found. Skipping XamlC.");
				return true;
			}

			var resolver = new XamlCAssemblyResolver();
			if (!string.IsNullOrEmpty(DependencyPaths))
			{
				foreach (var dep in DependencyPaths.Split(';'))
				{
					LogLine(3, "Adding searchpath {0}", dep);
					resolver.AddSearchDirectory(dep);
				}
			}

			if (!string.IsNullOrEmpty(ReferencePath))
			{
				var paths = ReferencePath.Replace("//", "/").Split(';');
				foreach (var p in paths)
				{
					var searchpath = Path.GetDirectoryName(p);
					LogLine(3, "Adding searchpath {0}", searchpath);
					resolver.AddSearchDirectory(searchpath);
					//					LogLine (3, "Referencing {0}", p);
					//					resolver.AddAssembly (p);
				}
			}

			var assemblyDefinition = AssemblyDefinition.ReadAssembly(Path.GetFullPath(Assembly), new ReaderParameters
			{
				AssemblyResolver = resolver,
				ReadSymbols = DebugSymbols
			});

			CustomAttribute xamlcAttr;
			if (assemblyDefinition.HasCustomAttributes &&
			    (xamlcAttr =
				    assemblyDefinition.CustomAttributes.FirstOrDefault(
					    ca => ca.AttributeType.FullName == "Xamarin.Forms.Xaml.XamlCompilationAttribute")) != null)
			{
				var options = (XamlCompilationOptions)xamlcAttr.ConstructorArguments[0].Value;
				if ((options & XamlCompilationOptions.Skip) == XamlCompilationOptions.Skip)
					skipassembly = true;
				if ((options & XamlCompilationOptions.Compile) == XamlCompilationOptions.Compile)
					skipassembly = false;
			}

			foreach (var module in assemblyDefinition.Modules)
			{
				var skipmodule = skipassembly;
				if (module.HasCustomAttributes &&
				    (xamlcAttr =
					    module.CustomAttributes.FirstOrDefault(
						    ca => ca.AttributeType.FullName == "Xamarin.Forms.Xaml.XamlCompilationAttribute")) != null)
				{
					var options = (XamlCompilationOptions)xamlcAttr.ConstructorArguments[0].Value;
					if ((options & XamlCompilationOptions.Skip) == XamlCompilationOptions.Skip)
						skipmodule = true;
					if ((options & XamlCompilationOptions.Compile) == XamlCompilationOptions.Compile)
						skipmodule = false;
				}

				LogLine(2, " Module: {0}", module.Name);
				var resourcesToPrune = new List<EmbeddedResource>();
				foreach (var resource in module.Resources.OfType<EmbeddedResource>())
				{
					Log(2, "  Resource: {0}... ", resource.Name);
					string classname;
					if (!resource.IsXaml(out classname))
					{
						LogLine(2, "skipped.");
						continue;
					}
					TypeDefinition typeDef = module.GetType(classname);
					if (typeDef == null)
					{
						LogLine(2, "no type found... skipped.");
						continue;
					}
					var skiptype = skipmodule;
					if (typeDef.HasCustomAttributes &&
					    (xamlcAttr =
						    typeDef.CustomAttributes.FirstOrDefault(
							    ca => ca.AttributeType.FullName == "Xamarin.Forms.Xaml.XamlCompilationAttribute")) != null)
					{
						var options = (XamlCompilationOptions)xamlcAttr.ConstructorArguments[0].Value;
						if ((options & XamlCompilationOptions.Skip) == XamlCompilationOptions.Skip)
							skiptype = true;
						if ((options & XamlCompilationOptions.Compile) == XamlCompilationOptions.Compile)
							skiptype = false;
					}
					if (skiptype)
					{
						LogLine(2, "Has XamlCompilationAttribute set to Skip and not Compile... skipped");
						continue;
					}

					var initComp = typeDef.Methods.FirstOrDefault(md => md.Name == "InitializeComponent");
					if (initComp == null)
					{
						LogLine(2, "no InitializeComponent found... skipped.");
						continue;
					}
					LogLine(2, "");

					Log(2, "   Parsing Xaml... ");
					var rootnode = ParseXaml(resource.GetResourceStream(), typeDef);
					if (rootnode == null)
					{
						LogLine(2, "failed.");
						continue;
					}
					LogLine(2, "done.");

					hasCompiledXamlResources = true;

					try
					{
						Log(2, "   Replacing {0}.InitializeComponent ()... ", typeDef.Name);
						var body = new MethodBody(initComp);
						var il = body.GetILProcessor();
						il.Emit(OpCodes.Nop);
						var visitorContext = new ILContext(il, body);

						rootnode.Accept(new XamlNodeVisitor((node, parent) => node.Parent = parent), null);
						rootnode.Accept(new ExpandMarkupsVisitor(visitorContext), null);
						rootnode.Accept(new CreateObjectVisitor(visitorContext), null);
						rootnode.Accept(new SetNamescopesAndRegisterNamesVisitor(visitorContext), null);
						rootnode.Accept(new SetFieldVisitor(visitorContext), null);
						rootnode.Accept(new SetResourcesVisitor(visitorContext), null);
						rootnode.Accept(new SetPropertiesVisitor(visitorContext, true), null);

						il.Emit(OpCodes.Ret);
						initComp.Body = body;
					}
					catch (XamlParseException xpe)
					{
						LogLine(2, "failed.");
						LogError(null, null, null, resource.Name, xpe.XmlInfo.LineNumber, xpe.XmlInfo.LinePosition, 0, 0, xpe.Message,
							xpe.HelpLink, xpe.Source);
						LogLine(4, xpe.StackTrace);
						success = false;
						continue;
					}
					catch (XmlException xe)
					{
						LogLine(2, "failed.");
						LogError(null, null, null, resource.Name, xe.LineNumber, xe.LinePosition, 0, 0, xe.Message, xe.HelpLink, xe.Source);
						LogLine(4, xe.StackTrace);
						success = false;
						continue;
					}
					catch (Exception e)
					{
						LogLine(2, "failed.");
						LogError(null, null, null, resource.Name, 0, 0, 0, 0, e.Message, e.HelpLink, e.Source);
						LogLine(4, e.StackTrace);
						success = false;
						continue;
					}
					LogLine(2, "done.");

					if (OptimizeIL)
					{
						Log(2, "   Optimizing IL... ");
						initComp.Body.OptimizeMacros();
						LogLine(2, "done");
					}

					if (OutputGeneratedILAsCode)
					{
						var filepath = Path.Combine(Path.GetDirectoryName(Assembly), typeDef.FullName + ".decompiled.cs");
						Log(2, "   Decompiling {0} into {1}...", typeDef.FullName, filepath);
						var decompilerContext = new DecompilerContext(module);
						using (var writer = new StreamWriter(filepath))
						{
							var output = new PlainTextOutput(writer);

							var codeDomBuilder = new AstBuilder(decompilerContext);
							codeDomBuilder.AddType(typeDef);
							codeDomBuilder.GenerateCode(output);
						}

						LogLine(2, "done");
					}
					resourcesToPrune.Add(resource);
				}
				if (!KeepXamlResources)
				{
					if (resourcesToPrune.Any())
						LogLine(2, "  Removing compiled xaml resources");
					foreach (var resource in resourcesToPrune)
					{
						Log(2, "   Removing {0}... ", resource.Name);
						module.Resources.Remove(resource);
						LogLine(2, "done");
					}
				}

				LogLine(2, "");
			}

			if (!hasCompiledXamlResources)
			{
				LogLine(1, "No compiled resources. Skipping writing assembly.");
				return success;
			}

			Log(1, "Writing the assembly... ");
			try
			{
				assemblyDefinition.Write(Assembly, new WriterParameters
				{
					WriteSymbols = DebugSymbols
				});
				LogLine(1, "done.");
			}
			catch (Exception e)
			{
				LogLine(1, "failed.");
				LogError(null, null, null, null, 0, 0, 0, 0, e.Message, e.HelpLink, e.Source);
				LogLine(4, e.StackTrace);
				success = false;
			}

			return success;
		}
Пример #33
0
        /// <summary>
        /// Patches the (entry) method to output the used MonoMod version in the console.
        /// </summary>
        /// <returns>The new entry method.</returns>
        /// <param name="entryOld">The old entry method.</param>
        public virtual MethodDefinition PatchEntry(MethodDefinition entryOld)
        {
            if (entryOld == null) {
                Log("Entry point not found; skipping...");
                return null;
            }

            Log("M:"+entryOld.Name);

            entryOld.Name = "orig_"+entryOld.Name;

            MethodDefinition entry = new MethodDefinition("Main", MethodAttributes.Public | MethodAttributes.Static, Module.Import(typeof(void)));
            entry.Parameters.Add(new ParameterDefinition(Module.Import(typeof(string[]))));

            MethodBody body = new MethodBody(entry);
            ILProcessor processor = body.GetILProcessor();

            processor.Emit(OpCodes.Ldstr, "MonoMod "+System.Reflection.Assembly.GetExecutingAssembly().GetName().Version);
            processor.Emit(OpCodes.Call, Module.Import(typeof(Console).GetMethod("WriteLine", new Type[] {typeof(string)})));

            processor.Emit(OpCodes.Ldarg_0);
            processor.Emit(OpCodes.Call, entryOld);

            processor.Emit(OpCodes.Ret);

            entry.Body = body;

            entryOld.DeclaringType.Methods.Add(entry);
            Module.EntryPoint = entry;

            return entry;
        }
Пример #34
0
        /// <summary>
        ///     Processes and writes IL to the provided method body.
        ///     Note that this cleans the existing method body (removes insturctions and exception handlers).
        /// </summary>
        /// <param name="body">Method body to write to.</param>
        /// <param name="original">Original method that transpiler can optionally call into</param>
        /// <exception cref="NotSupportedException">
        ///     One of IL opcodes contains a CallSide (e.g. calli), which is currently not
        ///     fully supported.
        /// </exception>
        /// <exception cref="ArgumentNullException">One of IL opcodes with an operand contains a null operand.</exception>
        public void WriteTo(MethodBody body, MethodBase original = null)
        {
            // Clean up the body of the target method
            body.Instructions.Clear();
            body.ExceptionHandlers.Clear();

            var il  = new CecilILGenerator(body.GetILProcessor());
            var cil = il.GetProxy();

            // Define an "empty" label
            // In Harmony, the first label can point to the end of the method
            // Apparently, some transpilers naively call new Label() to define a label and thus end up
            // using the first label without knowing it
            // By defining the first label we'll ensure label count is correct
            il.DefineLabel();

            // Step 1: Prepare labels for instructions
            Prepare(vDef => il.GetLocal(vDef), il.DefineLabel);

            // Step 2: Run the code instruction through transpilers
            var newInstructions = ApplyTranspilers(cil, original);

            // We don't remove trailing `ret`s because we need to do so only if prefixes/postfixes are present

            // Step 3: Emit code
            foreach (var ins in newInstructions)
            {
                ins.labels.ForEach(l => il.MarkLabel(l));
                ins.blocks.ForEach(b => il.MarkBlockBefore(b));

                // We don't replace `ret`s yet because we might not need to
                // We do that only if we add prefixes/postfixes
                // We also don't need to care for long/short forms thanks to Cecil/MonoMod

                // Temporary fix: CecilILGenerator doesn't properly handle ldarg
                switch (ins.opcode.OperandType)
                {
                case SRE.OperandType.InlineNone:
                    il.Emit(ins.opcode);
                    break;

                case SRE.OperandType.InlineSig:
                    throw new NotSupportedException(
                              "Emitting opcodes with CallSites is currently not fully implemented");

                default:
                    if (ins.operand == null)
                    {
                        throw new ArgumentNullException(nameof(ins.operand), $"Invalid argument for {ins}");
                    }

                    il.Emit(ins.opcode, ins.operand);
                    break;
                }

                ins.blocks.ForEach(b => il.MarkBlockAfter(b));
            }

            // Note: We lose all unassigned labels here along with any way to log them
            // On the contrary, we gain better logging anyway down the line by using Cecil

            // Step 4: Run the code through raw IL manipulators (if any)
            // TODO: IL Manipulators
        }
Пример #35
0
        protected virtual void InjectAdditionalInstructionBeforeStartCall(Mono.Cecil.Cil.MethodBody body, Instruction call)
        {
            Instruction pickMyself = body.GetILProcessor().Create(OpCodes.Ldarg_0);

            body.GetILProcessor().InsertBefore(call, pickMyself);
        }
Пример #36
0
        /// <summary>
        /// Inserts the invalid il.
        /// </summary>
        /// <param name="methodBody">The method body.</param>
        private static void InsertInvalidIl(MethodBody methodBody)
        {
            //Get the instructions and cil worker
            var instructions = methodBody.Instructions;
            if (instructions.Count <= 0)
                return; //We can only do this if we have instructions to work with
            ILProcessor il = methodBody.GetILProcessor();

            //First create an invalid il instruction
            OpCode fakeOpCode = CreateInvalidOpCode();
            Instruction invalidIlInstr1 = il.Create(fakeOpCode);
            Instruction invalidIlInstr2 = il.Create(fakeOpCode);
            Instruction originalFirst = instructions[0];

            //Insert invalid il at the start
            il.InsertBefore(originalFirst, invalidIlInstr1);
            il.InsertBefore(invalidIlInstr1, invalidIlInstr2);

            //Create the branch statement
            Instruction branchStatement = il.Create(OpCodes.Br_S, originalFirst);

            //Add the branch to the start
            il.InsertBefore(invalidIlInstr2, branchStatement);

            //Readjust the offsets
            il.AdjustOffsets(methodBody, 4);
        }
Пример #37
0
		public override bool Execute()
		{
			InMsBuild = true;
			Verbosity = Int32.MaxValue;
			LogLine(1, "Preparing debug code for xamlc");
			LogLine(1, "\nAssembly: {0}", Assembly);

			var resolver = new DefaultAssemblyResolver();
			if (!string.IsNullOrEmpty(DependencyPaths))
			{
				foreach (var dep in DependencyPaths.Split(';'))
				{
					LogLine(3, "Adding searchpath {0}", dep);
					resolver.AddSearchDirectory(dep);
				}
			}
			if (!string.IsNullOrEmpty(ReferencePath))
			{
				var paths = ReferencePath.Replace("//", "/").Split(';');
				foreach (var p in paths)
				{
					var searchpath = Path.GetDirectoryName(p);
					LogLine(3, "Adding searchpath {0}", searchpath);
					resolver.AddSearchDirectory(searchpath);
					//					LogLine (3, "Referencing {0}", p);
					//					resolver.AddAssembly (p);
				}
			}
			var assemblyDefinition = AssemblyDefinition.ReadAssembly(Assembly, new ReaderParameters
			{
				//ReadSymbols = DebugSymbols,
				AssemblyResolver = resolver
			});

			foreach (var module in assemblyDefinition.Modules)
			{
				LogLine(2, " Module: {0}", module.Name);
				foreach (var resource in module.Resources.OfType<EmbeddedResource>())
				{
					Log(2, "  Resource: {0}... ", resource.Name);
					string classname;
					if (!resource.IsXaml(out classname))
					{
						LogLine(2, "skipped.");
						continue;
					}
					TypeDefinition typeDef = module.GetType(classname);
					if (typeDef == null)
					{
						LogLine(2, "no type found... skipped.");
						continue;
					}
					var initComp = typeDef.Methods.FirstOrDefault(md => md.Name == "InitializeComponent");
					if (initComp == null)
					{
						LogLine(2, "no InitializeComponent found... skipped.");
						continue;
					}
					if (typeDef.Methods.FirstOrDefault(md => md.Name == "InitCompRuntime") != null)
					{
						LogLine(2, "InitCompRuntime already exists... skipped");
						continue;
					}
					LogLine(2, "");

					Log(2, "   Duplicating {0}.InitializeComponent () into {0}.InitCompRuntime ... ", typeDef.Name);
					var initCompRuntime = new MethodDefinition("InitCompRuntime", initComp.Attributes, initComp.ReturnType);
					initCompRuntime.Body = initComp.Body;
					typeDef.Methods.Add(initCompRuntime);
					LogLine(2, "done.");

					//					IL_0000:  ldarg.0 
					//					IL_0001:  callvirt instance void class [Xamarin.Forms.Core]Xamarin.Forms.ContentPage::'.ctor'()
					//
					//					IL_0006:  nop 
					//					IL_0007:  ldarg.1 
					//					IL_0008:  brfalse IL_0018
					//
					//					IL_000d:  ldarg.0 
					//					IL_000e:  callvirt instance void class Xamarin.Forms.Xaml.XamlcTests.MyPage::InitializeComponent()
					//					IL_0013:  br IL_001e
					//
					//					IL_0018:  ldarg.0 
					//					IL_0019:  callvirt instance void class Xamarin.Forms.Xaml.XamlcTests.MyPage::InitCompRuntime()
					//					IL_001e:  ret 

					var altCtor =
						typeDef.Methods.Where(
							md => md.IsConstructor && md.Parameters.Count == 1 && md.Parameters[0].ParameterType == module.TypeSystem.Boolean)
							.FirstOrDefault();
					if (altCtor != null)
						Log(2, "   Replacing body of {0}.{0} (bool {1}) ... ", typeDef.Name, altCtor.Parameters[0].Name);
					else
					{
						Log(2, "   Adding {0}.{0} (bool useCompiledXaml) ... ", typeDef.Name);
						altCtor = new MethodDefinition(".ctor",
							MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName |
							MethodAttributes.RTSpecialName, module.TypeSystem.Void);
						altCtor.Parameters.Add(new ParameterDefinition("useCompiledXaml", ParameterAttributes.None,
							module.TypeSystem.Boolean));
					}

					var body = new MethodBody(altCtor);
					var il = body.GetILProcessor();
					var br2 = Instruction.Create(OpCodes.Ldarg_0);
					var ret = Instruction.Create(OpCodes.Ret);
					il.Emit(OpCodes.Ldarg_0);
					il.Emit(OpCodes.Callvirt,
						module.Import(typeDef.BaseType.Resolve().GetConstructors().First(c => c.HasParameters == false)));

					il.Emit(OpCodes.Nop);
					il.Emit(OpCodes.Ldarg_1);
					il.Emit(OpCodes.Brfalse, br2);

					il.Emit(OpCodes.Ldarg_0);
					il.Emit(OpCodes.Callvirt, initComp);
					il.Emit(OpCodes.Br, ret);

					il.Append(br2);
					il.Emit(OpCodes.Callvirt, initCompRuntime);
					il.Append(ret);

					altCtor.Body = body;
					if (!typeDef.Methods.Contains(altCtor))
						typeDef.Methods.Add(altCtor);
					LogLine(2, "done.");
				}

				LogLine(2, "");
			}
			Log(1, "Writing the assembly... ");
			assemblyDefinition.Write(Assembly, new WriterParameters
			{
				WriteSymbols = DebugSymbols
			});
			LogLine(1, "done.");

			return true;
		}
Пример #38
0
        new void ProcessMethod(MethodDefinition method)
        {
            ProcessParameters (method);

            if (!method.HasBody)
                return;

            var body = new MethodBody (method);

            var il = body.GetILProcessor ();
            il.Emit (OpCodes.Call, get_nse);
            il.Emit (OpCodes.Throw);

            method.Body = body;
        }
Пример #39
0
        /// <summary>
        /// Callback when compliation finished
        /// <paramref name="assemblyPath"/> Path compiled assembly
        /// <paramref name="messages"/> Compliation messages
        /// </summary>
        public static void OnCompilationFinished(string assemblyPath, CompilerMessage[] messages)
        {
            if (assemblyPath.Contains("-Editor"))
            {
                return;
            }

            List <Type> derivedTypes             = new List <Type>();
            List <PropertyDefinition> properties = new List <PropertyDefinition>();

            bool isModified = false;

            #region Cecil
            using (AssemblyDefinition currentAssembly = AssemblyDefinition.ReadAssembly(assemblyPath, new ReaderParameters {
                ReadWrite = true, ReadSymbols = true                                                                                                             /*, AssemblyResolver = asmResolver*/
            }))
            {
                _mainModule = currentAssembly.MainModule;

                var p = currentAssembly.MainModule.Types.Where(o => o.IsClass).SelectMany(t => t.Properties);
                if (p != null)
                {
                    properties.AddRange(p);
                }

                foreach (PropertyDefinition pd in properties)
                {
                    CustomAttribute attr = pd.CustomAttributes.SingleOrDefault(i => i.AttributeType.Name == nameof(UIBindable));
                    if (attr != null)
                    {
                        Mono.Cecil.Cil.MethodBody body = pd.SetMethod.Body;

                        ILProcessor processor = body.GetILProcessor();

                        var instructions = body.Instructions;
                        var targetInst   = instructions.Last();

                        #region Trying Generic

                        /*// importing the generic type
                         * var eq = _mainModule.ImportReference(typeof(UIBindProxy<>));
                         *
                         * // importing the type of T we want to instantiate the generic type
                         * var t = _mainModule.ImportReference(typeof(float));
                         * var genericEq = new GenericInstanceType(eq);
                         * genericEq.GenericArguments.Add(t);
                         * var importedGenericEq = _mainModule.ImportReference(genericEq);
                         * // getting the method we want to call on the generic instance
                         * var td = SafeResolve(importedGenericEq);
                         * td.DeclaringType = SafeResolve(t);
                         * var defaultMethodDef = td.Methods.Single(m => m.Name == "UpdateValue");
                         *
                         * var methodRef = _mainModule.ImportReference(defaultMethodDef);
                         *
                         * // Important - setting the method declaring type to the correct instantiated type
                         * methodRef.DeclaringType = importedGenericEq;
                         *
                         *
                         * processor.InsertBefore(targetInst, processor.Create(OpCodes.Nop));
                         * processor.InsertBefore(targetInst, processor.Create(OpCodes.Ldarg_0));
                         * processor.InsertBefore(targetInst, processor.Create(OpCodes.Ldstr, pd.Name));
                         * processor.InsertBefore(targetInst, processor.Create(OpCodes.Ldarg_1));
                         * processor.InsertBefore(targetInst, processor.Create(OpCodes.Call, methodRef));
                         * isModified = true;
                         * continue;
                         *
                         * var td2 = _mainModule.GetType("HDV.UIBindProxy`1");
                         * td2.DeclaringType = SafeResolve(_mainModule.ImportReference(typeof(float)));
                         *
                         * //td.DeclaringType
                         * // td = _mainModule.GetType("HDV.UIBindProxyTest");
                         * foreach (var md in td2.Methods)
                         * {
                         *  if (md.Name == "UpdateValue")
                         *  {
                         *      processor.InsertBefore(targetInst, processor.Create(OpCodes.Nop));
                         *      processor.InsertBefore(targetInst, processor.Create(OpCodes.Ldarg_0));
                         *      processor.InsertBefore(targetInst, processor.Create(OpCodes.Ldstr, pd.Name));
                         *      processor.InsertBefore(targetInst, processor.Create(OpCodes.Ldarg_1));
                         *      processor.InsertBefore(targetInst, processor.Create(OpCodes.Call, md));
                         *      isModified = true;
                         *  }
                         * }
                         * continue;*/
                        #endregion

                        TypeDefinition td = _mainModule.GetType("HDV.UIBinding.UIBindProxy");
                        string         methodName;
                        switch (pd.PropertyType.MetadataType)
                        {
                        case MetadataType.Single:
                        {
                            methodName = "UpdateFloatValue";
                            break;
                        }

                        case MetadataType.Int32:
                        {
                            methodName = "UpdateIntValue";
                            break;
                        }

                        //TODO: Need Generic
                        case MetadataType.String:
                        case MetadataType.Class:
                        case MetadataType.Object:
                        {
                            methodName = "UpdateObjectValue";
                            break;
                        }

                        default:
                        {
                            UnityDebug.LogError("Missing type " + pd.PropertyType.MetadataType);
                            continue;
                        }
                        }

                        MethodDefinition md = td.Methods.Single(m => m.Name == methodName);

                        processor.InsertBefore(targetInst, processor.Create(OpCodes.Nop));
                        processor.InsertBefore(targetInst, processor.Create(OpCodes.Ldarg_0));
                        processor.InsertBefore(targetInst, processor.Create(OpCodes.Ldstr, pd.Name));
                        processor.InsertBefore(targetInst, processor.Create(OpCodes.Ldarg_1));

                        processor.InsertBefore(targetInst, processor.Create(OpCodes.Call, md));

                        isModified = true;
                    }
                }

                if (isModified)
                {
                    currentAssembly.Write(new WriterParameters {
                        WriteSymbols = true
                    });
                }
            }

            #endregion
        }
Пример #40
0
        public static void Apply(ModuleDefinition module, Logger logger)
        {
            //AppDomain currentDomain = AppDomain.CurrentDomain;
            //currentDomain.AssemblyResolve += new ResolveEventHandler(LoadFromSameFolder);
            Assembly assembly = Assembly.LoadFrom(Deobfuscator.sourceAssemblyPath.path + Path.DirectorySeparatorChar + Deobfuscator.sourceAssemblyPath.filename);

            Module target = assembly.GetModules()[0];

            logger.KeyInfo("Looking for string decryption calls...");
            int decryptStats = 0;
            List <MethodDefinition> decryptMethods = new List <MethodDefinition>();

            MethodDefinition[] mdefs = HelperClass.findMembers <MethodDefinition>(module, null, true);
            for (int __i = 0; __i < mdefs.Length; __i++)
            {
                MethodDefinition mdef = mdefs[__i];
                if (mdef.HasBody)
                {
                    Mono.Cecil.Cil.MethodBody mdefBody = mdef.Body;
                    for (int i = 0; i < (mdefBody.Instructions.Count - 1); i++)
                    {
                        Instruction instr1 = mdefBody.Instructions[i];
                        Instruction instr2 = mdefBody.Instructions[i + 1];
                        if (loadIntegerCodes.ContainsKey(instr1.OpCode.Code) &&
                            (instr2.OpCode == OpCodes.Call))
                        {
                            int key = loadIntegerCodes[instr1.OpCode.Code](instr1.Operand);                            //(int)instr1.Operand;
                            MethodDefinition targetMethod = ((MethodReference)instr2.Operand).Resolve();
                            if (targetMethod != null && targetMethod.IsStatic &&
                                targetMethod.Parameters.Count == 1 && targetMethod.ReturnType.FullName.Equals("System.String") &&
                                targetMethod.HasBody && targetMethod.Body.Instructions.Count > 5 && targetMethod.Body.Instructions[4].OpCode == OpCodes.Ldelem_U1)
                            {
                                Type       decryptorType   = null;
                                MethodInfo decryptorMethod = null;
                                try
                                {
                                    decryptorType   = target.GetType(targetMethod.DeclaringType.FullName);
                                    decryptorMethod = decryptorType.GetMethod(targetMethod.Name, BindingFlags.Static | BindingFlags.NonPublic);
                                    string      decrypted = (string)decryptorMethod.Invoke(null, new object[] { key });
                                    Instruction newInstr;
                                    ILProcessor proc = mdefBody.GetILProcessor();
                                    HelperClass.SafeInsertBefore(proc, instr1, (newInstr = mdefBody.GetILProcessor().Create(OpCodes.Ldstr, decrypted)));
                                    //mdefBody.GetILProcessor().InsertBefore(instr1, (newInstr = mdefBody.GetILProcessor().Create(OpCodes.Ldstr, decrypted)));
                                    HelperClass.PatchInstructionReferences(mdefBody, instr1, newInstr);
                                    for (int _i = 0; _i < 2; _i++)
                                    {
                                        HelperClass.SafeRemove(proc, mdefBody.Instructions[i + 1]);
                                    }
                                    //mdefBody.Instructions.RemoveAt(i+1);
                                    if (!decryptMethods.Contains(targetMethod))
                                    {
                                        decryptMethods.Add(targetMethod);
                                    }

                                    //logger.Info(decrypted);
                                    //i++;
                                    decryptStats++;
                                }
                                catch (Exception e)
                                {
                                    logger.Warning("Unable to decrypt " + targetMethod.Name + " (" + key + ") :\r\n" + e.ToString());
                                    continue;
                                }
                            }
                        }
                    }
                }
                if ((__i % (mdefs.Length / 10)) == 0 && __i > 0)
                {
                    logger.KeyInfo("Decrypted strings from method #" + (__i + 1) + ".");
                }
            }
            for (int i = 0; i < decryptMethods.Count; i++)
            {
                MethodDefinition mdef = decryptMethods[i];
                //module.Types.Remove(mdef.DeclaringType);
                mdef.DeclaringType.Name = "decryptor" + i;
                mdef.Name = "Decrypt";
            }
            logger.KeyInfo("Finished decrypting " + decryptStats + " strings!");
        }
Пример #41
0
		private void RewriteIL (MethodBody body, Dictionary<Expr,Instruction> instructionLookup, Expr remove, Expr insert)
		{
			var il = body.GetILProcessor ();
			Instruction instInsertBefore;
			if (remove != null) {
				var vInstExtent = new InstructionExtentVisitor (instructionLookup);
				vInstExtent.Visit (remove);
				instInsertBefore = vInstExtent.Instructions.Last ().Next;
				foreach (var instRemove in vInstExtent.Instructions) {
					il.Remove (instRemove);
				}
			} else {
				instInsertBefore = body.Instructions [0];
			}
			if (insert != null) {
				var compiler = new CompileVisitor (il, instructionLookup, inst => il.InsertBefore (instInsertBefore, inst));
				compiler.Visit (insert);
			}
		}
Пример #42
0
        private static MethodBody CloneMethodBody(MethodBody body, MethodDefinition source, MethodDefinition target)
        {
            var context = target.DeclaringType.Module;
            var nb = new MethodBody(target)
            {
                MaxStackSize = body.MaxStackSize,
                InitLocals = body.InitLocals,
                CodeSize = body.CodeSize
            };

            var worker = nb.GetILProcessor();

            foreach (var var in body.Variables)
                nb.Variables.Add(new VariableDefinition(
                    var.Name, FixTypeImport(context, source, target, var.VariableType)));

            foreach (var instr in body.Instructions)
            {
                var ni = new Instruction(instr.OpCode, OpCodes.Nop);

                switch (instr.OpCode.OperandType)
                {
                    case OperandType.InlineArg:
                    case OperandType.ShortInlineArg:
                        if (instr.Operand == body.ThisParameter)
                            ni.Operand = nb.ThisParameter;
                        else
                        {
                            var param = body.Method.Parameters.IndexOf((ParameterDefinition)instr.Operand);
                            ni.Operand = target.Parameters[param];
                        }
                        break;
                    case OperandType.InlineVar:
                    case OperandType.ShortInlineVar:
                        var var = body.Variables.IndexOf((VariableDefinition)instr.Operand);
                        ni.Operand = nb.Variables[var];
                        break;
                    case OperandType.InlineField:
                        ni.Operand = FixFieldImport(context, source, target, (FieldReference)instr.Operand);
                        break;
                    case OperandType.InlineMethod:
                        ni.Operand = FixMethodImport(context, source, target, (MethodReference)instr.Operand);
                        break;
                    case OperandType.InlineType:
                        ni.Operand = FixTypeImport(context, source, target, (TypeReference)instr.Operand);
                        break;
                    case OperandType.InlineTok:
                        if ((instr.Operand) is TypeReference)
                            ni.Operand = FixTypeImport(context, source, target, (TypeReference)instr.Operand);
                        else if ((instr.Operand) is FieldReference)
                            ni.Operand = FixFieldImport(context, source, target, (FieldReference)instr.Operand);
                        else if ((instr.Operand) is MethodReference)
                            ni.Operand = FixMethodImport(context, source, target, (MethodReference)instr.Operand);
                        break;
                    case OperandType.ShortInlineBrTarget:
                    case OperandType.InlineBrTarget:
                    case OperandType.InlineSwitch:
                        break;
                    default:
                        ni.Operand = instr.Operand;
                        break;
                }

                worker.Append(ni);
            }

            for (var i = 0; i < body.Instructions.Count; i++)
            {
                var instr = nb.Instructions[i];
                var oldi = body.Instructions[i];

                switch (instr.OpCode.OperandType)
                {
	                case OperandType.InlineSwitch:
	                {
		                var olds = (Instruction[])oldi.Operand;
		                var targets = new Instruction[olds.Length];

		                for (var j = 0; j < targets.Length; j++)
			                targets[j] = GetInstruction(body, nb, olds[j]);

		                instr.Operand = targets;
	                }
		                break;
	                case OperandType.InlineBrTarget:
	                case OperandType.ShortInlineBrTarget:
		                instr.Operand = GetInstruction(body, nb, (Instruction)oldi.Operand);
		                break;
                }
            }

            foreach (var eh in body.ExceptionHandlers)
            {
                var neh = new ExceptionHandler(eh.HandlerType)
				{
					TryStart = GetInstruction(body, nb, eh.TryStart),
					TryEnd = GetInstruction(body, nb, eh.TryEnd),
					HandlerStart = GetInstruction(body, nb, eh.HandlerStart),
					HandlerEnd = GetInstruction(body, nb, eh.HandlerEnd)
				};

                switch (eh.HandlerType)
                {
                    case ExceptionHandlerType.Catch:
                        neh.CatchType = FixTypeImport(context, source, target, eh.CatchType);
                        break;
                    case ExceptionHandlerType.Filter:
                        neh.FilterStart = GetInstruction(body, nb, eh.FilterStart);
                        break;
                }

                nb.ExceptionHandlers.Add(neh);
            }

            return nb;
        }
Пример #43
0
        /// <summary>
        /// Generates the xor decryption method.
        /// </summary>
        /// <param name="assembly">The assembly.</param>
        /// <param name="body">The body.</param>
        private static void GenerateXorDecryptionMethod(AssemblyDefinition assembly, MethodBody body)
        {
            var worker = body.GetILProcessor();

            //Generate the decryption method
            //Since this is XOR it is the same as the encryption method
            //In reality its a bit of a joke calling this encryption as its really
            //just obfusaction
            /*
                char[] characters = value.ToCharArray();
                for (int i = 0; i < characters.Length; i++)
                {
                    characters[i] = (char)(characters[i] ^ salt);
                }
                return new String(characters);
             */
            
            //Declare a local to store the char array
            body.InitLocals = true;
            body.Method.AddLocal(typeof(char[]));
            body.Method.AddLocal(typeof(int));
            body.Method.AddLocal(typeof(string));
            body.Method.AddLocal(typeof(bool));
            
            //Start with a nop
            worker.Append(worker.Create(OpCodes.Nop));

            //Load the first argument into the register
            Instruction ldArg0 = worker.Create(OpCodes.Ldarg_0);
            worker.Append(ldArg0);

            //Call ToCharArray on this -- need to find it first
            var toCharArrayMethodRef = assembly.Import(typeof(string).GetMethod("ToCharArray", Type.EmptyTypes));
            //Import the method first
            toCharArrayMethodRef = body.ImportMethod(toCharArrayMethodRef);
            Instruction toCharArray = worker.Create(OpCodes.Callvirt, toCharArrayMethodRef);
            worker.Append(toCharArray);
            //Store it in the first local
            Instruction stLoc0 = worker.Create(OpCodes.Stloc_0);
            worker.Append(stLoc0);

            //Set up the loop
            worker.Append(worker.Create(OpCodes.Ldc_I4_0));
            Instruction stLoc1 = worker.Create(OpCodes.Stloc_1);
            worker.Append(stLoc1);
            
            //We'll insert a br.s here later....

            //Insert another nop and do the rest of our loop
            Instruction loopNop = worker.Create(OpCodes.Nop);
            worker.Append(loopNop);
            worker.Append(worker.Create(OpCodes.Ldloc_0));
            worker.Append(worker.Create(OpCodes.Ldloc_1));
            worker.Append(worker.Create(OpCodes.Ldloc_0));
            worker.Append(worker.Create(OpCodes.Ldloc_1));
            worker.Append(worker.Create(OpCodes.Ldelem_U2)); //Load the array
            worker.Append(worker.Create(OpCodes.Ldarg_1));
            worker.Append(worker.Create(OpCodes.Xor)); //Do the xor
            worker.Append(worker.Create(OpCodes.Conv_U2));
            worker.Append(worker.Create(OpCodes.Stelem_I2)); //Store back in the array
            worker.Append(worker.Create(OpCodes.Nop));
            worker.Append(worker.Create(OpCodes.Ldloc_1));
            worker.Append(worker.Create(OpCodes.Ldc_I4_1));
            worker.Append(worker.Create(OpCodes.Add));
            worker.Append(worker.Create(OpCodes.Stloc_1));
            Instruction ldLoc = worker.Create(OpCodes.Ldloc_1);
            worker.Append(ldLoc);
            //Link to this line from an earlier statement
            worker.InsertAfter(stLoc1, worker.Create(OpCodes.Br_S, ldLoc));
            worker.Append(worker.Create(OpCodes.Ldloc_0));
            worker.Append(worker.Create(OpCodes.Ldlen));
            worker.Append(worker.Create(OpCodes.Conv_I4));
            worker.Append(worker.Create(OpCodes.Clt)); //i < array.Length
            worker.Append(worker.Create(OpCodes.Stloc_3));
            worker.Append(worker.Create(OpCodes.Ldloc_3));
            worker.Append(worker.Create(OpCodes.Brtrue_S, loopNop)); //Do the loop

            //Return a new string
            worker.Append(worker.Create(OpCodes.Ldloc_0));
            //Find the constructor we want to use
            MethodReference constructor = assembly.Import(typeof(string).GetConstructor(new [] { typeof(char[])}));
            constructor = body.ImportMethod(constructor);
            worker.Append(worker.Create(OpCodes.Newobj, constructor));
            Instruction stloc2 = worker.Create(OpCodes.Stloc_2);
            worker.Append(stloc2);
            Instruction ldloc2 = worker.Create(OpCodes.Ldloc_2);
            worker.Append(ldloc2);
            worker.InsertAfter(stloc2, worker.Create(OpCodes.Br_S, ldloc2));
            worker.Append(worker.Create(OpCodes.Ret));
        }
Пример #44
0
        public void UnattachedMethodBody()
        {
            var system_void = typeof (void).ToDefinition ();
            var method = new MethodDefinition ("NewMethod", MethodAttributes.Assembly | MethodAttributes.Static, system_void);
            var body = new MethodBody (method);
            var il = body.GetILProcessor ();
            il.Emit (OpCodes.Ret);
            method.Body = body;

            Assert.AreEqual (body, method.Body);
        }
Пример #45
0
        private void WeaveDependencyProperty(MethodBody staticCtorBody, FieldReference field, PropertyDefinition property)
        {
            var assembly = property.DeclaringType.Module.Assembly;
            var propertyType = assembly.ImportType(Type.GetType(property.PropertyType.FullName));
            var getTypeFromHandle = assembly.ImportMethod(typeof(Type).GetMethod("GetTypeFromHandle"));
            var register = assembly.ImportMethod(typeof(DependencyProperty).GetMethod("Register", new[] { typeof(string), typeof(Type), typeof(Type) }));

            // ignore previously weaved DPs
            if (staticCtorBody.Instructions.Any(i => i.Operand != null && i.Operand.ToString() == field.ToString()))
            {
                return;
            }

            var ret = staticCtorBody.Instructions.Last();
            if (ret.OpCode != OpCodes.Ret)
                throw new InvalidOperationException("The last instruction should be OpCode.Ret");

            HasChanges = true;

            var proc = staticCtorBody.GetILProcessor();
            proc.InsertBefore(ret, proc.Create(OpCodes.Ldstr, property.Name));
            proc.InsertBefore(ret, proc.Create(OpCodes.Ldtoken, propertyType));
            proc.InsertBefore(ret, proc.Create(OpCodes.Call, getTypeFromHandle));
            proc.InsertBefore(ret, proc.Create(OpCodes.Ldtoken, property.DeclaringType));
            proc.InsertBefore(ret, proc.Create(OpCodes.Call, getTypeFromHandle));
            proc.InsertBefore(ret, proc.Create(OpCodes.Call, register));
            proc.InsertBefore(ret, proc.Create(OpCodes.Stsfld, field));
        }
Пример #46
0
 public IlBuilder(MethodBody body)
 {
     _body    = body;
     this._il = body.GetILProcessor();
     _list    = new List <Instruction>();
 }
Пример #47
0
        //TODO: move this out of here
        public virtual Instruction Create(MethodBody methodBody, ModuleDefinition moduleDefinition)
        {
            object operand = 0;
            Instruction instruction = null;
            var processor = methodBody.GetILProcessor();

            switch (OpCode.OperandType)
            {
                case OperandType.ShortInlineR:
                    {
                        float parsedOpcode = 0.0f;

                        if (_operandSrc != null)
                        {
                            if (_operandSrc is string)
                            {
                                float.TryParse((string)_operandSrc, out parsedOpcode);
                            }
                            else if (_operandSrc is float)
                            {
                                parsedOpcode =(float)_operandSrc;
                            }
                        }

                        instruction = processor.Create(OpCode, parsedOpcode);
                        break;
                    }

                case OperandType.ShortInlineVar:
                case OperandType.InlineVar:
                    {
                        VariableDefinition variable = null;

                        if (_operandSrc != null)
                        {
                            if (_operandSrc is string)
                            {
                                int tempN = 0;
                                if (int.TryParse((string) _operandSrc, out tempN)) //deserialised ints come in as strings
                                {
                                    variable = methodBody.Variables[tempN];
                                }
                                else
                                {
                                    variable = methodBody.Variables.First(v => v.Name == (string) _operandSrc);
                                }
                            }
                            else if (_operandSrc is int || _operandSrc is short)
                            {
                                variable = methodBody.Variables[(int) _operandSrc];
                            }
                        }

                        instruction = processor.Create(OpCode, variable);
                        break;
                    }
                case OperandType.InlineMethod:
                    {
                        MethodReference method = CodeHelper.ResolveMethod(moduleDefinition, _operandSrc.ToString());

                        if (method == null)
                        {
                            Debug.WriteLine("Method {0} can't be resolved yet. Postponing.", _operandSrc.ToString());
                            instruction = processor.CreateUnsafe(OpCode, _operandSrc);
                            instruction.ResolveOperand = (ins) => CodeHelper.ResolveMethod(moduleDefinition, _operandSrc.ToString());
                        }
                        else
                        {
                            instruction = processor.Create(OpCode, method);
                        }
                    }
                    break;

                case OperandType.InlineString:
                    instruction = processor.Create(OpCode, _operandSrc.ToString());
                    break;

                case OperandType.InlineBrTarget:
                case OperandType.ShortInlineBrTarget:

                    if (_operandSrc == null)
                    {
                        throw new ApplicationException("invalid codeline");
                    }
                    instruction = processor.CreateUnsafe(OpCode, _operandSrc);
                    instruction.ResolveOperand = (ins) =>
                                                     {
                                                         //Debug.Assert(_operandSrc != "GOTO_ENDHW");
                                                         var resolved = processor.Body.Instructions.FirstOrDefault(i => !string.IsNullOrEmpty(i.Label) && i.Label == (string) _operandSrc);
                                                         if (resolved == null)
                                                         {
                                                             throw new ApplicationException("Unresolved break target");
                                                         }
                                                         return resolved;
                                                     };

                    break;

                case OperandType.InlineNone:
                    instruction = processor.Create(OpCode);
                    break;

                case OperandType.InlineField:
                    {
                        var names = _operandSrc.ToString().Split(new[] {" ", "::"}, 3, StringSplitOptions.RemoveEmptyEntries);

                        TypeReference foundType = CodeHelper.ResolveType(moduleDefinition, names[1]);

                        var typeDef = (TypeDefinition) (foundType is TypeDefinition ? foundType : foundType.Resolve());

                        FieldReference fieldReference = typeDef.Fields.FirstOrDefault(f => f.FullName == _operandSrc.ToString());

                        var importedRef = moduleDefinition.Import(fieldReference);

                        if (fieldReference == null)
                        {
                            throw new ApplicationException(String.Format("Field {0} not found", _operandSrc));
                        }
                        instruction = processor.Create(OpCode, importedRef);
                    }
                    break;

                default:
                    instruction = processor.CreateUnsafe(OpCode, _operandSrc);
                    break;
            }

            instruction.Label = Label;
            return instruction;
        }
Пример #48
0
        public static MethodDefinition Inject(ModuleDefinition mod, MethodDefinition mtd)
        {
            MethodDefinition ret = new MethodDefinition(mtd.Name, mtd.Attributes, mod.TypeSystem.Void);
            ret.Attributes = mtd.Attributes;
            ret.ImplAttributes = mtd.ImplAttributes;

            if (mtd.IsPInvokeImpl)
            {
                ret.PInvokeInfo = mtd.PInvokeInfo;
                bool has = false;
                foreach (ModuleReference modRef in mod.ModuleReferences)
                    if (modRef.Name == ret.PInvokeInfo.Module.Name)
                    {
                        has = true;
                        ret.PInvokeInfo.Module = modRef;
                        break;
                    }
                if (!has)
                    mod.ModuleReferences.Add(ret.PInvokeInfo.Module);
            }
            if (mtd.HasCustomAttributes)
            {
                foreach (CustomAttribute attr in mtd.CustomAttributes)
                {
                    CustomAttribute nAttr = new CustomAttribute(ImportMethod(attr.Constructor, mod, ret, null), attr.GetBlob());
                    ret.CustomAttributes.Add(nAttr);
                }
            }

            foreach (GenericParameter param in mtd.GenericParameters)
            {
                var p = new GenericParameter(param.Name, ret);
                if (param.HasCustomAttributes)
                {
                    foreach (CustomAttribute attr in param.CustomAttributes)
                    {
                        CustomAttribute nAttr = new CustomAttribute(ImportMethod(attr.Constructor, mod, ret, null), attr.GetBlob());
                        p.CustomAttributes.Add(nAttr);
                    }
                }
                ret.GenericParameters.Add(p);
            }

            ret.ReturnType = ImportType(mtd.ReturnType, mod, ret, null);

            foreach (ParameterDefinition param in mtd.Parameters)
            {
                var p = new ParameterDefinition(param.Name, param.Attributes, ImportType(param.ParameterType, mod, ret, null));
                if (param.HasCustomAttributes)
                {
                    foreach (CustomAttribute attr in param.CustomAttributes)
                    {
                        CustomAttribute nAttr = new CustomAttribute(ImportMethod(attr.Constructor, mod, ret, null), attr.GetBlob());
                        p.CustomAttributes.Add(nAttr);
                    }
                }
                ret.Parameters.Add(p);
            }

            if (mtd.HasBody)
            {
                MethodBody old = mtd.Body;
                MethodBody bdy = new MethodBody(ret);
                bdy.MaxStackSize = old.MaxStackSize;
                bdy.InitLocals = old.InitLocals;

                ILProcessor psr = bdy.GetILProcessor();

                foreach (VariableDefinition var in old.Variables)
                    bdy.Variables.Add(new VariableDefinition(var.Name, ImportType(var.VariableType, mod, ret, null)));

                foreach (Instruction inst in old.Instructions)
                {
                    switch (inst.OpCode.OperandType)
                    {
                        case OperandType.InlineArg:
                        case OperandType.ShortInlineArg:
                            if (inst.Operand == old.ThisParameter)
                                psr.Emit(inst.OpCode, bdy.ThisParameter);
                            else
                            {
                                int param = mtd.Parameters.IndexOf(inst.Operand as ParameterDefinition);
                                psr.Emit(inst.OpCode, ret.Parameters[param]);
                            }
                            break;
                        case OperandType.InlineVar:
                        case OperandType.ShortInlineVar:
                            int var = old.Variables.IndexOf(inst.Operand as VariableDefinition);
                            psr.Emit(inst.OpCode, bdy.Variables[var]);
                            break;
                        case OperandType.InlineField:
                            psr.Emit(inst.OpCode, ImportField(inst.Operand as FieldReference, mod, null));
                            break;
                        case OperandType.InlineMethod:
                            if (inst.Operand == mtd)
                                psr.Emit(inst.OpCode, ret);
                            else
                                psr.Emit(inst.OpCode, ImportMethod(inst.Operand as MethodReference, mod, ret, null));
                            break;
                        case OperandType.InlineType:
                            psr.Emit(inst.OpCode, ImportType(inst.Operand as TypeReference, mod, ret, null));
                            break;
                        case OperandType.InlineTok:
                            if (inst.Operand is TypeReference)
                                psr.Emit(inst.OpCode, ImportType(inst.Operand as TypeReference, mod, ret, null));
                            else if (inst.Operand is FieldReference)
                                psr.Emit(inst.OpCode, ImportField(inst.Operand as FieldReference, mod, null));
                            else if (inst.Operand is MethodReference)
                                psr.Emit(inst.OpCode, ImportMethod(inst.Operand as MethodReference, mod, ret, null));
                            break;
                        default:
                            psr.Append(inst.Clone());
                            break;
                    }
                }

                for (int i = 0; i < bdy.Instructions.Count; i++)
                {
                    Instruction inst = bdy.Instructions[i];
                    Instruction o = old.Instructions[i];

                    if (inst.OpCode.OperandType == OperandType.InlineSwitch)
                    {
                        Instruction[] olds = (Instruction[])o.Operand;
                        Instruction[] news = new Instruction[olds.Length];

                        for (int ii = 0; ii < news.Length; ii++)
                            news[ii] = bdy.Instructions[old.Instructions.IndexOf(olds[ii])];

                        inst.Operand = news;
                    }
                    else if (inst.OpCode.OperandType == OperandType.ShortInlineBrTarget || inst.OpCode.OperandType == OperandType.InlineBrTarget)
                        inst.Operand = bdy.Instructions[old.Instructions.IndexOf(inst.Operand as Instruction)];
                }

                foreach (ExceptionHandler eh in old.ExceptionHandlers)
                {
                    ExceptionHandler neh = new ExceptionHandler(eh.HandlerType);
                    if (old.Instructions.IndexOf(eh.TryStart) != -1)
                        neh.TryStart = bdy.Instructions[old.Instructions.IndexOf(eh.TryStart)];
                    if (old.Instructions.IndexOf(eh.TryEnd) != -1)
                        neh.TryEnd = bdy.Instructions[old.Instructions.IndexOf(eh.TryEnd)];
                    if (old.Instructions.IndexOf(eh.HandlerStart) != -1)
                        neh.HandlerStart = bdy.Instructions[old.Instructions.IndexOf(eh.HandlerStart)];
                    if (old.Instructions.IndexOf(eh.HandlerEnd) != -1)
                        neh.HandlerEnd = bdy.Instructions[old.Instructions.IndexOf(eh.HandlerEnd)];

                    switch (eh.HandlerType)
                    {
                        case ExceptionHandlerType.Catch:
                            neh.CatchType = ImportType(eh.CatchType, mod, ret, null);
                            break;
                        case ExceptionHandlerType.Filter:
                            neh.FilterStart = bdy.Instructions[old.Instructions.IndexOf(eh.FilterStart)];
                            //neh.FilterEnd = bdy.Instructions[old.Instructions.IndexOf(eh.FilterEnd)];
                            break;
                    }

                    bdy.ExceptionHandlers.Add(neh);
                }

                ret.Body = bdy;
            }

            return ret;
        }
Пример #49
0
        //protected override void InjectAdditionalInstructionBeforeStartCall(Mono.Cecil.Cil.MethodBody body, Mono.Cecil.Cil.Instruction call)
        //{
        //    Instruction pickMyself = body.GetILProcessor().Create(OpCodes.Ldarg_0);
        //    body.GetILProcessor().InsertBefore(call, pickMyself);
        //}

        protected override void InjectAdditionalInstructionAfterStartCall(Mono.Cecil.Cil.MethodBody body, Mono.Cecil.Cil.Instruction call)
        {
            var ret = body.GetILProcessor().Create(OpCodes.Ret);

            body.GetILProcessor().InsertAfter(call, ret);
        }
        public override void ProcessType(TypeDefinition type)
        {
            if (!type.Is ("ObjCRuntime", "RuntimeOptions"))
                return;

            MethodDefinition method = type.Methods.First (x => x.Name == "GetHttpMessageHandler" && !x.HasParameters);

            AssemblyDefinition systemNetHTTPAssembly = context.GetAssemblies ().First (x => x.Name.Name == "System.Net.Http");
            TypeDefinition handler = RuntimeOptions.GetHttpMessageHandler (Options.RuntimeOptions, systemNetHTTPAssembly.MainModule, type.Module);
            MethodReference handler_ctor = handler.Methods.First (x => x.IsConstructor && !x.HasParameters && !x.IsStatic);

            // HttpClientHandler is defined not in Xamarin.Mac.dll so we need to import
            if (handler.Name.Contains ("HttpClientHandler"))
                handler_ctor = type.Module.Import (handler_ctor);

            var body = new MethodBody (method);
            var il = body.GetILProcessor ();
            il.Emit (OpCodes.Newobj, handler_ctor);
            il.Emit (OpCodes.Ret);
            method.Body = body;
        }
Пример #51
0
        private static void FoldAndReplace(
            ref Dictionary<KeyValuePair<int, int>, ExInstruction> markings,
            ref MethodBody body)
        {
            var instrList = body.Instructions;
            var foldedBody = new Collection<Instruction>();

            foreach(var marking in markings)
            {
                for(var i = 0;i < instrList.Count;i++)
                {
                    if(marking.Key.Key == i)
                    {
                        for (var x = 0; x < marking.Key.Value +1; x++)
                            instrList.RemoveAt(marking.Key.Key -2);

                        switch(marking.Value.OpCode.Code)
                        {
                            case Code.Ldc_I4:
                                instrList.Insert(marking.Key.Key -3,
                                                 body.GetILProcessor().Create(OpCodes.Ldc_I4, (int)marking.Value.Value));
                                break;

                            case Code.Ldc_I8:
                                instrList.Insert(marking.Key.Key -3,
                                                 body.GetILProcessor().Create(OpCodes.Ldc_I8, (long)marking.Value.Value));
                                break;
                        }

                        break;
                    }
                }
            }

            body.Instructions.Clear();

            //body.SimplifyMacros();

            var ilProc = body.GetILProcessor();

            foreach (var instr in instrList)
                ilProc.Append(instr);

            //body.OptimizeMacros();//it can't resolve the tokens from rocks
        }
        public override void ProcessType(TypeDefinition type)
        {
            #if XAMARIN_NO_TLS
            return;
            #else
            if (!type.Is (Namespaces.ObjCRuntime, "Runtime"))
                return;

            MethodDefinition callbackMethod = null;

            foreach (var m in type.Methods) {
                if (!m.IsStatic || m.HasParameters)
                    continue;
                if (m.Name.Equals ("TlsProviderFactoryCallback", StringComparison.Ordinal)) {
                    callbackMethod = m;
                    break;
                }
            }

            if (callbackMethod == null)
                throw new Exception ("Could not set the default TlsProvider");

            var providerCtor = FindProviderConstructor (type.Module);
            if (providerCtor == null)
                return;

            // re-write TlsProviderFactoryCallback()
            var body = new MethodBody (callbackMethod);
            var il = body.GetILProcessor ();
            if (providerCtor != null)
                il.Emit (OpCodes.Newobj, providerCtor);
            else
                il.Emit (OpCodes.Ldnull);
            il.Emit (OpCodes.Ret);
            callbackMethod.Body = body;
            #endif
        }
Пример #53
0
        public void PatchModifications()
        {
            foreach (XElement classNode in mModifications.Elements("Class"))
            {
                // We load the class in which the modifications will take place
                string         nameTypeToPatch = classNode.Attribute("Name").Value;
                TypeDefinition typeToPatch     = GetAssembly("Assembly-CSharp").MainModule.Types.FirstOrDefault(t => t.Name == nameTypeToPatch);

                if (typeToPatch == null)
                {
                    MessageBox.Show("Couldn't find type/class named" + nameTypeToPatch, "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    continue;
                }

                foreach (XElement methodNode in classNode.Elements("Method"))
                {
                    string           nameMethodTopatch = methodNode.Attribute("Name").Value;
                    MethodDefinition methodToPatch     = typeToPatch.Methods.FirstOrDefault(m => m.Name == nameMethodTopatch);

                    if (methodToPatch == null)
                    {
                        MessageBox.Show("Couldn't find method named" + nameMethodTopatch, "Error!", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        continue;
                    }

                    Mono.Cecil.Cil.MethodBody methodBody = methodToPatch.Body;

                    ILProcessor processor = methodBody.GetILProcessor();

                    // By default, we place the modification just before the "ret" instruction
                    // (i.e. before the last instruction)
                    int indexBegin = methodToPatch.Body.Instructions.Count - 1;

                    // But, if the user specified a location, we place the modification there
                    if (methodNode.Attribute("Location") != null)
                    {
                        indexBegin = int.Parse(methodNode.Attribute("Location").Value);
                    }

                    // If the user specified a count of instructions to delete,
                    // we delete them
                    if (methodNode.Attribute("DeleteCount") != null)
                    {
                        int countInstrToDelete = int.Parse(methodNode.Attribute("DeleteCount").Value);

                        for (int i = 0; i < countInstrToDelete; i++)
                        {
                            processor.Remove(methodToPatch.Body.Instructions.ElementAt(indexBegin));
                        }
                    }

                    Instruction locationInstr = methodToPatch.Body.Instructions.ElementAt(indexBegin);
                    Instruction prevInstr     = locationInstr.Previous;

                    foreach (XElement instrNode in methodNode.Elements("Instruction"))
                    {
                        Instruction instr = Call.ParseInstruction(processor, typeToPatch, instrNode);
                        //MessageBox.Show(instr.ToString());
                        if (instr == null)
                        {
                            continue;
                        }

                        if (prevInstr == null)
                        {
                            processor.InsertBefore(locationInstr, instr);
                        }
                        else
                        {
                            processor.InsertAfter(prevInstr, instr);
                        }

                        prevInstr = instr;
                    }

                    // Optimize the method
                    methodToPatch.Body.OptimizeMacros();
                }
            }
        }
        private void _CopyMethodToDefinition()
        {
            MethodBase method     = OriginalMethod;
            Module     moduleFrom = method.Module;

            System.Reflection.MethodBody bodyFrom = method.GetMethodBody();
            byte[] data = bodyFrom?.GetILAsByteArray();
            if (data == null)
            {
                throw new NotSupportedException("Body-less method");
            }

            MethodDefinition def      = Definition;
            ModuleDefinition moduleTo = def.Module;

            Mono.Cecil.Cil.MethodBody bodyTo = def.Body;
            ILProcessor processor            = bodyTo.GetILProcessor();

            Type[] typeArguments = null;
            if (method.DeclaringType.IsGenericType)
            {
                typeArguments = method.DeclaringType.GetGenericArguments();
            }

            Type[] methodArguments = null;
            if (method.IsGenericMethod)
            {
                methodArguments = method.GetGenericArguments();
            }

            foreach (LocalVariableInfo info in bodyFrom.LocalVariables)
            {
                TypeReference type = moduleTo.ImportReference(info.LocalType);
                if (info.IsPinned)
                {
                    type = new PinnedType(type);
                }
                bodyTo.Variables.Add(new VariableDefinition(type));
            }

            using (BinaryReader reader = new BinaryReader(new MemoryStream(data))) {
                for (Instruction instr = null, prev = null; reader.BaseStream.Position < reader.BaseStream.Length; prev = instr)
                {
                    int offset = (int)reader.BaseStream.Position;
                    instr = Instruction.Create(OpCodes.Nop);
                    byte op = reader.ReadByte();
                    instr.OpCode = op != 0xfe ? _CecilOpCodes1X[op] : _CecilOpCodes2X[reader.ReadByte()];
                    instr.Offset = offset;
                    if (prev != null)
                    {
                        prev.Next = instr;
                    }
                    instr.Previous = prev;
                    ReadOperand(reader, instr);
                    bodyTo.Instructions.Add(instr);
                }
            }

            foreach (Instruction instr in bodyTo.Instructions)
            {
                switch (instr.OpCode.OperandType)
                {
                case OperandType.ShortInlineBrTarget:
                case OperandType.InlineBrTarget:
                    instr.Operand = GetInstruction((int)instr.Operand);
                    break;

                case OperandType.InlineSwitch:
                    int[]         offsets = (int[])instr.Operand;
                    Instruction[] targets = new Instruction[offsets.Length];
                    for (int i = 0; i < offsets.Length; i++)
                    {
                        targets[i] = GetInstruction(offsets[i]);
                    }
                    instr.Operand = targets;
                    break;
                }
            }

            foreach (ExceptionHandlingClause clause in bodyFrom.ExceptionHandlingClauses)
            {
                ExceptionHandler handler = new ExceptionHandler((ExceptionHandlerType)clause.Flags);
                bodyTo.ExceptionHandlers.Add(handler);

                handler.TryStart = GetInstruction(clause.TryOffset);
                handler.TryEnd   = GetInstruction(clause.TryOffset + clause.TryLength);

                handler.FilterStart  = handler.HandlerType != ExceptionHandlerType.Filter ? null : GetInstruction(clause.FilterOffset);
                handler.HandlerStart = GetInstruction(clause.HandlerOffset);
                handler.HandlerEnd   = GetInstruction(clause.HandlerOffset + clause.HandlerLength);

                handler.CatchType = handler.HandlerType != ExceptionHandlerType.Catch ? null : clause.CatchType == null ? null : moduleTo.ImportReference(clause.CatchType);
            }

            void ReadOperand(BinaryReader reader, Instruction instr)
            {
                int index, offs, length;

                switch (instr.OpCode.OperandType)
                {
                case OperandType.InlineNone:
                    instr.Operand = null;
                    break;

                case OperandType.InlineSwitch:
                    length = reader.ReadInt32();
                    offs   = (int)reader.BaseStream.Position + (4 * length);
                    int[] targets = new int[length];
                    for (int i = 0; i < length; i++)
                    {
                        targets[i] = reader.ReadInt32() + offs;
                    }
                    instr.Operand = targets;
                    break;

                case OperandType.ShortInlineBrTarget:
                    offs          = reader.ReadSByte();
                    instr.Operand = (int)reader.BaseStream.Position + offs;
                    break;

                case OperandType.InlineBrTarget:
                    offs          = reader.ReadInt32();
                    instr.Operand = (int)reader.BaseStream.Position + offs;
                    break;

                case OperandType.ShortInlineI:
                    instr.Operand = instr.OpCode == OpCodes.Ldc_I4_S ? reader.ReadSByte() : (object)reader.ReadByte();
                    break;

                case OperandType.InlineI:
                    instr.Operand = reader.ReadInt32();
                    break;

                case OperandType.ShortInlineR:
                    instr.Operand = reader.ReadSingle();
                    break;

                case OperandType.InlineR:
                    instr.Operand = reader.ReadDouble();
                    break;

                case OperandType.InlineI8:
                    instr.Operand = reader.ReadInt64();
                    break;

                case OperandType.InlineSig:
                    instr.Operand = moduleTo.ImportCallSite(moduleFrom, moduleFrom.ResolveSignature(reader.ReadInt32()));
                    break;

                case OperandType.InlineString:
                    instr.Operand = moduleFrom.ResolveString(reader.ReadInt32());
                    break;

                case OperandType.InlineTok:
                    instr.Operand = ResolveTokenAs(reader.ReadInt32(), TokenResolutionMode.Any);
                    break;

                case OperandType.InlineType:
                    instr.Operand = ResolveTokenAs(reader.ReadInt32(), TokenResolutionMode.Type);
                    break;

                case OperandType.InlineMethod:
                    instr.Operand = ResolveTokenAs(reader.ReadInt32(), TokenResolutionMode.Method);
                    break;

                case OperandType.InlineField:
                    instr.Operand = ResolveTokenAs(reader.ReadInt32(), TokenResolutionMode.Field);
                    break;

                case OperandType.ShortInlineVar:
                case OperandType.InlineVar:
                    index         = instr.OpCode.OperandType == OperandType.ShortInlineVar ? reader.ReadByte() : reader.ReadInt16();
                    instr.Operand = bodyTo.Variables[index];
                    break;

                case OperandType.InlineArg:
                case OperandType.ShortInlineArg:
                    index         = instr.OpCode.OperandType == OperandType.ShortInlineArg ? reader.ReadByte() : reader.ReadInt16();
                    instr.Operand = def.Parameters[index];
                    break;

                case OperandType.InlinePhi:     // No opcode seems to use this
                default:
                    throw new NotSupportedException($"Unsupported opcode ${instr.OpCode.Name}");
                }
            }

            MemberReference ResolveTokenAs(int token, TokenResolutionMode resolveMode)
            {
                try {
                    switch (resolveMode)
                    {
                    case TokenResolutionMode.Type:
                        return(moduleTo.ImportReference(moduleFrom.ResolveType(token, typeArguments, methodArguments)));

                    case TokenResolutionMode.Method:
                        return(moduleTo.ImportReference(moduleFrom.ResolveMethod(token, typeArguments, methodArguments)));

                    case TokenResolutionMode.Field:
                        return(moduleTo.ImportReference(moduleFrom.ResolveField(token, typeArguments, methodArguments)));

                    case TokenResolutionMode.Any:
                        switch (moduleFrom.ResolveMember(token, typeArguments, methodArguments))
                        {
                        case Type i:
                            return(moduleTo.ImportReference(i));

                        case MethodBase i:
                            return(moduleTo.ImportReference(i));

                        case FieldInfo i:
                            return(moduleTo.ImportReference(i));

                        case var resolved:
                            throw new NotSupportedException($"Invalid resolved member type {resolved.GetType()}");
                        }

                    default:
                        throw new NotSupportedException($"Invalid TokenResolutionMode {resolveMode}");
                    }
                } catch (MissingMemberException) {
                    // we could not resolve the method normally, so lets read the import table
                    // but we can only do that if the module was loaded from disk
                    // this can still throw if the assembly is a dynamic one, but if that's broken, you have bigger issues
                    string filePath = moduleFrom.Assembly.Location;
                    if (!File.Exists(filePath))
                    {
                        // in this case, the fallback cannot be followed, and so throwing the original error gives the user information
                        throw;
                    }

                    // TODO: make this cached somehow so its not read and re-opened a bunch
                    using (AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly(filePath, new ReaderParameters {
                        ReadingMode = ReadingMode.Deferred
                    })) {
                        ModuleDefinition module = assembly.Modules.First(m => m.Name == moduleFrom.Name);
                        // this should only fail if the token itself is somehow wrong
                        MemberReference reference = (MemberReference)module.LookupToken(token);
                        // the explicit casts here are to throw if they are incorrect
                        // normally the references would need to be imported, but moduleTo isn't written to anywhere
                        switch (resolveMode)
                        {
                        case TokenResolutionMode.Type:
                            return((TypeReference)reference);

                        case TokenResolutionMode.Method:
                            return((MethodReference)reference);

                        case TokenResolutionMode.Field:
                            return((FieldReference)reference);

                        case TokenResolutionMode.Any:
                            return(reference);

                        default:
                            throw new NotSupportedException($"Invalid TokenResolutionMode {resolveMode}");
                        }
                    }
                }
            }

            Instruction GetInstruction(int offset)
            {
                int last = bodyTo.Instructions.Count - 1;

                if (offset < 0 || offset > bodyTo.Instructions[last].Offset)
                {
                    return(null);
                }

                int min = 0;
                int max = last;

                while (min <= max)
                {
                    int         mid   = min + ((max - min) / 2);
                    Instruction instr = bodyTo.Instructions[mid];

                    if (offset == instr.Offset)
                    {
                        return(instr);
                    }

                    if (offset < instr.Offset)
                    {
                        max = mid - 1;
                    }
                    else
                    {
                        min = mid + 1;
                    }
                }

                return(null);
            }
        }