Esempio n. 1
0
        /// <summary>
        /// Converts the provided trilean to an I4 stack value, pushes it onto the stack and returns the success
        /// dispatcher result.
        /// </summary>
        /// <param name="context">The current execution context.</param>
        /// <param name="result">The trilean value.</param>
        /// <returns>The dispatch result.</returns>
        protected static DispatchResult ConvertToI4AndReturnSuccess(CilExecutionContext context, Trilean result)
        {
            var i4Result = new I4Value(result.ToBooleanOrFalse() ? 1 : 0, 0xFFFFFFFEu | (result.IsKnown ? 1u : 0u));

            context.ProgramState.Stack.Push(i4Result);
            return(DispatchResult.Success());
        }
Esempio n. 2
0
        /// <inheritdoc />
        public override DispatchResult Execute(CilExecutionContext context, CilInstruction instruction)
        {
            var stack = context.ProgramState.Stack;

            // Pop arguments.
            var valueValue = stack.Pop();
            var indexValue = stack.Pop();
            var arrayValue = stack.Pop();

            // Check if both array and index are known.
            if (!arrayValue.IsKnown)
            {
                throw new DispatchException($"Destination array value for instruction at offset IL_{instruction.Offset:X4} is unknown.");
            }
            if (!indexValue.IsKnown)
            {
                throw new DispatchException($"Index for instruction at offset IL_{instruction.Offset:X4} is unknown.");
            }

            // Expect an int32 or a native int for index, and extract its value.
            if (indexValue.CliValueType != CliValueType.Int32 && indexValue.CliValueType != CliValueType.NativeInt)
            {
                return(DispatchResult.InvalidProgram());
            }

            int index = indexValue.InterpretAsI4().I32;

            // Expect an O value with a .NET array in it.
            switch (arrayValue)
            {
            case OValue {
                    IsZero: { Value : TrileanValue.True }
            } :
                // Pushed array object is null.
                return(new DispatchResult(new NullReferenceException()));
Esempio n. 3
0
 /// <inheritdoc />
 protected override DispatchResult Execute(
     CilExecutionContext context, CilInstruction instruction, FValue left, FValue right)
 {
     left.F64 /= right.F64;
     context.ProgramState.Stack.Push(left);
     return(DispatchResult.Success());
 }
Esempio n. 4
0
File: Clt.cs Progetto: lanicon/Echo
        /// <inheritdoc />
        protected override DispatchResult Execute(CilExecutionContext context, CilInstruction instruction,
                                                  IntegerValue left, IntegerValue right)
        {
            var result = left.IsLessThan(right, instruction.OpCode.Code == CilCode.Clt);

            return(ConvertToI4AndReturnSuccess(context, result));
        }
Esempio n. 5
0
File: Ret.cs Progetto: lanicon/Echo
        /// <inheritdoc />
        public DispatchResult Execute(CilExecutionContext context, CilInstruction instruction)
        {
            var environment = context.GetService <ICilRuntimeEnvironment>();

            // If the containing method is expected to return a value, the stack should contain exactly one value,
            // and no values otherwise.

            int popCount = environment.Architecture.GetStackPopCount(instruction);

            if (context.ProgramState.Stack.Size != popCount)
            {
                return(DispatchResult.InvalidProgram());
            }

            // Pop result.
            if (popCount == 1)
            {
                context.Result.ReturnValue = context.ProgramState.Stack.Pop();
            }

            return(new DispatchResult
            {
                HasTerminated = true
            });
        }
Esempio n. 6
0
        /// <inheritdoc />
        public override DispatchResult Execute(CilExecutionContext context, CilInstruction instruction)
        {
            var environment = context.GetService <ICilRuntimeEnvironment>();
            var factory     = environment.Module.CorLibTypeFactory;

            var stack        = context.ProgramState.Stack;
            var valueValue   = stack.Pop();
            var pointerValue = (IPointerValue)stack.Pop();

            var marshaller = environment.CliMarshaller;

            switch (instruction.OpCode.Code)
            {
            case CilCode.Stind_I:
                if (pointerValue.Is32Bit)
                {
                    pointerValue.WriteInteger32(0, valueValue.InterpretAsI4());
                }
                else
                {
                    pointerValue.WriteInteger64(0, valueValue.InterpretAsI8());
                }
                break;

            case CilCode.Stind_I1:
                pointerValue.WriteInteger8(0,
                                           (Integer8Value)marshaller.ToCtsValue(valueValue.InterpretAsI1(), factory.SByte));
                break;

            case CilCode.Stind_I2:
                pointerValue.WriteInteger16(0,
                                            (Integer16Value)marshaller.ToCtsValue(valueValue.InterpretAsI2(), factory.Int16));
                break;

            case  CilCode.Stind_I4:
                pointerValue.WriteInteger32(0,
                                            (Integer32Value)marshaller.ToCtsValue(valueValue.InterpretAsI4(), factory.Int32));
                break;

            case CilCode.Stind_I8:
                pointerValue.WriteInteger64(0,
                                            (Integer64Value)marshaller.ToCtsValue(valueValue.InterpretAsI8(), factory.Int64));
                break;

            case CilCode.Stind_R4:
                pointerValue.WriteFloat32(0,
                                          (Float32Value)marshaller.ToCtsValue(valueValue.InterpretAsR4(), factory.Single));
                break;

            case CilCode.Stind_R8:
                pointerValue.WriteFloat64(0,
                                          (Float64Value)marshaller.ToCtsValue(valueValue.InterpretAsR8(), factory.Double));
                break;

            default:
                return(DispatchResult.InvalidProgram());
            }

            return(base.Execute(context, instruction));
        }
Esempio n. 7
0
        /// <inheritdoc />
        public DispatchResult Execute(CilExecutionContext context, CilInstruction instruction)
        {
            var result = VerifyCondition(context, instruction);

            int newOffset;

            if (result.IsKnown)
            {
                if (result)
                {
                    newOffset = ((ICilLabel)instruction.Operand).Offset;
                }
                else
                {
                    newOffset = instruction.Offset + instruction.Size;
                }
            }
            else
            {
                // TODO: dispatch event, allowing the user to handle unknown branch conditions.
                throw new DispatchException("Branch condition could not be evaluated.");
            }

            var stack = context.ProgramState.Stack;

            for (int i = 0; i < ArgumentCount; i++)
            {
                stack.Pop();
            }

            context.ProgramState.ProgramCounter = newOffset;
            return(DispatchResult.Success());
        }
Esempio n. 8
0
 /// <inheritdoc />
 protected override DispatchResult Execute(CilExecutionContext context, CilInstruction instruction,
                                           IntegerValue left, IntegerValue right)
 {
     left.Xor(right);
     context.ProgramState.Stack.Push((ICliValue)left);
     return(DispatchResult.Success());
 }
Esempio n. 9
0
        /// <inheritdoc />
        public override DispatchResult Execute(CilExecutionContext context, CilInstruction instruction)
        {
            var environment = context.GetService <ICilRuntimeEnvironment>();

            var variables = new IVariable[1];

            if (environment.Architecture.GetReadVariables(instruction, variables) != 1)
            {
                throw new DispatchException(
                          $"Architecture returned an incorrect number of variables being read from instruction {instruction}.");
            }

            switch (variables[0])
            {
            case CilParameter parameter:
                var value = environment.CliMarshaller.ToCliValue(
                    context.ProgramState.Variables[variables[0]],
                    parameter.Parameter.ParameterType);

                context.ProgramState.Stack.Push(value);
                return(base.Execute(context, instruction));

            default:
                return(DispatchResult.InvalidProgram());
            }
        }
Esempio n. 10
0
        /// <inheritdoc />
        protected override ICliValue GetUnknownElementValue(CilExecutionContext context, CilInstruction instruction)
        {
            var environment = context.GetService <ICilRuntimeEnvironment>();
            var type        = (ITypeDefOrRef)instruction.Operand;

            return(environment.CliMarshaller.ToCliValue(new UnknownValue(), type.ToTypeSignature()));
        }
Esempio n. 11
0
        /// <inheritdoc />
        public override DispatchResult Execute(CilExecutionContext context, CilInstruction instruction)
        {
            var environment = context.GetService <ICilRuntimeEnvironment>();

            var variables = new IVariable[1];

            if (environment.Architecture.GetWrittenVariables(instruction, variables) != 1)
            {
                throw new DispatchException(
                          $"Architecture returned an incorrect number of variables being written by instruction {instruction}.");
            }

            switch (variables[0])
            {
            case CilVariable cilVariable:
                var value = environment.CliMarshaller.ToCtsValue(
                    context.ProgramState.Stack.Pop(),
                    cilVariable.Variable.VariableType);

                context.ProgramState.Variables[variables[0]] = value;
                return(base.Execute(context, instruction));

            default:
                return(DispatchResult.InvalidProgram());
            }
        }
Esempio n. 12
0
File: Cgt.cs Progetto: lanicon/Echo
        /// <inheritdoc />
        protected override DispatchResult Execute(CilExecutionContext context, CilInstruction instruction,
                                                  FValue left, FValue right)
        {
            bool result = left.IsGreaterThan(right, instruction.OpCode.Code == CilCode.Cgt_Un);

            return(ConvertToI4AndReturnSuccess(context, result));
        }
Esempio n. 13
0
        /// <inheritdoc />
        public override DispatchResult Execute(CilExecutionContext context, CilInstruction instruction)
        {
            var stack = context.ProgramState.Stack;

            stack.Push((ICliValue)stack.Top.Copy());
            return(base.Execute(context, instruction));
        }
Esempio n. 14
0
        /// <inheritdoc />
        public override DispatchResult Execute(CilExecutionContext context, CilInstruction instruction)
        {
            var stack = context.ProgramState.Stack;

            // Pop arguments.
            var lengthValue        = stack.Pop();
            var sourceAddress      = stack.Pop();
            var destinationAddress = stack.Pop();

            // Interpret arguments.
            if (!(destinationAddress is IPointerValue destinationPointer) || !(sourceAddress is IPointerValue sourcePointer))
            {
                return(DispatchResult.InvalidProgram());
            }

            if (!lengthValue.IsKnown)
            {
                throw new DispatchException("Number of bytes to copy is unknown.");
            }
            int length = lengthValue.InterpretAsI4().I32;

            // Copy data.
            Span <byte> data    = stackalloc byte[length];
            Span <byte> bitmask = stackalloc byte[length];

            sourcePointer.ReadBytes(0, data, bitmask);
            destinationPointer.WriteBytes(0, data, bitmask);

            return(base.Execute(context, instruction));
        }
Esempio n. 15
0
File: Ceq.cs Progetto: lanicon/Echo
        /// <inheritdoc />
        protected override DispatchResult Execute(CilExecutionContext context, CilInstruction instruction,
                                                  OValue left, OValue right)
        {
            var result = left.IsEqualTo(right);

            return(ConvertToI4AndReturnSuccess(context, result));
        }
Esempio n. 16
0
File: Beq.cs Progetto: lanicon/Echo
 /// <inheritdoc />
 protected override Trilean VerifyCondition(CilExecutionContext context, CilInstruction instruction,
                                            OValue left, OValue right)
 {
     return(left.IsKnown && right.IsKnown
         ? ReferenceEquals(left.ReferencedObject, right.ReferencedObject)
         : Trilean.Unknown);
 }
Esempio n. 17
0
        /// <inheritdoc />
        public override DispatchResult Execute(CilExecutionContext context, CilInstruction instruction)
        {
            var stack = context.ProgramState.Stack;

            // Pop arguments.
            var indexValue = stack.Pop();
            var arrayValue = stack.Pop();

            // Check if both array and index are known.
            if (!arrayValue.IsKnown || !indexValue.IsKnown)
            {
                stack.Push(GetUnknownElementValue(context, instruction));
                return(base.Execute(context, instruction));
            }

            // Expect an int32 or a native int for index, and extract its value.
            if (indexValue.CliValueType != CliValueType.Int32 && indexValue.CliValueType != CliValueType.NativeInt)
            {
                return(DispatchResult.InvalidProgram());
            }
            int index = indexValue.InterpretAsI4().I32;

            // Obtain element.
            ICliValue elementValue;

            switch (arrayValue)
            {
            case OValue {
                    IsZero: { Value : TrileanValue.True }
            } :
                // Pushed array object is null.
                return(new DispatchResult(new NullReferenceException()));
Esempio n. 18
0
 /// <inheritdoc />
 protected override DispatchResult Execute(CilExecutionContext context, CilInstruction instruction,
                                           IntegerValue value, int shiftCount)
 {
     value.RightShift(shiftCount, instruction.OpCode.Code == CilCode.Shr);
     context.ProgramState.Stack.Push((ICliValue)value);
     return(DispatchResult.Success());
 }
Esempio n. 19
0
        /// <inheritdoc />
        public override DispatchResult Execute(CilExecutionContext context, CilInstruction instruction)
        {
            var environment = context.GetService <ICilRuntimeEnvironment>();
            var field       = ((IFieldDescriptor)instruction.Operand).Resolve();
            var stack       = context.ProgramState.Stack;

            var objectValue = stack.Pop();

            IConcreteValue fieldValue;

            if (field.IsStatic)
            {
                // Undocumented: The runtime does allow access of static fields through the ldfld opcode.
                // In this case, the object instance that is pushed is ignored, allowing constructs like:
                //
                //    ldnull
                //    ldfld <some_static_field>
                //
                // without the runtime throwing a NullReferenceException.

                var staticField = environment.StaticFieldFactory.Get(field);
                fieldValue = environment.CliMarshaller.ToCliValue(staticField.Value, field.Signature.FieldType);
            }
            else
            {
                // Attempt to dereference the object instance.

                switch (objectValue)
                {
                case { IsKnown: false } :
Esempio n. 20
0
        /// <inheritdoc />
        protected override Trilean VerifyCondition(CilExecutionContext context, CilInstruction instruction,
                                                   FValue left, FValue right)
        {
            // ReSharper disable once CompareOfFloatsByEqualityOperator
            bool equal    = left.F64 == right.F64;
            bool lessThan = left.IsLessThan(right, IsSigned(instruction));

            return(lessThan || equal);
        }
Esempio n. 21
0
        public static (ICliValue left, ICliValue right) PopBinaryOperationArguments(CilExecutionContext context)
        {
            var values = PeekBinaryOperationArguments(context);
            var stack  = context.ProgramState.Stack;

            stack.Pop();
            stack.Pop();
            return(values);
        }
Esempio n. 22
0
        /// <inheritdoc />
        protected override ICliValue GetElementValue(CilExecutionContext context, CilInstruction instruction, IDotNetArrayValue array, int index)
        {
            var environment = context.GetService <ICilRuntimeEnvironment>();

            var type       = (ITypeDescriptor)instruction.Operand;
            var typeLayout = environment.ValueFactory.GetTypeMemoryLayout(type);

            return(array.LoadElement(index, typeLayout, environment.CliMarshaller));
        }
Esempio n. 23
0
File: Ceq.cs Progetto: lanicon/Echo
        /// <inheritdoc />
        protected override DispatchResult Execute(CilExecutionContext context, CilInstruction instruction,
                                                  FValue left, FValue right)
        {
            // ReSharper disable once CompareOfFloatsByEqualityOperator
            var i4Result = new I4Value(left.F64 == right.F64 ? 1 : 0);

            context.ProgramState.Stack.Push(i4Result);
            return(DispatchResult.Success());
        }
Esempio n. 24
0
        private static DispatchResult ExecuteDefault(CilExecutionContext context, IntegerValue value, IntegerValue left)
        {
            if (value.IsNonZero.IsUnknown)
            {
                value.MarkFullyUnknown();
            }

            context.ProgramState.Stack.Push((ICliValue)left);
            return(DispatchResult.Success());
        }
Esempio n. 25
0
        /// <inheritdoc />
        public override DispatchResult Execute(CilExecutionContext context, CilInstruction instruction)
        {
            var environment = context.GetService <ICilRuntimeEnvironment>();
            var stack       = context.ProgramState.Stack;

            var value = (ICliValue)stack.Pop();

            bool      overflowed = false;
            ICliValue newValue   = instruction.OpCode.Code switch
            {
                CilCode.Conv_I1 => value.ConvertToI1(false, out _),
                CilCode.Conv_Ovf_I1 => value.ConvertToI1(false, out overflowed),
                CilCode.Conv_Ovf_I1_Un => value.ConvertToI1(true, out overflowed),
                CilCode.Conv_U1 => value.ConvertToU1(false, out _),
                CilCode.Conv_Ovf_U1 => value.ConvertToU1(false, out overflowed),
                CilCode.Conv_Ovf_U1_Un => value.ConvertToU1(true, out overflowed),
                CilCode.Conv_I2 => value.ConvertToI2(false, out _),
                CilCode.Conv_Ovf_I2 => value.ConvertToI2(false, out overflowed),
                CilCode.Conv_Ovf_I2_Un => value.ConvertToI2(true, out overflowed),
                CilCode.Conv_U2 => value.ConvertToU2(false, out _),
                CilCode.Conv_Ovf_U2 => value.ConvertToU2(false, out overflowed),
                CilCode.Conv_Ovf_U2_Un => value.ConvertToU2(true, out overflowed),
                CilCode.Conv_I4 => value.ConvertToI4(false, out _),
                CilCode.Conv_Ovf_I4 => value.ConvertToI4(false, out overflowed),
                CilCode.Conv_Ovf_I4_Un => value.ConvertToI4(true, out overflowed),
                CilCode.Conv_U4 => value.ConvertToU4(false, out _),
                CilCode.Conv_Ovf_U4 => value.ConvertToU4(false, out overflowed),
                CilCode.Conv_Ovf_U4_Un => value.ConvertToU4(true, out overflowed),
                CilCode.Conv_I8 => value.ConvertToI8(false, out _),
                CilCode.Conv_Ovf_I8 => value.ConvertToI8(false, out overflowed),
                CilCode.Conv_Ovf_I8_Un => value.ConvertToI8(true, out overflowed),
                CilCode.Conv_U8 => value.ConvertToU8(false, out _),
                CilCode.Conv_Ovf_U8 => value.ConvertToU8(false, out overflowed),
                CilCode.Conv_Ovf_U8_Un => value.ConvertToU8(true, out overflowed),
                CilCode.Conv_I => value.ConvertToI(environment.Is32Bit, false, out _),
                CilCode.Conv_Ovf_I => value.ConvertToI(environment.Is32Bit, false, out overflowed),
                CilCode.Conv_Ovf_I_Un => value.ConvertToI(environment.Is32Bit, true, out overflowed),
                CilCode.Conv_U => value.ConvertToU(environment.Is32Bit, false, out _),
                CilCode.Conv_Ovf_U => value.ConvertToU(environment.Is32Bit, false, out overflowed),
                CilCode.Conv_Ovf_U_Un => value.ConvertToU(environment.Is32Bit, true, out overflowed),
                CilCode.Conv_R4 => value.ConvertToR4(),
                CilCode.Conv_R8 => value.ConvertToR8(),
                CilCode.Conv_R_Un => value.ConvertToR(),
                _ => throw new ArgumentOutOfRangeException()
            };

            if (overflowed)
            {
                return(new DispatchResult(new OverflowException()));
            }

            context.ProgramState.Stack.Push(newValue);
            return(base.Execute(context, instruction));
        }
    }
Esempio n. 26
0
        /// <inheritdoc />
        public override Trilean VerifyCondition(CilExecutionContext context, CilInstruction instruction)
        {
            var(left, right) = BinaryOperationHelper.PeekBinaryOperationArguments(context);

            return((left, right) switch
            {
                (IntegerValue a, IntegerValue b) => VerifyCondition(context, instruction, a, b),
                (FValue a, FValue b) => VerifyCondition(context, instruction, a, b),
                (OValue a, OValue b) => VerifyCondition(context, instruction, a, b),
                _ => Trilean.Unknown,
            });
Esempio n. 27
0
        /// <inheritdoc />
        public override DispatchResult Execute(CilExecutionContext context, CilInstruction instruction)
        {
            var type        = instruction.Operand as ITypeDefOrRef;
            var environment = context.GetService <ICilRuntimeEnvironment>();
            var allocator   = environment.ValueFactory;
            var layout      = allocator.GetTypeMemoryLayout(type);

            context.ProgramState.Stack.Push(new I4Value((int)layout.Size));

            return(base.Execute(context, instruction));
        }
Esempio n. 28
0
        /// <inheritdoc />
        public DispatchResult Execute(CilExecutionContext context, CilInstruction instruction)
        {
            var(left, right) = BinaryOperationHelper.PopBinaryOperationArguments(context);

            var result = (left, right) switch
            {
                (IntegerValue a, IntegerValue b) => Execute(context, instruction, a, b),
                (FValue a, FValue b) => Execute(context, instruction, a, b),
                (OValue a, OValue b) => Execute(context, instruction, a, b),
                _ => DispatchResult.InvalidProgram(),
            };
Esempio n. 29
0
        /// <inheritdoc />
        public override DispatchResult Execute(CilExecutionContext context, CilInstruction instruction)
        {
            var type         = (ITypeDefOrRef)instruction.Operand;
            var memoryLayout = context.GetService <ICilRuntimeEnvironment>().ValueFactory.GetTypeMemoryLayout(type);

            var sourceAddress      = context.ProgramState.Stack.Pop();
            var destinationAddress = context.ProgramState.Stack.Pop();

            switch (destinationAddress)
            {
            case { IsKnown: false } :
Esempio n. 30
0
        /// <inheritdoc />
        public override DispatchResult Execute(CilExecutionContext context, CilInstruction instruction)
        {
            var environment = context.GetService <ICilRuntimeEnvironment>();

            var referencedField = (IFieldDescriptor)instruction.Operand;
            var staticField     = environment.StaticFieldFactory.Get(referencedField);
            var value           = environment.CliMarshaller.ToCliValue(staticField.Value, referencedField.Signature.FieldType);

            context.ProgramState.Stack.Push(value);

            return(base.Execute(context, instruction));
        }