LogLine() private method

private LogLine ( uint mask ) : void
mask uint
return void
Esempio n. 1
0
        internal static InjectionDefinition FindInjectionDefinition(TypeDefinition type,
                                                                    string name,
                                                                    MethodDefinition target,
                                                                    InjectFlags flags,
                                                                    int[] localVarIDs = null,
                                                                    params FieldDefinition[] memberReferences)
        {
            Logger.LogLine(LogMask.GetInjectionMethod, "##### GET INJECTION METHOD BEGIN #####");
            Logger.LogLine(
                LogMask.GetInjectionMethod,
                $"Attempting to get a suitable injection method for {type.Name}.{target?.Name}");

            if (string.IsNullOrEmpty(name))
            {
                Logger.LogLine(LogMask.GetInjectionMethod, "No injection method name specified");
                return(null);
            }
            if (target == null || !target.HasBody)
            {
                Logger.LogLine(LogMask.GetInjectionMethod, "No target specified or the target has no definition");
                return(null);
            }

            InjectValues hFlags = flags.ToValues();

#if DEBUG
            Logger.LogLine(LogMask.GetInjectionMethod, "Patch parameters:");
            Logger.LogLine(LogMask.GetInjectionMethod, $"Pass tag: {hFlags.PassTag}");
            Logger.LogLine(LogMask.GetInjectionMethod, $"Modify return value: {hFlags.ModifyReturn}");
            Logger.LogLine(LogMask.GetInjectionMethod, $"Pass THIS: {hFlags.PassInvokingInstance}");
            Logger.LogLine(LogMask.GetInjectionMethod, $"Pass method locals: {hFlags.PassLocals}");
            Logger.LogLine(LogMask.GetInjectionMethod, $"Pass member fields: {hFlags.PassFields}");
            Logger.LogLine(LogMask.GetInjectionMethod, $"Pass member parameters: {hFlags.PassParameters}");
            if (hFlags.PassParameters)
            {
                Logger.LogLine(
                    LogMask.GetInjectionMethod,
                    $"Member parameters are passed by {(hFlags.PassParametersByRef ? "reference" : "value")}");
            }
#endif

            if (hFlags.PassInvokingInstance && target.IsStatic)
            {
                Logger.LogLine(
                    LogMask.GetInjectionMethod,
                    $"{nameof(hFlags.PassInvokingInstance)} is true, but target is static!");
                return(null);
            }
            if (hFlags.PassFields && (target.IsStatic || memberReferences == null || memberReferences.Length == 0))
            {
                Logger.LogLine(
                    LogMask.GetInjectionMethod,
                    $"{nameof(hFlags.PassFields)} is true, but target is either static or no member references were specified");
                return(null);
            }
            if (hFlags.PassLocals && (!target.Body.HasVariables || localVarIDs == null || localVarIDs.Length == 0))
            {
                Logger.LogLine(
                    LogMask.GetInjectionMethod,
                    $"{nameof(hFlags.PassLocals)} is true, but target either doesn't have any locals or no local IDs were specified");
                return(null);
            }

            int parameterCount = 0;

            MethodDefinition injection =
                type.Methods.FirstOrDefault(m =>
            {
                try
                {
                    parameterCount = VerifyInjectionDefinition(m, target, flags, localVarIDs, memberReferences);
                }
                catch (InjectionDefinitionException e)
                {
                    Logger.LogLine(LogMask.GetInjectionMethod, e.Message);
                    return(false);
                }
                return(true);
            });

            if (injection == null)
            {
                Logger.LogLine(LogMask.GetInjectionMethod, "Did not find any matching methods!");
                return(null);
            }
            Logger.LogLine(LogMask.GetInjectionMethod, "Found injection method.");
            Logger.LogLine(LogMask.GetInjectionMethod, "##### GET INJECTION METHOD END #####");
            return(new InjectionDefinition
            {
                InjectMethod = injection,
                InjectTarget = target,
                Flags = flags,
                MemberReferences = memberReferences,
                LocalVarIDs = localVarIDs,
                ParameterCount = parameterCount
            });
        }
Esempio n. 2
0
        /// <summary>
        ///     Inject the call of the injection method into the target.
        /// </summary>
        /// <param name="startCode">The instruction from which to start injecting.</param>
        /// <param name="token">
        ///     If <see cref="InjectFlags.PassTag" /> is specified, the value of this parameter will be passed as a
        ///     parameter to the injection method.
        /// </param>
        /// <param name="direction">The direction in which to insert the call: either above the start code or below it.</param>
        public void Inject(Instruction startCode,
                           object token = null,
                           InjectDirection direction = InjectDirection.Before)
        {
            InjectValues flags = Flags.ToValues();

#if DEBUG
            Logger.LogLine(LogMask.Inject, "##### INJECTION START #####");
            Logger.LogLine(
                LogMask.Inject,
                $"Injecting a call to {InjectMethod.Module.Name}.{InjectMethod.Name} into {InjectTarget.Module.Name}.{InjectTarget.Name}.");
            Logger.LogLine(LogMask.Inject, "Patch parameters:");
            Logger.LogLine(LogMask.Inject, $"Pass tag: {flags.PassTag}");
            Logger.LogLine(LogMask.Inject, $"Modify return value: {flags.ModifyReturn}");
            Logger.LogLine(LogMask.Inject, $"Pass THIS: {flags.PassInvokingInstance}");
            Logger.LogLine(LogMask.Inject, $"Pass method locals: {flags.PassLocals}");
            Logger.LogLine(LogMask.Inject, $"Pass member fields: {flags.PassFields}");
            Logger.LogLine(LogMask.Inject, $"Pass member parameters: {flags.PassParameters}");
            if (flags.PassParameters)
            {
                Logger.LogLine(
                    LogMask.Inject,
                    $"Member parameters are passed by {(flags.PassParametersByRef ? "reference" : "value")}");
            }
#endif

            bool isVoid = InjectTarget.ReturnType.FullName == "System.Void";

            MethodReference hookRef = InjectTarget.Module.Import(InjectMethod);

            // If the hook is generic but not instantiated fully, attempt to fill in the generic arguments with the ones specified in the target method/class
            if (hookRef.HasGenericParameters &&
                (!hookRef.IsGenericInstance ||
                 hookRef.IsGenericInstance &&
                 ((GenericInstanceMethod)hookRef).GenericArguments.Count <
                 hookRef.GenericParameters.Count))
            {
                GenericInstanceMethod genericInjectMethod = new GenericInstanceMethod(hookRef);
                foreach (GenericParameter genericParameter in InjectMethod.GenericParameters)
                {
                    List <GenericParameter> @params = new List <GenericParameter>();
                    @params.AddRange(InjectTarget.GenericParameters);
                    @params.AddRange(InjectTarget.DeclaringType.GenericParameters);
                    GenericParameter param = @params.FirstOrDefault(p => p.Name == genericParameter.Name);
                    if (param == null)
                    {
                        throw new Exception(
                                  "Could not find a suitable type to bind to the generic injection method. Try to manually instantiate the generic injection method before injecting.");
                    }
                    genericInjectMethod.GenericArguments.Add(param);
                }
                hookRef = genericInjectMethod;
            }

            MethodBody  targetBody = InjectTarget.Body;
            ILProcessor il         = targetBody.GetILProcessor();
            int         startIndex = targetBody.Instructions.IndexOf(startCode);
            if (startIndex == -1)
            {
                throw new ArgumentOutOfRangeException(nameof(startCode));
            }
            Instruction startInstruction = startCode;

            if (direction == InjectDirection.Before && startIndex != 0)
            {
                Instruction oldIns = ILUtils.CopyInstruction(startCode);
                ILUtils.ReplaceInstruction(startCode, il.Create(OpCodes.Nop));
                Instruction ins = targetBody.Instructions[startIndex];
                il.InsertAfter(ins, oldIns);
                startInstruction = targetBody.Instructions[startIndex + 1];
            }
            else if (direction == InjectDirection.After)
            {
                il.InsertAfter(startCode, il.Create(OpCodes.Nop));
                startInstruction = targetBody.Instructions[startIndex + 1];
            }

            VariableDefinition returnDef = null;
            if (flags.ModifyReturn && !isVoid)
            {
                targetBody.InitLocals = true;
                returnDef             = new VariableDefinition(
                    InjectMethod.Name + "_return",
                    InjectTarget.ReturnType);
                targetBody.Variables.Add(returnDef);
            }


            if (flags.PassTag)
            {
                Logger.LogLine(LogMask.Inject, $"Passing custom token value: {token}");

                switch (flags.TagType)
                {
                case InjectValues.PassTagType.Int32:
                {
                    int tag = token as int? ?? 0;
                    il.InsertBefore(startInstruction, il.Create(OpCodes.Ldc_I4, tag));
                }
                break;

                case InjectValues.PassTagType.String:
                {
                    string tag = token as string;
                    il.InsertBefore(startInstruction, il.Create(OpCodes.Ldstr, tag));
                }
                break;

                case InjectValues.PassTagType.None:
                    break;

                case InjectValues.PassTagType.Max:
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }
            if (flags.PassInvokingInstance)
            {
                Logger.LogLine(LogMask.Inject, "Passing THIS argument");
                il.InsertBefore(startInstruction, il.Create(OpCodes.Ldarg_0));
            }
            if (flags.ModifyReturn && !isVoid)
            {
                Logger.LogLine(LogMask.Inject, "Passing return reference");
                il.InsertBefore(startInstruction, il.Create(OpCodes.Ldloca_S, returnDef));
            }
            if (flags.PassLocals)
            {
                Logger.LogLine(LogMask.Inject, "Passing local variable references");
                foreach (int i in LocalVarIDs)
                {
                    Logger.LogLine(LogMask.Inject, $"Passing local variable index: {i}");
                    il.InsertBefore(startInstruction, il.Create(OpCodes.Ldloca_S, (byte)i));
                }
            }
            if (flags.PassFields)
            {
                Logger.LogLine(LogMask.Inject, "Passing member field references");
                IEnumerable <FieldReference> memberRefs = MemberReferences.Select(t => t.Module.Import(t));
                foreach (FieldReference t in memberRefs)
                {
                    Logger.LogLine(LogMask.Inject, $"Passing member field {t.FullName}");
                    il.InsertBefore(startInstruction, il.Create(OpCodes.Ldarg_0));
                    il.InsertBefore(startInstruction, il.Create(OpCodes.Ldflda, t));
                }
            }
            if (flags.PassParameters)
            {
                Logger.LogLine(
                    LogMask.Inject,
                    $"Passing member parameters by {(flags.PassParametersByRef ? "reference" : "value")}");
                int icr = Convert.ToInt32(!InjectTarget.IsStatic);
                for (int i = 0; i < ParameterCount; i++)
                {
                    Logger.LogLine(LogMask.Inject, $"Passing parameter of index {i + icr}");
                    il.InsertBefore(
                        startInstruction,
                        flags.PassParametersByRef
                            ? il.Create(OpCodes.Ldarga_S, (byte)(i + icr))
                            : il.Create(OpCodes.Ldarg_S, (byte)(i + icr)));
                }
            }
            Logger.LogLine(LogMask.Inject, "Injecting the call to the method");
            il.InsertBefore(startInstruction, il.Create(OpCodes.Call, hookRef));
            if (flags.ModifyReturn)
            {
                Logger.LogLine(LogMask.Inject, "Inserting return check");
                il.InsertBefore(startInstruction, il.Create(OpCodes.Brfalse_S, startInstruction));
                if (!isVoid)
                {
                    Logger.LogLine(LogMask.Inject, "Inserting return value");
                    il.InsertBefore(startInstruction, il.Create(OpCodes.Ldloc_S, returnDef));
                }
                Logger.LogLine(LogMask.Inject, "Inserting return command");
                il.InsertBefore(startInstruction, il.Create(OpCodes.Ret));
            }
            // If we don't use the return value of InjectMethod, pop it from the ES
            else if (InjectMethod.ReturnType.FullName != "System.Void")
            {
                il.InsertBefore(startInstruction, il.Create(OpCodes.Pop));
            }
            if (direction == InjectDirection.After)
            {
                il.Remove(startInstruction);
            }
            Logger.LogLine(LogMask.Inject, "Injection complete");
            Logger.LogLine(LogMask.Inject, "##### INJECTION END #####");
        }