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); } }
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;
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(); } }
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(); } }
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); }
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; } }
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); }
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(); } }
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; } }
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); }
public abstract string?TryEncode(Encoder encoder, out ConstantOffsets constantOffsets, out bool isOriginalInstruction);
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);
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(); } }
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);