Наследование: IVariableDefinitionProvider
Пример #1
0
		void CreateScopes (MethodBody body, ScopeCollection scopes, SymbolToken localVarToken)
		{
			foreach (Scope s in scopes) {
				int startOffset = s.Start.Offset;
				int endOffset = s.End == body.Instructions.Outside ?
					body.Instructions[body.Instructions.Count - 1].Offset + 1 :
					s.End.Offset;

				m_writer.OpenScope (startOffset);
				m_writer.UsingNamespace (body.Method.DeclaringType.Namespace);
				m_writer.OpenNamespace (body.Method.DeclaringType.Namespace);

				int start = body.Instructions.IndexOf (s.Start);
				int end = s.End == body.Instructions.Outside ?
					body.Instructions.Count - 1 :
					body.Instructions.IndexOf (s.End);

				ArrayList instructions = CollectSequencePoints (body, start, end);
				DefineSequencePoints (instructions);

				CreateLocalVariable (s, startOffset, endOffset, localVarToken);

				CreateScopes (body, s.Scopes, localVarToken);
				m_writer.CloseNamespace ();

				m_writer.CloseScope (endOffset);
			}
		}
		public override void VisitMethodBody (MethodBody body)
		{
			MethodDefinition meth = body.Method;
			MethodBody methBody = body;
			BinaryReader br = m_reflectReader.Module.ImageReader.MetadataReader.GetDataReader (meth.RVA);

			// lets read the method
			int flags = br.ReadByte ();
			switch (flags & 0x3) {
			case (int) MethodHeader.TinyFormat :
				methBody.CodeSize = flags >> 2;
				methBody.MaxStack = 8;
				ReadCilBody (methBody, br);
				break;
			case (int) MethodHeader.FatFormat :
				br.BaseStream.Position--;
				int fatflags = br.ReadUInt16 ();
				//int headersize = (fatflags >> 12) & 0xf;
				methBody.MaxStack = br.ReadUInt16 ();
				methBody.CodeSize = br.ReadInt32 ();
				methBody.LocalVarToken = br.ReadInt32 ();
				body.InitLocals = (fatflags & (int) MethodHeader.InitLocals) != 0;
				if (methBody.LocalVarToken != 0)
					VisitVariableDefinitionCollection (methBody.Variables);
				ReadCilBody (methBody, br);
				if ((fatflags & (int) MethodHeader.MoreSects) != 0)
					ReadSection (methBody, br);
				break;
			}
		}
Пример #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
        private static void SwapMethods(MethodBody body, IEnumerable<Instruction> oldInstructions, IDictionary<MethodReference, MethodReference> methodMap, 
            TypeDefinition targetDependency)
        {
            var IL = body.CilWorker;
            foreach (var instruction in oldInstructions)
            {
                var opCode = instruction.OpCode;
                if (opCode != OpCodes.Call && opCode != OpCodes.Callvirt)
                {
                    IL.Append(instruction);
                    continue;
                }

                var currentMethod = instruction.Operand as MethodReference;
                if (currentMethod == null || !methodMap.ContainsKey(currentMethod))
                {
                    IL.Append(instruction);
                    continue;
                }

                if (currentMethod.DeclaringType != targetDependency)
                {
                    IL.Append(instruction);
                    continue;
                }

                var interfaceMethod = methodMap[currentMethod];
                instruction.Operand = interfaceMethod;
                instruction.OpCode = OpCodes.Callvirt;

                IL.Append(instruction);
            }
        }
        public void Write(MethodBody body, /*Telerik Authorship*/ MetadataToken methodToken, /*Telerik Authorship*/ MetadataToken localVarToken)
        {
            var method = new SourceMethod (body.Method);

            var instructions = GetInstructions (body);
            int count = instructions.Count;
            if (count == 0)
                return;

            var offsets = new int [count];
            var start_rows = new int [count];
            var start_cols = new int [count];

            SourceFile file;
            Populate (instructions, offsets, start_rows, start_cols, out file);

            var builder = writer.OpenMethod (file.CompilationUnit, 0, method);

            for (int i = 0; i < count; i++)
                builder.MarkSequencePoint (
                    offsets [i],
                    file.CompilationUnit.SourceFile,
                    start_rows [i],
                    start_cols [i],
                    false);

            if (body.HasVariables)
                AddVariables (body.Variables);

            writer.CloseMethod ();
        }
Пример #6
0
        public void Write(MethodBody body)
        {
            var method_token = body.Method.MetadataToken;
            var sym_token = new SymbolToken (method_token.ToInt32 ());

            var instructions = CollectInstructions (body);
            if (instructions.Count == 0 && !body.HasVariables)
                return;

            writer.OpenMethod (sym_token);

            DefineSequencePoints (instructions);

            if (body.Scope != null)
                WriteScope (body, body.Scope);
            else
            if (body.HasVariables)
            {
                var start_offset = 0;
                var end_offset = body.CodeSize;

                writer.OpenScope  (start_offset);
                DefineVariables   (body, body.Variables, start_offset, end_offset);
                writer.CloseScope (end_offset);
            }

            if (body.IteratorType != null)
                DefineIteratorType   (sym_token, body.IteratorType.Name);

            if (body.iterator_scopes != null)
                DefineIteratorScopes (sym_token, body.IteratorScopes, body.CodeSize);

            writer.CloseMethod ();
        }
Пример #7
0
		public void Write (MethodBody body)
		{
			CreateDocuments (body);
			m_writer.OpenMethod (new SymbolToken ((int) body.Method.MetadataToken.ToUInt ()));
			CreateScopes (body, body.Scopes, new SymbolToken (body.LocalVarToken));
			m_writer.CloseMethod ();
		}
 public void VisitMethodBody(MethodBody body)
 {
     this.MethodBody = body;
     //VisitVariableDefinitionCollection(body.Variables);
     //VisitInstructionCollection(body.Instructions);
     //VisitExceptionHandlerCollection(body.ExceptionHandlers);
 }
Пример #9
0
        private static void EmitArchsInit(MethodBody body, FieldReference archRef, Action<Instruction> emit)
        {
            var module = body.Method.Module;
              GenericInstanceType dictStrStrRef = (GenericInstanceType)archRef.FieldType;
              TypeReference dictOpenRef = dictStrStrRef.ElementType;
              GenericInstanceType iEqCompStrRef = new GenericInstanceType(module.Import(typeof(IEqualityComparer<>)));
              iEqCompStrRef.GenericArguments.Add(dictOpenRef.GenericParameters[0]);
              MethodReference dictStrStrCtor = CecilUtils.ImportInstanceMethodRef(module, dictStrStrRef, ".ctor", null, iEqCompStrRef);
              MethodReference dictAddRef = CecilUtils.ImportInstanceMethodRef(module, dictStrStrRef, "Add", null, dictOpenRef.GenericParameters[0], dictOpenRef.GenericParameters[1]);

            // Variables
              body.Variables.Add(new VariableDefinition(dictStrStrRef));
              int varIdx = body.Variables.Count - 1;
            Instruction varSt = CecilUtils.ShortestStloc(varIdx);
            Instruction varLd = CecilUtils.ShortestLdloc(varIdx);

            emit(Instruction.Create(OpCodes.Ldnull));
            emit(Instruction.Create(OpCodes.Newobj, dictStrStrCtor));
              emit(varSt.Clone());
              emit(varLd.Clone());
              emit(Instruction.Create(OpCodes.Stsfld, archRef));
              Action<string, string> emitAddPair = (k, v) =>
              {
              emit(varLd.Clone());
                emit(Instruction.Create(OpCodes.Ldstr, k));
                emit(Instruction.Create(OpCodes.Ldstr, v));
            emit(Instruction.Create(OpCodes.Callvirt, dictAddRef));
              };
              emitAddPair("x86", "Win32");
              emitAddPair("AMD64", "x64");
              emitAddPair("IA64", "Itanium");
              emitAddPair("ARM", "WinCE");
        }
Пример #10
0
 public void Write(MethodBody body, byte [][] variables)
 {
     CreateDocuments (body);
     m_writer.OpenMethod (new SymbolToken ((int) body.Method.MetadataToken.ToUInt ()));
     CreateScopes (body, body.Scopes, variables);
     m_writer.CloseMethod ();
 }
Пример #11
0
        public override void TerminateMethodBody(MethodBody body)
        {
            long pos = m_binaryWriter.BaseStream.Position;

            if (body.Variables.Count > 0 || body.ExceptionHandlers.Count > 0
                || m_codeWriter.BaseStream.Length >= 64 || body.MaxStack > 8) {

                MethodHeader header = MethodHeader.FatFormat;
                if (body.InitLocals)
                    header |= MethodHeader.InitLocals;
                if (body.ExceptionHandlers.Count > 0)
                    header |= MethodHeader.MoreSects;

                m_binaryWriter.Write ((byte) header);
                m_binaryWriter.Write ((byte) 0x30); // (header size / 4) << 4
                m_binaryWriter.Write ((short) body.MaxStack);
                m_binaryWriter.Write ((int) m_codeWriter.BaseStream.Length);
                m_binaryWriter.Write (((int) TokenType.Signature | body.LocalVarToken));

                WriteExceptionHandlerCollection (body.ExceptionHandlers);
            } else
                m_binaryWriter.Write ((byte) ((byte) MethodHeader.TinyFormat |
                    m_codeWriter.BaseStream.Length << 2));

            m_binaryWriter.Write (m_codeWriter);
            m_binaryWriter.QuadAlign ();

            m_reflectWriter.MetadataWriter.AddData (
                (int) (m_binaryWriter.BaseStream.Position - pos));
        }
Пример #12
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;
        }
        protected BlockStatement RunInternal(MethodBody body, BlockStatement block, ILanguage language)
        {
            try
            {
                if (body.Instructions.Count != 0 || body.Method.IsJustDecompileGenerated)
                {
                    foreach (IDecompilationStep step in steps)
                    {
                        if (language != null && language.IsStopped)
                        {
                            break;
                        }

                        block = step.Process(Context, block);
                    }
                }
            }
            finally
            {
                if (Context.MethodContext.IsMethodBodyChanged)
                {
                    body.Method.RefreshBody();
                }
            }

            return block;
        }
Пример #14
0
        public void Replace(MethodBody currentBody, ICollection<MethodReference> modifiedItems)
        {
            var invalidCalls = _callFilter.GetInvalidCalls(currentBody, modifiedItems);
            if (invalidCalls.Count == 0)
                return;

            var currentInstructions = currentBody.Instructions.Cast<Instruction>().ToArray();
            var stackCtor = _targetModule.ImportConstructor<Stack<object>>(new Type[0]);
            var IL = currentBody.CilWorker;

            var targetMethod = currentBody.Method;
            var currentArgument = targetMethod.AddLocal<object>();
            var currentArguments = targetMethod.AddLocal<Stack<object>>();

            currentBody.Instructions.Clear();

            // Create the stack that will hold the method arguments
            IL.Emit(OpCodes.Newobj, stackCtor);
            IL.Emit(OpCodes.Stloc, currentArguments);
            foreach (var currentInstruction in currentInstructions)
            {
                var currentMethod = currentInstruction.Operand as MethodReference;

                // Ignore any instructions that weren't affected by the
                // interface extraction
                if (currentMethod != null && invalidCalls.ContainsKey(currentMethod))
                {
                    var context = new MethodContext(IL, currentArguments, currentMethod, currentArgument);
                    _replaceMethodCall.Replace(context, _targetModule);
                }

                IL.Append(currentInstruction);
            }
        }
Пример #15
0
 public static bool ContainsCallTo(MethodBody m,
     string methodFullName)
 {
     return m.Instructions.Any(i =>
         (i.OpCode == OpCodes.Call || i.OpCode == OpCodes.Callvirt) &&
         ((MethodReference)i.Operand).FullName == methodFullName);
 }
Пример #16
0
		public void Analyze(MethodBody body, NodeBase analyzedNode)
		{
			if (analyzedNode is MethodNode)
				((MethodNode)analyzedNode).CyclomaticComplexity = 0;
			
			if (body == null)
				return;
			
			foreach (var instruction in body.Instructions) {
				// IL cyclomatic complexity
				if (instruction.OpCode.FlowControl == FlowControl.Cond_Branch && analyzedNode is MethodNode)
					((MethodNode)analyzedNode).CyclomaticComplexity++;

				var operand = ReadOperand(instruction);
				
				if (operand is MethodReference) {
					var md = ((MethodReference)operand).Resolve();
					if (md != null && assemblies.Contains(md.DeclaringType.Module.Assembly) && mappings.cecilMappings.ContainsKey(md)) {
						if (md.IsGetter || md.IsSetter) {
							var propertyNode = mappings.propertyMappings[(IProperty)mappings.cecilMappings[md]];
							analyzedNode.AddRelationship(propertyNode);
						} else {
							var methodNode = mappings.methodMappings[(IMethod)mappings.cecilMappings[md]];
							analyzedNode.AddRelationship(methodNode);
						}
					}
				} else if (operand is FieldReference) {
					var fd = ((FieldReference)operand).Resolve();
					if (fd != null && assemblies.Contains(fd.DeclaringType.Module.Assembly) && mappings.cecilMappings.ContainsKey(fd)) {
						var fieldNode = mappings.fieldMappings[(IField)mappings.cecilMappings[fd]];
						analyzedNode.AddRelationship(fieldNode);
					}
				}
			}
		}
Пример #17
0
        public CecilVisitor(AssemblyDefinition assembly, ModuleDefinition module)
        {
            _assembly = assembly;
            _module = module;

            var program = _module.Types.First(t => t.Name == "Program");
            _main = program.Methods.First(m => m.Name == "Main");

            _body = _main.Body;
            _instructions = _body.Instructions;
            _instructions.Clear();

            _objCtor = _module.Import(typeof(object).GetConstructor(new System.Type[0]));

            var systemFunctions = _module.Types.First(t => t.Name == "SystemFunctions");
            // Math methods
            _fact = systemFunctions.Methods.First(m => m.Name == "Fact");
            _max = systemFunctions.Methods.First(m => m.Name == "Max");
            _min = systemFunctions.Methods.First(m => m.Name == "Min");
            _pow = systemFunctions.Methods.First(m => m.Name == "Pow");
            // Console methods
            _printBool = systemFunctions.Methods.First(m => m.Name == "PrintBool");
            _printInt = systemFunctions.Methods.First(m => m.Name == "PrintInt");

            _userFunctions = _module.Types.First(t => t.Name == "UserFunctions");
        }
		internal ControlFlowGraphBuilder (MethodDefinition method)
		{
			body = method.Body;

			if (body.ExceptionHandlers.Count > 0)
				exception_objects_offsets = new HashSet<int> ();
		}
Пример #19
0
 protected override void ProxyMethod(MethodBody body, MethodReference proceedTargetMethod)
 {
     // Create base call
     if (!Method.IsAbstract)
     {
         callBaseMethod = new MethodDefinition(Name + "$Base", MethodAttributes.Private, Method.ReturnType);
         Method.CopyParameters(callBaseMethod);
         Method.CopyGenericParameters(callBaseMethod);
         callBaseMethod.Body.Emit(il =>
         {
             il.Emit(OpCodes.Ldarg_0);
             for (var i = 0; i < Method.Parameters.Count; i++)
             {
                 il.Emit(OpCodes.Ldarg, (short)i + 1);
             }
             var methodReference = GetProceedMethodTarget();
             if (Method.GenericParameters.Count > 0)
                 methodReference = methodReference.MakeGenericMethod(callBaseMethod.GenericParameters.ToArray());
             il.Emit(OpCodes.Call, methodReference);
             il.Emit(OpCodes.Ret);
         });
         ClassWeaver.ProxyType.Methods.Add(callBaseMethod);
     }
     base.ProxyMethod(body, proceedTargetMethod);
 }
Пример #20
0
Файл: View.cs Проект: ynkbt/moon
    public override Widget GetView()
    {
        if (scrolled_tree != null)
        {
            return(scrolled_tree);
        }

        // Create ui
        store      = new ListStore(typeof(string), typeof(string), typeof(string));
        tree       = new TreeView();
        tree.Model = store;
        tree.AppendColumn("Offset", new CellRendererText(), "text", 0);
        tree.AppendColumn("Instruction", new CellRendererText(), "text", 1);
        tree.AppendColumn("Operand", new CellRendererText(), "text", 2);
        tree.HeadersVisible = true;
        scrolled_tree       = new ScrolledWindow();
        scrolled_tree.Add(tree);

        Mono.Cecil.Cil.MethodBody  body = method.Body;
        Mono.Cecil.Cil.Instruction instr;
        if (body != null)
        {
            for (int i = 0; i < body.Instructions.Count; i++)
            {
                instr = body.Instructions [i];

                store.AppendValues("IL_" + instr.Offset.ToString("0000"), instr.OpCode.ToString(), FormatOperand(instr.Operand));
            }
        }
        return(scrolled_tree);
    }
            /// <summary>
            /// Create the Ctor
            /// </summary>
            private static void CreateDefaultCtor(ReachableContext reachableContext, TypeDefinition type)
            {
                var typeSystem = type.Module.TypeSystem;
                var ctor = new MethodDefinition(".ctor", MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, typeSystem.Void);
                ctor.DeclaringType = type;

                var body = new MethodBody(ctor);
                body.InitLocals = true;
                ctor.Body = body;

                // Prepare code
                var seq = new ILSequence();
                seq.Emit(OpCodes.Nop);
                seq.Emit(OpCodes.Ret);

                // Append ret sequence
                seq.AppendTo(body);

                // Update offsets
                body.ComputeOffsets();

                // Add ctor
                type.Methods.Add(ctor);
                ctor.SetReachable(reachableContext);
            }
		internal DecompilationContext (MethodBody body, ControlFlowGraph cfg)
		{
			this.body = body;
			this.method = body.Method;
			this.variables = CloneCollection (body.Variables);
			this.cfg = cfg;
		}
Пример #23
0
            /// <summary>
            /// Create a CopyFrom method.
            /// </summary>
            private static MethodDefinition CreateCopyFromMethod(ReachableContext reachableContext, TypeDefinition type)
            {
                var typeSystem = type.Module.TypeSystem;
                var method = new MethodDefinition(NameConstants.Struct.CopyFromMethodName, MethodAttributes.Public, type);
                var sourceParam = new ParameterDefinition(type);
                method.Parameters.Add(sourceParam);
                method.DeclaringType = type;

                var body = new MethodBody(method);
                body.InitLocals = true;
                method.Body = body;

                // Prepare code
                var seq = new ILSequence();
                seq.Emit(OpCodes.Nop);

                // Call base CopyFrom
                var baseType = (type.BaseType != null) ? type.BaseType.GetElementType().Resolve() : null;
                if ((baseType != null) && baseType.IsValueType && (baseType.FullName != "System.ValueType"))
                {
                    var baseMethod = new MethodReference(NameConstants.Struct.CopyFromMethodName, baseType, baseType) { HasThis = true };
                    baseMethod.Parameters.Add(new ParameterDefinition(baseType));
                    seq.Emit(OpCodes.Ldarg, sourceParam);
                    seq.Emit(OpCodes.Call, baseMethod);
                }

                // Copy all fields
                foreach (var field in type.Fields.Where(x => !x.IsStatic))
                {
                    // Not need to bother with cloning struct-type fields here, 
                    // as this will be done automatically by one of the Converters.

                    // Prepare for stfld
                    seq.Emit(OpCodes.Ldarg, body.ThisParameter);

                    // Load from source
                    seq.Emit(OpCodes.Ldarg, sourceParam);
                    seq.Emit(OpCodes.Ldfld, field);

                    // Save in this
                    seq.Emit(OpCodes.Stfld, field);
                }

                // Return this
                seq.Emit(OpCodes.Ldarg, body.ThisParameter);
                seq.Emit(OpCodes.Ret);

                // Append ret sequence
                seq.AppendTo(body);

                // Update offsets
                body.ComputeOffsets();

                // Add method
                type.Methods.Add(method);
                method.SetReachable(reachableContext);

                return method;
            }        
Пример #24
0
        private void UpdateCallsToGetCurrentClassLogger(MethodBody ctorBody)
        {
            // Convert this:
            //
            // call class [Catel.Core]Catel.Logging.ILog [Catel.Core]Catel.Logging.LogManager::GetCurrentClassLogger()
            // stsfld class [Catel.Core]Catel.Logging.ILog Catel.Fody.TestAssembly.LoggingClass::AutoLog
            //
            // into this:
            //
            // ldtoken Catel.Fody.TestAssembly.LoggingClass
            // call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
            // call class [Catel.Core]Catel.Logging.ILog [Catel.Core]Catel.Logging.LogManager::GetLogger(class [mscorlib]System.Type)
            // stsfld class [Catel.Core]Catel.Logging.ILog Catel.Fody.TestAssembly.LoggingClass::ManualLog

            var type = ctorBody.Method.DeclaringType;
            var instructions = ctorBody.Instructions;

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

                var methodReference = instruction.Operand as MethodReference;
                if (methodReference != null)
                {
                    FodyEnvironment.LogDebug($"Weaving auto log to specific log for '{type.FullName}'");

                    if (string.Equals(methodReference.Name, "GetCurrentClassLogger"))
                    {
                        // We have a possible match
                        var getLoggerMethod = GetGetLoggerMethod(methodReference.DeclaringType);
                        if (getLoggerMethod == null)
                        {
                            var point = instruction.SequencePoint;

                            var message = $"Cannot change method call for log '{type.FullName}', the GetLogger(type) method does not exist on the calling type (try to use LogManager.GetCurrentClassLogger())";

                            if (point != null)
                            {
                                FodyEnvironment.LogWarningPoint(message, point);
                            }
                            else
                            {
                                FodyEnvironment.LogWarning(message);
                            }
                            continue;
                        }

                        var getTypeFromHandle = type.Module.GetMethodAndImport("GetTypeFromHandle");

                        instructions.RemoveAt(i);

                        instructions.Insert(i, 
                            Instruction.Create(OpCodes.Ldtoken, type), 
                            Instruction.Create(OpCodes.Call, getTypeFromHandle), 
                            Instruction.Create(OpCodes.Call, type.Module.Import(getLoggerMethod)));
                    }
                }
            }
        }
Пример #25
0
 public ControlFlowGraph(Mono.Cecil.Cil.MethodBody body, InstructionBlock[] blocks, Dictionary<int, InstructionData> instructionData, List<ExceptionHandlerData> exception_data, HashSet<int> exception_objects_offsets)
 {
     this.body = body;
     this.blocks = blocks;
     this.data = instructionData;
     this.exception_data = exception_data;
     this.exception_objects_offsets = exception_objects_offsets;
 }
		Instruction GetInstruction (MethodBody body, IDictionary instructions, int offset)
		{
			Instruction instr = (Instruction) instructions [offset];
			if (instr != null)
				return instr;

			return body.Instructions.Outside;
		}
Пример #27
0
 public void InjectInstructions(MethodBody body, int line, params Instruction[] instructions)
 {
     foreach (Instruction instr in instructions)
     {
         body.Instructions.Insert(line, instr);
         line++;
     }
 }
Пример #28
0
		public ILBlock(MethodBody body) : this(ILBlockType.Root, 0, body.CodeSize)
		{
			AddExceptionHandlerBlocks(body);
			List<InstructionPair> allBranches = FindAllBranches(body);

			AddBlocks(allBranches);
			SortChildren();
		}
Пример #29
0
		static void AssertOpCodeSequence (OpCode [] expected, MethodBody body)
		{
			var opcodes = body.Instructions.Select (i => i.OpCode).ToArray ();
			Assert.AreEqual (expected.Length, opcodes.Length);

			for (int i = 0; i < opcodes.Length; i++)
				Assert.AreEqual (expected [i], opcodes [i]);
		}
Пример #30
0
		string GetFileForMethodBody(MethodBody body)
		{
			if(body == null)
				return null;

			SequencePoint sp = body.Instructions[0].SequencePoint;
			return sp.Document.Url;
		}
Пример #31
0
        static string GetVariableName(VariableDefinition variable, MethodBody body)
        {
            string name;
            if (body.Method.DebugInformation.TryGetName (variable, out name))
                return name;

            return variable.ToString ();
        }
Пример #32
0
        internal static MethodBody Clone(MethodBody body, MethodDefinition parent, ImportContext context)
        {
            MethodBody nb = new MethodBody(parent);

            nb.MaxStack   = body.MaxStack;
            nb.InitLocals = body.InitLocals;
            nb.CodeSize   = body.CodeSize;

            CilWorker worker = nb.CilWorker;

            if (body.HasVariables)
            {
                foreach (VariableDefinition var in body.Variables)
                {
                    nb.Variables.Add(new VariableDefinition(
                                         var.Name, var.Index, parent,
                                         context.Import(var.VariableType)));
                }
            }

            foreach (Instruction instr in body.Instructions)
            {
                Instruction ni = new Instruction(instr.OpCode);

                switch (instr.OpCode.OperandType)
                {
                case OperandType.InlineParam:
                case OperandType.ShortInlineParam:
                    if (instr.Operand == body.Method.This)
                    {
                        ni.Operand = nb.Method.This;
                    }
                    else
                    {
                        int param = body.Method.Parameters.IndexOf((ParameterDefinition)instr.Operand);
                        ni.Operand = parent.Parameters [param];
                    }
                    break;

                case OperandType.InlineVar:
                case OperandType.ShortInlineVar:
                    int var = body.Variables.IndexOf((VariableDefinition)instr.Operand);
                    ni.Operand = nb.Variables [var];
                    break;

                case OperandType.InlineField:
                    ni.Operand = context.Import((FieldReference)instr.Operand);
                    break;

                case OperandType.InlineMethod:
                    ni.Operand = context.Import((MethodReference)instr.Operand);
                    break;

                case OperandType.InlineType:
                    ni.Operand = context.Import((TypeReference)instr.Operand);
                    break;

                case OperandType.InlineTok:
                    if (instr.Operand is TypeReference)
                    {
                        ni.Operand = context.Import((TypeReference)instr.Operand);
                    }
                    else if (instr.Operand is FieldReference)
                    {
                        ni.Operand = context.Import((FieldReference)instr.Operand);
                    }
                    else if (instr.Operand is MethodReference)
                    {
                        ni.Operand = context.Import((MethodReference)instr.Operand);
                    }
                    break;

                case OperandType.ShortInlineBrTarget:
                case OperandType.InlineBrTarget:
                case OperandType.InlineSwitch:
                    break;

                default:
                    ni.Operand = instr.Operand;
                    break;
                }

                worker.Append(ni);
            }

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

                if (instr.OpCode.OperandType == OperandType.InlineSwitch)
                {
                    Instruction [] olds    = (Instruction [])oldi.Operand;
                    Instruction [] targets = new Instruction [olds.Length];

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

                    instr.Operand = targets;
                }
                else if (instr.OpCode.OperandType == OperandType.ShortInlineBrTarget || instr.OpCode.OperandType == OperandType.InlineBrTarget)
                {
                    instr.Operand = GetInstruction(body, nb, (Instruction)oldi.Operand);
                }
            }

            if (!body.HasExceptionHandlers)
            {
                return(nb);
            }

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

                switch (eh.Type)
                {
                case ExceptionHandlerType.Catch:
                    neh.CatchType = context.Import(eh.CatchType);
                    break;

                case ExceptionHandlerType.Filter:
                    neh.FilterStart = GetInstruction(body, nb, eh.FilterStart);
                    neh.FilterEnd   = GetInstruction(body, nb, eh.FilterEnd);
                    break;
                }

                nb.ExceptionHandlers.Add(neh);
            }

            return(nb);
        }
Пример #33
0
        public override void VisitInstructionCollection(InstructionCollection instructions)
        {
            MethodBody body  = instructions.Container;
            long       start = m_codeWriter.BaseStream.Position;

            ComputeMaxStack(instructions);
            foreach (Instruction instr in instructions)
            {
                instr.Offset = (int)(m_codeWriter.BaseStream.Position - start);

                if (instr.OpCode.Size == 1)
                {
                    m_codeWriter.Write(instr.OpCode.Op2);
                }
                else
                {
                    m_codeWriter.Write(instr.OpCode.Op1);
                    m_codeWriter.Write(instr.OpCode.Op2);
                }

                if (instr.OpCode.OperandType != OperandType.InlineNone &&
                    instr.Operand == null)
                {
                    throw new ReflectionException("OpCode {0} have null operand", instr.OpCode.Name);
                }

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

                case OperandType.InlineSwitch:
                    Instruction[] targets = (Instruction[])instr.Operand;
                    for (int i = 0; i < targets.Length + 1; i++)
                    {
                        m_codeWriter.Write((uint)0);
                    }
                    break;

                case OperandType.ShortInlineBrTarget:
                    m_codeWriter.Write((byte)0);
                    break;

                case OperandType.InlineBrTarget:
                    m_codeWriter.Write(0);
                    break;

                case OperandType.ShortInlineI:
                    if (instr.OpCode == OpCodes.Ldc_I4_S)
                    {
                        m_codeWriter.Write((sbyte)instr.Operand);
                    }
                    else
                    {
                        m_codeWriter.Write((byte)instr.Operand);
                    }
                    break;

                case OperandType.ShortInlineVar:
                    m_codeWriter.Write((byte)body.Variables.IndexOf(
                                           (VariableDefinition)instr.Operand));
                    break;

                case OperandType.ShortInlineParam:
                    m_codeWriter.Write((byte)GetParameterIndex(body, (ParameterDefinition)instr.Operand));
                    break;

                case OperandType.InlineSig:
                    WriteToken(GetCallSiteToken((CallSite)instr.Operand));
                    break;

                case OperandType.InlineI:
                    m_codeWriter.Write((int)instr.Operand);
                    break;

                case OperandType.InlineVar:
                    m_codeWriter.Write((short)body.Variables.IndexOf(
                                           (VariableDefinition)instr.Operand));
                    break;

                case OperandType.InlineParam:
                    m_codeWriter.Write((short)GetParameterIndex(
                                           body, (ParameterDefinition)instr.Operand));
                    break;

                case OperandType.InlineI8:
                    m_codeWriter.Write((long)instr.Operand);
                    break;

                case OperandType.ShortInlineR:
                    m_codeWriter.Write((float)instr.Operand);
                    break;

                case OperandType.InlineR:
                    m_codeWriter.Write((double)instr.Operand);
                    break;

                case OperandType.InlineString:
                    WriteToken(new MetadataToken(TokenType.String,
                                                 m_reflectWriter.MetadataWriter.AddUserString(instr.Operand as string)));
                    break;

                case OperandType.InlineField:
                    if (instr.Operand is FieldReference)
                    {
                        WriteToken((instr.Operand as FieldReference).MetadataToken);
                    }
                    else
                    {
                        throw new ReflectionException("Wrong operand for InlineField: {0}",
                                                      instr.Operand.GetType().FullName);
                    }
                    break;

                case OperandType.InlineMethod:
                    if (instr.Operand is GenericInstanceMethod)
                    {
                        WriteToken(m_reflectWriter.GetMethodSpecToken(instr.Operand as GenericInstanceMethod));
                    }
                    else if (instr.Operand is MethodReference)
                    {
                        WriteToken((instr.Operand as MethodReference).MetadataToken);
                    }
                    else
                    {
                        throw new ReflectionException("Wrong operand for InlineMethod: {0}",
                                                      instr.Operand.GetType().FullName);
                    }
                    break;

                case OperandType.InlineType:
                    if (instr.Operand is TypeReference)
                    {
                        WriteToken(m_reflectWriter.GetTypeDefOrRefToken(
                                       instr.Operand as TypeReference));
                    }
                    else
                    {
                        throw new ReflectionException("Wrong operand for InlineType: {0}",
                                                      instr.Operand.GetType().FullName);
                    }
                    break;

                case OperandType.InlineTok:
                    if (instr.Operand is TypeReference)
                    {
                        WriteToken(m_reflectWriter.GetTypeDefOrRefToken(
                                       instr.Operand as TypeReference));
                    }
                    else if (instr.Operand is GenericInstanceMethod)
                    {
                        WriteToken(m_reflectWriter.GetMethodSpecToken(instr.Operand as GenericInstanceMethod));
                    }
                    else if (instr.Operand is IMetadataTokenProvider)
                    {
                        WriteToken((instr.Operand as IMetadataTokenProvider).MetadataToken);
                    }
                    else
                    {
                        throw new ReflectionException(
                                  string.Format("Wrong operand for {0} OpCode: {1}",
                                                instr.OpCode.OperandType,
                                                instr.Operand.GetType().FullName));
                    }
                    break;
                }
            }
            long pos = m_codeWriter.BaseStream.Position;

            foreach (Instruction instr in instructions)
            {
                switch (instr.OpCode.OperandType)
                {
                case OperandType.InlineSwitch:
                    m_codeWriter.BaseStream.Position = instr.Offset + instr.OpCode.Size;
                    Instruction[] targets = (Instruction[])instr.Operand;
                    m_codeWriter.Write((uint)targets.Length);
                    foreach (Instruction tgt in targets)
                    {
                        m_codeWriter.Write((tgt.Offset - (instr.Offset +
                                                          instr.OpCode.Size + (4 * (targets.Length + 1)))));
                    }
                    break;

                case OperandType.ShortInlineBrTarget:
                    m_codeWriter.BaseStream.Position = instr.Offset + instr.OpCode.Size;
                    m_codeWriter.Write((byte)(((Instruction)instr.Operand).Offset -
                                              (instr.Offset + instr.OpCode.Size + 1)));
                    break;

                case OperandType.InlineBrTarget:
                    m_codeWriter.BaseStream.Position = instr.Offset + instr.OpCode.Size;
                    m_codeWriter.Write(((Instruction)instr.Operand).Offset -
                                       (instr.Offset + instr.OpCode.Size + 4));
                    break;
                }
            }
            m_codeWriter.BaseStream.Position = pos;
        }
Пример #34
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();
                }
            }
        }
Пример #35
0
        void checkPatchStatus()
        {
            mscloaderUpdate = false;
            isgameUpdated   = false;
            oldPatchFound   = false;
            oldFilesFound   = false;
            button1.Enabled = false;
            button3.Enabled = false;
            bool             newpatchfound = false;
            bool             oldpatchfound = false;
            TypeDefinition   typeToPatch   = AssemblyDefinition.ReadAssembly(AssemblyFullPath).MainModule.Types.FirstOrDefault(t => t.Name == "PlayMakerArrayListProxy");
            MethodDefinition methodToPatch = typeToPatch.Methods.FirstOrDefault(m => m.Name == "Awake");

            Mono.Cecil.Cil.MethodBody methodBody = methodToPatch.Body;
            // MessageBox.Show(methodBody.CodeSize.ToString()); //debug
            if (methodBody.CodeSize == 24)
            {
                //not patched
                newpatchfound = false;
            }
            else if (methodBody.CodeSize == 29)
            {
                //patch found
                newpatchfound = true;
            }
            if (!newpatchfound)
            {
                TypeDefinition            typeToPatch2   = AssemblyDefinition.ReadAssembly(AssemblyFullPath).MainModule.Types.FirstOrDefault(t => t.Name == "StartGame");
                MethodDefinition          methodToPatch2 = typeToPatch2.Methods.FirstOrDefault(m => m.Name == ".ctor");
                Mono.Cecil.Cil.MethodBody methodBody2    = methodToPatch2.Body;
                if (methodBody2.CodeSize == 18)
                {
                    //not patched
                    oldpatchfound = false;
                }
                else if (methodBody2.CodeSize == 23)
                {
                    //0.1 patch found
                    oldpatchfound = true;
                }
            }
            if (!newpatchfound && !oldpatchfound)
            {
                if (File.Exists(Path.Combine(mscPath, @"mysummercar_Data\Managed\Assembly-CSharp.original.dll")))
                {
                    statusLabelText.Text = "Not patched, but MSCLoader 0.1 found (probably there was game update)";
                    Log("Patch not found, but MSCLoader 0.1 files found (probably there was game update)");
                    button1.Text    = "Install MSCLoader";
                    button1.Enabled = true;
                    oldFilesFound   = true;
                }
                else if (File.Exists(Path.Combine(mscPath, @"mysummercar_Data\Managed\MSCLoader.dll")) && File.Exists(Path.Combine(mscPath, @"mysummercar_Data\Managed\Assembly-CSharp.dll.backup")))
                {
                    statusLabelText.Text = "Not patched, but MSCLoader found (probably there was game update)";
                    Log("Patch not found, but MSCLoader files found (looks like there was game update)");
                    button1.Text    = "Install MSCLoader";
                    button1.Enabled = true;
                    isgameUpdated   = true;
                }
                else
                {
                    statusLabelText.Text = "Not installed";
                    Log("Patch not found, ready to install patch");
                    button1.Text    = "Install MSCLoader";
                    button1.Enabled = true;
                }
                statusLabelText.ForeColor = Color.Red;
            }
            else if (newpatchfound)
            {
                if (MD5HashFile(Path.Combine(mscPath, @"mysummercar_Data\Managed\MSCLoader.dll")) == MD5HashFile(Path.GetFullPath(Path.Combine("MSCLoader.dll", ""))))
                {
                    statusLabelText.Text = "Installed, MSCLoader.dll is up to date.";
                    Log("Newest patch found, no need to patch again");
                    button1.Enabled           = false;
                    button3.Enabled           = true;
                    statusLabelText.ForeColor = Color.Green;
                    mscloaderUpdate           = false;
                }
                else
                {
                    statusLabelText.Text = "Installed, but MSCLoader.dll mismatch, Update?";
                    Log("Newest patch found, but MSCLoader.dll version mismatch, update MSCLoader?");
                    button1.Enabled           = true;
                    button1.Text              = "Update MSCLoader";
                    button3.Enabled           = true;
                    statusLabelText.ForeColor = Color.Blue;
                    mscloaderUpdate           = true;
                }
            }
            else if (oldpatchfound)
            {
                statusLabelText.Text = "0.1 patch found, upgrade available";
                Log("Old patch found, ready to upgrade");
                button1.Text              = "Upgrade MSCLoader";
                button1.Enabled           = true;
                statusLabelText.ForeColor = Color.Orange;
                oldPatchFound             = true;
            }
        }
Пример #36
0
 public void Write(Mono.Cecil.Cil.MethodBody body)
 {
 }
Пример #37
0
 internal CilWorker(MethodBody body)
 {
     m_mbody  = body;
     m_instrs = m_mbody.Instructions;
 }
        private static void EncapsulateMethod(AssemblyDefinition assembly, ModuleDefinition module,
                                              TypeDefinition type, MethodDefinition method, string overrideName = null, string overrideMethod =
                                              nameof(AOPProcessor.OnMethod))
        {
            // New body for current method (capsule)
            var newMethodBody = new List <Instruction>();

            newMethodBody.Add(Instruction.Create(method.IsStatic ? OpCodes.Ldnull : OpCodes.Ldarg_0)); // ldnull / ldarg_0
            newMethodBody.Add(Instruction.Create(OpCodes.Ldtoken, type));
            newMethodBody.Add(Instruction.Create(OpCodes.Call, typeof(Type).GetMonoMethod(module, nameof(Type.GetTypeFromHandle))));

            var mName = method.Name;

            if (!string.IsNullOrEmpty(overrideName))
            {
                mName = overrideName;
            }

            newMethodBody.Add(Instruction.Create(OpCodes.Ldstr, mName));
            newMethodBody.Add(Instruction.Create(OpCodes.Ldc_I4, method.Parameters.Count));
            newMethodBody.Add(Instruction.Create(OpCodes.Newarr, module.ImportReference(typeof(object))));

            for (var num = 0; num < method.Parameters.Count; num++)
            {
                var param = method.Parameters[num];
                var pType = param.ParameterType;

                newMethodBody.Add(Instruction.Create(OpCodes.Dup));
                newMethodBody.Add(Instruction.Create(OpCodes.Ldc_I4, num));
                newMethodBody.Add(Instruction.Create(OpCodes.Ldarg, param));
                if (param.ParameterType.IsValueType || param.ParameterType.IsGenericParameter)
                {
                    newMethodBody.Add(Instruction.Create(OpCodes.Box, pType));
                }
                newMethodBody.Add(Instruction.Create(OpCodes.Stelem_Ref));
            }


            if (module.HasType(typeof(AOPProcessor)))
            {
                newMethodBody.Add(Instruction.Create(OpCodes.Call,
                                                     module.GetType(typeof(AOPProcessor))
                                                     .GetMethod(overrideMethod)));
            }
            else
            {
                newMethodBody.Add(Instruction.Create(OpCodes.Call, typeof(AOPProcessor).GetMonoMethod(module,
                                                                                                      overrideMethod)));
            }

            if (method.ReturnType.FullName != typeof(void).FullName)
            {
                if (method.ReturnType.IsValueType)
                {
                    newMethodBody.Add(Instruction.Create(OpCodes.Unbox_Any, method.ReturnType));
                }
            }
            else
            {
                newMethodBody.Add(Instruction.Create(OpCodes.Pop));
            }

            newMethodBody.Add(Instruction.Create(OpCodes.Ret));

            // Create new method
            var internalMethod = new MethodDefinition(method.Name + AOPProcessor.APPENDIX, method.Attributes, method.ReturnType);

            foreach (var param in method.Parameters)
            {
                var newParam = new ParameterDefinition(param.Name, param.Attributes, param.ParameterType);
                newParam.HasDefault = false;
                newParam.IsOptional = false;
                internalMethod.Parameters
                .Add(newParam);
            }

            // Copy generic parameters
            foreach (var genericParameter in method.GenericParameters)
            {
                internalMethod.GenericParameters
                .Add(new GenericParameter(genericParameter.Name, internalMethod));
            }

            var bodyClone = new MethodBody(method);

            bodyClone.AppendInstructions(newMethodBody);
            bodyClone.MaxStackSize = 8;

            // Replace method bodies
            internalMethod.Body = method.Body;
            method.Body         = bodyClone;
            type.Methods.Add(internalMethod);
        }
Пример #39
0
        private void ExtractBasicBlocksOfMethod(MethodReference method_reference)
        {
            MethodReference original_method_reference = method_reference;

            _methods_done.Add(original_method_reference.FullName);

            //          MethodReference new_method_reference = original_method_reference.SubstituteMethod2();
            //          method_reference = new_method_reference != null ? new_method_reference : original_method_reference;

            MethodDefinition method_definition = method_reference.Resolve();

            if (method_definition == null || method_definition.Body == null)
            {
                return;
            }
            int         change_set        = Cfg.StartChangeSet();
            int         instruction_count = method_definition.Body.Instructions.Count;
            List <INST> split_point       = new List <INST>();

            CFG.Vertex basic_block = (CFG.Vertex)Cfg.AddVertex(new CFG.Vertex()
            {
                Name = Cfg.NewNodeNumber().ToString()
            });
            basic_block._method_definition = method_definition;
            basic_block._method_reference  = original_method_reference;
            basic_block.Entry = basic_block;
            basic_block.Exit  = basic_block;
            basic_block.Entry.BlocksOfMethod = new List <CFG.Vertex>();
            basic_block.Entry.BlocksOfMethod.Add(basic_block);
            Cfg.Entries.Add(basic_block);

            // Add instructions to the basic block, including debugging information.
            // First, get debugging information on line/column/offset in method.
            if (!original_method_reference.Module.HasSymbols)
            {
                // Try to get symbols, but if none available, don't worry about it.
                try { original_method_reference.Module.ReadSymbols(); } catch { }
            }
            var symbol_reader            = original_method_reference.Module.SymbolReader;
            var method_debug_information = symbol_reader?.Read(method_definition);
            Collection <SequencePoint> sequence_points = method_debug_information != null ? method_debug_information.SequencePoints : new Collection <SequencePoint>();

            Mono.Cecil.Cil.MethodBody body = method_definition.Body;
            if (body == null)
            {
                throw new Exception("Body null, not expecting it to be.");
            }
            if (body.Instructions == null)
            {
                throw new Exception("Body has instructions collection.");
            }
            if (body.Instructions.Count == 0)
            {
                throw new Exception("Body instruction count is zero.");
            }
            SequencePoint previous_sp = null;

            for (int j = 0; j < instruction_count; ++j)
            {
                Mono.Cecil.Cil.Instruction instruction = body.Instructions[j];
                SequencePoint sp = sequence_points.Where(s => { return(s.Offset == instruction.Offset); }).FirstOrDefault();
                if (sp == null)
                {
                    sp = previous_sp;
                }
                INST wrapped_instruction = INST.Wrap(instruction, basic_block, sp);
                basic_block.Instructions.Add(wrapped_instruction);
                if (sp != null)
                {
                    previous_sp = sp;
                }
            }

            var instructions_before_splits = basic_block.Instructions.ToList();

            // Accumulate targets of jumps. These are split points for block "v".
            // Accumalated splits are in "leader_list" following this for-loop.
            for (int j = 0; j < instruction_count; ++j)
            {
                INST wrapped_instruction                = basic_block.Instructions[j];
                Mono.Cecil.Cil.OpCode      opcode       = wrapped_instruction.OpCode;
                Mono.Cecil.Cil.FlowControl flow_control = opcode.FlowControl;

                switch (flow_control)
                {
                case Mono.Cecil.Cil.FlowControl.Branch:
                case Mono.Cecil.Cil.FlowControl.Cond_Branch:
                {
                    object operand = wrapped_instruction.Operand;
                    // Two cases of branches:
                    // 1) operand is a single instruction;
                    // 2) operand is an array of instructions via a switch instruction.
                    // In doing this type casting, the resulting instructions are turned
                    // into def's, and operands no longer correspond to what was in the original
                    // method. We override the List<> compare to correct this problem.
                    Mono.Cecil.Cil.Instruction   single_instruction    = operand as Mono.Cecil.Cil.Instruction;
                    Mono.Cecil.Cil.Instruction[] array_of_instructions = operand as Mono.Cecil.Cil.Instruction[];
                    if (single_instruction != null)
                    {
                        INST sp = null;
                        for (int i = 0; i < basic_block.Instructions.Count(); ++i)
                        {
                            if (basic_block.Instructions[i].Offset == single_instruction.Offset &&
                                basic_block.Instructions[i].OpCode == single_instruction.OpCode)
                            {
                                sp = basic_block.Instructions[i];
                                break;
                            }
                        }
                        if (sp == null)
                        {
                            throw new Exception("Instruction go to not found.");
                        }
                        bool found = false;
                        foreach (INST split in split_point)
                        {
                            if (split.Offset == sp.Offset && split.OpCode == sp.OpCode)
                            {
                                found = true;
                                break;
                            }
                        }
                        if (!found)
                        {
                            split_point.Add(sp);
                        }
                    }
                    else if (array_of_instructions != null)
                    {
                        foreach (var ins in array_of_instructions)
                        {
                            Debug.Assert(ins != null);
                            INST sp = null;
                            for (int i = 0; i < basic_block.Instructions.Count(); ++i)
                            {
                                if (basic_block.Instructions[i].Offset == ins.Offset &&
                                    basic_block.Instructions[i].OpCode == ins.OpCode)
                                {
                                    sp = basic_block.Instructions[i];
                                    break;
                                }
                            }
                            if (sp == null)
                            {
                                throw new Exception("Instruction go to not found.");
                            }
                            bool found = false;
                            foreach (INST split in split_point)
                            {
                                if (split.Offset == sp.Offset && split.OpCode == sp.OpCode)
                                {
                                    found = true;
                                    break;
                                }
                            }
                            if (!found)
                            {
                                split_point.Add(sp);
                            }
                        }
                    }
                    else
                    {
                        throw new Exception("Unknown operand type for basic block partitioning.");
                    }
                }
                break;
                }

                // Split blocks after certain instructions, too.
                switch (flow_control)
                {
                case Mono.Cecil.Cil.FlowControl.Branch:
                case Mono.Cecil.Cil.FlowControl.Call:
                case Mono.Cecil.Cil.FlowControl.Cond_Branch:
                case Mono.Cecil.Cil.FlowControl.Return:
                case Mono.Cecil.Cil.FlowControl.Throw:
                {
                    if (flow_control == Mono.Cecil.Cil.FlowControl.Call && !Campy.Utils.Options.IsOn("split_at_calls"))
                    {
                        break;
                    }
                    if (j + 1 < instruction_count)
                    {
                        var  ins = basic_block.Instructions[j + 1].Instruction;
                        INST sp  = null;
                        for (int i = 0; i < basic_block.Instructions.Count(); ++i)
                        {
                            if (basic_block.Instructions[i].Offset == ins.Offset &&
                                basic_block.Instructions[i].OpCode == ins.OpCode)
                            {
                                sp = basic_block.Instructions[i];
                                break;
                            }
                        }
                        if (sp == null)
                        {
                            throw new Exception("Instruction go to not found.");
                        }
                        bool found = false;
                        foreach (INST split in split_point)
                        {
                            if (split.Offset == sp.Offset && split.OpCode == sp.OpCode)
                            {
                                found = true;
                                break;
                            }
                        }
                        if (!found)
                        {
                            split_point.Add(sp);
                        }
                    }
                }
                break;
                }
            }

            // Get try-catch blocks and add those split points.
            foreach (var eh in body.ExceptionHandlers)
            {
                var start = eh.TryStart;
                var end   = eh.TryEnd;
                // Split at try start.
                Instruction ins = start;
                INST        sp  = null;
                for (int i = 0; i < basic_block.Instructions.Count(); ++i)
                {
                    if (basic_block.Instructions[i].Offset == ins.Offset &&
                        basic_block.Instructions[i].OpCode == ins.OpCode)
                    {
                        sp = basic_block.Instructions[i];
                        break;
                    }
                }
                if (sp == null)
                {
                    throw new Exception("Instruction go to not found.");
                }
                bool found = false;
                foreach (INST split in split_point)
                {
                    if (split.Offset == sp.Offset && split.OpCode == sp.OpCode)
                    {
                        found = true;
                        break;
                    }
                }
                if (!found)
                {
                    split_point.Add(sp);
                }
            }

            // Note, we assume that these splits are within the same method.
            // Order the list according to offset from beginning of the method.
            List <INST> ordered_leader_list = new List <INST>();

            for (int j = 0; j < instruction_count; ++j)
            {
                // Order jump targets. These denote locations
                // where to split blocks. However, it's ordered,
                // so that splitting is done from last instruction in block
                // to first instruction in block.
                INST i = basic_block.Instructions[j];
                if (split_point.Contains(i,
                                         new LambdaComparer <INST>(
                                             (INST a, INST b)
                                             =>
                {
                    if (a.Offset != b.Offset)
                    {
                        return(false);
                    }
                    if (a.OpCode != b.OpCode)
                    {
                        return(false);
                    }
                    return(true);
                })))
                {
                    ordered_leader_list.Add(i);
                }
            }

            if (ordered_leader_list.Count != split_point.Count)
            {
                throw new Exception(
                          "Mono Cecil giving weird results for instruction operand type casting. Size of original split points not the same as order list of split points.");
            }

            // Split block at all jump targets.
            foreach (INST i in ordered_leader_list)
            {
                var owner = Cfg.PeekChangeSet(change_set).Where(
                    n => n.Instructions.Where(ins =>
                {
                    if (ins.Offset != i.Offset)
                    {
                        return(false);
                    }
                    if (ins.OpCode != i.OpCode)
                    {
                        return(false);
                    }
                    return(true);
                }
                                              ).Any()).ToList();
                // Check if there are multiple nodes with the same instruction or if there isn't
                // any node found containing the instruction. Either way, it's a programming error.
                if (owner.Count != 1)
                {
                    throw new Exception("Cannot find instruction!");
                }
                CFG.Vertex target_node = owner.FirstOrDefault();
                var        j           = target_node.Instructions.FindIndex(a =>
                {
                    if (a.Offset != i.Offset)
                    {
                        return(false);
                    }
                    if (a.OpCode != i.OpCode)
                    {
                        return(false);
                    }
                    return(true);
                });
                CFG.Vertex new_node = Split(target_node, j);
            }


            LambdaComparer <Instruction> fixed_comparer = new LambdaComparer <Instruction>(
                (Instruction a, Instruction b)
                => a.Offset == b.Offset &&
                a.OpCode == b.OpCode
                );

            // Add in all edges.
            var list_new_nodes = Cfg.PopChangeSet(change_set);

            foreach (var node in list_new_nodes)
            {
                int  node_instruction_count = node.Instructions.Count;
                INST last_instruction       = node.Instructions[node_instruction_count - 1];

                Mono.Cecil.Cil.OpCode      opcode       = last_instruction.OpCode;
                Mono.Cecil.Cil.FlowControl flow_control = opcode.FlowControl;

                // Add jump edge.
                switch (flow_control)
                {
                case Mono.Cecil.Cil.FlowControl.Branch:
                case Mono.Cecil.Cil.FlowControl.Cond_Branch:
                {
                    // Two cases: i.Operand is a single instruction, or an array of instructions.
                    if (last_instruction.Operand as Mono.Cecil.Cil.Instruction != null)
                    {
                        // Handel leave instructions with code below.
                        if (!(last_instruction.OpCode.Code == Code.Leave ||
                              last_instruction.OpCode.Code == Code.Leave_S))
                        {
                            Mono.Cecil.Cil.Instruction target_instruction =
                                last_instruction.Operand as Mono.Cecil.Cil.Instruction;
                            CFG.Vertex target_node = list_new_nodes.FirstOrDefault(
                                (CFG.Vertex x) =>
                                {
                                    if (!fixed_comparer.Equals(x.Instructions.First().Instruction,
                                                               target_instruction))
                                    {
                                        return(false);
                                    }
                                    return(true);
                                });
                            if (target_node != null)
                            {
                                Cfg.AddEdge(new CFG.Edge()
                                    {
                                        From = node, To = target_node
                                    });
                            }
                        }
                    }
                    else if (last_instruction.Operand as Mono.Cecil.Cil.Instruction[] != null)
                    {
                        foreach (Mono.Cecil.Cil.Instruction target_instruction in
                                 (last_instruction.Operand as Mono.Cecil.Cil.Instruction[]))
                        {
                            CFG.Vertex target_node = list_new_nodes.FirstOrDefault(
                                (CFG.Vertex x) =>
                                {
                                    if (!fixed_comparer.Equals(x.Instructions.First().Instruction, target_instruction))
                                    {
                                        return(false);
                                    }
                                    return(true);
                                });
                            if (target_node != null)
                            {
                                Cfg.AddEdge(new CFG.Edge()
                                    {
                                        From = node, To = target_node
                                    });
                            }
                        }
                    }
                    else
                    {
                        throw new Exception("Unknown operand type for conditional branch.");
                    }
                    break;
                }
                }

                // Add fall through edge.
                switch (flow_control)
                {
                //case Mono.Cecil.Cil.FlowControl.Branch:
                //case Mono.Cecil.Cil.FlowControl.Break:
                case Mono.Cecil.Cil.FlowControl.Call:
                case Mono.Cecil.Cil.FlowControl.Cond_Branch:
                case Mono.Cecil.Cil.FlowControl.Meta:
                case Mono.Cecil.Cil.FlowControl.Next:
                case Mono.Cecil.Cil.FlowControl.Phi:
                case Mono.Cecil.Cil.FlowControl.Throw:
                {
                    int next = instructions_before_splits.FindIndex(
                        n =>
                        {
                            var r = n == last_instruction;
                            return(r);
                        }
                        );
                    if (next < 0)
                    {
                        break;
                    }
                    next += 1;
                    if (next >= instructions_before_splits.Count)
                    {
                        break;
                    }
                    var        next_instruction = instructions_before_splits[next];
                    var        owner            = next_instruction.Block;
                    CFG.Vertex target_node      = owner;
                    Cfg.AddEdge(new CFG.Edge()
                        {
                            From = node, To = target_node
                        });
                }
                break;

                case Mono.Cecil.Cil.FlowControl.Return:
                    if (last_instruction.Instruction.OpCode.Code == Code.Endfinally)
                    {
                        // Although the exception handling is like a procedure call,
                        // local variables are all accessible. So, we need to copy stack
                        // values around. In addition, we have to create a fall through
                        // even though there is stack unwinding.
                        int next = instructions_before_splits.FindIndex(
                            n =>
                        {
                            var r = n == last_instruction;
                            return(r);
                        }
                            );
                        if (next < 0)
                        {
                            break;
                        }
                        next += 1;
                        if (next >= instructions_before_splits.Count)
                        {
                            break;
                        }
                        var        next_instruction = instructions_before_splits[next];
                        var        owner            = next_instruction.Block;
                        CFG.Vertex target_node      = owner;
                        Cfg.AddEdge(new CFG.Edge()
                        {
                            From = node, To = target_node
                        });
                    }
                    break;
                }
            }

            // Get inclusive start/exclusive end ranges of try/catch/finally.
            Dictionary <int, int> exclusive_eh_range = new Dictionary <int, int>();

            foreach (var eh in body.ExceptionHandlers)
            {
                int try_start = eh.TryStart.Offset;
                int eh_end    = eh.TryEnd != null ? eh.TryEnd.Offset : 0;
                if (eh.TryEnd != null && eh.TryEnd.Offset > eh_end)
                {
                    eh_end = eh.TryEnd.Offset;
                }
                if (eh.HandlerEnd != null && eh.HandlerEnd.Offset > eh_end)
                {
                    eh_end = eh.HandlerEnd.Offset;
                }
                exclusive_eh_range[try_start] = eh_end;
            }
            // Get inclusive start/inclusive end ranges of try/catch/finally.
            Dictionary <int, int> inclusive_eh_range = new Dictionary <int, int>();

            foreach (var pair in exclusive_eh_range)
            {
                int previous_instruction_address = 0;
                foreach (var i in body.Instructions)
                {
                    if (pair.Value == i.Offset)
                    {
                        inclusive_eh_range[pair.Key] = previous_instruction_address;
                        break;
                    }
                    previous_instruction_address = i.Offset;
                }
            }
            // Get "finally" blocks for each try, if there is one.
            Dictionary <int, CFG.Vertex> try_finally_block = new Dictionary <int, CFG.Vertex>();

            foreach (var eh in body.ExceptionHandlers)
            {
                if (eh.HandlerType == ExceptionHandlerType.Finally)
                {
                    var finally_entry_block = list_new_nodes.Where(
                        n =>
                    {
                        var first = n.Instructions.First().Instruction;
                        if (first.Offset == eh.HandlerStart.Offset)
                        {
                            return(true);
                        }
                        else
                        {
                            return(false);
                        }
                    }).First();
                    try_finally_block[eh.TryStart.Offset] = finally_entry_block;
                }
            }
            // Set block properties.
            foreach (var eh in body.ExceptionHandlers)
            {
                var block = list_new_nodes.Where(
                    n =>
                {
                    var first = n.Instructions.First().Instruction;
                    if (first.Offset == eh.HandlerStart.Offset)
                    {
                        return(true);
                    }
                    else
                    {
                        return(false);
                    }
                }).First();
                block.CatchType        = eh.CatchType;
                block.IsCatch          = eh.HandlerType == ExceptionHandlerType.Catch;
                block.ExceptionHandler = eh;
            }
            // Get "try" block for each try.
            Dictionary <int, CFG.Vertex> try_entry_block = new Dictionary <int, CFG.Vertex>();

            foreach (var pair in inclusive_eh_range)
            {
                int start       = pair.Key;
                var entry_block = list_new_nodes.Where(
                    n =>
                {
                    var first = n.Instructions.First().Instruction;
                    if (first.Offset == start)
                    {
                        return(true);
                    }
                    else
                    {
                        return(false);
                    }
                }).First();
                try_entry_block[start] = entry_block;
            }
            // Get entry block for each exception handler.
            Dictionary <int, CFG.Vertex> eh_entry_block = new Dictionary <int, CFG.Vertex>();

            foreach (var eh in body.ExceptionHandlers)
            {
                int start       = eh.HandlerStart.Offset;
                var entry_block = list_new_nodes.Where(
                    n =>
                {
                    var first = n.Instructions.First().Instruction;
                    if (first.Offset == start)
                    {
                        return(true);
                    }
                    else
                    {
                        return(false);
                    }
                }).First();
                eh_entry_block[start] = entry_block;
            }

            foreach (var eh in body.ExceptionHandlers)
            {
                int start     = eh.TryStart.Offset;
                var try_block = try_entry_block[start];
                int eh_start  = eh.HandlerStart.Offset;
                var eh_block  = eh_entry_block[eh_start];
                if (eh.HandlerType == ExceptionHandlerType.Finally)
                {
                    continue;
                }
                foreach (var prev in list_new_nodes.First()._graph.Predecessors(try_block))
                {
                    Cfg.AddEdge(new CFG.Edge()
                    {
                        From = prev, To = eh_block
                    });
                }
            }

            // Go through all CIL "leave" instructions and draw up edges. Any leave to end of
            // endfinally block requires edge to finally block, not the following instruction.
            foreach (var node in list_new_nodes)
            {
                int  node_instruction_count             = node.Instructions.Count;
                INST leave_instruction                  = node.Instructions[node_instruction_count - 1];
                Mono.Cecil.Cil.OpCode      opcode       = leave_instruction.OpCode;
                Mono.Cecil.Cil.FlowControl flow_control = opcode.FlowControl;
                if (!(leave_instruction.OpCode.Code == Code.Leave || leave_instruction.OpCode.Code == Code.Leave_S))
                {
                    continue;
                }

                // Link up any leave instructions
                object operand = leave_instruction.Operand;
                Mono.Cecil.Cil.Instruction   single_instruction    = operand as Mono.Cecil.Cil.Instruction;
                Mono.Cecil.Cil.Instruction[] array_of_instructions = operand as Mono.Cecil.Cil.Instruction[];
                if (single_instruction == null)
                {
                    throw new Exception("Malformed leave instruction.");
                }
                KeyValuePair <int, int> pair = inclusive_eh_range.Where(p => p.Key <= leave_instruction.Instruction.Offset &&
                                                                        leave_instruction.Instruction.Offset <= p.Value).FirstOrDefault();
                // pair indicates what try/catch/finally block. If not in a try/catch/finally,
                // draw edge to destination. If the destination is outside try/catch/finally,
                // draw edge to destination.
                if (pair.Value == 0 || single_instruction.Offset >= pair.Key && single_instruction.Offset <= pair.Value)
                {
                    var whereever = list_new_nodes.Where(
                        n =>
                    {
                        var first = n.Instructions.First().Instruction;
                        if (first.Offset == single_instruction.Offset)
                        {
                            return(true);
                        }
                        else
                        {
                            return(false);
                        }
                    }).First();
                    Cfg.AddEdge(new CFG.Edge()
                    {
                        From = node, To = whereever
                    });
                    continue;
                }
                if (try_finally_block.ContainsKey(pair.Key))
                {
                    Cfg.AddEdge(new CFG.Edge()
                    {
                        From = node, To = try_finally_block[pair.Key]
                    });
                }
                else
                {
                    var whereever = list_new_nodes.Where(
                        n =>
                    {
                        var first = n.Instructions.First().Instruction;
                        if (first.Offset == single_instruction.Offset)
                        {
                            return(true);
                        }
                        else
                        {
                            return(false);
                        }
                    }).First();
                    Cfg.AddEdge(new CFG.Edge()
                    {
                        From = node, To = whereever
                    });
                }
            }

            if (Campy.Utils.Options.IsOn("detailed_import_computation_trace"))
            {
                Cfg.OutputDotGraph();
            }
            if (Campy.Utils.Options.IsOn("detailed_import_computation_trace"))
            {
                Cfg.OutputEntireGraph();
            }
        }
Пример #40
0
    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 isMethodLogExecEndAttributeExist = Method.CustomAttributes.ContainsAttribute("Yagasoft.Libraries.Common.LogExecEndAttribute");

        if (isMethodLogExecEndAttributeExist)
        {
            LogInfo($">> Method is set to end execution.");
            endInstructions.AddRange(GetExecEndInstructions());
        }

        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();
    }
        private bool GenerateCalls(TypeReference producerRef, TypeReference jobStructType, MethodBody body, ILProcessor processor, HashSet <string> declaredGenerics)
        {
            try
            {
                var carrierType = producerRef.CheckedResolve();
                MethodDefinition methodToCall = null;
                while (carrierType != null)
                {
                    methodToCall = carrierType.GetMethods().FirstOrDefault((x) => x.Name == "EarlyJobInit" && x.Parameters.Count == 0 && x.IsStatic && x.IsPublic);

                    if (methodToCall != null)
                    {
                        break;
                    }

                    carrierType = carrierType.DeclaringType;
                }

                // Legacy jobs lazy initialize.
                if (methodToCall == null)
                {
                    return(false);
                }

                // We need a separate solution for generic jobs
                if (jobStructType.HasGenericParameters)
                {
                    if (!declaredGenerics.Contains(jobStructType.FullName))
                    {
                        AddDiagnostic(UserError.DC3002(jobStructType));
                    }
                    return(false);
                }

                var asm = AssemblyDefinition.MainModule;

                var errorHandler      = asm.ImportReference((asm.ImportReference(typeof(EarlyInitHelpers)).Resolve().Methods.First(x => x.Name == nameof(EarlyInitHelpers.JobReflectionDataCreationFailed))));
                var typeType          = asm.ImportReference(typeof(Type)).CheckedResolve();
                var getTypeFromHandle = asm.ImportReference(typeType.Methods.FirstOrDefault((x) => x.Name == "GetTypeFromHandle"));

                var mref = asm.ImportReference(asm.ImportReference(methodToCall).MakeGenericInstanceMethod(jobStructType));

                var callInsn   = Instruction.Create(OpCodes.Call, mref);
                var handler    = Instruction.Create(OpCodes.Nop);
                var landingPad = Instruction.Create(OpCodes.Nop);

                processor.Append(callInsn);
                processor.Append(handler);

                // This craziness is equivalent to typeof(n)
                processor.Append(Instruction.Create(OpCodes.Ldtoken, jobStructType));
                processor.Append(Instruction.Create(OpCodes.Call, getTypeFromHandle));
                processor.Append(Instruction.Create(OpCodes.Call, errorHandler));
                processor.Append(landingPad);

                var leaveSuccess = Instruction.Create(OpCodes.Leave, landingPad);
                var leaveFail    = Instruction.Create(OpCodes.Leave, landingPad);
                processor.InsertAfter(callInsn, leaveSuccess);
                processor.InsertBefore(landingPad, leaveFail);

                var exc = new ExceptionHandler(ExceptionHandlerType.Catch);
                exc.TryStart     = callInsn;
                exc.TryEnd       = leaveSuccess.Next;
                exc.HandlerStart = handler;
                exc.HandlerEnd   = leaveFail.Next;
                exc.CatchType    = asm.ImportReference(typeof(Exception));
                body.ExceptionHandlers.Add(exc);
                return(true);
            }
            catch (Exception ex)
            {
                AddDiagnostic(InternalCompilerError.DCICE300(producerRef, jobStructType, ex));
            }

            return(false);
        }
Пример #42
0
        /// <summary>
        /// Emits the IL that calculates a hash code from a given service type.
        /// </summary>
        /// <param name="module">The module that holds the target type.</param>
        /// <param name="body">The body of the GetServiceHashCode method.</param>
        /// <param name="il">The <see cref="ILProcessor"/> that will be used to emit the instructions.</param>
        /// <param name="getHashCodeMethod">The <see cref="Object.GetHashCode"/> method.</param>
        /// <returns>The variable that holds the hash code.</returns>
        private static VariableDefinition EmitGetServiceTypeHashCode(ModuleDefinition module, Mono.Cecil.Cil.MethodBody body, ILProcessor il, MethodReference getHashCodeMethod)
        {
            // Get the hash code for the service type
            var hashVariable = AddLocals(module, body);

            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Callvirt, getHashCodeMethod);
            il.Emit(OpCodes.Stloc, hashVariable);

            return(hashVariable);
        }
Пример #43
0
        private void PatchAssembly(Action <byte[]> callback)
        {
            if (isPatching)
            {
                Interface.Oxide.LogWarning("Already patching plugin assembly: {0} (ignoring)", PluginNames.ToSentence());
                RemoteLogger.Warning($"Already patching plugin assembly: {PluginNames.ToSentence()}");
                return;
            }

            var startedAt = Interface.Oxide.Now;

            isPatching = true;
            ThreadPool.QueueUserWorkItem(_ =>
            {
                try
                {
                    AssemblyDefinition definition;
                    using (var stream = new MemoryStream(RawAssembly))
                        definition = AssemblyDefinition.ReadAssembly(stream);

                    var exceptionConstructor = typeof(UnauthorizedAccessException).GetConstructor(new[] { typeof(string) });
                    var securityException    = definition.MainModule.Import(exceptionConstructor);

                    Action <TypeDefinition> patchModuleType = null;
                    patchModuleType = type =>
                    {
                        foreach (var method in type.Methods)
                        {
                            var changedMethod = false;

                            if (method.Body == null)
                            {
                                if (method.HasPInvokeInfo)
                                {
                                    method.Attributes &= ~MethodAttributes.PInvokeImpl;
                                    var body           = new MethodBody(method);
                                    body.Instructions.Add(Instruction.Create(OpCodes.Ldstr, "PInvoke access is restricted, you are not allowed to use PInvoke"));
                                    body.Instructions.Add(Instruction.Create(OpCodes.Newobj, securityException));
                                    body.Instructions.Add(Instruction.Create(OpCodes.Throw));
                                    method.Body = body;
                                }
                            }
                            else
                            {
                                var replacedMethod = false;
                                foreach (var variable in method.Body.Variables)
                                {
                                    if (!IsNamespaceBlacklisted(variable.VariableType.FullName))
                                    {
                                        continue;
                                    }

                                    var body = new MethodBody(method);
                                    body.Instructions.Add(Instruction.Create(OpCodes.Ldstr, $"System access is restricted, you are not allowed to use {variable.VariableType.FullName}"));
                                    body.Instructions.Add(Instruction.Create(OpCodes.Newobj, securityException));
                                    body.Instructions.Add(Instruction.Create(OpCodes.Throw));
                                    method.Body    = body;
                                    replacedMethod = true;
                                    break;
                                }
                                if (replacedMethod)
                                {
                                    continue;
                                }

                                var instructions = method.Body.Instructions;
                                var ilProcessor  = method.Body.GetILProcessor();
                                var first        = instructions.First();

                                var i = 0;
                                while (i < instructions.Count)
                                {
                                    if (changedMethod)
                                    {
                                        break;
                                    }
                                    var instruction = instructions[i];
                                    if (instruction.OpCode == OpCodes.Ldtoken)
                                    {
                                        var operand = instruction.Operand as IMetadataTokenProvider;
                                        var token   = operand?.ToString();
                                        if (IsNamespaceBlacklisted(token))
                                        {
                                            ilProcessor.InsertBefore(first, Instruction.Create(OpCodes.Ldstr, $"System access is restricted, you are not allowed to use {token}"));
                                            ilProcessor.InsertBefore(first, Instruction.Create(OpCodes.Newobj, securityException));
                                            ilProcessor.InsertBefore(first, Instruction.Create(OpCodes.Throw));
                                            changedMethod = true;
                                        }
                                    }
                                    else if (instruction.OpCode == OpCodes.Call || instruction.OpCode == OpCodes.Calli || instruction.OpCode == OpCodes.Callvirt)
                                    {
                                        var methodCall    = instruction.Operand as MethodReference;
                                        var fullNamespace = methodCall?.DeclaringType.FullName;

                                        if ((fullNamespace == "System.Type" && methodCall.Name == "GetType") || IsNamespaceBlacklisted(fullNamespace))
                                        {
                                            ilProcessor.InsertBefore(first, Instruction.Create(OpCodes.Ldstr, $"System access is restricted, you are not allowed to use {fullNamespace}"));
                                            ilProcessor.InsertBefore(first, Instruction.Create(OpCodes.Newobj, securityException));
                                            ilProcessor.InsertBefore(first, Instruction.Create(OpCodes.Throw));
                                            changedMethod = true;
                                        }
                                    }
                                    else if (instruction.OpCode == OpCodes.Ldfld)
                                    {
                                        var fieldType     = instruction.Operand as FieldReference;
                                        var fullNamespace = fieldType?.FieldType.FullName;
                                        if (IsNamespaceBlacklisted(fullNamespace))
                                        {
                                            ilProcessor.InsertBefore(first, Instruction.Create(OpCodes.Ldstr, $"System access is restricted, you are not allowed to use {fullNamespace}"));
                                            ilProcessor.InsertBefore(first, Instruction.Create(OpCodes.Newobj, securityException));
                                            ilProcessor.InsertBefore(first, Instruction.Create(OpCodes.Throw));
                                            changedMethod = true;
                                        }
                                    }
                                    i++;
                                }
                            }

                            if (changedMethod)
                            {
                                method.Body?.OptimizeMacros();

                                /*//Interface.Oxide.LogDebug("Updating {0} instruction offsets: {1}", instructions.Count, method.FullName);
                                 * int curoffset = 0;
                                 * for (var i = 0; i < instructions.Count; i++)
                                 * {
                                 *  var instruction = instructions[i];
                                 *  instruction.Previous = (i == 0) ? null : instructions[i - 1];
                                 *  instruction.Next = (i == instructions.Count - 1) ? null : instructions[i + 1];
                                 *  instruction.Offset = curoffset;
                                 *  curoffset += instruction.GetSize();
                                 *  //Interface.Oxide.LogDebug("    {0}", instruction.ToString());
                                 * }*/
                            }
                        }
                        foreach (var nestedType in type.NestedTypes)
                        {
                            patchModuleType(nestedType);
                        }
                    };

                    foreach (var type in definition.MainModule.Types)
                    {
                        patchModuleType(type);

                        if (type.Namespace == "Oxide.Plugins")
                        {
                            if (PluginNames.Contains(type.Name))
                            {
                                var constructor = type.Methods.FirstOrDefault(m => !m.IsStatic && m.IsConstructor && !m.HasParameters && !m.IsPublic);
                                if (constructor != null)
                                {
                                    var plugin = CompilablePlugins.SingleOrDefault(p => p.Name == type.Name);
                                    if (plugin != null)
                                    {
                                        plugin.CompilerErrors = "Primary constructor in main class must be public";
                                    }
                                }
                                else
                                {
                                    new DirectCallMethod(definition.MainModule, type);
                                }
                            }
                            else
                            {
                                Interface.Oxide.LogWarning(
                                    $"A plugin has polluted the global namespace by defining {type.Name}: {PluginNames.ToSentence()}");
                                RemoteLogger.Info(
                                    $"A plugin has polluted the global namespace by defining {type.Name}: {PluginNames.ToSentence()}");
                            }
                        }
                    }

                    // TODO: Why is there no error on boot using this?
                    foreach (var type in definition.MainModule.Types)
                    {
                        if (type.Namespace != "Oxide.Plugins" || !PluginNames.Contains(type.Name))
                        {
                            continue;
                        }
                        foreach (var m in type.Methods.Where(m => !m.IsStatic && !m.HasGenericParameters && !m.ReturnType.IsGenericParameter && !m.IsSetter && !m.IsGetter))
                        {
                            foreach (var parameter in m.Parameters)
                            {
                                foreach (var attribute in parameter.CustomAttributes)
                                {
                                    //Interface.Oxide.LogInfo($"{m.FullName} - {parameter.Name} - {attribute.Constructor.FullName}");
                                }
                            }
                        }
                    }

                    using (var stream = new MemoryStream())
                    {
                        definition.Write(stream);
                        PatchedAssembly = stream.ToArray();
                    }

                    Interface.Oxide.NextTick(() =>
                    {
                        isPatching = false;
                        //Interface.Oxide.LogDebug("Patching {0} assembly took {1:0.00} ms", ScriptName, Interface.Oxide.Now - startedAt);
                        callback(PatchedAssembly);
                    });
                }
                catch (Exception ex)
                {
                    Interface.Oxide.NextTick(() =>
                    {
                        isPatching = false;
                        Interface.Oxide.LogException($"Exception while patching: {PluginNames.ToSentence()}", ex);
                        RemoteLogger.Exception($"Exception while patching: {PluginNames.ToSentence()}", ex);
                        callback(null);
                    });
                }
            });
        }
Пример #44
0
        internal static MethodBody Clone(MethodBody body, MethodDefinition parent, ImportContext context)
        {
            MethodBody nb = new MethodBody(parent);

            nb.MaxStack   = body.MaxStack;
            nb.InitLocals = body.InitLocals;
            nb.CodeSize   = body.CodeSize;
            foreach (VariableDefinition var in body.Variables)
            {
                nb.Variables.Add(new VariableDefinition(
                                     context.Import(var.VariableType)));
            }

            foreach (Instruction instr in body.Instructions)
            {
                Instruction ni = new Instruction(instr.OpCode);

                switch (instr.OpCode.OperandType)
                {
                case OperandType.InlineParam:
                case OperandType.ShortInlineParam:
                    int param = body.Method.Parameters.IndexOf((ParameterDefinition)instr.Operand);
                    ni.Operand = parent.Parameters [param];
                    break;

                case OperandType.InlineVar:
                case OperandType.ShortInlineVar:
                    int var = body.Variables.IndexOf((VariableDefinition)instr.Operand);
                    ni.Operand = nb.Variables [var];
                    break;

                case OperandType.InlineField:
                    ni.Operand = context.Import((FieldReference)instr.Operand);
                    break;

                case OperandType.InlineMethod:
                    ni.Operand = context.Import((MethodReference)instr.Operand);
                    break;

                case OperandType.InlineType:
                    ni.Operand = context.Import((TypeReference)instr.Operand);
                    break;

                case OperandType.InlineTok:
                    if (instr.Operand is TypeReference)
                    {
                        ni.Operand = context.Import((TypeReference)instr.Operand);
                    }
                    else if (instr.Operand is FieldReference)
                    {
                        ni.Operand = context.Import((FieldReference)instr.Operand);
                    }
                    else if (instr.Operand is MethodReference)
                    {
                        ni.Operand = context.Import((MethodReference)instr.Operand);
                    }
                    break;

                case OperandType.ShortInlineBrTarget:
                case OperandType.InlineBrTarget:
                    break;

                default:
                    ni.Operand = instr.Operand;
                    break;
                }

                nb.Instructions.Add(ni);
            }

            for (int i = 0; i < body.Instructions.Count; i++)
            {
                Instruction instr = nb.Instructions [i];
                if (instr.OpCode.OperandType != OperandType.ShortInlineBrTarget &&
                    instr.OpCode.OperandType != OperandType.InlineBrTarget)
                {
                    continue;
                }

                instr.Operand = GetInstruction(body, nb, (Instruction)body.Instructions [i].Operand);
            }

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

                switch (eh.Type)
                {
                case ExceptionHandlerType.Catch:
                    neh.CatchType = context.Import(eh.CatchType);
                    break;

                case ExceptionHandlerType.Filter:
                    neh.FilterStart = GetInstruction(body, nb, eh.FilterStart);
                    neh.FilterEnd   = GetInstruction(body, nb, eh.FilterEnd);
                    break;
                }

                nb.ExceptionHandlers.Add(neh);
            }

            return(nb);
        }
Пример #45
0
 static bool IsEmptyMethodBody(MethodBody body)
 {
     return(body.instructions.IsNullOrEmpty() &&
            body.variables.IsNullOrEmpty());
 }
        private void _CopyMethodToDefinition()
        {
            MethodBase method     = Method;
            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, false);
                    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], false);
                    }
                    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, false);
                handler.TryEnd   = GetInstruction(handler.TryStart.Offset + clause.TryLength - 1, false);

                handler.HandlerStart = GetInstruction(clause.HandlerOffset, false);
                handler.FilterStart  = GetInstruction(clause.FilterOffset, false);
                handler.HandlerEnd   = GetInstruction((handler.FilterStart ?? handler.HandlerStart).Offset + clause.HandlerLength + 1, true);

                handler.CatchType = 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, bool isEnd)
            {
                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 (isEnd)
                    {
                        if (offset == instr.Offset + instr.GetSize() - 1)
                        {
                            return(instr);
                        }
                    }
                    else
                    {
                        if (offset == instr.Offset)
                        {
                            return(instr);
                        }
                    }

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

                return(null);
            }
        }
Пример #47
0
        private List <Instruction> CreateInstructionsToInject(ModuleDefinition moduleDefinition, MethodBody body)
        {
            var mRef2 = moduleDefinition.ImportReference(typeof(Console).GetMethod("WriteLine", BindingFlags.Public | BindingFlags.Static, null, new Type[]
            {
                typeof(string), typeof(object)
            }, null));

            var instructions = new List <Instruction>();

            //build up call
            instructions.Add(Instruction.Create(OpCodes.Ldstr, "Hello {0}!"));
            instructions.Add(Instruction.Create(OpCodes.Ldstr, "Joe"));
            instructions.Add(Instruction.Create(OpCodes.Call, mRef2));
            instructions.Add(Instruction.Create(OpCodes.Nop));

            //instructions.Add(Instruction.Create(OpCodes.Ldstr, "Hello {0}!"));
            //instructions.Add(Instruction.Create(OpCodes.Ldstr, "Jim"));
            //instructions.Add(Instruction.Create(OpCodes.Call, mRef2));

            //instructions.Add(Instruction.Create(OpCodes.Ldstr, "Bye {0}!"));
            //instructions.Add(Instruction.Create(OpCodes.Ldstr, "Jim"));
            //instructions.Add(Instruction.Create(OpCodes.Call, mRef2));

            return(instructions);
        }
Пример #48
0
 public static MethodReference Import(MethodBody body, MethodReference newMeth)
 => body.Method.DeclaringType.Module.ImportReference(newMeth);
Пример #49
0
 public Branch(MethodBody body, OpCode branch)
 {
     this.Body        = body;
     this.Instruction = Instruction.Create(branch, Instruction.Create(OpCodes.Nop));
 }
Пример #50
0
        private void PatchAssembly(int version, Action callback)
        {
            if (isPatching)
            {
                Interface.GetMod().LogInfo("Already patching plugin assembly: {0} (ignoring)", ScriptName);
                return;
            }

            if (version == LastGoodVersion)
            {
                //Interface.GetMod().LogInfo("Plugin assembly has already been patched: {0}", Name);
                callback();
                return;
            }

            var path = string.Format("{0}\\{1}_{2}.dll", Interface.GetMod().TempDirectory, Name, version);

            //Interface.GetMod().LogInfo("Patching plugin assembly: {0}", Name);
            isPatching = true;
            ThreadPool.QueueUserWorkItem((_) =>
            {
                try
                {
                    var definition            = AssemblyDefinition.ReadAssembly(path);
                    var exception_constructor = typeof(UnauthorizedAccessException).GetConstructor(new Type[] { typeof(string) });
                    var security_exception    = definition.MainModule.Import(exception_constructor);

                    Action <TypeDefinition> patch_module_type = null;
                    patch_module_type = (type) =>
                    {
                        foreach (var method in type.Methods)
                        {
                            Collection <Instruction> instructions = null;
                            var changed_method = false;

                            if (method.Body == null)
                            {
                                if (method.HasPInvokeInfo)
                                {
                                    method.Attributes &= ~Mono.Cecil.MethodAttributes.PInvokeImpl;
                                    var body           = new Mono.Cecil.Cil.MethodBody(method);
                                    body.Instructions.Add(Instruction.Create(OpCodes.Ldstr, "PInvoke access is restricted, you are not allowed to use PInvoke"));
                                    body.Instructions.Add(Instruction.Create(OpCodes.Newobj, security_exception));
                                    body.Instructions.Add(Instruction.Create(OpCodes.Throw));
                                    method.Body = body;
                                }
                            }
                            else
                            {
                                var replaced_method = false;
                                foreach (var variable in method.Body.Variables)
                                {
                                    foreach (var namespace_name in blacklistedNamespaces)
                                    {
                                        if (variable.VariableType.FullName.StartsWith(namespace_name))
                                        {
                                            if (whitelistedNamespaces.Any(name => variable.VariableType.FullName.StartsWith(name)))
                                            {
                                                continue;
                                            }
                                            var body = new Mono.Cecil.Cil.MethodBody(method);
                                            body.Instructions.Add(Instruction.Create(OpCodes.Ldstr, "System access is restricted, you are not allowed to use " + variable.VariableType.FullName));
                                            body.Instructions.Add(Instruction.Create(OpCodes.Newobj, security_exception));
                                            body.Instructions.Add(Instruction.Create(OpCodes.Throw));
                                            method.Body     = body;
                                            replaced_method = true;
                                            break;
                                        }
                                    }
                                    if (replaced_method)
                                    {
                                        break;
                                    }
                                }
                                if (replaced_method)
                                {
                                    continue;
                                }

                                instructions = method.Body.Instructions;

                                var i = 0;
                                while (i < instructions.Count)
                                {
                                    var instruction = instructions[i];
                                    if (instruction.OpCode == OpCodes.Ldtoken)
                                    {
                                        var operand = instruction.Operand as IMetadataTokenProvider;
                                        var token   = operand.ToString();
                                        foreach (var namespace_name in blacklistedNamespaces)
                                        {
                                            if (token.StartsWith(namespace_name))
                                            {
                                                if (whitelistedNamespaces.Any(name => token.StartsWith(name)))
                                                {
                                                    continue;
                                                }
                                                instructions[i++] = Instruction.Create(OpCodes.Ldstr, "System access is restricted, you are not allowed to use " + token);
                                                instructions.Insert(i++, Instruction.Create(OpCodes.Newobj, security_exception));
                                                instructions.Insert(i, Instruction.Create(OpCodes.Throw));
                                                changed_method = true;
                                            }
                                        }
                                    }
                                    else if (instruction.OpCode == OpCodes.Call)
                                    {
                                        var method_call    = instruction.Operand as MethodReference;
                                        var full_namespace = method_call.DeclaringType.FullName;

                                        foreach (var namespace_name in blacklistedNamespaces)
                                        {
                                            if (full_namespace.StartsWith(namespace_name))
                                            {
                                                if (whitelistedNamespaces.Any(name => full_namespace.StartsWith(name)))
                                                {
                                                    continue;
                                                }

                                                for (var n = 0; n < method.Parameters.Count; n++)
                                                {
                                                    instructions.Insert(i++, Instruction.Create(OpCodes.Pop));
                                                }

                                                instructions[i++] = Instruction.Create(OpCodes.Ldstr, "System access is restricted, you are not allowed to use " + full_namespace);
                                                instructions.Insert(i++, Instruction.Create(OpCodes.Newobj, security_exception));
                                                instructions.Insert(i, Instruction.Create(OpCodes.Throw));

                                                changed_method = true;
                                            }
                                        }
                                    }
                                    i++;
                                }
                            }

                            if (changed_method)
                            {
                                //Interface.GetMod().LogInfo("Updating {0} instruction offsets: {1}", instructions.Count, method.FullName);
                                int curoffset = 0;
                                for (var i = 0; i < instructions.Count; i++)
                                {
                                    var instruction      = instructions[i];
                                    instruction.Previous = (i == 0) ? null : instructions[i - 1];
                                    instruction.Next     = (i == instructions.Count - 1) ? null : instructions[i + 1];
                                    instruction.Offset   = curoffset;
                                    curoffset           += instruction.GetSize();
                                    //Interface.GetMod().LogInfo("    {0}", instruction.ToString());
                                }
                            }
                        }
                        foreach (var nested_type in type.NestedTypes)
                        {
                            patch_module_type(nested_type);
                        }
                    };

                    foreach (var type in definition.MainModule.Types)
                    {
                        patch_module_type(type);
                    }

                    definition.Write(path);

                    Interface.GetMod().NextTick(() =>
                    {
                        isPatching = false;
                        callback();
                    });
                }
                catch (Exception ex)
                {
                    isPatching = false;
                    Interface.GetMod().NextTick(() => Interface.GetMod().LogInfo("Exception while patching {0} assembly: {1}", ScriptName, ex.ToString()));
                }
            });
        }
Пример #51
0
 public override void VisitMethodBody(MethodBody body)
 {
     m_codeWriter.Empty();
 }
Пример #52
0
        private void ReplaceReturnWithLeaveInstructions(
            Mono.Cecil.Cil.MethodBody methodBody,
            Instruction leaveInstructionOperand,
            VariableDefinition returnVariable = null)
        {
            var ilProcessor = methodBody.GetILProcessor();
            var instructions = methodBody.Instructions;
            var exceptionHandlers = methodBody.ExceptionHandlers;

            Instruction storeReturnVariableInstruction = null;

            if (returnVariable != null)
            {
                storeReturnVariableInstruction = ilProcessor.Create(OpCodes.Stloc, returnVariable);
            }

            foreach (var instruction in instructions.ToList())
            {
                if (instruction.OpCode == OpCodes.Ret)
                {
                    var leaveInstruction = ilProcessor.Create(OpCodes.Leave, leaveInstructionOperand);
                    ilProcessor.Replace(instruction, leaveInstruction);

                    if (returnVariable != null)
                    {
                        ilProcessor.InsertBefore(leaveInstruction, storeReturnVariableInstruction);
                    }

                    instructions
                        .ToList()
                        .ForEach(i =>
                        {
                            if (i.Operand is Instruction operandInstruction &&
                                operandInstruction.Equals(instruction))
                            {
                                i.Operand = leaveInstruction;
                            }
                        });

                    exceptionHandlers
                        .ToList()
                        .ForEach(eHandler =>
                        {
                            if (eHandler.TryStart.Equals(instruction))
                            {
                                eHandler.TryStart = storeReturnVariableInstruction ?? leaveInstruction;
                            }

                            if (eHandler.TryEnd.Equals(instruction))
                            {
                                eHandler.TryEnd = storeReturnVariableInstruction ?? leaveInstruction;
                            }

                            if (eHandler.HandlerStart.Equals(instruction))
                            {
                                eHandler.HandlerStart = storeReturnVariableInstruction ?? leaveInstruction;
                            }

                            if (eHandler.HandlerEnd.Equals(instruction))
                            {
                                eHandler.HandlerEnd = storeReturnVariableInstruction ?? leaveInstruction;
                            }
                        });
                }
            }
        }
Пример #53
0
        private static Instruction GetFirstConstructorInstruction(MethodBody body)
        {
            var constructorInstruction = body.Instructions.FirstOrDefault(a => a.OpCode == OpCodes.Call && (a.Operand as MethodReference)?.Name == ".ctor");

            return(constructorInstruction);
        }
Пример #54
0
 internal ILProcessor(MethodBody body)
 {
     this.body         = body;
     this.instructions = body.Instructions;
 }
Пример #55
0
        private static bool AnalyzeMethodCalls(MethodDefinition methodDefinition, XElement entity, XElement newMethodNode)
        {
            XElement callsNode = null;

            bool result = false;

            Mono.Cecil.Cil.MethodBody body = methodDefinition.Body;
            if (null != body)
            {
                // method calls
                foreach (Instruction itemInstruction in body.Instructions)
                {
                    if (itemInstruction.OpCode.Name.StartsWith("callvirt"))
                    {
                        Mono.Cecil.Cil.Instruction methodInstruction = itemInstruction as Mono.Cecil.Cil.Instruction;
                        Mono.Cecil.MethodReference methodReference   = methodInstruction.Operand as Mono.Cecil.MethodReference;
                        string callName      = GetCallNameFromAnalyzeMethodCalls(methodReference);
                        string typeName      = GetNameFromNewObjMethodReference(methodReference);
                        string componentName = NetOfficeSupportTable.GetLibrary(typeName);

                        string[] testArray = typeName.Split(new string[] { "." }, StringSplitOptions.RemoveEmptyEntries);
                        if (testArray.Length >= 3 && testArray[2] == "Tools")
                        {
                            continue;
                        }
                        if ((typeName.StartsWith(_apiName)) && !typeName.Equals(_apiName + ".dll", StringComparison.InvariantCultureIgnoreCase) &&
                            CountOf(typeName, ".") > 1 && (!typeName.StartsWith("NetOffice.DeveloperToolbox")))
                        {
                            string[] supportByLibrary = _netOfficeSupportTable.GetTypeCallSupport(callName);
                            result = true;
                            if (null == callsNode)
                            {
                                callsNode = new XElement("Calls");
                                newMethodNode.Add(callsNode);
                            }

                            XElement newObject = new XElement("Entity",
                                                              new XElement("Parameters"),
                                                              new XAttribute("Type", typeName),
                                                              new XAttribute("Name", callName),
                                                              new XAttribute("Api", componentName));

                            callsNode.Add(newObject);
                            XElement supportByNode = new XElement("SupportByLibrary", new XAttribute("Api", componentName));
                            newObject.Add(supportByNode);
                            if (null != supportByLibrary)
                            {
                                supportByNode.Add(new XAttribute("Name", callName));
                                foreach (string item in supportByLibrary)
                                {
                                    supportByNode.Add(new XElement("Version", item));
                                }
                            }

                            bool resultParameter = AnalyzeMethodCallParameters(itemInstruction, newObject);
                        }
                    }
                }
            }

            return(result);
        }