Exemple #1
0
 internal static FuzzerInstruction CreateInvalidLegacy(FuzzerOpCodeTable table, OpCode opCode, int groupIndex, bool isModrmMemory, MandatoryPrefix mandatoryPrefix) =>
 new FuzzerInstruction(Code.INVALID, FuzzerInstructionFlags.None, 0, 0, mandatoryPrefix, table, opCode, groupIndex, -1, isModrmMemory, 0, 0);
Exemple #2
0
 internal static FuzzerInstruction CreateInvalidVec(FuzzerOpCodeTable table, OpCode opCode, int groupIndex, int rmGroupIndex, bool isModrmMemory, MandatoryPrefix mandatoryPrefix, uint w, uint l, FuzzerInstructionFlags flags) =>
 new FuzzerInstruction(Code.INVALID, flags, w, l, mandatoryPrefix, table, opCode, groupIndex, rmGroupIndex, isModrmMemory, 0, 0);
Exemple #3
0
        FuzzerInstruction(Code code, FuzzerInstructionFlags flags, uint w, uint l, MandatoryPrefix mandatoryPrefix, FuzzerOpCodeTable table, OpCode opCode, int groupIndex, int rmGroupIndex, bool isModrmMemory, int operandSize, int addressSize)
        {
            // Should be a 2-byte opcode instead (groupIndex = modrm.reg and rmGroupIndex = modrm.rm bits)
            Assert.True(groupIndex < 0 || rmGroupIndex < 0);
            Assert.True(groupIndex >= -1 && groupIndex <= 7);
            Assert.True(rmGroupIndex >= -1 && rmGroupIndex <= 7);
            var opc = code.ToOpCode();

            Assert.True(opc.IsInstruction || code == Code.INVALID);

            if (isModrmMemory)
            {
                if (opc.CanBroadcast)
                {
                    flags |= FuzzerInstructionFlags.CanBroadcast;
                }
                if (opc.CanUseLockPrefix)
                {
                    flags |= FuzzerInstructionFlags.CanUseLockPrefix;
                }
            }
            else
            {
                if (opc.CanUseRoundingControl)
                {
                    flags |= FuzzerInstructionFlags.CanUseRoundingControl;
                }
                if (opc.CanSuppressAllExceptions)
                {
                    flags |= FuzzerInstructionFlags.CanSuppressAllExceptions;
                }
            }
            if (opc.RequireNonZeroOpMaskRegister)
            {
                flags |= FuzzerInstructionFlags.RequireNonZeroOpMaskRegister;
            }
            if (opc.CanUseZeroingMasking)
            {
                flags |= FuzzerInstructionFlags.CanUseZeroingMasking;
            }
            if (opc.CanUseOpMaskRegister)
            {
                flags |= FuzzerInstructionFlags.CanUseOpMaskRegister;
            }
            switch (code)
            {
            case Code.Xchg_r16_AX:
            case Code.Xchg_r32_EAX:
            case Code.Xchg_r64_RAX:
                flags |= FuzzerInstructionFlags.IsXchgRegAcc;
                break;

            case Code.Nopw:
            case Code.Nopd:
            case Code.Nopq:
                flags |= FuzzerInstructionFlags.IsNop;
                break;

            case Code.Rdrand_r16:
            case Code.Rdrand_r32:
            case Code.Rdrand_r64:
            case Code.Rdseed_r16:
            case Code.Rdseed_r32:
            case Code.Rdseed_r64:
            case Code.Movbe_r16_m16:
            case Code.Movbe_r32_m32:
            case Code.Movbe_r64_m64:
            case Code.Movbe_m16_r16:
            case Code.Movbe_m32_r32:
            case Code.Movbe_m64_r64:
                Assert.True(mandatoryPrefix == MandatoryPrefix.None);
                mandatoryPrefix = MandatoryPrefix.PNP;
                flags          |= FuzzerInstructionFlags.IsNFx;
                break;
            }

            Code            = code;
            Flags           = flags;
            W               = w;
            L               = l;
            MandatoryPrefix = mandatoryPrefix;
            Table           = table;
            OpCode          = opCode;
            GroupIndex      = groupIndex;
            RmGroupIndex    = rmGroupIndex;
            IsModrmMemory   = isModrmMemory;
            OperandSize     = operandSize;
            AddressSize     = addressSize;

            if (MandatoryPrefix == MandatoryPrefix.P66 && operandSize != 64 && CodeUtils.IsReservedNop(Code))
            {
                MandatoryPrefix = MandatoryPrefix.None;
            }

            FuzzerOperand[]? operands = null;
            // Special support for reserved nop instructions since we may have transformed them to
            // a 2-byte opcode (no ops) or a reg or rm group (one operand).
            if (CodeUtils.IsReservedNop(code))
            {
                // Verify our assumptions
                Assert.True(opc.OpCount == 2);
                const int RM_INDEX  = 0;
                const int REG_INDEX = 1;
                switch (opc.GetOpKind(RM_INDEX))
                {
                case OpCodeOperandKind.r16_or_mem:
                case OpCodeOperandKind.r32_or_mem:
                case OpCodeOperandKind.r64_or_mem:
                    break;

                default:
                    throw ThrowHelpers.Unreachable;
                }
                switch (opc.GetOpKind(REG_INDEX))
                {
                case OpCodeOperandKind.r16_reg:
                case OpCodeOperandKind.r32_reg:
                case OpCodeOperandKind.r64_reg:
                    break;

                default:
                    throw ThrowHelpers.Unreachable;
                }

                if (OpCode.IsTwobyte)
                {
                    Assert.True(groupIndex < 0 && rmGroupIndex < 0);
                    operands = Array.Empty <FuzzerOperand>();
                }
                else if (groupIndex >= 0)
                {
                    Assert.True(rmGroupIndex < 0);
                    // reg bits are hard coded, rm bits can be used
                    operands = new FuzzerOperand[1] {
                        FuzzerOperands.GetOperand(opc.GetOpKind(RM_INDEX), isModrmMemory)
                    };
                }
                else if (rmGroupIndex >= 0)
                {
                    // rm bits are hard coded, reg bits can be used
                    operands = new FuzzerOperand[1] {
                        FuzzerOperands.GetOperand(opc.GetOpKind(REG_INDEX), isModrmMemory)
                    };
                }
            }
            if (operands is null)
            {
                int opCount = opc.OpCount + (opc.CanUseOpMaskRegister ? 1 : 0);
                operands = opCount == 0 ? Array.Empty <FuzzerOperand>() : new FuzzerOperand[opCount];
                int i;
                for (i = 0; i < opc.OpCount; i++)
                {
                    operands[i] = FuzzerOperands.GetOperand(opc.GetOpKind(i), isModrmMemory);
                }
                if (opc.CanUseOpMaskRegister)
                {
                    operands[i++] = FuzzerOperands.OpMaskRegister;
                }
                Assert.True(i == operands.Length);
            }
            operands = operands.Where(a => a.Kind != FuzzerOperandKind.None).ToArray();
            Operands = operands;
            Assert.True(!opc.CanUseOpMaskRegister || (operands.Length > 0 && operands[operands.Length - 1] == FuzzerOperands.OpMaskRegister));
            ImmediateOperands   = operands.OfType <ImmediateFuzzerOperand>().ToArray();
            MemOffsOperands     = operands.Where(a => a.Kind == FuzzerOperandKind.MemOffs).ToArray();
            ImpliedMemOperands  = operands.Where(a => a.Kind == FuzzerOperandKind.ImpliedMem).ToArray();
            ModrmMemoryOperands = operands.OfType <ModrmMemoryFuzzerOperand>().ToArray();
            RegisterOperands    = operands.OfType <RegisterFuzzerOperand>().ToArray();
            // There are fuzzers that test only some of these op kinds, so if there's a new op kind, a new fuzzer would need
            // to be added, see eg AllMemOffsFuzzerGen
            Assert.True(Operands.Length == ImmediateOperands.Length + MemOffsOperands.Length + ImpliedMemOperands.Length + ModrmMemoryOperands.Length + RegisterOperands.Length);

            foreach (var memOp in ModrmMemoryOperands)
            {
                if (memOp.IsVSIB)
                {
                    Flags |= FuzzerInstructionFlags.IsVsib;
                    break;
                }
            }
        }