Exemple #1
0
 public MethodBody(MethodDefinition meth)
 {
     m_method = meth;
     m_instructions = new InstructionCollection (this);
     m_exceptions = new ExceptionHandlerCollection (this);
     m_variables = new VariableDefinitionCollection (this);
 }
		void MarkBlockStarts (InstructionCollection instructions)
		{
			Instruction instruction = instructions[0];

			// the first instruction starts a block
			MarkBlockStart (instruction);
			for (int i = 1; i < instructions.Count; ++i) {
				instruction = instructions[i];
				if (!IsBlockDelimiter (instruction))
					continue;

				if (HasMultipleBranches (instruction)) {
					// each switch case first instruction starts a block
					foreach (Instruction target in GetBranchTargets (instruction))
						if (target != null)
							MarkBlockStart (target);
				} else {
					// the target of a branch starts a block
					Instruction target = GetBranchTarget (instruction);
					if (null != target) MarkBlockStart (target);
				}

				// the next instruction after a branch starts a block
				if (null != instruction.Next) MarkBlockStart (instruction.Next);
			}
		}
Exemple #3
0
 public override void VisitInstructionCollection(InstructionCollection instructions)
 {
   foreach (Instruction instruction in instructions)
   {
     instruction.Accept(this);
   }
 }
Exemple #4
0
 private void Init([NonNull] InstructionCollection instructions,
         [NonNull] MethodDefinition method)
 {
     this.instructions = instructions;
     this.method = method;
     BuildGraph();
 }
		public override void VisitInstructionCollection (InstructionCollection instructionCollection) 
		{
			foreach (Instruction instruction in instructionCollection) {
				if (IsDelimiter (instruction)) 
					CreateExpressionAndAddToExpressionContainer ();
				if (IsAcceptable (instruction)) 
					AddToExpression (instruction);
			}
		}
Exemple #6
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;
        }
Exemple #7
0
		void ComputeMaxStack (InstructionCollection instructions)
		{
			InstructionCollection ehs = new InstructionCollection (null);
			foreach (ExceptionHandler eh in instructions.Container.ExceptionHandlers)
				switch (eh.Type) {
				case ExceptionHandlerType.Catch :
					ehs.Add (eh.HandlerStart);
					break;
				case ExceptionHandlerType.Filter :
					ehs.Add (eh.FilterStart);
					break;
				}

			int max = 0, current = 0;
			foreach (Instruction instr in instructions) {

				if (ehs.Contains (instr))
					current++;

				switch (instr.OpCode.StackBehaviourPush) {
				case StackBehaviour.Push1:
				case StackBehaviour.Pushi:
				case StackBehaviour.Pushi8:
				case StackBehaviour.Pushr4:
				case StackBehaviour.Pushr8:
				case StackBehaviour.Pushref:
				case StackBehaviour.Varpush:
					current++;
					break;
				case StackBehaviour.Push1_push1:
					current += 2;
					break;
				}

				if (max < current)
					max = current;

				switch (instr.OpCode.StackBehaviourPop) {
				case StackBehaviour.Varpop:
					break;
				case StackBehaviour.Pop1:
				case StackBehaviour.Popi:
				case StackBehaviour.Popref:
					current--;
					break;
				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:
					current -= 2;
					break;
				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:
					current -= 3;
					break;
				}
			}

			instructions.Container.MaxStack = max;
		}
		public void VisitInstructionCollection (InstructionCollection instructions)
		{
			foreach (Instruction instr in instructions)
				instr.Accept (this);
		}
		void MarkBlockEnds (InstructionCollection instructions)
		{
			InstructionBlock [] blocks = this.RegisteredBlocks;
			InstructionBlock current = blocks [0];

			for (int i = 1; i < blocks.Length; ++i) {
				InstructionBlock block = blocks [i];
				current.SetLastInstruction (block.FirstInstruction.Previous);
				current = block;
			}

			current.SetLastInstruction (instructions [instructions.Count - 1]);
		}
Exemple #10
0
 static bool IsRangeFat(Instruction start, Instruction end, InstructionCollection instructions)
 {
     return(GetLength(start, end, instructions) >= 256 ||
            start.Offset >= 65536);
 }
		void MarkBlockEnds (InstructionCollection instructions)
		{
			var blocks = ToArray ();
			var current = blocks [0];

			for (int i = 1; i < blocks.Length; ++i) {
				var block = blocks [i];
				current.Last = block.First.Previous;
				current = block;
			}

			current.Last = instructions [instructions.Count - 1];
		}
        /// <summary>
        /// Reads method calls by extracting instrunctions
        /// </summary>
        /// <param name="method"></param>
        /// <param name="methodDefinition"></param>
        /// <param name="instructions"></param>
        public void ReadInstructions(Method method, MethodDefinition methodDefinition,
            InstructionCollection instructions)
        {
            foreach (Instruction instruction in instructions)
            {
                var instr = ReadInstruction(instruction);

                if (instr is MethodDefinition)
                {
                    var md = instr as MethodDefinition;
                    var type = (from n in method.Type.Namespace.Module.Namespaces
                                from t in n.Types
                                where t.Name == FormatTypeName(md.DeclaringType) &&
                                n.Name == t.Namespace.Name
                                select t).SingleOrDefault();

                    method.TypeUses.Add(type);

                    var findTargetMethod = (from m in type.Methods
                                            where m.Name == FormatMethodName(md)
                                            select m).SingleOrDefault();

                    if (findTargetMethod != null && type == method.Type)
                        method.MethodUses.Add(findTargetMethod);
                }

                if (instr is FieldDefinition)
                {
                    var fd = instr as FieldDefinition;
                    var field = (from f in method.Type.Fields
                                where f.Name == fd.Name
                                select f).SingleOrDefault();

                    if (field != null)
                        method.FieldUses.Add(field);
                }
            }
        }
 public override void VisitInstructionCollection(InstructionCollection instructions)
 {
     for (var i = 0; i < instructions.Count; i++)
         this.VisitInstruction(instructions[i]);
 }
Exemple #14
0
 internal CilWorker(MethodBody body)
 {
     m_mbody  = body;
     m_instrs = m_mbody.Instructions;
 }
Exemple #15
0
 public BasicBlock([NonNull] InstructionCollection instructions)
 {
     this.instructions = instructions;
 }
Exemple #16
0
        static void ComputeMaxStack(InstructionCollection instructions)
        {
            InstructionCollection ehs = new InstructionCollection(null);

            foreach (ExceptionHandler eh in instructions.Container.ExceptionHandlers)
            {
                switch (eh.Type)
                {
                case ExceptionHandlerType.Catch:
                    ehs.Add(eh.HandlerStart);
                    break;

                case ExceptionHandlerType.Filter:
                    ehs.Add(eh.FilterStart);
                    break;
                }
            }

            int max = 0, current = 0;

            foreach (Instruction instr in instructions)
            {
                if (ehs.Contains(instr))
                {
                    current++;
                }

                switch (instr.OpCode.StackBehaviourPush)
                {
                case StackBehaviour.Push1:
                case StackBehaviour.Pushi:
                case StackBehaviour.Pushi8:
                case StackBehaviour.Pushr4:
                case StackBehaviour.Pushr8:
                case StackBehaviour.Pushref:
                case StackBehaviour.Varpush:
                    current++;
                    break;

                case StackBehaviour.Push1_push1:
                    current += 2;
                    break;
                }

                if (max < current)
                {
                    max = current;
                }

                switch (instr.OpCode.StackBehaviourPop)
                {
                case StackBehaviour.Varpop:
                    break;

                case StackBehaviour.Pop1:
                case StackBehaviour.Popi:
                case StackBehaviour.Popref:
                    current--;
                    break;

                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:
                    current -= 2;
                    break;

                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:
                    current -= 3;
                    break;
                }

                if (current < 0)
                {
                    current = 0;
                }
            }

            instructions.Container.MaxStack = max;
        }
 public MethodBody(MethodDefinition meth)
 {
     m_method = meth;
     // there is always a RET instruction (if a body is present)
     m_instructions = new InstructionCollection(this);
 }
Exemple #18
0
		private static FieldReference DoGetOwnedField(TypeDefinition type, InstructionCollection instructions, int index)
		{
			FieldReference owned = null;
			
			Instruction instruction = instructions[index];
			if (instruction.OpCode.Code == Code.Stfld)	
			{
				FieldReference fr = (FieldReference) instruction.Operand;
				FieldDefinition field = type.Fields.GetField(fr.Name);
				if (field != null && field.MetadataToken == fr.MetadataToken)
				{
					if (!field.IsStatic)					// we should be checking the store field's target to see if it is 'this', but hopefully ctors won't be assigning to other class instances
					{
						do
						{
							// newobj instance void class [mscorlib]System.IO.StringWriter::.ctor()
							// stfld  class [mscorlib]System.IO.StringWriter Smokey.DisposableFieldsTest/GoodCase::m_writer
							if (instructions[index - 1].OpCode.Code == Code.Newobj || instructions[index - 1].OpCode.Code == Code.Newarr)
							{
								owned = field;
								break;
							}	

							// call  native int class Smokey.DisposeNativeResourcesTest/GoodCase2::CreateHandle()
							// stfld native int Smokey.DisposeNativeResourcesTest/GoodCase2::m_resource
							if (instructions[index - 1].OpCode.Code == Code.Call || instructions[index - 1].OpCode.Code == Code.Callvirt)
							{
								MethodReference target = (MethodReference) instructions[index - 1].Operand;
								if (!target.Name.StartsWith("get_") && target.Name != "op_Explicit")	// ignore property and (IntPtr) 0
								{
									if (target.ToString().IndexOf("Create") >= 0 || target.ToString().IndexOf("Make") >= 0)
									{
										owned = field;
										break;
									}
								}		
							}
						}
						while (false);
					}
				}
			}
			// ldarg.0  this
			// ldflda   System.Runtime.InteropServices.HandleRef Smokey.Tests.DisposeNativeResourcesTest/BadCase2::m_resource
			// ldc.i4.s 0x64
			// call instance void native int::'.ctor'(int32)
			//
        	// ldarg.0 
    	    // ldflda valuetype [mscorlib]System.Runtime.InteropServices.HandleRef Smokey.Tests.DisposeNativeResourcesTest/BadCase3::m_resource
	        // initobj [mscorlib]System.Runtime.InteropServices.HandleRef
			else if (instruction.OpCode.Code == Code.Ldflda)
			{
				if (instructions[index - 1].OpCode.Code == Code.Ldarg_0)
				{
					FieldReference fr = (FieldReference) instruction.Operand;
					FieldDefinition field = type.Fields.GetField(fr.Name);
					if (field != null && field.MetadataToken == fr.MetadataToken)
					{
						if (!field.IsStatic)
						{
							int i = index + 1;
							while (i < instructions.Count)
							{
								if (DoIsLoad(instructions[i].OpCode.Code))
									++i;
								else
									break;
							}
							
							if (i < instructions.Count)
							{
								if (instructions[i].OpCode.Code == Code.Call || instructions[i].OpCode.Code == Code.Callvirt)
								{
									MethodReference target = (MethodReference) instructions[i].Operand;
									if (target.ToString().IndexOf("ctor") >= 0 || target.ToString().IndexOf("Create") >= 0 || target.ToString().IndexOf("Make") >= 0)
									{
										owned = field;
									}
								}
								else if (instructions[i].OpCode.Code == Code.Initobj)
								{
									owned = field;
								}
							}
						}
					}
				}
			}
			
			return owned;
		}		
Exemple #19
0
 internal ILProcessor(MethodBody body)
 {
     this.body         = body;
     this.instructions = (InstructionCollection)body.Instructions;
 }
		public MethodBody (MethodDefinition meth)
		{
			m_method = meth;
			// there is always a RET instruction (if a body is present)
			m_instructions = new InstructionCollection (this);
		}
Exemple #21
0
		public override void VisitInstructionCollection (InstructionCollection instructions)
		{
			foreach (Instruction instr in instructions) {
				CheckExceptionHandlers (instr);
				m_writer.Write ("{0}:  {1}",
					Label (instr), instr.OpCode.Name);

				switch (instr.OpCode.OperandType) {
				case OperandType.InlineNone :
					break;
				case OperandType.InlineSwitch :
					m_writer.WriteLine ("(");
					m_writer.Indent ();
					Instruction [] targets = (Instruction []) instr.Operand;
					for (int i = 0; i < targets.Length; i++) {
						m_writer.Write (Label (targets [i]));
						m_writer.WriteLine (i < targets.Length - 1 ? "," : string.Empty);
					}
					m_writer.Unindent ();
					m_writer.Write (")");
					break;
				case OperandType.ShortInlineBrTarget :
				case OperandType.InlineBrTarget :
					m_writer.WriteLine (Label ((Instruction) instr.Operand));
					break;
				case OperandType.ShortInlineVar :
				case OperandType.InlineVar :
					VariableDefinition var = (VariableDefinition) instr.Operand;
					if (var.Name != null && var.Name.Length > 0)
						m_writer.Write (var.Name);
					else
						m_writer.Write (instructions.Container.Variables.IndexOf (var));
					break;
				case OperandType.ShortInlineParam :
				case OperandType.InlineParam :
					ParameterDefinition param = (ParameterDefinition) instr.Operand;
					if (param.Name != null && param.Name.Length > 0)
						m_writer.Write (Formater.Escape (param.Name));
					else
						m_writer.Write (instructions.Container.Method.Parameters.IndexOf (param));
					break;
				case OperandType.InlineI :
				case OperandType.InlineI8 :
				case OperandType.InlineR :
				case OperandType.ShortInlineI :
				case OperandType.ShortInlineR :
					m_writer.Write (instr.Operand.ToString ());
					break;
				case OperandType.InlineString :
					// FIXME: Handle unicode strings with non zero high byte
					//StringBuilder sb = new StringBuilder (instr.Operand.ToString ());
					// FIXME: extract to a method
					//sb.Replace ("\"", "\\\"");
					//sb.Replace ("\t", "\\t");
					//sb.Replace ("\r", "\\r");
					//sb.Replace ("\n", "\\n");
					String s = Formater.LiteralReplace(instr.Operand.ToString());

					m_writer.Write(String.Concat("\"", s, "\""));
					break;
				case OperandType.InlineType :
					m_writer.Write (Formater.Signature ((TypeReference) instr.Operand));
					break;
				case OperandType.InlineMethod :
				case OperandType.InlineField :
					VisitMemberReference (instr.Operand as MemberReference);
					break;
				case OperandType.InlineTok :
					if (instr.Operand is TypeReference) {
						m_writer.Write (Formater.Signature ((TypeReference) instr.Operand, true));
					} else if (instr.Operand is MemberReference) {
						if (instr.Operand is FieldReference)
							m_writer.Write ("field");
						//FIXME: method
						VisitMemberReference ((MemberReference) instr.Operand);
					}
					break;
				}

				m_writer.WriteLine ();
			}
		}
Exemple #22
0
 public override void VisitInstructionCollection(InstructionCollection instructions)
 {
     for (int i = 0; i < instructions.Count; i++)
     {
         if (_jumpDestination != null)
         {
             for (int j = 0; j < instructions.Count; j++)
             {
                 if (instructions[j].Offset == _jumpDestination.Offset)
                 {
                     i = j;
                     _jumpDestination = null;
                     break;
                 }
             }
             throw new InvalidOperationException("Did not jump when expected to jump.");
         }
         VisitInstruction(instructions[i]);
     }
 }
Exemple #23
0
        static int GetLength(Instruction start, Instruction end, InstructionCollection instructions)
        {
            Instruction last = instructions[instructions.Count - 1];

            return((end == instructions.Outside ? last.Offset + GetSize(last) : end.Offset) - start.Offset);
        }
		internal CilWorker (MethodBody body)
		{
			m_mbody = body;
			m_instrs = m_mbody.Instructions;
		}
Exemple #25
0
		void ComputeMaxStack (InstructionCollection instructions)
		{
			int current = 0;
			int max = 0;
			m_stackSizes.Clear ();

			foreach (ExceptionHandler eh in instructions.Container.ExceptionHandlers) {
				switch (eh.Type) {
				case ExceptionHandlerType.Catch :
				case ExceptionHandlerType.Filter :
					m_stackSizes [eh.HandlerStart] = 1;
					max = 1;
					break;
				}
			}

			foreach (Instruction instr in instructions) {

				object savedSize = m_stackSizes [instr];
				if (savedSize != null)
					current = (int) savedSize;

				current -= GetPopDelta (instructions.Container.Method, instr, current);

				if (current < 0)
					current = 0;

				current += GetPushDelta (instr);

				if (current > max)
					max = current;

				// for forward branches, copy the stack size for the instruction that is being branched to
				switch (instr.OpCode.OperandType) {
					case OperandType.InlineBrTarget:
					case OperandType.ShortInlineBrTarget:
						m_stackSizes [instr.Operand] = current;
					break;
					case OperandType.InlineSwitch:
						foreach (Instruction target in (Instruction []) instr.Operand)
							m_stackSizes [target] = current;
					break;
				}

				switch (instr.OpCode.FlowControl) {
				case FlowControl.Branch:
				case FlowControl.Throw:
				case FlowControl.Return:
					// next statement is not reachable from this statement, so reset the stack depth to 0
					current = 0;
					break;
				}
			}

			instructions.Container.MaxStack = max + 1; // you never know
		}
Exemple #26
0
        void ReadCilBody(MethodBody body, BinaryReader br, out IDictionary instructions)
        {
            long                  start = br.BaseStream.Position;
            Instruction           last  = null;
            InstructionCollection code  = body.Instructions;

            instructions = new Hashtable();
            GenericContext context = new GenericContext(body.Method);

            while (br.BaseStream.Position < start + body.CodeSize)
            {
                OpCode op;
                long   offset = br.BaseStream.Position - start;
                int    cursor = br.ReadByte();
                if (cursor == 0xfe)
                {
                    op = OpCodes.TwoBytesOpCode [br.ReadByte()];
                }
                else
                {
                    op = OpCodes.OneByteOpCode [cursor];
                }

                Instruction instr = new Instruction((int)offset, op);
                switch (op.OperandType)
                {
                case OperandType.InlineNone:
                    break;

                case OperandType.InlineSwitch:
                    uint   length   = br.ReadUInt32();
                    int [] branches = new int [length];
                    int [] buf      = new int [length];
                    for (int i = 0; i < length; i++)
                    {
                        buf [i] = br.ReadInt32();
                    }
                    for (int i = 0; i < length; i++)
                    {
                        branches [i] = Convert.ToInt32(br.BaseStream.Position - start + buf [i]);
                    }
                    instr.Operand = branches;
                    break;

                case OperandType.ShortInlineBrTarget:
                    sbyte sbrtgt = br.ReadSByte();
                    instr.Operand = Convert.ToInt32(br.BaseStream.Position - start + sbrtgt);
                    break;

                case OperandType.InlineBrTarget:
                    int brtgt = br.ReadInt32();
                    instr.Operand = Convert.ToInt32(br.BaseStream.Position - start + brtgt);
                    break;

                case OperandType.ShortInlineI:
                    if (op == OpCodes.Ldc_I4_S)
                    {
                        instr.Operand = br.ReadSByte();
                    }
                    else
                    {
                        instr.Operand = br.ReadByte();
                    }
                    break;

                case OperandType.ShortInlineVar:
                    instr.Operand = GetVariable(body, br.ReadByte());
                    break;

                case OperandType.ShortInlineParam:
                    instr.Operand = GetParameter(body, br.ReadByte());
                    break;

                case OperandType.InlineSig:
                    instr.Operand = GetCallSiteAt(br.ReadInt32(), context);
                    break;

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

                case OperandType.InlineVar:
                    instr.Operand = GetVariable(body, br.ReadInt16());
                    break;

                case OperandType.InlineParam:
                    instr.Operand = GetParameter(body, br.ReadInt16());
                    break;

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

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

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

                case OperandType.InlineString:
                    instr.Operand = m_root.Streams.UserStringsHeap [GetRid(br.ReadInt32())];
                    break;

                case OperandType.InlineField:
                    MetadataToken field = new MetadataToken(br.ReadInt32());
                    switch (field.TokenType)
                    {
                    case TokenType.Field:
                        instr.Operand = m_reflectReader.GetFieldDefAt(field.RID);
                        break;

                    case TokenType.MemberRef:
                        instr.Operand = m_reflectReader.GetMemberRefAt(field.RID, context);
                        break;

                    default:
                        throw new ReflectionException("Wrong token for InlineField Operand: " + field);
                    }
                    break;

                case OperandType.InlineMethod:
                    MetadataToken meth = new MetadataToken(br.ReadInt32());
                    switch (meth.TokenType)
                    {
                    case TokenType.Method:
                        instr.Operand = m_reflectReader.GetMethodDefAt(meth.RID);
                        break;

                    case TokenType.MemberRef:
                        instr.Operand = m_reflectReader.GetMemberRefAt(meth.RID, context);
                        break;

                    case TokenType.MethodSpec:
                        instr.Operand = m_reflectReader.GetMethodSpecAt(meth.RID, context);
                        break;

                    default:
                        throw new ReflectionException("Wrong token for InlineMethod Operand: " + meth);
                    }
                    break;

                case OperandType.InlineType:
                    MetadataToken type = new MetadataToken(br.ReadInt32());
                    switch (type.TokenType)
                    {
                    case TokenType.TypeDef:
                        instr.Operand = m_reflectReader.GetTypeDefAt(type.RID);
                        break;

                    case TokenType.TypeRef:
                        instr.Operand = m_reflectReader.GetTypeRefAt(type.RID);
                        break;

                    case TokenType.TypeSpec:
                        instr.Operand = m_reflectReader.GetTypeSpecAt(type.RID, context);
                        break;

                    default:
                        throw new ReflectionException("Wrong token for InlineType Operand: " + type);
                    }
                    break;

                case OperandType.InlineTok:
                    MetadataToken token = new MetadataToken(br.ReadInt32());
                    switch (token.TokenType)
                    {
                    case TokenType.TypeDef:
                        instr.Operand = m_reflectReader.GetTypeDefAt(token.RID);
                        break;

                    case TokenType.TypeRef:
                        instr.Operand = m_reflectReader.GetTypeRefAt(token.RID);
                        break;

                    case TokenType.TypeSpec:
                        instr.Operand = m_reflectReader.GetTypeSpecAt(token.RID, context);
                        break;

                    case TokenType.Field:
                        instr.Operand = m_reflectReader.GetFieldDefAt(token.RID);
                        break;

                    case TokenType.Method:
                        instr.Operand = m_reflectReader.GetMethodDefAt(token.RID);
                        break;

                    case TokenType.MethodSpec:
                        instr.Operand = m_reflectReader.GetMethodSpecAt(token.RID, context);
                        break;

                    case TokenType.MemberRef:
                        instr.Operand = m_reflectReader.GetMemberRefAt(token.RID, context);
                        break;

                    default:
                        throw new ReflectionException("Wrong token following ldtoken: " + token);
                    }
                    break;
                }

                instructions.Add(instr.Offset, instr);

                if (last != null)
                {
                    last.Next      = instr;
                    instr.Previous = last;
                }

                last = instr;

                code.Add(instr);
            }

            // resolve branches
            foreach (Instruction i in code)
            {
                switch (i.OpCode.OperandType)
                {
                case OperandType.ShortInlineBrTarget:
                case OperandType.InlineBrTarget:
                    i.Operand = GetInstruction(body, instructions, (int)i.Operand);
                    break;

                case OperandType.InlineSwitch:
                    int []         lbls   = (int [])i.Operand;
                    Instruction [] instrs = new Instruction [lbls.Length];
                    for (int j = 0; j < lbls.Length; j++)
                    {
                        instrs [j] = GetInstruction(body, instructions, lbls [j]);
                    }
                    i.Operand = instrs;
                    break;
                }
            }
        }
Exemple #27
0
        static void ComputeMaxStack(InstructionCollection instructions)
        {
            InstructionCollection ehs = new InstructionCollection (null);
            foreach (ExceptionHandler eh in instructions.Container.ExceptionHandlers) {
                switch (eh.Type) {
                case ExceptionHandlerType.Catch :
                    ehs.Add (eh.HandlerStart);
                    break;
                case ExceptionHandlerType.Filter :
                    ehs.Add (eh.FilterStart);
                    break;
                }
            }

            int max = 0;
            foreach (Instruction instr in instructions) {
                if (ehs.Contains (instr))
                    max++;

                switch (instr.OpCode.StackBehaviourPush) {
                case StackBehaviour.Push1:
                case StackBehaviour.Pushi:
                case StackBehaviour.Pushi8:
                case StackBehaviour.Pushr4:
                case StackBehaviour.Pushr8:
                case StackBehaviour.Pushref:
                case StackBehaviour.Varpush:
                    max++;
                    break;
                case StackBehaviour.Push1_push1:
                    max += 2;
                    break;
                }

                if (instr.OpCode.OperandType == OperandType.InlineMethod) {
                    IMethodSignature signature = instr.Operand as IMethodSignature;
                    if (signature != null && signature.ReturnType.ReturnType.FullName != Constants.Void)
                        max++;
                }
            }

            instructions.Container.MaxStack = max;
        }
 public void VisitInstructionCollection(InstructionCollection instructions)
 {
     foreach (Instruction instruction in instructions)
     {
         //VisitLabel(instruction);
         VisitInstruction(instruction);
     }
 }
Exemple #29
0
 static int GetLength(Instruction start, Instruction end, InstructionCollection instructions)
 {
     Instruction last = instructions [instructions.Count - 1];
     return (end == instructions.Outside ? last.Offset + last.GetSize () : end.Offset) - start.Offset;
 }
Exemple #30
0
 internal ILProcessor(MethodBody body)
 {
     this.body = body;
     this.instructions = (InstructionCollection)body.Instructions;
 }
Exemple #31
0
 static bool IsRangeFat(Instruction start, Instruction end, InstructionCollection instructions)
 {
     return GetLength (start, end, instructions) >= 256 ||
         start.Offset >= 65536;
 }
Exemple #32
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 = instr.Operand as Instruction [];
					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 :
					throw new NotImplementedException ();
				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.ToString (),
								instr.Operand.GetType ().FullName));
					break;
				}
			}

			// patch branches
			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 = instr.Operand as Instruction [];
					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) ((instr.Operand as Instruction).Offset -
						(instr.Offset + instr.OpCode.Size + 1)));
					break;
				case OperandType.InlineBrTarget :
					m_codeWriter.BaseStream.Position = instr.Offset + instr.OpCode.Size;
					m_codeWriter.Write ((instr.Operand as Instruction).Offset -
						(instr.Offset + instr.OpCode.Size + 4));
					break;
				}
			}

			m_codeWriter.BaseStream.Position = pos;
		}
Exemple #33
0
        void ReadCode()
        {
            start = position;
            var code_size = body.code_size;

            if (code_size < 0 || buffer.Length <= (uint) (code_size + position))
                code_size = 0;

            var end = start + code_size;
            InstructionCollection instructions = new InstructionCollection (code_size / 3);
            body.instructions = instructions;
            instructions.initing = true;

            while (position < end) {
                var offset = base.position - start;
                var opcode = ReadOpCode ();
                var current = new Instruction (offset, opcode);
                current.index = instructions.Count;

                if (opcode.OperandType != OperandType.InlineNone)
                    current.operand = ReadOperand (current);

                instructions.Add (current);
            }

            ResolveBranches (instructions);

            instructions.initing = false;
        }