Trace() public static method

public static Trace ( string line ) : void
line string
return void
Esempio n. 1
0
        public DynamicMethod RecompileMethod(Cecil.MethodDefinition methodDef)
        {
            Debug.Trace("Recompiling method: {0}", methodDef.FullName);

            var declaringType = FindType(methodDef.DeclaringType);
            var returnType    = FindType(methodDef.ReturnType);

            Type[] paramTypes = methodDef.Parameters.Select((paramDef) => {
                return(FindType(paramDef.ParameterType));
            }).ToArray();

            if (!methodDef.IsStatic)
            {
                paramTypes = new Type[] { declaringType }.Concat(paramTypes).ToArray();
            }

            var         dynMethod = new DynamicMethod(methodDef.Name, returnType, paramTypes, true);
            ILGenerator il        = dynMethod.GetILGenerator();

            dynMethod.InitLocals = methodDef.Body.InitLocals;
            foreach (var variable in methodDef.Body.Variables)
            {
                var localType = FindType(variable.VariableType);
                Debug.Trace("Declaring local (cecil type: {0}) of type (runtime type: {1})", variable.VariableType, localType);
                il.DeclareLocal(localType);
            }

            var labels = new Dictionary <Cecil.Cil.Instruction, Label>();

            foreach (var inst in methodDef.Body.Instructions)
            {
                if (inst.Operand != null && inst.Operand.GetType() == typeof(Cecil.Cil.Instruction))
                {
                    var opinst = (Cecil.Cil.Instruction)(inst.Operand);
                    labels[opinst] = il.DefineLabel();
                }
            }

            foreach (var inst in Instrument.IterateInstructions(methodDef))
            {
                Debug.Trace("Emitting: {0}", inst);

                Label label;
                if (labels.TryGetValue(inst, out label))
                {
                    il.MarkLabel(label);
                }

                var ilop = FindOpcode(inst.OpCode);

                if (inst.Operand != null)
                {
                    var operand     = inst.Operand;
                    var operandType = operand.GetType();

                    // Dynamic dispatch implementation:

                    // We have to run different processing code depending on the type of instruction
                    // operand. Visitor pattern cannot be implemented here, because we don't actually
                    // own the classes that are the operands (and some of them are primitive or system
                    // types).

                    // Therefore, dynamic dispatcher is used. Method for each operand type is implemented
                    // in this class, and reflection is used to find correct method to call.

                    // In newer .net versions we would be able to do EmitInstruction(il, ilop, (dynamic)operand),
                    // but the .net version we are targeting (because of Unity compatibility) does not
                    // have `dynamic`.

                    if (operandType == typeof(Cecil.Cil.Instruction))
                    {
                        //branch location
                        var operandInst = (Cecil.Cil.Instruction)operand;

                        il.Emit(ilop, labels[operandInst]);
                    }
                    else if (primitiveOperandTypes.Contains(operandType))
                    {
                        //if operand is primitive, call il.Emit directly
                        Reflection.MethodInfo method;
                        if (!EmitPrimitiveCache.TryGetValue(operandType, out method))
                        {
                            method = typeof(ILGenerator).GetMethod("Emit", new Type[] { typeof(OpCode), operandType });
                            EmitPrimitiveCache[operandType] = method;
                        }

                        if (method == null)
                        {
                            throw new Exception(String.Format("Emit method for primitive type {0} not found.", operandType.Name));
                        }

                        method.Invoke(il, new object[] { ilop, operand });
                    }
                    else
                    {
                        //or else, call our EmitInstruction
                        Reflection.MethodInfo method;
                        if (!EmitInstructionCache.TryGetValue(operandType, out method))
                        {
                            method = GetType().GetMethod("EmitInstruction",
                                                         bindingAttr: bflags_all_instance,
                                                         binder: null,
                                                         modifiers: null,
                                                         types: new Type[] { typeof(ILGenerator), typeof(OpCode), operandType });
                            EmitInstructionCache[operandType] = method;
                        }

                        if (method == null)
                        {
                            throw new Exception(String.Format("Don't know what to do with operand {0}", operandType.Name));
                        }

                        method.Invoke(this, new object[] { il, ilop, operand });
                    }
                }
                else
                {
                    il.Emit(ilop);
                }
            }

            return(dynMethod);
        }
Esempio n. 2
0
        public void HotPatch(string assemblyFilename)
        {
            Debug.Trace("Started hotpatching {0}", assemblyFilename);

            var newAssembly = Cecil.AssemblyDefinition.ReadAssembly(assemblyFilename);

            foreach (var method in IterateMethods(newAssembly))
            {
                Debug.Trace($"Searching for {method.FullName}");
                LocalMethod localMethod;
                if (!localMethods.TryGetValue(method.FullName, out localMethod))
                {
                    Debug.Trace($"Did not find loaded method {method.FullName}. New method or a bug.");
                    continue;
                }

                string newBody     = ConcatBody(method);
                int    newBodyHash = newBody.GetHashCode();
                if (localMethod.BodyHashCode == newBody.GetHashCode())
                {
                    Debug.Trace($"Found {method.FullName}, but hash code didn't change.");
                    continue;
                }

                string oldBody = localMethod.BodyString;

                Debug.Log($"<i>Trying to hotpatch {method.FullName}...</i>");

                if (localMethod.Method == null)
                {
                    Debug.Log($"Can't hotpatch {method.FullName} - local method not found,");
                    continue;
                }

                Debug.Trace("----------");

                Debug.Trace("Hotswapping {0}", method.FullName);
                Debug.Trace("Method body hashcode was: {0}, is: {1}", localMethod.BodyHashCode, newBodyHash);

                Debug.Trace("Method body was:");
                Debug.Trace(oldBody);

                Debug.Trace("Method body is:");
                Debug.Trace(newBody);

                try {
                    var dynmethod = recompiler.RecompileMethod(method);
                    if (dynmethod != null)
                    {
                        SwapMethod(localMethod.Method, dynmethod);

                        localMethod.CurrentSwap  = dynmethod;
                        localMethod.BodyString   = newBody;
                        localMethod.BodyHashCode = newBodyHash;
                    }
                }
                catch (Exception e) {
                    Debug.LogWarningFormat("Failed to patch {0}. <i>See full stacktrace in Temp/hotpatch.log.</i>\nError is: {1}",
                                           method.FullName, e.Message);
                    Debug.Trace(e.StackTrace);
                }
                finally {
                    Debug.Trace("----------");
                }
            }
        }