Ejemplo n.º 1
0
 public override string TryEncode(Encoder encoder, out ConstantOffsets constantOffsets, out bool isOriginalInstruction)
 {
     if (useOrigInstruction)
     {
         isOriginalInstruction          = true;
         instruction.NearBranch64Target = targetInstr.GetAddress();
         encoder.Encode(ref instruction, IP, out var errorMessage);
         if (errorMessage != null)
         {
             constantOffsets = default;
             return(CreateErrorMessage(errorMessage, ref instruction));
         }
         constantOffsets = encoder.GetConstantOffsets();
         return(null);
     }
     else
     {
         Debug.Assert(pointerData != null);
         isOriginalInstruction = false;
         constantOffsets       = default;
         pointerData.Data      = targetInstr.GetAddress();
         var errorMessage = EncodeBranchToPointerData(encoder, isCall: true, IP, pointerData, out var size, Size);
         if (errorMessage != null)
         {
             return(CreateErrorMessage(errorMessage, ref instruction));
         }
         return(null);
     }
 }
Ejemplo n.º 2
0
 static bool Equals(ref ConstantOffsets a, ref ConstantOffsets b) =>
 a.DisplacementOffset == b.DisplacementOffset &&
 a.ImmediateOffset == b.ImmediateOffset &&
 a.ImmediateOffset2 == b.ImmediateOffset2 &&
 a.DisplacementSize == b.DisplacementSize &&
 a.ImmediateSize == b.ImmediateSize &&
 a.ImmediateSize2 == b.ImmediateSize2;
Ejemplo n.º 3
0
        public override string TryEncode(Encoder encoder, out ConstantOffsets constantOffsets, out bool isOriginalInstruction)
        {
            string errorMessage;

            switch (instrKind)
            {
            case InstrKind.Unchanged:
            case InstrKind.Short:
            case InstrKind.Near:
                isOriginalInstruction = true;
                if (instrKind == InstrKind.Unchanged)
                {
                    // nothing
                }
                else if (instrKind == InstrKind.Short)
                {
                    instruction.Code = instruction.Code.ToShortBranchCode();
                }
                else
                {
                    Debug.Assert(instrKind == InstrKind.Near);
                    instruction.Code = instruction.Code.ToNearBranchCode();
                }
                instruction.NearBranch64 = targetInstr.GetAddress();
                if (!encoder.TryEncode(ref instruction, IP, out _, out errorMessage))
                {
                    constantOffsets = default;
                    return(CreateErrorMessage(errorMessage, ref instruction));
                }
                constantOffsets = encoder.GetConstantOffsets();
                return(null);

            case InstrKind.Long:
                Debug.Assert(pointerData != null);
                isOriginalInstruction = false;
                constantOffsets       = default;
                pointerData.Data      = targetInstr.GetAddress();
                var instr = new Instruction();
                instr.Code    = instruction.Code.ToNegatedJcc().ToShortBranchCode().ShortJccToNativeJcc(encoder.Bitness);
                instr.Op0Kind = OpKind.NearBranch64;
                Debug.Assert(encoder.Bitness == 64);
                Debug.Assert(longInstructionSize64 <= sbyte.MaxValue);
                instr.NearBranch64 = IP + longInstructionSize64;
                if (!encoder.TryEncode(ref instr, IP, out uint instrLen, out errorMessage))
                {
                    return(CreateErrorMessage(errorMessage, ref instruction));
                }
                errorMessage = EncodeBranchToPointerData(encoder, isCall: false, IP + (uint)instrLen, pointerData, out _, Size - (uint)instrLen);
                if (errorMessage != null)
                {
                    return(CreateErrorMessage(errorMessage, ref instruction));
                }
                return(null);

            case InstrKind.Uninitialized:
            default:
                throw new InvalidOperationException();
            }
        }
Ejemplo n.º 4
0
        public override string TryEncode(Encoder encoder, out ConstantOffsets constantOffsets, out bool isOriginalInstruction)
        {
            switch (instrKind)
            {
            case InstrKind.Unchanged:
            case InstrKind.Rip:
            case InstrKind.Eip:
                isOriginalInstruction = true;

                uint instrSize;
                if (instrKind == InstrKind.Rip)
                {
                    instrSize = ripInstructionSize;
                    instruction.MemoryBase = Register.RIP;
                }
                else if (instrKind == InstrKind.Eip)
                {
                    instrSize = eipInstructionSize;
                    instruction.MemoryBase = Register.EIP;
                }
                else
                {
                    Debug.Assert(instrKind == InstrKind.Unchanged);
                    instrSize = instruction.MemoryBase == Register.EIP ? eipInstructionSize : ripInstructionSize;
                }

                var targetAddress = targetInstr.GetAddress();
                var nextRip       = IP + instrSize;
                instruction.NextIP64           = nextRip;
                instruction.MemoryDisplacement = (uint)targetAddress - (uint)nextRip;
                encoder.Encode(ref instruction, IP, out var errorMessage);
                bool b = instruction.IPRelativeMemoryAddress == (instruction.MemoryBase == Register.EIP ? (uint)targetAddress : targetAddress);
                Debug.Assert(b);
                if (!b)
                {
                    errorMessage = "Invalid IP relative address";
                }
                if (errorMessage != null)
                {
                    constantOffsets = default;
                    return(CreateErrorMessage(errorMessage, ref instruction));
                }
                constantOffsets = encoder.GetConstantOffsets();
                return(null);

            case InstrKind.Long:
                isOriginalInstruction = false;
                constantOffsets       = default;
                return("IP relative memory operand is too far away and isn't currently supported");

            case InstrKind.Uninitialized:
            default:
                throw new InvalidOperationException();
            }
        }
Ejemplo n.º 5
0
 public override string TryEncode(Encoder encoder, out ConstantOffsets constantOffsets, out bool isOriginalInstruction)
 {
     isOriginalInstruction = true;
     if (!encoder.TryEncode(ref instruction, IP, out _, out var errorMessage))
     {
         constantOffsets = default;
         return(CreateErrorMessage(errorMessage, ref instruction));
     }
     constantOffsets = encoder.GetConstantOffsets();
     return(null);
 }
Ejemplo n.º 6
0
        static void FixCA(ref ConstantOffsets ca, int origInstrLen, int newInstrLen)
        {
            byte diff = (byte)(origInstrLen - newInstrLen);

            if (ca.HasDisplacement)
            {
                ca.DisplacementOffset += diff;
            }
            if (ca.HasImmediate)
            {
                ca.ImmediateOffset += diff;
            }
        }
Ejemplo n.º 7
0
 public override string TryEncode(Encoder encoder, out ConstantOffsets constantOffsets, out bool isOriginalInstruction)
 {
     isOriginalInstruction          = true;
     instruction.NearBranch64Target = targetInstr.GetAddress();
     encoder.Encode(ref instruction, IP, out var errorMessage);
     if (errorMessage != null)
     {
         constantOffsets = default;
         return(CreateErrorMessage(errorMessage, ref instruction));
     }
     constantOffsets = encoder.GetConstantOffsets();
     return(null);
 }
Ejemplo n.º 8
0
        public override string TryEncode(Encoder encoder, out ConstantOffsets constantOffsets, out bool isOriginalInstruction)
        {
            string errorMessage;

            switch (instrKind)
            {
            case InstrKind.Unchanged:
            case InstrKind.Short:
            case InstrKind.Near:
                isOriginalInstruction = true;
                if (instrKind == InstrKind.Unchanged)
                {
                    // nothing
                }
                else if (instrKind == InstrKind.Short)
                {
                    instruction.Code = instruction.Code.ToShortBranchCode();
                }
                else
                {
                    Debug.Assert(instrKind == InstrKind.Near);
                    instruction.Code = instruction.Code.ToNearBranchCode();
                }
                instruction.NearBranch64Target = targetInstr.GetAddress();
                encoder.Encode(ref instruction, IP, out errorMessage);
                if (errorMessage != null)
                {
                    constantOffsets = default;
                    return(CreateErrorMessage(errorMessage, ref instruction));
                }
                constantOffsets = encoder.GetConstantOffsets();
                return(null);

            case InstrKind.Long:
                Debug.Assert(pointerData != null);
                isOriginalInstruction = false;
                constantOffsets       = default;
                pointerData.Data      = targetInstr.GetAddress();
                errorMessage          = EncodeBranchToPointerData(encoder, isCall: false, IP, pointerData, out _, Size);
                if (errorMessage != null)
                {
                    return(CreateErrorMessage(errorMessage, ref instruction));
                }
                return(null);

            case InstrKind.Uninitialized:
            default:
                throw new InvalidOperationException();
            }
        }
Ejemplo n.º 9
0
        static void FixConstantOffsets(ref ConstantOffsets co, int origInstrLen, int newInstrLen)
        {
            byte diff = (byte)(origInstrLen - newInstrLen);

            if (co.HasDisplacement)
            {
                co.DisplacementOffset += diff;
            }
            if (co.HasImmediate)
            {
                co.ImmediateOffset += diff;
            }
            if (co.HasImmediate2)
            {
                co.ImmediateOffset2 += diff;
            }
        }
Ejemplo n.º 10
0
        static bool TryParseConstantOffsets(string value, out ConstantOffsets constantOffsets)
        {
            constantOffsets = default;
            if (value is null)
            {
                return(false);
            }

            var parts = value.Split(coSeps);

            if (parts.Length != 6)
            {
                return(false);
            }
            constantOffsets.ImmediateOffset    = ToUInt8(parts[0]);
            constantOffsets.ImmediateSize      = ToUInt8(parts[1]);
            constantOffsets.ImmediateOffset2   = ToUInt8(parts[2]);
            constantOffsets.ImmediateSize2     = ToUInt8(parts[3]);
            constantOffsets.DisplacementOffset = ToUInt8(parts[4]);
            constantOffsets.DisplacementSize   = ToUInt8(parts[5]);
            return(true);
        }
Ejemplo n.º 11
0
 public abstract string?TryEncode(Encoder encoder, out ConstantOffsets constantOffsets, out bool isOriginalInstruction);
Ejemplo n.º 12
0
 void Test16_DecodeMemOps_as32(string hexBytes, Code code, Register register, Register prefixSeg, Register segReg, Register baseReg, Register indexReg, int scale, uint displ, int displSize, ConstantOffsets constantOffsets, string encodedHexBytes) =>
 DecodeMemOpsBase(16, hexBytes, code, register, prefixSeg, segReg, baseReg, indexReg, scale, displ, displSize, constantOffsets, encodedHexBytes);
Ejemplo n.º 13
0
        public override string TryEncode(Encoder encoder, out ConstantOffsets constantOffsets, out bool isOriginalInstruction)
        {
            string      errorMessage;
            Instruction instr;
            uint        size;
            uint        instrLen;

            switch (instrKind)
            {
            case InstrKind.Unchanged:
            case InstrKind.Short:
                isOriginalInstruction    = true;
                instruction.NearBranch64 = targetInstr.GetAddress();
                if (!encoder.TryEncode(ref instruction, IP, out instrLen, out errorMessage))
                {
                    constantOffsets = default;
                    return(CreateErrorMessage(errorMessage, ref instruction));
                }
                constantOffsets = encoder.GetConstantOffsets();
                return(null);

            case InstrKind.Near:
                isOriginalInstruction = false;
                constantOffsets       = default;

                // Code:
                //		brins tmp		; nativeInstructionSize
                //		jmp short skip	; 2
                //	tmp:
                //		jmp near target	; 3/5/5
                //	skip:

                instr              = instruction;
                instr.Code         = nativeCode;
                instr.NearBranch64 = IP + nativeInstructionSize + 2;
                if (!encoder.TryEncode(ref instr, IP, out size, out errorMessage))
                {
                    return(CreateErrorMessage(errorMessage, ref instruction));
                }

                instr = new Instruction();
                instr.NearBranch64 = IP + nearInstructionSize;
                Code codeNear;
                switch (encoder.Bitness)
                {
                case 16:
                    instr.Code    = Code.Jmp_rel8_16;
                    codeNear      = Code.Jmp_rel16;
                    instr.Op0Kind = OpKind.NearBranch16;
                    break;

                case 32:
                    instr.Code    = Code.Jmp_rel8_32;
                    codeNear      = Code.Jmp_rel32_32;
                    instr.Op0Kind = OpKind.NearBranch32;
                    break;

                case 64:
                    instr.Code    = Code.Jmp_rel8_64;
                    codeNear      = Code.Jmp_rel32_64;
                    instr.Op0Kind = OpKind.NearBranch64;
                    break;

                default:
                    throw new InvalidOperationException();
                }
                if (!encoder.TryEncode(ref instr, IP + size, out instrLen, out errorMessage))
                {
                    return(CreateErrorMessage(errorMessage, ref instruction));
                }
                size += instrLen;

                instr.Code         = codeNear;
                instr.NearBranch64 = targetInstr.GetAddress();
                encoder.TryEncode(ref instr, IP + size, out instrLen, out errorMessage);
                if (errorMessage != null)
                {
                    return(CreateErrorMessage(errorMessage, ref instruction));
                }
                return(null);

            case InstrKind.Long:
                Debug.Assert(encoder.Bitness == 64);
                Debug.Assert(pointerData != null);
                isOriginalInstruction = false;
                constantOffsets       = default;
                pointerData.Data      = targetInstr.GetAddress();

                // Code:
                //		brins tmp		; nativeInstructionSize
                //		jmp short skip	; 2
                //	tmp:
                //		jmp [mem_loc]	; 6
                //	skip:

                instr              = instruction;
                instr.Code         = nativeCode;
                instr.NearBranch64 = IP + nativeInstructionSize + 2;
                if (!encoder.TryEncode(ref instr, IP, out instrLen, out errorMessage))
                {
                    return(CreateErrorMessage(errorMessage, ref instruction));
                }
                size = (uint)instrLen;

                instr = new Instruction();
                instr.NearBranch64 = IP + longInstructionSize;
                switch (encoder.Bitness)
                {
                case 16:
                    instr.Code    = Code.Jmp_rel8_16;
                    instr.Op0Kind = OpKind.NearBranch16;
                    break;

                case 32:
                    instr.Code    = Code.Jmp_rel8_32;
                    instr.Op0Kind = OpKind.NearBranch32;
                    break;

                case 64:
                    instr.Code    = Code.Jmp_rel8_64;
                    instr.Op0Kind = OpKind.NearBranch64;
                    break;

                default:
                    throw new InvalidOperationException();
                }
                if (!encoder.TryEncode(ref instr, IP + size, out instrLen, out errorMessage))
                {
                    return(CreateErrorMessage(errorMessage, ref instruction));
                }
                size += (uint)instrLen;

                errorMessage = EncodeBranchToPointerData(encoder, isCall: false, IP + size, pointerData, out _, Size - size);
                if (errorMessage != null)
                {
                    return(CreateErrorMessage(errorMessage, ref instruction));
                }
                return(null);

            case InstrKind.Uninitialized:
            default:
                throw new InvalidOperationException();
            }
        }
Ejemplo n.º 14
0
 void Test32_DecodeMemOps(string hexBytes, Code code, Register register, Register prefixSeg, Register segReg, Register baseReg, Register indexReg, int scale, ulong displ, int displSize, ConstantOffsets constantOffsets, string encodedHexBytes, DecoderOptions options) =>
 DecodeMemOpsBase(32, hexBytes, code, register, prefixSeg, segReg, baseReg, indexReg, scale, displ, displSize, constantOffsets, encodedHexBytes, options);