Beispiel #1
0
        public void BaseCaseFieldOperandTest()
        {
            const int EXPECTED_VALUE = 848;
            var       message        = new Message
            {
                SizeInBytes = EXPECTED_VALUE
            };

            var operand = new FieldOperand("SizeInBytes");

            Assert.AreEqual(EXPECTED_VALUE, (int)operand.Value().Invoke(message));
        }
Beispiel #2
0
        public void DotCaseFieldOperandTest()
        {
            var points = new List <Point>
            {
                new Point(),
                new Point(),
                new Point()
            };

            var message = new Message
            {
                Points = points
            };


            var expectedValue = points.Count;

            var operand = new FieldOperand("Points.Count");
            var result  = operand.Value().Invoke(message);

            Assert.AreEqual(expectedValue, (int)result);
        }
Beispiel #3
0
        public Operand Field(Type returnType, string name)
        {
            var operand = new FieldOperand(this, null, new CriteriaMetadataInfo(returnType, name, CriteriaMetadataToken.Field));
            operand.WriteEmit(null);

            return operand;
        }
Beispiel #4
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Ldfld"/> class.
 /// </summary>
 /// <param name="result">The result.</param>
 /// <param name="value">The value.</param>
 public Ldfld(Register result, FieldOperand value)
     : base("Ldfld", result, new Operand [] { value })
 {
 }
Beispiel #5
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Stsfld"/> class.
 /// </summary>
 /// <param name="field">The field.</param>
 /// <param name="value">The value.</param>
 public Stsfld(FieldOperand field, Register value)
     : base("Stsfld", null, new Operand [] { field, value })
 {
 }
Beispiel #6
0
        private static Instruction Parse(MethodInfo methodInfo)
        {
            Instruction head = null;
            Instruction tail = null;

            var data = methodInfo.GetMethodBody().GetILAsByteArray();

            var offset = 0u;

            while (offset < data.Length)
            {
                IOperand operand = null;

                short opcodeValue = data[offset++];
                if (opcodeValue == 0xFE)
                {
                    opcodeValue |= (short)data[offset++];
                }

                OpCode opcode = _opcodes[opcodeValue];

                switch (opcode.OperandType)
                {
                case OperandType.InlineBrTarget:
                {
                    var branchTarget = Read <uint>(data, ref offset) + offset;
                    operand = new BranchTargetOperand(branchTarget);
                    break;
                }

                case OperandType.InlineField:
                {
                    var metadataToken = Read <int>(data, ref offset);
                    try {
                        var fieldInfo = methodInfo.Module.ResolveField(metadataToken);
                        operand = new FieldOperand(fieldInfo);
                    } catch (Exception) {
                        operand = new FieldOperand(null);
                    }
                    break;
                }

                case OperandType.InlineI:
                    operand = new ImmediateOperand <uint>(opcode.OperandType, Read <uint>(data, ref offset));
                    break;

                case OperandType.InlineI8:
                    operand = new ImmediateOperand <ulong>(opcode.OperandType, Read <ulong>(data, ref offset));
                    break;

                case OperandType.InlineMethod:
                {
                    var metadataToken = Read <int>(data, ref offset);
                    try {
                        var inlineMethodInfo = methodInfo.Module.ResolveMethod(metadataToken);
                        operand = new MethodOperand(inlineMethodInfo);
                    } catch (Exception) {
                        operand = new MethodOperand(null);
                    }
                    break;
                }

                case OperandType.InlineNone:
                    break;

                case OperandType.InlineR:
                    operand = new ImmediateOperand <double>(opcode.OperandType, Read <double>(data, ref offset));
                    break;

                case OperandType.InlineSig:
                {
                    var metadataToken = Read <int>(data, ref offset);
                    try {
                        var blobData = methodInfo.Module.ResolveSignature(metadataToken);
                        operand = new DataBlobOperand(blobData);
                    } catch (Exception) {
                        operand = new DataBlobOperand(null);
                    }
                    break;
                }

                case OperandType.InlineString:
                {
                    var metadataToken = Read <int>(data, ref offset);
                    try {
                        var stringInfo = methodInfo.Module.ResolveString(metadataToken);
                        operand = new StringOperand(stringInfo);
                    } catch (Exception) {
                        operand = new StringOperand(null);
                    }
                    break;
                }

                case OperandType.InlineSwitch:
                {
                    var count         = Read <uint>(data, ref offset);
                    var tableOffset   = offset;
                    var switchTargets = new uint[count];
                    for (var i = 0; i < count; ++i)
                    {
                        switchTargets[i] = Read <uint>(data, ref offset) + tableOffset * count * 4;
                    }
                    throw new NotImplementedException();
                }

                case OperandType.InlineTok:
                {
                    var metadataToken = Read <int>(data, ref offset);
                    try {
                        var tokenRef = methodInfo.Module.ResolveType(metadataToken);
                        operand = new TypeOperand(opcode.OperandType, tokenRef);
                    } catch (Exception) {
                        operand = new TypeOperand(opcode.OperandType, null);
                    }
                    break;
                }

                case OperandType.InlineType:
                {
                    var metadataToken = Read <int>(data, ref offset);
                    try {
                        var tokenRef = methodInfo.Module.ResolveType(metadataToken, methodInfo.DeclaringType.GetGenericArguments(), methodInfo.GetGenericArguments());
                        operand = new TypeOperand(opcode.OperandType, tokenRef);
                    } catch (Exception) {
                        operand = new TypeOperand(opcode.OperandType, null);
                    }
                    break;
                }

                case OperandType.InlineVar:
                {
                    var variableOrdinal = Read <ushort>(data, ref offset);
                    operand = new VariableOperand(methodInfo.GetMethodBody().LocalVariables[variableOrdinal]);
                    break;
                }
                }

                var instruction = new Instruction(opcode, operand);

                if (head == null)
                {
                    head = tail = instruction;
                }
                else
                {
                    tail = tail.Next = instruction;
                }
            }

            // Fix branch instruction targets
            tail = head;
            while (tail != null)
            {
                if (tail.Operand is BranchTargetOperand branchTargetOperand)
                {
                    var next = tail.Next;
                    while (next != null && next.Offset != branchTargetOperand.BranchTarget)
                    {
                        next = next.Next;
                    }
                    branchTargetOperand.Target = next ?? throw new InvalidProgramException("Unable to resolve branch target");
                }
                tail = tail.Next;
            }

            return(head);
        }