예제 #1
0
        public IpRelMemOpInstr(BlockEncoder blockEncoder, ref Instruction instruction)
            : base(blockEncoder, instruction.IP64)
        {
            Debug.Assert(instruction.IsIPRelativeMemoryOp);
            this.instruction = instruction;
            instrKind        = InstrKind.Uninitialized;

            string errorMessage;

            instruction.MemoryBase = Register.RIP;
            ripInstructionSize     = (uint)blockEncoder.NullEncoder.Encode(ref instruction, instruction.IP64, out errorMessage);
            if (errorMessage != null)
            {
                ripInstructionSize = DecoderConstants.MaxInstructionLength;
            }

            instruction.MemoryBase = Register.EIP;
            eipInstructionSize     = (uint)blockEncoder.NullEncoder.Encode(ref instruction, instruction.IP64, out errorMessage);
            if (errorMessage != null)
            {
                eipInstructionSize = DecoderConstants.MaxInstructionLength;
            }

            Debug.Assert(eipInstructionSize >= ripInstructionSize);
            Size = eipInstructionSize;
        }
예제 #2
0
        public IpRelMemOpInstr(BlockEncoder blockEncoder, ref Instruction instruction)
            : base(blockEncoder, instruction.IP)
        {
            Debug.Assert(instruction.IsIPRelativeMemoryOperand);
            this.instruction = instruction;
            instrKind        = InstrKind.Uninitialized;

            string errorMessage;

            var instrCopy = instruction;

            instrCopy.MemoryBase = Register.RIP;
            if (!blockEncoder.NullEncoder.TryEncode(ref instrCopy, instrCopy.IP, out ripInstructionSize, out errorMessage))
            {
                ripInstructionSize = DecoderConstants.MaxInstructionLength;
            }

            instrCopy.MemoryBase = Register.EIP;
            if (!blockEncoder.NullEncoder.TryEncode(ref instrCopy, instrCopy.IP, out eipInstructionSize, out errorMessage))
            {
                eipInstructionSize = DecoderConstants.MaxInstructionLength;
            }

            Debug.Assert(eipInstructionSize >= ripInstructionSize);
            Size = eipInstructionSize;
        }
예제 #3
0
파일: JccInstr.cs 프로젝트: xoofx/iced
        public JccInstr(BlockEncoder blockEncoder, ref Instruction instruction)
            : base(blockEncoder, instruction.IP64)
        {
            bitness          = blockEncoder.Bitness;
            this.instruction = instruction;
            instrKind        = InstrKind.Uninitialized;

            string errorMessage;

            if (!blockEncoder.FixBranches)
            {
                instrKind = InstrKind.Unchanged;
                Size      = (uint)blockEncoder.NullEncoder.Encode(ref instruction, instruction.IP64, out errorMessage);
                if (errorMessage != null)
                {
                    Size = DecoderConstants.MaxInstructionLength;
                }
            }
            else
            {
                Instruction instrCopy;

                instrCopy      = instruction;
                instrCopy.Code = instruction.Code.ToShortBranchCode();
                instrCopy.NearBranch64Target = 0;
                shortInstructionSize         = (uint)blockEncoder.NullEncoder.Encode(ref instrCopy, 0, out errorMessage);
                if (errorMessage != null)
                {
                    shortInstructionSize = DecoderConstants.MaxInstructionLength;
                }

                instrCopy      = instruction;
                instrCopy.Code = instruction.Code.ToNearBranchCode();
                instrCopy.NearBranch64Target = 0;
                nearInstructionSize          = (uint)blockEncoder.NullEncoder.Encode(ref instrCopy, 0, out errorMessage);
                if (errorMessage != null)
                {
                    nearInstructionSize = DecoderConstants.MaxInstructionLength;
                }

                if (blockEncoder.Bitness == 64)
                {
                    // Make sure it's not shorter than the real instruction. It can happen if there are extra prefixes.
                    Size = Math.Max(nearInstructionSize, longInstructionSize64);
                }
                else
                {
                    Size = nearInstructionSize;
                }
            }
        }
예제 #4
0
        bool TryOptimize()
        {
            if (instrKind == InstrKind.Unchanged || instrKind == InstrKind.Short)
            {
                return(false);
            }

            var  targetAddress = targetInstr.GetAddress();
            var  nextRip       = IP + shortInstructionSize;
            long diff          = (long)(targetAddress - nextRip);

            if (sbyte.MinValue <= diff && diff <= sbyte.MaxValue)
            {
                if (pointerData != null)
                {
                    pointerData.IsValid = false;
                }
                instrKind = InstrKind.Short;
                Size      = shortInstructionSize;
                return(true);
            }

            // If it's in the same block, we assume the target is at most 2GB away.
            bool useNear = bitness != 64 || targetInstr.IsInBlock(Block);

            if (!useNear)
            {
                targetAddress = targetInstr.GetAddress();
                nextRip       = IP + nearInstructionSize;
                diff          = (long)(targetAddress - nextRip);
                useNear       = int.MinValue <= diff && diff <= int.MaxValue;
            }
            if (useNear)
            {
                if (pointerData != null)
                {
                    pointerData.IsValid = false;
                }
                instrKind = InstrKind.Near;
                Size      = nearInstructionSize;
                return(true);
            }

            if (pointerData == null)
            {
                pointerData = Block.AllocPointerLocation();
            }
            instrKind = InstrKind.Long;
            return(false);
        }
예제 #5
0
        public JmpInstr(BlockEncoder blockEncoder, ref Instruction instruction)
            : base(blockEncoder, instruction.IP64)
        {
            bitness          = blockEncoder.Bitness;
            this.instruction = instruction;
            instrKind        = InstrKind.Uninitialized;

            string      errorMessage;
            Instruction instrCopy;

            if (!blockEncoder.FixBranches)
            {
                instrKind = InstrKind.Unchanged;
                instrCopy = instruction;
                instrCopy.NearBranch64 = 0;
                if (!blockEncoder.NullEncoder.TryEncode(ref instrCopy, 0, out Size, out errorMessage))
                {
                    Size = DecoderConstants.MaxInstructionLength;
                }
            }
            else
            {
                instrCopy              = instruction;
                instrCopy.Code         = instruction.Code.ToShortBranchCode();
                instrCopy.NearBranch64 = 0;
                if (!blockEncoder.NullEncoder.TryEncode(ref instrCopy, 0, out shortInstructionSize, out errorMessage))
                {
                    shortInstructionSize = DecoderConstants.MaxInstructionLength;
                }

                instrCopy              = instruction;
                instrCopy.Code         = instruction.Code.ToNearBranchCode();
                instrCopy.NearBranch64 = 0;
                if (!blockEncoder.NullEncoder.TryEncode(ref instrCopy, 0, out nearInstructionSize, out errorMessage))
                {
                    nearInstructionSize = DecoderConstants.MaxInstructionLength;
                }

                if (blockEncoder.Bitness == 64)
                {
                    // Make sure it's not shorter than the real instruction. It can happen if there are extra prefixes.
                    Size = Math.Max(nearInstructionSize, CallOrJmpPointerDataInstructionSize64);
                }
                else
                {
                    Size = nearInstructionSize;
                }
            }
        }
예제 #6
0
        bool TryOptimize()
        {
            if (instrKind == InstrKind.Unchanged || instrKind == InstrKind.Rip || instrKind == InstrKind.Eip)
            {
                return(false);
            }

            // If it's in the same block, we assume the target is at most 2GB away.
            bool useRip        = targetInstr.IsInBlock(Block);
            var  targetAddress = targetInstr.GetAddress();

            if (!useRip)
            {
                var  nextRip = IP + ripInstructionSize;
                long diff    = (long)(targetAddress - nextRip);
                useRip = int.MinValue <= diff && diff <= int.MaxValue;
            }

            if (useRip)
            {
                Size      = ripInstructionSize;
                instrKind = InstrKind.Rip;
                return(true);
            }

            // If it's in the lower 4GB we can use EIP relative addressing
            if (targetAddress <= uint.MaxValue)
            {
                Size      = eipInstructionSize;
                instrKind = InstrKind.Eip;
                return(true);
            }

            instrKind = InstrKind.Long;
            return(false);
        }
예제 #7
0
        public SimpleBranchInstr(BlockEncoder blockEncoder, ref Instruction instruction)
            : base(blockEncoder, instruction.IP)
        {
            bitness          = blockEncoder.Bitness;
            this.instruction = instruction;
            instrKind        = InstrKind.Uninitialized;

            string      errorMessage;
            Instruction instrCopy;

            if (!blockEncoder.FixBranches)
            {
                instrKind = InstrKind.Unchanged;
                instrCopy = instruction;
                instrCopy.NearBranch64 = 0;
                if (!blockEncoder.NullEncoder.TryEncode(ref instrCopy, 0, out Size, out errorMessage))
                {
                    Size = DecoderConstants.MaxInstructionLength;
                }
            }
            else
            {
                instrCopy = instruction;
                instrCopy.NearBranch64 = 0;
                if (!blockEncoder.NullEncoder.TryEncode(ref instrCopy, 0, out shortInstructionSize, out errorMessage))
                {
                    shortInstructionSize = DecoderConstants.MaxInstructionLength;
                }

                nativeCode = ToNativeBranchCode(instruction.Code, blockEncoder.Bitness);
                if (nativeCode == instruction.Code)
                {
                    nativeInstructionSize = shortInstructionSize;
                }
                else
                {
                    instrCopy              = instruction;
                    instrCopy.Code         = nativeCode;
                    instrCopy.NearBranch64 = 0;
                    if (!blockEncoder.NullEncoder.TryEncode(ref instrCopy, 0, out nativeInstructionSize, out errorMessage))
                    {
                        nativeInstructionSize = DecoderConstants.MaxInstructionLength;
                    }
                }

                switch (blockEncoder.Bitness)
                {
                case 16:
                    nearInstructionSize = nativeInstructionSize + 2 + 3;
                    break;

                case 32:
                case 64:
                    nearInstructionSize = nativeInstructionSize + 2 + 5;
                    break;

                default:
                    throw new InvalidOperationException();
                }

                if (blockEncoder.Bitness == 64)
                {
                    longInstructionSize = nativeInstructionSize + 2 + CallOrJmpPointerDataInstructionSize64;
                    Size = Math.Max(Math.Max(shortInstructionSize, nearInstructionSize), longInstructionSize);
                }
                else
                {
                    Size = Math.Max(shortInstructionSize, nearInstructionSize);
                }
            }
        }