Beispiel #1
0
		public static Instruction FindInstruction(AssemblyDefinition assembly, string typeName, string testMethodName, OpCode testInstruction)
		{
			MethodDefinition testMethod = FindMethod(assembly, typeName, testMethodName);
			Assert.IsNotNull(testMethod);

			return FindInstruction(testMethod, testInstruction);
		}
Beispiel #2
0
 private static int GetNegativeModifier(OpCode opCode)
 {
     switch (opCode.StackBehaviourPop)
     {
         case StackBehaviour.Pop0:
             return 0;
         case StackBehaviour.Pop1:
         case StackBehaviour.Popi:
         case StackBehaviour.Popref:
         case StackBehaviour.Varpop:
             return 1;
         case StackBehaviour.Pop1_pop1:
         case StackBehaviour.Popi_pop1:
         case StackBehaviour.Popi_popi:
         case StackBehaviour.Popi_popi8:
         case StackBehaviour.Popi_popr4:
         case StackBehaviour.Popi_popr8:
         case StackBehaviour.Popref_pop1:
         case StackBehaviour.Popref_popi:
             return 2;
         case StackBehaviour.Popi_popi_popi:
         case StackBehaviour.Popref_popi_popi:
         case StackBehaviour.Popref_popi_popi8:
         case StackBehaviour.Popref_popi_popr4:
         case StackBehaviour.Popref_popi_popr8:
         case StackBehaviour.Popref_popi_popref:
             return 3;
         case StackBehaviour.PopAll:
             return 1000;
     }
     return 0;
 }
Beispiel #3
0
        public static Instruction Create(OpCode opcode)
        {
            if (opcode.OperandType != OperandType.InlineNone)
                throw new ArgumentException ("opcode");

            return new Instruction (opcode, null);
        }
        static DynamicMethodDefinition()
        {
            foreach (FieldInfo field in typeof(System.Reflection.Emit.OpCodes).GetFields(BindingFlags.Public | BindingFlags.Static))
            {
                System.Reflection.Emit.OpCode reflOpCode = (System.Reflection.Emit.OpCode)field.GetValue(null);
                _ReflOpCodes[reflOpCode.Value] = reflOpCode;
            }

            foreach (FieldInfo field in typeof(Mono.Cecil.Cil.OpCodes).GetFields(BindingFlags.Public | BindingFlags.Static))
            {
                Mono.Cecil.Cil.OpCode cecilOpCode = (Mono.Cecil.Cil.OpCode)field.GetValue(null);
                _CecilOpCodes[cecilOpCode.Value] = cecilOpCode;
            }

            foreach (MethodInfo method in typeof(ILGenerator).GetMethods())
            {
                if (method.Name != "Emit")
                {
                    continue;
                }

                ParameterInfo[] args = method.GetParameters();
                if (args.Length != 2)
                {
                    continue;
                }

                if (args[0].ParameterType != typeof(System.Reflection.Emit.OpCode))
                {
                    continue;
                }
                _Emitters[args[1].ParameterType] = method;
            }
        }
Beispiel #5
0
 public static bool ReadSigKey(MethodDefinition DecryptMethod, OpCode[] KeySig, ref object val)
 {
     int score = 0;
     for (int i = 0; i < DecryptMethod.Body.Instructions.Count; i++)
     {
         if (DecryptMethod.Body.Instructions[i].OpCode == KeySig[score])
         {
             score++;
             if (score == KeySig.Length)
             {
                 if (DecryptMethod.Body.Instructions[i].Next != null)
                 {
                     if (DecryptMethod.Body.Instructions[i].Next.Operand != null)
                     {
                         val = DecryptMethod.Body.Instructions[i].Next.Operand;
                         return true;
                     }
                 }
             }
         }
         else
         {
             score = 0;
         }
     }
     return false;
 }
Beispiel #6
0
 static Instruction create(OpCode opcode, object operand)
 {
     return(new Instruction {
         OpCode = opcode,
         Operand = operand,
     });
 }
 private OpCodeInfo(Mono.Cecil.Cil.OpCode opcode)
 {
     base();
     this.opcode = opcode;
     this.set_CanThrow(true);
     return;
 }
		public Instruction Create (OpCode opcode)
		{
			if (opcode.OperandType != OperandType.InlineNone)
				throw new ArgumentException ("opcode");

			return FinalCreate (opcode);
		}
        private static AssemblyDefinition CreateTestAssembly(OpCode arithmeticOperator)
        {
            var name = new AssemblyNameDefinition("TestBitwiseOperatorTurtleOr", new Version(1, 0));
            var assembly = AssemblyDefinition.CreateAssembly(name, "TestClass", ModuleKind.Dll);
            var type = new TypeDefinition("TestBitwiseOperatorTurtleOr", "TestClass",
                               TypeAttributes.Class | TypeAttributes.Public);
            var intType = assembly.MainModule.Import(typeof(int));
            var method = new MethodDefinition("TestMethod", MethodAttributes.Public, intType);
            var leftParam = new ParameterDefinition("left", ParameterAttributes.In, intType);
            var rightParam = new ParameterDefinition("right", ParameterAttributes.In, intType);
            method.Parameters.Add(leftParam);
            method.Parameters.Add(rightParam);
            var resultVariable = new VariableDefinition(intType);
            method.Body.Variables.Add(resultVariable);

            var processor = method.Body.GetILProcessor();
            method.Body.Instructions.Add(processor.Create(OpCodes.Ldarg, leftParam));
            method.Body.Instructions.Add(processor.Create(OpCodes.Ldarg, rightParam));
            method.Body.Instructions.Add(processor.Create(arithmeticOperator));
            method.Body.Instructions.Add(processor.Create(OpCodes.Stloc, resultVariable));
            method.Body.Instructions.Add(processor.Create(OpCodes.Ldloc, resultVariable));
            method.Body.Instructions.Add(processor.Create(OpCodes.Ret));

            type.Methods.Add(method);
            assembly.MainModule.Types.Add(type);
            return assembly;
        }
Beispiel #10
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="toSimplify"></param>
 /// <returns></returns>
 private static OpCode SimplifyOpCode(OpCode toSimplify)
 {
     switch (toSimplify.Code) {
         case Code.Br_S:
             return OpCodes.Br;
         case Code.Brfalse_S:
             return OpCodes.Brfalse;
         case Code.Brtrue_S:
             return OpCodes.Brtrue;
         case Code.Beq_S:
             return OpCodes.Beq;
         case Code.Bge_S:
             return OpCodes.Bge;
         case Code.Bgt_S:
             return OpCodes.Bgt;
         case Code.Ble_S:
             return OpCodes.Ble;
         case Code.Blt_S:
             return OpCodes.Blt;
         case Code.Bne_Un_S:
             return OpCodes.Bne_Un;
         case Code.Bge_Un_S:
             return OpCodes.Bge_Un;
         case Code.Bgt_Un_S:
             return OpCodes.Bgt_Un;
         case Code.Ble_Un_S:
             return OpCodes.Ble_Un;
         case Code.Blt_Un_S:
             return OpCodes.Blt_Un;
         case Code.Leave_S:
             return OpCodes.Leave;
         default:
             return toSimplify;
     }
 }
		internal static void AssertInstruction(Instruction actual, OpCode opCode, MemberReference expectedCtor)
		{
			Assert.AreEqual(opCode, actual.OpCode);
			MethodReference actualCtor = (MethodReference)actual.Operand;
			Assert.AreEqual(expectedCtor.DeclaringType.Name, actualCtor.DeclaringType.Name, opCode.ToString());
			Assert.AreEqual(expectedCtor, actualCtor.Resolve(), opCode.ToString());
		}
        private bool TryGetInstruction(List<ILRange> ilRanges, OpCode opCode, out Instruction instruction) {
            int fromOffset = 0;
            int toOffset = 0;

            if (ilRanges == null || ilRanges.Count == 0) {
                instruction = null;
                return false;
            }

            fromOffset = ilRanges[0].From;
            toOffset = ilRanges[0].To;
            instruction = InstructionAt(fromOffset);

            do {
                if (instruction.OpCode == opCode) {
                    return true;
                }

                instruction = instruction.Next;
                fromOffset = instruction.Offset;
            }
            while (fromOffset != toOffset);

            return instruction.OpCode == opCode;
        }
        private static AssemblyDefinition CreateTestAssembly(OpCode opCode, bool invert)
        {
            var name = new AssemblyNameDefinition("TestConditionalsBoundaryTurtle", new Version(1, 0));
            var assembly = AssemblyDefinition.CreateAssembly(name, "TestClass", ModuleKind.Dll);
            var type = new TypeDefinition("TestConditionalsBoundaryTurtle", "TestClass",
                               TypeAttributes.Class | TypeAttributes.Public);
            var intType = assembly.MainModule.Import(typeof(int));
            var boolType = assembly.MainModule.Import(typeof(bool));
            var method = new MethodDefinition("TestMethod", MethodAttributes.Public, intType);
            var param = new ParameterDefinition("input", ParameterAttributes.In, intType);
            method.Parameters.Add(param);
            var resultVariable = new VariableDefinition(boolType);
            method.Body.Variables.Add(resultVariable);

            var processor = method.Body.GetILProcessor();
            Instruction loadReturnValueInstruction = processor.Create(OpCodes.Ldloc, resultVariable);
            method.Body.Instructions.Add(processor.Create(OpCodes.Ldarg, param));
            method.Body.Instructions.Add(processor.Create(OpCodes.Ldc_I4, 0));
            method.Body.Instructions.Add(processor.Create(opCode));
            if (invert)
            {
                method.Body.Instructions.Add(processor.Create(OpCodes.Ldc_I4, 0));
                method.Body.Instructions.Add(processor.Create(OpCodes.Ceq));
            }
            method.Body.Instructions.Add(processor.Create(OpCodes.Stloc, resultVariable));
            method.Body.Instructions.Add(loadReturnValueInstruction);
            method.Body.Instructions.Add(processor.Create(OpCodes.Ret));

            type.Methods.Add(method);
            assembly.MainModule.Types.Add(type);
            return assembly;
        }
Beispiel #14
0
		public Instruction Create (OpCode opcode, FieldReference field)
		{
			if (opcode.OperandType != OperandType.InlineField &&
				opcode.OperandType != OperandType.InlineTok)
				throw new ArgumentException ("opcode");

			return FinalCreate (opcode, field);
		}
Beispiel #15
0
		public Instruction Create (OpCode opcode, MethodReference meth)
		{
			if (opcode.OperandType != OperandType.InlineMethod &&
				opcode.OperandType != OperandType.InlineTok)
				throw new ArgumentException ("opcode");

			return FinalCreate (opcode, meth);
		}
Beispiel #16
0
		public Instruction Create (OpCode opcode, TypeReference type)
		{
			if (opcode.OperandType != OperandType.InlineType &&
				opcode.OperandType != OperandType.InlineTok)
				throw new ArgumentException ("opcode");

			return FinalCreate (opcode, type);
		}
Beispiel #17
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]);
		}
Beispiel #18
0
 public static bool ReadSigKey(MethodDefinition DecryptMethod, OpCode[] KeySig, ref string val)
 {
     object value = null;
     bool ret = ReadSigKey(DecryptMethod, KeySig, ref value);
     if (value != null)
         val = value.ToString();
     return ret;
 }
Beispiel #19
0
 public static bool ReadSigKey(MethodDefinition DecryptMethod, OpCode[] KeySig, ref int val)
 {
     object value = null;
     bool ret = ReadSigKey(DecryptMethod, KeySig, ref value);
     if (value != null)
         val = Convert.ToInt32(value);
     return ret;
 }
		public Instruction Create (OpCode opcode, CallSite site)
		{
			if (site == null)
				throw new ArgumentNullException ("site");
			if (opcode.Code != Code.Calli)
				throw new ArgumentException ("code");

			return FinalCreate (opcode, site);
		}
Beispiel #21
0
 public PatternInstruction(OpCode[] eligibleOpCodes, Terminal terminal = null, Predicate predicate = null) {
     if (eligibleOpCodes == null)
         throw new ArgumentNullException(Name.Of(eligibleOpCodes));
     if (eligibleOpCodes.Length == 0)
         throw new ArgumentException("Array length must be greater than zero", Name.Of(eligibleOpCodes));
     EligibleOpCodes = eligibleOpCodes;
     Terminal = terminal;
     this.predicate = predicate ?? PredicateDummy;
 }
        private bool isAnotherPath(OpCode opCode)
        {
            if (opCode.FlowControl == FlowControl.Branch)
                return true;

            if (opCode.Code == Code.Jmp)
                return true;

            return false;
        }
Beispiel #23
0
		public Instruction Create (OpCode opcode, byte value)
		{
			if (opcode.OperandType == OperandType.ShortInlineVar)
				return Instruction.Create (opcode, body.Variables [value]);

			if (opcode.OperandType == OperandType.ShortInlineArg)
				return Instruction.Create (opcode, body.GetParameter (value));

			return Instruction.Create (opcode, value);
		}
Beispiel #24
0
        ROpCode convertOpCode(OpCode opcode)
        {
            ROpCode ropcode;

            if (cecilToReflection.TryGetValue(opcode, out ropcode))
            {
                return(ropcode);
            }
            return(ROpCodes.Nop);
        }
        internal static OpCode Map(Cil.OpCode cecilOpCode)
        {
            OpCode opCode;

            if (!_opCodes.TryGetValue(cecilOpCode.Code.ToString(), out opCode))
            {
                opCode = OpCodes.Nop;
            }

            return(opCode);
        }
		void InjectNewWriter(MethodDefinition sendData, ILProcessor processor, out VariableDefinition mswriter, out OpCode binaryWriter)
		{
			var buffer = sendData.Body.Instructions.First(
				x => x.OpCode == OpCodes.Ldsfld
				&& (x.Operand as FieldReference).Name == "buffer"
			);

			while (!(buffer.Next.OpCode == OpCodes.Callvirt
				&& (buffer.Next.Operand as MethodReference).Name == "set_Position"))
			{
				processor.Remove(buffer.Next);
			}
			processor.Remove(buffer.Next);
			//processor.Remove(buffer);

			//VariableDefinition mswriter;
			sendData.Body.Variables.Add(mswriter = new VariableDefinition("mswriter",
				this.SourceDefinition.MainModule.Import(typeof(MemoryStream))
			));

			var res = processor.InsertBefore(buffer.Previous.Previous,
				new
				{
					OpCodes.Newobj,
					Operand = this.SourceDefinition.MainModule.Import(typeof(MemoryStream)
						.GetConstructors()
						.Single(x => x.GetParameters().Count() == 0)
					)
				},
				new { OpCodes.Stloc, Operand = mswriter },
				new { OpCodes.Ldloc, Operand = mswriter }
			);

			buffer.Previous.Previous.ReplaceTransfer(res[0], sendData);
			processor.Remove(buffer.Previous);
			processor.Remove(buffer.Previous);

			buffer.OpCode = OpCodes.Newobj;
			buffer.Operand = this.SourceDefinition.MainModule.Import(typeof(BinaryWriter)
				.GetConstructors()
				.Single(x => x.GetParameters().Count() == 1)
			);
			if (buffer.Next.OpCode != OpCodes.Ldloc_1)
			{
				throw new NotSupportedException("Expected Ldloc_1");
			}

			/*var*/
			binaryWriter = buffer.Next.OpCode;
			processor.InsertAfter(buffer,
				new { OpCodes.Stloc_1 }
			);
		}
Beispiel #27
0
        private static Instruction FindInstruction(Mono.Collections.Generic.Collection<Instruction> instructions, OpCode opCode, string operand)
        {
            foreach(var ins in instructions)
            {

                if(ins.OpCode.Code == opCode.Code && ins.Operand.ToString() == operand)
                {
                    return ins;
                }
            }
            return null;
        }
Beispiel #28
0
 public static bool isFallThrough(OpCode opCode)
 {
     switch (opCode.FlowControl) {
     case FlowControl.Call:
         return opCode != OpCodes.Jmp;
     case FlowControl.Cond_Branch:
     case FlowControl.Next:
         return true;
     default:
         return false;
     }
 }
            protected override void ImplementProceed(MethodDefinition methodInfo, MethodBody methodBody, ILProcessor il, FieldReference methodInfoField, MethodReference proceed, Action<ILProcessor> emitProceedTarget, MethodReference proceedTargetMethod, OpCode proceedOpCode)
            {
                // If T is an interface, then we want to check if target is null; if so, we want to just return the default value
                var targetNotNull = il.Create(OpCodes.Nop);
                EmitProxyFromProceed(il);
                il.Emit(OpCodes.Ldfld, ClassWeaver.Target);  // Load "target" from "this"
                il.Emit(OpCodes.Brtrue, targetNotNull);      // If target is not null, jump below
                CecilExtensions.CreateDefaultMethodImplementation(methodBody.Method, il);

                il.Append(targetNotNull);                    // Mark where the previous branch instruction should jump to                        

                base.ImplementProceed(methodInfo, methodBody, il, methodInfoField, proceed, emitProceedTarget, proceedTargetMethod, proceedOpCode);
            }
        static unsafe CecilILGenerator()
        {
            foreach (FieldInfo field in typeof(OpCodes).GetFields(BindingFlags.Public | BindingFlags.Static))
            {
                OpCode cecilOpCode = (OpCode)field.GetValue(null);
                _MCCOpCodes[cecilOpCode.Value] = cecilOpCode;
            }

            Label l = default;

            *(int *)&l = -1;
            NullLabel  = l;
        }
        public bool TryGetOpCode(AstNode node, OpCode[] opCodes, out Instruction instruction) {
            List<ILRange> ilRanges = node.Annotation<List<ILRange>>();

            instruction = null;

            foreach (var opCode in opCodes) {
                if (TryGetInstruction(ilRanges, opCode, out instruction)) {
                    return true;
                }
            }

            return false;
        }
Beispiel #32
0
        public static void ExpandMacro(ref OpCode opCode, ref object operand, MethodBody methodBody)
        {
            if (opCode.OpCodeType != OpCodeType.Macro)
                return;

            switch (opCode.Code) {
                case Code.Ldarg_0: 		opCode = OpCodes.Ldarg; operand = methodBody.GetParameter(0); break;
                case Code.Ldarg_1: 		opCode = OpCodes.Ldarg; operand = methodBody.GetParameter(1); break;
                case Code.Ldarg_2: 		opCode = OpCodes.Ldarg; operand = methodBody.GetParameter(2); break;
                case Code.Ldarg_3: 		opCode = OpCodes.Ldarg; operand = methodBody.GetParameter(3); break;
                case Code.Ldloc_0: 		opCode = OpCodes.Ldloc; operand = methodBody.Variables[0]; break;
                case Code.Ldloc_1: 		opCode = OpCodes.Ldloc; operand = methodBody.Variables[1]; break;
                case Code.Ldloc_2: 		opCode = OpCodes.Ldloc; operand = methodBody.Variables[2]; break;
                case Code.Ldloc_3: 		opCode = OpCodes.Ldloc; operand = methodBody.Variables[3]; break;
                case Code.Stloc_0: 		opCode = OpCodes.Stloc; operand = methodBody.Variables[0]; break;
                case Code.Stloc_1: 		opCode = OpCodes.Stloc; operand = methodBody.Variables[1]; break;
                case Code.Stloc_2: 		opCode = OpCodes.Stloc; operand = methodBody.Variables[2]; break;
                case Code.Stloc_3: 		opCode = OpCodes.Stloc; operand = methodBody.Variables[3]; break;
                case Code.Ldarg_S: 		opCode = OpCodes.Ldarg; break;
                case Code.Ldarga_S: 		opCode = OpCodes.Ldarga; break;
                case Code.Starg_S: 		opCode = OpCodes.Starg; break;
                case Code.Ldloc_S: 		opCode = OpCodes.Ldloc; break;
                case Code.Ldloca_S: 		opCode = OpCodes.Ldloca; break;
                case Code.Stloc_S: 		opCode = OpCodes.Stloc; break;
                case Code.Ldc_I4_M1: 	opCode = OpCodes.Ldc_I4; operand = -1; break;
                case Code.Ldc_I4_0: 		opCode = OpCodes.Ldc_I4; operand = 0; break;
                case Code.Ldc_I4_1: 		opCode = OpCodes.Ldc_I4; operand = 1; break;
                case Code.Ldc_I4_2: 		opCode = OpCodes.Ldc_I4; operand = 2; break;
                case Code.Ldc_I4_3: 		opCode = OpCodes.Ldc_I4; operand = 3; break;
                case Code.Ldc_I4_4: 		opCode = OpCodes.Ldc_I4; operand = 4; break;
                case Code.Ldc_I4_5: 		opCode = OpCodes.Ldc_I4; operand = 5; break;
                case Code.Ldc_I4_6: 		opCode = OpCodes.Ldc_I4; operand = 6; break;
                case Code.Ldc_I4_7: 		opCode = OpCodes.Ldc_I4; operand = 7; break;
                case Code.Ldc_I4_8: 		opCode = OpCodes.Ldc_I4; operand = 8; break;
                case Code.Ldc_I4_S: 		opCode = OpCodes.Ldc_I4; operand = (int) (sbyte) operand; break;
                case Code.Br_S: 			opCode = OpCodes.Br; break;
                case Code.Brfalse_S: 	opCode = OpCodes.Brfalse; break;
                case Code.Brtrue_S: 		opCode = OpCodes.Brtrue; break;
                case Code.Beq_S: 		opCode = OpCodes.Beq; break;
                case Code.Bge_S: 		opCode = OpCodes.Bge; break;
                case Code.Bgt_S: 		opCode = OpCodes.Bgt; break;
                case Code.Ble_S: 		opCode = OpCodes.Ble; break;
                case Code.Blt_S: 		opCode = OpCodes.Blt; break;
                case Code.Bne_Un_S: 		opCode = OpCodes.Bne_Un; break;
                case Code.Bge_Un_S: 		opCode = OpCodes.Bge_Un; break;
                case Code.Bgt_Un_S: 		opCode = OpCodes.Bgt_Un; break;
                case Code.Ble_Un_S: 		opCode = OpCodes.Ble_Un; break;
                case Code.Blt_Un_S:		opCode = OpCodes.Blt_Un; break;
                case Code.Leave_S:		opCode = OpCodes.Leave; break;
            }
        }
Beispiel #33
0
        static _DMDEmit()
        {
            foreach (FieldInfo field in typeof(System.Reflection.Emit.OpCodes).GetFields(BindingFlags.Public | BindingFlags.Static))
            {
                System.Reflection.Emit.OpCode reflOpCode = (System.Reflection.Emit.OpCode)field.GetValue(null);
                _ReflOpCodes[reflOpCode.Value] = reflOpCode;
            }

            foreach (FieldInfo field in typeof(Mono.Cecil.Cil.OpCodes).GetFields(BindingFlags.Public | BindingFlags.Static))
            {
                Mono.Cecil.Cil.OpCode cecilOpCode = (Mono.Cecil.Cil.OpCode)field.GetValue(null);
                _CecilOpCodes[cecilOpCode.Value] = cecilOpCode;
            }
        }
Beispiel #34
0
		public static Instruction FindInstruction(MethodDefinition method, OpCode opCode)
		{
			Instruction current = method.Body.Instructions[0];

			Instruction instruction = current;
			while (instruction != null && instruction.OpCode != opCode)
			{
				instruction = instruction.Next;
			}

			Assert.IsNotNull(instruction);
			Assert.AreEqual(opCode, instruction.OpCode);
			current = instruction;
			return current;
		}
Beispiel #35
0
        public static Instruction FindInstructionSeq(MethodBody body, OpCode[] instrs)
        {
            for (int i = 0; i < body.Instructions.Count - instrs.Length; i++)
            {
                for (int j = 0; j < instrs.Length; j++)
                {
                    if (body.Instructions[i + j].OpCode.Code != instrs[j].Code)
                        goto next_try;
                }

                return body.Instructions[i];
            next_try:
                ;
            }

            return null;
        }
Beispiel #36
0
		public static bool IsUnconditionalBranch(OpCode opcode)
		{
			if (opcode.OpCodeType == OpCodeType.Prefix)
				return false;
			switch (opcode.FlowControl) {
				case FlowControl.Branch:
				case FlowControl.Throw:
				case FlowControl.Return:
					return true;
				case FlowControl.Next:
				case FlowControl.Call:
				case FlowControl.Cond_Branch:
					return false;
				default:
					throw new NotSupportedException(opcode.FlowControl.ToString());
			}
		}
Beispiel #37
0
        static void InsertMusicHook()
        {
            // First, add the UpdateMusicHook() function that TMain will override.
            var updateMusicHook = new MethodDefinition("UpdateMusicHook", MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual, _typeSystem.Void);
            var proc = updateMusicHook.Body.GetILProcessor();
            proc.Emit(OpCodes.Ret);
            mainTypeDef.Methods.Add(updateMusicHook);

            // Then add a hook to call it.
            OpCode[] searchSeq = new OpCode[]
            {
                OpCodes.Ldarg_0,    // IL_0e31: ldarg.0
                OpCodes.Ldfld,      // IL_0e32: ldfld int32 Terraria.Main::newMusic
                OpCodes.Stsfld      // IL_0e37: stsfld int32 Terraria.Main::curMusic
            };

            var updateMusic = mainTypeDef.GetMethod("UpdateMusic").Body;

            proc = updateMusic.GetILProcessor();

            var firstInstr = CecilHelper.FindInstructionSeq(updateMusic, searchSeq);

            if (firstInstr == null)
            {
                Console.WriteLine("Mainpatcher.InsertMusicHook() was unable to locate the instruction sequence that indicates curMusic being set to newMusic. Terraria.Main.UpdateMusic() has probably changed and this hook needs to be modified accordingly.");
            }
            else
            {
                var musicHook = mainTypeDef.GetMethod("UpdateMusicHook");
                var lastInstr = firstInstr;
                for (int i = 1; i < searchSeq.Length; i++)
                {
                    lastInstr = lastInstr.Next;
                }
                var call_hook = new[]
                {
                    Instruction.Create(OpCodes.Ldarg_0),
                    Instruction.Create(OpCodes.Callvirt, musicHook)
                };
                for (int i = call_hook.Length - 1; i >= 0; i--)
                {
                    proc.InsertAfter(lastInstr, call_hook[i]);
                }
            }
        }
        private void _EmitInlineVar(OpCode opcode, int index)
        {
            // System.Reflection.Emit has only got (Short)InlineVar and allows index refs.
            // Mono.Cecil has also got (Short)InlineArg and requires definition refs.
            switch (opcode.OperandType)
            {
            case MCC.OperandType.ShortInlineArg:
            case MCC.OperandType.InlineArg:
                Emit(IL.Create(opcode, IL.Body.Method.Parameters[index]));
                break;

            case MCC.OperandType.ShortInlineVar:
            case MCC.OperandType.InlineVar:
                Emit(IL.Create(opcode, IL.Body.Variables[index]));
                break;

            default:
                throw new NotSupportedException(
                          $"Unsupported SRE InlineVar -> Cecil {opcode.OperandType} for {opcode} {index}");
            }
        }
        public static bool IsUnconditionalBranch(Mono.Cecil.Cil.OpCode opcode)
        {
            if (opcode.get_OpCodeType() == 4)
            {
                return(false);
            }
            switch (opcode.get_FlowControl())
            {
            case 0:
            case 7:
            case 8:
            {
                return(true);
            }

            case 1:
            case 4:
            case 6:
            {
Label0:
                V_1 = opcode.get_FlowControl();
                throw new NotSupportedException(V_1.ToString());
            }

            case 2:
            case 3:
            case 5:
            {
                return(false);
            }

            default:
            {
                goto Label0;
            }
            }
        }
Beispiel #40
0
 public void Add(OpCode opcode, VariableDefinition op) => Add(Instruction.Create(opcode, op));
Beispiel #41
0
 public void Add(OpCode opcode) => Add(Instruction.Create(opcode));
 public FluentEmitter Emit(OpCode opcode)
 {
     return(Emit(Instruction.Create(opcode)));
 }
 public FluentEmitter Emit(OpCode opcode, double arg)
 {
     return(Emit(Instruction.Create(opcode, arg)));
 }
 public FluentEmitter Emit(OpCode opcode, FieldInfo arg)
 {
     return(Emit(Instruction.Create(opcode, Module.SafeImport(arg))));
 }
Beispiel #45
0
 public void Emit(OpCode opcode, Type type)
 => _Insert(IL.Create(opcode, type));
Beispiel #46
0
        private static System.Reflection.Emit.OpCode MapOpCode(Mono.Cecil.Cil.OpCode cecilOpcode)
        {
            switch (cecilOpcode.Code)
            {
            case Code.Nop: return(System.Reflection.Emit.OpCodes.Nop);

            case Code.Break: return(System.Reflection.Emit.OpCodes.Break);

            case Code.Ldarg_0: return(System.Reflection.Emit.OpCodes.Ldarg_0);

            case Code.Ldarg_1: return(System.Reflection.Emit.OpCodes.Ldarg_1);

            case Code.Ldarg_2: return(System.Reflection.Emit.OpCodes.Ldarg_2);

            case Code.Ldarg_3: return(System.Reflection.Emit.OpCodes.Ldarg_3);

            case Code.Ldloc_0: return(System.Reflection.Emit.OpCodes.Ldloc_0);

            case Code.Ldloc_1: return(System.Reflection.Emit.OpCodes.Ldloc_1);

            case Code.Ldloc_2: return(System.Reflection.Emit.OpCodes.Ldloc_2);

            case Code.Ldloc_3: return(System.Reflection.Emit.OpCodes.Ldloc_3);

            case Code.Stloc_0: return(System.Reflection.Emit.OpCodes.Stloc_0);

            case Code.Stloc_1: return(System.Reflection.Emit.OpCodes.Stloc_1);

            case Code.Stloc_2: return(System.Reflection.Emit.OpCodes.Stloc_2);

            case Code.Stloc_3: return(System.Reflection.Emit.OpCodes.Stloc_3);

            case Code.Ldarg_S: return(System.Reflection.Emit.OpCodes.Ldarg_S);

            case Code.Ldarga_S: return(System.Reflection.Emit.OpCodes.Ldarga_S);

            case Code.Starg_S: return(System.Reflection.Emit.OpCodes.Starg_S);

            case Code.Ldloc_S: return(System.Reflection.Emit.OpCodes.Ldloc_S);

            case Code.Ldloca_S: return(System.Reflection.Emit.OpCodes.Ldloca_S);

            case Code.Stloc_S: return(System.Reflection.Emit.OpCodes.Stloc_S);

            case Code.Ldnull: return(System.Reflection.Emit.OpCodes.Ldnull);

            case Code.Ldc_I4_M1: return(System.Reflection.Emit.OpCodes.Ldc_I4_M1);

            case Code.Ldc_I4_0: return(System.Reflection.Emit.OpCodes.Ldc_I4_0);

            case Code.Ldc_I4_1: return(System.Reflection.Emit.OpCodes.Ldc_I4_1);

            case Code.Ldc_I4_2: return(System.Reflection.Emit.OpCodes.Ldc_I4_2);

            case Code.Ldc_I4_3: return(System.Reflection.Emit.OpCodes.Ldc_I4_3);

            case Code.Ldc_I4_4: return(System.Reflection.Emit.OpCodes.Ldc_I4_4);

            case Code.Ldc_I4_5: return(System.Reflection.Emit.OpCodes.Ldc_I4_5);

            case Code.Ldc_I4_6: return(System.Reflection.Emit.OpCodes.Ldc_I4_6);

            case Code.Ldc_I4_7: return(System.Reflection.Emit.OpCodes.Ldc_I4_7);

            case Code.Ldc_I4_8: return(System.Reflection.Emit.OpCodes.Ldc_I4_8);

            case Code.Ldc_I4_S: return(System.Reflection.Emit.OpCodes.Ldc_I4_S);

            case Code.Ldc_I4: return(System.Reflection.Emit.OpCodes.Ldc_I4);

            case Code.Ldc_I8: return(System.Reflection.Emit.OpCodes.Ldc_I8);

            case Code.Ldc_R4: return(System.Reflection.Emit.OpCodes.Ldc_R4);

            case Code.Ldc_R8: return(System.Reflection.Emit.OpCodes.Ldc_R8);

            case Code.Dup: return(System.Reflection.Emit.OpCodes.Dup);

            case Code.Pop: return(System.Reflection.Emit.OpCodes.Pop);

            case Code.Jmp: return(System.Reflection.Emit.OpCodes.Jmp);

            case Code.Call: return(System.Reflection.Emit.OpCodes.Call);

            case Code.Calli: return(System.Reflection.Emit.OpCodes.Calli);

            case Code.Ret: return(System.Reflection.Emit.OpCodes.Ret);

            case Code.Br_S: return(System.Reflection.Emit.OpCodes.Br_S);

            case Code.Brfalse_S: return(System.Reflection.Emit.OpCodes.Brfalse_S);

            case Code.Brtrue_S: return(System.Reflection.Emit.OpCodes.Brtrue_S);

            case Code.Beq_S: return(System.Reflection.Emit.OpCodes.Beq_S);

            case Code.Bge_S: return(System.Reflection.Emit.OpCodes.Bge_S);

            case Code.Bgt_S: return(System.Reflection.Emit.OpCodes.Bgt_S);

            case Code.Ble_S: return(System.Reflection.Emit.OpCodes.Ble_S);

            case Code.Blt_S: return(System.Reflection.Emit.OpCodes.Blt_S);

            case Code.Bne_Un_S: return(System.Reflection.Emit.OpCodes.Bne_Un_S);

            case Code.Bge_Un_S: return(System.Reflection.Emit.OpCodes.Bge_Un_S);

            case Code.Bgt_Un_S: return(System.Reflection.Emit.OpCodes.Bgt_Un_S);

            case Code.Ble_Un_S: return(System.Reflection.Emit.OpCodes.Ble_Un_S);

            case Code.Blt_Un_S: return(System.Reflection.Emit.OpCodes.Blt_Un_S);

            case Code.Br: return(System.Reflection.Emit.OpCodes.Br);

            case Code.Brfalse: return(System.Reflection.Emit.OpCodes.Brfalse);

            case Code.Brtrue: return(System.Reflection.Emit.OpCodes.Brtrue);

            case Code.Beq: return(System.Reflection.Emit.OpCodes.Beq);

            case Code.Bge: return(System.Reflection.Emit.OpCodes.Bge);

            case Code.Bgt: return(System.Reflection.Emit.OpCodes.Bgt);

            case Code.Ble: return(System.Reflection.Emit.OpCodes.Ble);

            case Code.Blt: return(System.Reflection.Emit.OpCodes.Blt);

            case Code.Bne_Un: return(System.Reflection.Emit.OpCodes.Bne_Un);

            case Code.Bge_Un: return(System.Reflection.Emit.OpCodes.Bge_Un);

            case Code.Bgt_Un: return(System.Reflection.Emit.OpCodes.Bgt_Un);

            case Code.Ble_Un: return(System.Reflection.Emit.OpCodes.Ble_Un);

            case Code.Blt_Un: return(System.Reflection.Emit.OpCodes.Blt_Un);

            case Code.Switch: return(System.Reflection.Emit.OpCodes.Switch);

            case Code.Ldind_I1: return(System.Reflection.Emit.OpCodes.Ldind_I1);

            case Code.Ldind_U1: return(System.Reflection.Emit.OpCodes.Ldind_U1);

            case Code.Ldind_I2: return(System.Reflection.Emit.OpCodes.Ldind_I2);

            case Code.Ldind_U2: return(System.Reflection.Emit.OpCodes.Ldind_U2);

            case Code.Ldind_I4: return(System.Reflection.Emit.OpCodes.Ldind_I4);

            case Code.Ldind_U4: return(System.Reflection.Emit.OpCodes.Ldind_U4);

            case Code.Ldind_I8: return(System.Reflection.Emit.OpCodes.Ldind_I8);

            case Code.Ldind_I: return(System.Reflection.Emit.OpCodes.Ldind_I);

            case Code.Ldind_R4: return(System.Reflection.Emit.OpCodes.Ldind_R4);

            case Code.Ldind_R8: return(System.Reflection.Emit.OpCodes.Ldind_R8);

            case Code.Ldind_Ref: return(System.Reflection.Emit.OpCodes.Ldind_Ref);

            case Code.Stind_Ref: return(System.Reflection.Emit.OpCodes.Stind_Ref);

            case Code.Stind_I1: return(System.Reflection.Emit.OpCodes.Stind_I1);

            case Code.Stind_I2: return(System.Reflection.Emit.OpCodes.Stind_I2);

            case Code.Stind_I4: return(System.Reflection.Emit.OpCodes.Stind_I4);

            case Code.Stind_I8: return(System.Reflection.Emit.OpCodes.Stind_I8);

            case Code.Stind_R4: return(System.Reflection.Emit.OpCodes.Stind_R4);

            case Code.Stind_R8: return(System.Reflection.Emit.OpCodes.Stind_R8);

            case Code.Add: return(System.Reflection.Emit.OpCodes.Add);

            case Code.Sub: return(System.Reflection.Emit.OpCodes.Sub);

            case Code.Mul: return(System.Reflection.Emit.OpCodes.Mul);

            case Code.Div: return(System.Reflection.Emit.OpCodes.Div);

            case Code.Div_Un: return(System.Reflection.Emit.OpCodes.Div_Un);

            case Code.Rem: return(System.Reflection.Emit.OpCodes.Rem);

            case Code.Rem_Un: return(System.Reflection.Emit.OpCodes.Rem_Un);

            case Code.And: return(System.Reflection.Emit.OpCodes.And);

            case Code.Or: return(System.Reflection.Emit.OpCodes.Or);

            case Code.Xor: return(System.Reflection.Emit.OpCodes.Xor);

            case Code.Shl: return(System.Reflection.Emit.OpCodes.Shl);

            case Code.Shr: return(System.Reflection.Emit.OpCodes.Shr);

            case Code.Shr_Un: return(System.Reflection.Emit.OpCodes.Shr_Un);

            case Code.Neg: return(System.Reflection.Emit.OpCodes.Neg);

            case Code.Not: return(System.Reflection.Emit.OpCodes.Not);

            case Code.Conv_I1: return(System.Reflection.Emit.OpCodes.Conv_I1);

            case Code.Conv_I2: return(System.Reflection.Emit.OpCodes.Conv_I2);

            case Code.Conv_I4: return(System.Reflection.Emit.OpCodes.Conv_I4);

            case Code.Conv_I8: return(System.Reflection.Emit.OpCodes.Conv_I8);

            case Code.Conv_R4: return(System.Reflection.Emit.OpCodes.Conv_R4);

            case Code.Conv_R8: return(System.Reflection.Emit.OpCodes.Conv_R8);

            case Code.Conv_U4: return(System.Reflection.Emit.OpCodes.Conv_U4);

            case Code.Conv_U8: return(System.Reflection.Emit.OpCodes.Conv_U8);

            case Code.Callvirt: return(System.Reflection.Emit.OpCodes.Callvirt);

            case Code.Cpobj: return(System.Reflection.Emit.OpCodes.Cpobj);

            case Code.Ldobj: return(System.Reflection.Emit.OpCodes.Ldobj);

            case Code.Ldstr: return(System.Reflection.Emit.OpCodes.Ldstr);

            case Code.Newobj: return(System.Reflection.Emit.OpCodes.Newobj);

            case Code.Castclass: return(System.Reflection.Emit.OpCodes.Castclass);

            case Code.Isinst: return(System.Reflection.Emit.OpCodes.Isinst);

            case Code.Conv_R_Un: return(System.Reflection.Emit.OpCodes.Conv_R_Un);

            case Code.Unbox: return(System.Reflection.Emit.OpCodes.Unbox);

            case Code.Throw: return(System.Reflection.Emit.OpCodes.Throw);

            case Code.Ldfld: return(System.Reflection.Emit.OpCodes.Ldfld);

            case Code.Ldflda: return(System.Reflection.Emit.OpCodes.Ldflda);

            case Code.Stfld: return(System.Reflection.Emit.OpCodes.Stfld);

            case Code.Ldsfld: return(System.Reflection.Emit.OpCodes.Ldsfld);

            case Code.Ldsflda: return(System.Reflection.Emit.OpCodes.Ldsflda);

            case Code.Stsfld: return(System.Reflection.Emit.OpCodes.Stsfld);

            case Code.Stobj: return(System.Reflection.Emit.OpCodes.Stobj);

            case Code.Conv_Ovf_I1_Un: return(System.Reflection.Emit.OpCodes.Conv_Ovf_I1_Un);

            case Code.Conv_Ovf_I2_Un: return(System.Reflection.Emit.OpCodes.Conv_Ovf_I2_Un);

            case Code.Conv_Ovf_I4_Un: return(System.Reflection.Emit.OpCodes.Conv_Ovf_I4_Un);

            case Code.Conv_Ovf_I8_Un: return(System.Reflection.Emit.OpCodes.Conv_Ovf_I8_Un);

            case Code.Conv_Ovf_U1_Un: return(System.Reflection.Emit.OpCodes.Conv_Ovf_U1_Un);

            case Code.Conv_Ovf_U2_Un: return(System.Reflection.Emit.OpCodes.Conv_Ovf_U2_Un);

            case Code.Conv_Ovf_U4_Un: return(System.Reflection.Emit.OpCodes.Conv_Ovf_U4_Un);

            case Code.Conv_Ovf_U8_Un: return(System.Reflection.Emit.OpCodes.Conv_Ovf_U8_Un);

            case Code.Conv_Ovf_I_Un: return(System.Reflection.Emit.OpCodes.Conv_Ovf_I_Un);

            case Code.Conv_Ovf_U_Un: return(System.Reflection.Emit.OpCodes.Conv_Ovf_U_Un);

            case Code.Box: return(System.Reflection.Emit.OpCodes.Box);

            case Code.Newarr: return(System.Reflection.Emit.OpCodes.Newarr);

            case Code.Ldlen: return(System.Reflection.Emit.OpCodes.Ldlen);

            case Code.Ldelema: return(System.Reflection.Emit.OpCodes.Ldelema);

            case Code.Ldelem_I1: return(System.Reflection.Emit.OpCodes.Ldelem_I1);

            case Code.Ldelem_U1: return(System.Reflection.Emit.OpCodes.Ldelem_U1);

            case Code.Ldelem_I2: return(System.Reflection.Emit.OpCodes.Ldelem_I2);

            case Code.Ldelem_U2: return(System.Reflection.Emit.OpCodes.Ldelem_U2);

            case Code.Ldelem_I4: return(System.Reflection.Emit.OpCodes.Ldelem_I4);

            case Code.Ldelem_U4: return(System.Reflection.Emit.OpCodes.Ldelem_U4);

            case Code.Ldelem_I8: return(System.Reflection.Emit.OpCodes.Ldelem_I8);

            case Code.Ldelem_I: return(System.Reflection.Emit.OpCodes.Ldelem_I);

            case Code.Ldelem_R4: return(System.Reflection.Emit.OpCodes.Ldelem_R4);

            case Code.Ldelem_R8: return(System.Reflection.Emit.OpCodes.Ldelem_R8);

            case Code.Ldelem_Ref: return(System.Reflection.Emit.OpCodes.Ldelem_Ref);

            case Code.Stelem_I: return(System.Reflection.Emit.OpCodes.Stelem_I);

            case Code.Stelem_I1: return(System.Reflection.Emit.OpCodes.Stelem_I1);

            case Code.Stelem_I2: return(System.Reflection.Emit.OpCodes.Stelem_I2);

            case Code.Stelem_I4: return(System.Reflection.Emit.OpCodes.Stelem_I4);

            case Code.Stelem_I8: return(System.Reflection.Emit.OpCodes.Stelem_I8);

            case Code.Stelem_R4: return(System.Reflection.Emit.OpCodes.Stelem_R4);

            case Code.Stelem_R8: return(System.Reflection.Emit.OpCodes.Stelem_R8);

            case Code.Stelem_Ref: return(System.Reflection.Emit.OpCodes.Stelem_Ref);

            case Code.Ldelem_Any: return(System.Reflection.Emit.OpCodes.Ldelem);    // *

            case Code.Stelem_Any: return(System.Reflection.Emit.OpCodes.Stelem);    // *

            case Code.Unbox_Any: return(System.Reflection.Emit.OpCodes.Unbox_Any);

            case Code.Conv_Ovf_I1: return(System.Reflection.Emit.OpCodes.Conv_Ovf_I1);

            case Code.Conv_Ovf_U1: return(System.Reflection.Emit.OpCodes.Conv_Ovf_U1);

            case Code.Conv_Ovf_I2: return(System.Reflection.Emit.OpCodes.Conv_Ovf_I2);

            case Code.Conv_Ovf_U2: return(System.Reflection.Emit.OpCodes.Conv_Ovf_U2);

            case Code.Conv_Ovf_I4: return(System.Reflection.Emit.OpCodes.Conv_Ovf_I4);

            case Code.Conv_Ovf_U4: return(System.Reflection.Emit.OpCodes.Conv_Ovf_U4);

            case Code.Conv_Ovf_I8: return(System.Reflection.Emit.OpCodes.Conv_Ovf_I8);

            case Code.Conv_Ovf_U8: return(System.Reflection.Emit.OpCodes.Conv_Ovf_U8);

            case Code.Refanyval: return(System.Reflection.Emit.OpCodes.Refanyval);

            case Code.Ckfinite: return(System.Reflection.Emit.OpCodes.Ckfinite);

            case Code.Mkrefany: return(System.Reflection.Emit.OpCodes.Mkrefany);

            case Code.Ldtoken: return(System.Reflection.Emit.OpCodes.Ldtoken);

            case Code.Conv_U2: return(System.Reflection.Emit.OpCodes.Conv_U2);

            case Code.Conv_U1: return(System.Reflection.Emit.OpCodes.Conv_U1);

            case Code.Conv_I: return(System.Reflection.Emit.OpCodes.Conv_I);

            case Code.Conv_Ovf_I: return(System.Reflection.Emit.OpCodes.Conv_Ovf_I);

            case Code.Conv_Ovf_U: return(System.Reflection.Emit.OpCodes.Conv_Ovf_U);

            case Code.Add_Ovf: return(System.Reflection.Emit.OpCodes.Add_Ovf);

            case Code.Add_Ovf_Un: return(System.Reflection.Emit.OpCodes.Add_Ovf_Un);

            case Code.Mul_Ovf: return(System.Reflection.Emit.OpCodes.Mul_Ovf);

            case Code.Mul_Ovf_Un: return(System.Reflection.Emit.OpCodes.Mul_Ovf_Un);

            case Code.Sub_Ovf: return(System.Reflection.Emit.OpCodes.Sub_Ovf);

            case Code.Sub_Ovf_Un: return(System.Reflection.Emit.OpCodes.Sub_Ovf_Un);

            case Code.Endfinally: return(System.Reflection.Emit.OpCodes.Endfinally);

            case Code.Leave: return(System.Reflection.Emit.OpCodes.Leave);

            case Code.Leave_S: return(System.Reflection.Emit.OpCodes.Leave_S);

            case Code.Stind_I: return(System.Reflection.Emit.OpCodes.Stind_I);

            case Code.Conv_U: return(System.Reflection.Emit.OpCodes.Conv_U);

            case Code.Arglist: return(System.Reflection.Emit.OpCodes.Arglist);

            case Code.Ceq: return(System.Reflection.Emit.OpCodes.Ceq);

            case Code.Cgt: return(System.Reflection.Emit.OpCodes.Cgt);

            case Code.Cgt_Un: return(System.Reflection.Emit.OpCodes.Cgt_Un);

            case Code.Clt: return(System.Reflection.Emit.OpCodes.Clt);

            case Code.Clt_Un: return(System.Reflection.Emit.OpCodes.Clt_Un);

            case Code.Ldftn: return(System.Reflection.Emit.OpCodes.Ldftn);

            case Code.Ldvirtftn: return(System.Reflection.Emit.OpCodes.Ldvirtftn);

            case Code.Ldarg: return(System.Reflection.Emit.OpCodes.Ldarg);

            case Code.Ldarga: return(System.Reflection.Emit.OpCodes.Ldarga);

            case Code.Starg: return(System.Reflection.Emit.OpCodes.Starg);

            case Code.Ldloc: return(System.Reflection.Emit.OpCodes.Ldloc);

            case Code.Ldloca: return(System.Reflection.Emit.OpCodes.Ldloca);

            case Code.Stloc: return(System.Reflection.Emit.OpCodes.Stloc);

            case Code.Localloc: return(System.Reflection.Emit.OpCodes.Localloc);

            case Code.Endfilter: return(System.Reflection.Emit.OpCodes.Endfilter);

            case Code.Unaligned: return(System.Reflection.Emit.OpCodes.Unaligned);

            case Code.Volatile: return(System.Reflection.Emit.OpCodes.Volatile);

            case Code.Tail: return(System.Reflection.Emit.OpCodes.Tailcall);    // *

            case Code.Initobj: return(System.Reflection.Emit.OpCodes.Initobj);

            case Code.Constrained: return(System.Reflection.Emit.OpCodes.Constrained);

            case Code.Cpblk: return(System.Reflection.Emit.OpCodes.Cpblk);

            case Code.Initblk: return(System.Reflection.Emit.OpCodes.Initblk);

            //case Code.No: return System.Reflection.Emit.OpCodes.No; // no such opcode
            case Code.Rethrow: return(System.Reflection.Emit.OpCodes.Rethrow);

            case Code.Sizeof: return(System.Reflection.Emit.OpCodes.Sizeof);

            case Code.Refanytype: return(System.Reflection.Emit.OpCodes.Refanytype);

            case Code.Readonly: return(System.Reflection.Emit.OpCodes.Readonly);

            default:
                throw new NotSupportedException(string.Format("Unsupported opcode: {0}.", cecilOpcode));
            }
        }
Beispiel #47
0
 public void Emit(OpCode opcode, CallSite site)
 => _Insert(IL.Create(opcode, site));
Beispiel #48
0
 public void Emit(OpCode opcode, int value)
 => _Insert(IL.Create(opcode, value));
Beispiel #49
0
 public void Emit(OpCode opcode, FieldInfo field)
 => _Insert(IL.Create(opcode, field));
Beispiel #50
0
 public void Emit(OpCode opcode, VariableDefinition variable)
 => _Insert(IL.Create(opcode, variable));
Beispiel #51
0
 public void Emit(OpCode opcode, object operand)
 => _Insert(IL.Create(opcode, operand));
Beispiel #52
0
 public void Add(OpCode opcode, FieldReference op) => Add(Instruction.Create(opcode, op));
Beispiel #53
0
 public void Add(OpCode opcode, Instruction op) => Add(Instruction.Create(opcode, op));
Beispiel #54
0
 public void Emit(OpCode opcode, FieldReference field)
 => _Insert(IL.Create(opcode, field));
Beispiel #55
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();
            }
        }
Beispiel #56
0
 public void Emit(OpCode opcode, MethodBase method)
 => _Insert(IL.Create(opcode, method));
Beispiel #57
0
        private void ExtractBasicBlocksOfMethod(Tuple <MethodReference, List <TypeReference> > definition)
        {
            MethodReference method_reference          = definition.Item1;
            MethodReference original_method_reference = method_reference;

            _methods_done.Add(original_method_reference.FullName);
            MethodDefinition method_definition = Rewrite(original_method_reference);

            if (method_definition == null || method_definition.Body == null)
            {
                return;
            }
            _methods_done.Add(method_definition.FullName);
            int change_set        = Cfg.StartChangeSet();
            int instruction_count = method_definition.Body.Instructions.Count;
            List <Mono.Cecil.Cil.Instruction> split_point = new List <Mono.Cecil.Cil.Instruction>();

            // Each method is a leader of a block.
            CFG.Vertex basic_block = (CFG.Vertex)Cfg.AddVertex(new CFG.Vertex()
            {
                Name = Cfg.NewNodeNumber().ToString()
            });
            basic_block._method_definition         = method_definition;
            basic_block._original_method_reference = original_method_reference;
            basic_block.Entry = 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.");
            }
            for (int j = 0; j < instruction_count; ++j)
            {
                Mono.Cecil.Cil.Instruction instruction = body.Instructions[j];
                INST wrapped_instruction = INST.Wrap(instruction,
                                                     body,
                                                     basic_block, sequence_points.Where(sp => { return(sp.Offset == instruction.Offset); }).FirstOrDefault());
                basic_block.Instructions.Add(wrapped_instruction);
            }

            // 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.
                    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)
                    {
                        if (!split_point.Contains(single_instruction))
                        {
                            split_point.Add(single_instruction);
                        }
                    }
                    else if (array_of_instructions != null)
                    {
                        foreach (var ins in array_of_instructions)
                        {
                            Debug.Assert(ins != null);
                            if (!split_point.Contains(single_instruction))
                            {
                                split_point.Add(ins);
                            }
                        }
                    }
                    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;
                        if (!split_point.Contains(ins))
                        {
                            split_point.Add(ins);
                        }
                    }
                }
                break;
                }
            }

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

            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.
                Mono.Cecil.Cil.Instruction i = method_definition.Body.Instructions[j];
                if (split_point.Contains(i))
                {
                    ordered_leader_list.Add(i);
                }
            }

            // Split block at all jump targets.
            foreach (var i in ordered_leader_list)
            {
                var owner = Cfg.Vertices.Where(
                    n => n.Instructions.Where(ins => ins.Instruction == i).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 => a.Instruction == i);
                CFG.Vertex new_node    = Split(target_node, j);
            }

            // 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)
                    {
                        Mono.Cecil.Cil.Instruction target_instruction =
                            last_instruction.Operand as Mono.Cecil.Cil.Instruction;
                        CFG.Vertex target_node = Cfg.Vertices.FirstOrDefault(
                            (CFG.Vertex x) =>
                            {
                                if (!x.Instructions.First().Instruction.Equals(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 = Cfg.Vertices.FirstOrDefault(
                                (CFG.Vertex x) =>
                                {
                                    if (!x.Instructions.First().Instruction.Equals(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.Return:
                case Mono.Cecil.Cil.FlowControl.Throw:
                {
                    int next = method_definition.Body.Instructions.ToList().FindIndex(
                        n =>
                        {
                            var r = n == last_instruction.Instruction &&
                                    n.Offset == last_instruction.Instruction.Offset
                            ;
                            return(r);
                        }
                        );
                    if (next < 0)
                    {
                        break;
                    }
                    next += 1;
                    if (next >= method_definition.Body.Instructions.Count)
                    {
                        break;
                    }
                    var next_instruction = method_definition.Body.Instructions[next];
                    var owner            = Cfg.Vertices.Where(
                        n => n.Instructions.Where(ins => ins.Instruction == next_instruction).Any()).ToList();
                    if (owner.Count != 1)
                    {
                        throw new Exception("Cannot find instruction!");
                    }
                    CFG.Vertex target_node = owner.FirstOrDefault();
                    Cfg.AddEdge(new CFG.Edge()
                        {
                            From = node, To = target_node
                        });
                }
                break;
                }
            }
            Cfg.OutputDotGraph();
            Cfg.OutputEntireGraph();
        }
 public FluentEmitter Emit(OpCode opcode, SystemTypeOrTypeReference arg)
 {
     return(Emit(Instruction.Create(opcode, arg.GetTypeReference(Module))));
 }
Beispiel #59
0
 public void Emit(OpCode opcode, ParameterDefinition parameter)
 => _Insert(IL.Create(opcode, parameter));
Beispiel #60
0
 public void Emit(OpCode opcode, Instruction target)
 => _Insert(IL.Create(opcode, target));