Ejemplo n.º 1
0
 public override bool TryPeekPointer(EndianImageReader rdr, out ulong target)
 {
     if (!rdr.IsValidOffset(rdr.Offset + 4 - 1))
     {
         target = 0;
         return(false);
     }
     else
     {
         target = rdr.PeekLeUInt32(0);
         return(true);
     }
 }
Ejemplo n.º 2
0
 public override bool MatchCall(EndianImageReader rdr, uint opcode, out ulong target)
 {
     if (opcode == 0xE8 // CALL NEAR
         &&
         rdr.IsValidOffset(rdr.Offset + 4u))
     {
         int callOffset = rdr.PeekLeInt32(1);
         target = ((ulong)(long)callOffset + rdr.Address.ToLinear() + 5);
         return(true);
     }
     target = 0;
     return(false);
 }
Ejemplo n.º 3
0
 public override bool MatchCall(EndianImageReader rdr, uint opcode, out uint target)
 {
     if ((opcode & 0xFC000000) == 0x0C000000 // JAL
         &&
         rdr.IsValidOffset(rdr.Offset + 4u))
     {
         var off = (opcode & 0x03FFFFFF) << 2;
         target = (((uint)rdr.Address.ToLinear() + 4) & 0xF0000000u) | off;
         return(true);
     }
     target = 0;
     return(false);
 }
Ejemplo n.º 4
0
 public override bool MatchCall(EndianImageReader rdr, uint opcode, out uint target)
 {
     if (opcode == 0xE8 // CALL NEAR
         &&
         rdr.IsValidOffset(rdr.Offset + 2u))
     {
         int callOffset = rdr.PeekLeInt16(1);
         target = (uint)(callOffset + (uint)rdr.Address.ToLinear() + 3);
         return(true);
     }
     if (opcode == 0x9A // CALL FAR
         &&
         rdr.IsValidOffset(rdr.Offset + 5u))
     {
         ushort callOff = rdr.PeekLeUInt16(1);
         ushort callSeg = rdr.PeekLeUInt16(3);
         target = ((uint)callSeg << 4) + callOff;
         return(true);
     }
     target = 0;
     return(false);
 }
Ejemplo n.º 5
0
        public override bool MatchJump(EndianImageReader rdr, uint opcode, out uint target)
        {
            if ((opcode & 0xFC000000) == 0x08000000  // J - far jump
                &&
                rdr.IsValidOffset(rdr.Offset + 4u))
            {
                var off = (opcode & 0x03FFFFFF) << 2;
                target = (((uint)rdr.Address.ToLinear() + 4) & 0xF0000000u) | off;
                return(true);
            }

            if ((opcode & 0xF0000000) == 0x10000000  // b** - far jump
                &&
                rdr.IsValidOffset(rdr.Offset + 4u))
            {
                int off = (short)opcode;
                off  <<= 2;
                target = (uint)(((int)rdr.Address.ToLinear() + 4) + off);
                return(true);
            }
            target = 0;
            return(false);
        }
Ejemplo n.º 6
0
        private bool RelativeBranchCall(EndianImageReader rdr, uint opcode, out uint target)
        {
            int callOffset = (sbyte)opcode;

            if (callOffset == -1// bsr.l
                &&
                rdr.IsValidOffset(rdr.Offset + 4u))
            {
                callOffset = rdr.PeekBeInt32(2);
                target     = (uint)(callOffset + (long)rdr.Address.ToLinear() + 2);
                return(true);
            }
            if (callOffset == 0x00 // bsr.w)
                &&
                rdr.IsValidOffset(rdr.Offset + 2u))
            {
                callOffset = rdr.PeekBeInt16(2);
                target     = (uint)(callOffset + (long)rdr.Address.ToLinear() + 2);
                return(true);
            }
            target = (uint)(callOffset + (long)rdr.Address.ToLinear() + 2);
            return(true);
        }
Ejemplo n.º 7
0
        private MachineOperand DecodeModRM(PrimitiveType dataWidth, RegisterStorage segOverride, Func <int, PrimitiveType, RegisterStorage> regFn)
        {
            if (!TryEnsureModRM(out byte modRm))
            {
                return(null);
            }

            int rm  = this.currentDecodingContext.ModRegMemByte & 0x07;
            int mod = this.currentDecodingContext.ModRegMemByte >> 6;

            RegisterStorage b;
            RegisterStorage idx;
            byte            scale       = 1;
            PrimitiveType   offsetWidth = null;

            if (addressWidth == PrimitiveType.Word16)
            {
                // 16-bit addressing modes are weird.

                b     = s_ma16Base[rm];
                idx   = s_ma16Index[rm];
                scale = 1;

                switch (mod)
                {
                case 0:
                    if (rm == 0x06)
                    {
                        offsetWidth = PrimitiveType.Word16;
                        b           = RegisterStorage.None;
                        idx         = RegisterStorage.None;
                    }
                    else
                    {
                        offsetWidth = null;
                    }
                    break;

                case 1:
                    offsetWidth = PrimitiveType.SByte;
                    break;

                case 2:
                    offsetWidth = PrimitiveType.Word16;
                    break;

                case 3:
                    return(new RegisterOperand(RegFromBitsRexB(rm, dataWidth, regFn)));
                }
            }
            else
            {
                idx = RegisterStorage.None;

                switch (mod)
                {
                case 0:
                    if (rm == 0x05)
                    {
                        if (defaultAddressWidth.BitSize == 64)      //$REFACTOR: should subclass this type of behaviour.
                        {
                            b           = Registers.rip;
                            offsetWidth = PrimitiveType.Int32;
                        }
                        else
                        {
                            offsetWidth = PrimitiveType.Ptr32;
                            b           = RegisterStorage.None;
                        }
                    }
                    else
                    {
                        b           = RegFromBitsRexB(rm, addressWidth, GpRegFromBits);
                        offsetWidth = null;
                    }
                    break;

                case 1:
                    b           = RegFromBitsRexB(rm, addressWidth, GpRegFromBits);
                    offsetWidth = PrimitiveType.SByte;
                    break;

                case 2:
                    b           = RegFromBitsRexB(rm, addressWidth, GpRegFromBits);
                    offsetWidth = PrimitiveType.Word32;
                    break;

                case 3:
                    return(new RegisterOperand(RegFromBitsRexB(rm, dataWidth, regFn)));

                default:
                    throw new InvalidOperationException("Impossiburu.");
                }

                // Handle possible s-i-b byte.

                if (rm == 0x04)
                {
                    // We have SIB'ness, your majesty!

                    if (!rdr.TryReadByte(out byte sib))
                    {
                        return(null);
                    }
                    if (((this.currentDecodingContext.ModRegMemByte & 0xC0) == 0) && ((sib & 0x7) == 5))
                    {
                        offsetWidth = PrimitiveType.Word32;
                        b           = RegisterStorage.None;
                    }
                    else
                    {
                        b = RegFromBitsRexB(sib, addressWidth, GpRegFromBits);
                    }

                    int i = (sib >> 3) & 0x7;
                    idx   = (i == 0x04) ? RegisterStorage.None : RegFromBitsRexX(i, addressWidth, GpRegFromBits);
                    scale = (byte)(1 << (sib >> 6));
                }
            }

            // Now fetch the offset if there was any.

            Constant offset;

            if (offsetWidth != null)
            {
                if (!rdr.IsValidOffset(rdr.Offset + (uint)offsetWidth.Size - 1))
                {
                    return(null);
                }
                if (!rdr.TryReadLe(offsetWidth, out offset))
                {
                    return(null);
                }
            }
            else
            {
                offset = Constant.Invalid;
            }

            return(new MemoryOperand(dataWidth, offset)
            {
                Base = b,
                Index = idx,
                Scale = scale,
                SegOverride = segOverride,
            });
        }