diff --git a/core/codegen/include/codegen/x86/X64InstructionRewriter.hpp b/core/codegen/include/codegen/x86/X64InstructionRewriter.hpp index 638a8c806..5a4289b60 100644 --- a/core/codegen/include/codegen/x86/X64InstructionRewriter.hpp +++ b/core/codegen/include/codegen/x86/X64InstructionRewriter.hpp @@ -26,42 +26,6 @@ private: std::size_t FieldOffset; }; - static constexpr std::uint8_t OpcodePrefixLock = 0xF0; - static constexpr std::uint8_t OpcodePrefixRepne = 0xF2; - static constexpr std::uint8_t OpcodePrefixRep = 0xF3; - static constexpr std::uint8_t OpcodePrefixSegCs = 0x2E; - static constexpr std::uint8_t OpcodePrefixSegSs = 0x36; - static constexpr std::uint8_t OpcodePrefixSegDs = 0x3E; - static constexpr std::uint8_t OpcodePrefixSegEs = 0x26; - static constexpr std::uint8_t OpcodePrefixSegFs = 0x64; - static constexpr std::uint8_t OpcodePrefixSegGs = 0x65; - static constexpr std::uint8_t OpcodePrefixOperandSize = 0x66; - static constexpr std::uint8_t OpcodePrefixAddressSize = 0x67; - - static constexpr std::uint8_t RexMin = 0x40; - static constexpr std::uint8_t RexMax = 0x4F; - - static constexpr std::uint8_t TwoByteOpcodeEscape = 0x0F; - - static constexpr std::uint8_t OpcodeCallRel32 = 0xE8; - static constexpr std::uint8_t OpcodeJmpRel32 = 0xE9; - static constexpr std::uint8_t OpcodeJmpRel8 = 0xEB; - static constexpr std::uint8_t OpcodeJccRel8Min = 0x70; - static constexpr std::uint8_t OpcodeJccRel8Max = 0x7F; - static constexpr std::uint8_t OpcodeJccRel32Min = 0x80; - static constexpr std::uint8_t OpcodeJccRel32Max = 0x8F; - - static constexpr std::size_t Rel32InstructionLength = 5; - static constexpr std::size_t Rel8FieldSize = 1; - static constexpr std::size_t Rel32FieldSize = 4; - static constexpr std::size_t Disp32FieldSize = 4; - - static constexpr std::uint8_t ModRmModShift = 6; - static constexpr std::uint8_t ModRmModMask = 0x03; - static constexpr std::uint8_t ModRmRmMask = 0x07; - static constexpr std::uint8_t ModRmModIndirect = 0x00; - static constexpr std::uint8_t ModRmRmRipRelative = 0x05; - [[nodiscard]] static ReferenceSite ClassifyInstruction( const std::uint8_t* data, std::size_t length diff --git a/core/codegen/include/codegen/x86/X64OpcodeConstants.hpp b/core/codegen/include/codegen/x86/X64OpcodeConstants.hpp new file mode 100644 index 000000000..20ce0420b --- /dev/null +++ b/core/codegen/include/codegen/x86/X64OpcodeConstants.hpp @@ -0,0 +1,152 @@ +#ifndef CODEGEN_X86_X64OPCODECONSTANTS_HPP +#define CODEGEN_X86_X64OPCODECONSTANTS_HPP + +#include + +namespace Codegen::X64OpcodeConstants { + +inline constexpr std::uint8_t PrefixLock = 0xF0; +inline constexpr std::uint8_t PrefixRepne = 0xF2; +inline constexpr std::uint8_t PrefixRep = 0xF3; +inline constexpr std::uint8_t PrefixSegCs = 0x2E; +inline constexpr std::uint8_t PrefixSegSs = 0x36; +inline constexpr std::uint8_t PrefixSegDs = 0x3E; +inline constexpr std::uint8_t PrefixSegEs = 0x26; +inline constexpr std::uint8_t PrefixSegFs = 0x64; +inline constexpr std::uint8_t PrefixSegGs = 0x65; +inline constexpr std::uint8_t PrefixOperandSize = 0x66; +inline constexpr std::uint8_t PrefixAddressSize = 0x67; + +inline constexpr std::uint8_t RexMin = 0x40; +inline constexpr std::uint8_t RexMax = 0x4F; +inline constexpr std::uint8_t RexWBit = 0x08; + +inline constexpr std::uint8_t TwoByteOpcodeEscape = 0x0F; + +inline constexpr std::uint8_t OneByteModRmRangeAMin = 0x00; +inline constexpr std::uint8_t OneByteModRmRangeAMax = 0x03; +inline constexpr std::uint8_t OneByteModRmRangeBMin = 0x08; +inline constexpr std::uint8_t OneByteModRmRangeBMax = 0x0B; +inline constexpr std::uint8_t OneByteModRmRangeCMin = 0x10; +inline constexpr std::uint8_t OneByteModRmRangeCMax = 0x13; +inline constexpr std::uint8_t OneByteModRmRangeDMin = 0x18; +inline constexpr std::uint8_t OneByteModRmRangeDMax = 0x1B; +inline constexpr std::uint8_t OneByteModRmRangeEMin = 0x20; +inline constexpr std::uint8_t OneByteModRmRangeEMax = 0x23; +inline constexpr std::uint8_t OneByteModRmRangeFMin = 0x28; +inline constexpr std::uint8_t OneByteModRmRangeFMax = 0x2B; +inline constexpr std::uint8_t OneByteModRmRangeGMin = 0x30; +inline constexpr std::uint8_t OneByteModRmRangeGMax = 0x33; +inline constexpr std::uint8_t OneByteModRmRangeHMin = 0x38; +inline constexpr std::uint8_t OneByteModRmRangeHMax = 0x3B; +inline constexpr std::uint8_t OneByteArpl = 0x62; +inline constexpr std::uint8_t OneByteMovsxd = 0x63; +inline constexpr std::uint8_t OneByteModRmRangeIMin = 0x84; +inline constexpr std::uint8_t OneByteModRmRangeIMax = 0x8F; +inline constexpr std::uint8_t OneByteGrp2Rm8Imm8 = 0xC0; +inline constexpr std::uint8_t OneByteGrp2RmImm8 = 0xC1; +inline constexpr std::uint8_t OneByteVex3 = 0xC4; +inline constexpr std::uint8_t OneByteVex2 = 0xC5; +inline constexpr std::uint8_t OneByteMovImm8 = 0xC6; +inline constexpr std::uint8_t OneByteMovImm32 = 0xC7; +inline constexpr std::uint8_t OneByteShiftRm8By1 = 0xD0; +inline constexpr std::uint8_t OneByteShiftRmBy1 = 0xD1; +inline constexpr std::uint8_t OneByteShiftRm8ByCl = 0xD2; +inline constexpr std::uint8_t OneByteShiftRmByCl = 0xD3; +inline constexpr std::uint8_t OneByteTestGrp3Rm8 = 0xF6; +inline constexpr std::uint8_t OneByteTestGrp3Rm = 0xF7; +inline constexpr std::uint8_t OneByteIncDecRm8 = 0xFE; +inline constexpr std::uint8_t OneByteGrp5Rm = 0xFF; +inline constexpr std::uint8_t OneByteModRmRangeJMin = 0x88; +inline constexpr std::uint8_t OneByteModRmRangeJMax = 0x8B; + +inline constexpr std::uint8_t OneByteImm8AluOrGrp3 = 0xC6; +inline constexpr std::uint8_t OneByteImm8AluCmp = 0x80; +inline constexpr std::uint8_t OneByteImm8AddAl = 0x04; +inline constexpr std::uint8_t OneByteImm8OrAl = 0x0C; +inline constexpr std::uint8_t OneByteImm8AdcAl = 0x14; +inline constexpr std::uint8_t OneByteImm8SbbAl = 0x1C; +inline constexpr std::uint8_t OneByteImm8AndAl = 0x24; +inline constexpr std::uint8_t OneByteImm8SubAl = 0x2C; +inline constexpr std::uint8_t OneByteImm8XorAl = 0x34; +inline constexpr std::uint8_t OneByteImm8CmpAl = 0x3C; +inline constexpr std::uint8_t OneByteMovImm8RegMin = 0xB0; +inline constexpr std::uint8_t OneByteMovImm8RegMax = 0xB7; +inline constexpr std::uint8_t OneBytePushImm8 = 0x6A; +inline constexpr std::uint8_t OneByteTestAlImm8 = 0xA8; + +inline constexpr std::uint8_t OneByteImm32AluCmp = 0x81; +inline constexpr std::uint8_t OneByteImm32AddEax = 0x05; +inline constexpr std::uint8_t OneByteImm32OrEax = 0x0D; +inline constexpr std::uint8_t OneByteImm32AdcEax = 0x15; +inline constexpr std::uint8_t OneByteImm32SbbEax = 0x1D; +inline constexpr std::uint8_t OneByteImm32AndEax = 0x25; +inline constexpr std::uint8_t OneByteImm32SubEax = 0x2D; +inline constexpr std::uint8_t OneByteImm32XorEax = 0x35; +inline constexpr std::uint8_t OneByteImm32CmpEax = 0x3D; +inline constexpr std::uint8_t OneBytePushImm32 = 0x68; +inline constexpr std::uint8_t OneByteTestEaxImm32 = 0xA9; +inline constexpr std::uint8_t OneByteMovImm32RegMin = 0xB8; +inline constexpr std::uint8_t OneByteMovImm32RegMax = 0xBF; + +inline constexpr std::uint8_t OneByteImm8Grp1 = 0x83; + +inline constexpr std::uint8_t OneByteJccRel8Min = 0x70; +inline constexpr std::uint8_t OneByteJccRel8Max = 0x7F; + +inline constexpr std::uint8_t OneByteCallRel32 = 0xE8; +inline constexpr std::uint8_t OneByteJmpRel32 = 0xE9; +inline constexpr std::uint8_t OneByteJmpRel8 = 0xEB; + +inline constexpr std::uint8_t TwoByteJccRel32Min = 0x80; +inline constexpr std::uint8_t TwoByteJccRel32Max = 0x8F; +inline constexpr std::uint8_t TwoByteMovImm8ModRm = 0xBA; +inline constexpr std::uint8_t TwoByteStringOpMovs = 0xA4; +inline constexpr std::uint8_t TwoByteStringOpCmps = 0xAC; +inline constexpr std::uint8_t TwoByteCmovRangeMin = 0x40; +inline constexpr std::uint8_t TwoByteCmovRangeMax = 0x4F; +inline constexpr std::uint8_t TwoByteModRmRangeAMin = 0xA3; +inline constexpr std::uint8_t TwoByteModRmRangeAMax = 0xAB; +inline constexpr std::uint8_t TwoByteModRmRangeBMin = 0xB0; +inline constexpr std::uint8_t TwoByteModRmRangeBMax = 0xB7; +inline constexpr std::uint8_t TwoByteModRmRangeCMin = 0xBC; +inline constexpr std::uint8_t TwoByteModRmRangeCMax = 0xBF; +inline constexpr std::uint8_t TwoByteModRmRangeDMin = 0x10; +inline constexpr std::uint8_t TwoByteModRmRangeDMax = 0x17; +inline constexpr std::uint8_t TwoByteModRmRangeEMin = 0x28; +inline constexpr std::uint8_t TwoByteModRmRangeEMax = 0x2F; +inline constexpr std::uint8_t TwoByteModRmRangeFMin = 0x38; +inline constexpr std::uint8_t TwoByteModRmRangeFMax = 0x3A; +inline constexpr std::uint8_t TwoByteModRmRangeGMin = 0x54; +inline constexpr std::uint8_t TwoByteModRmRangeGMax = 0x77; +inline constexpr std::uint8_t TwoByteModRmRangeHMin = 0xD0; +inline constexpr std::uint8_t TwoByteModRmRangeHMax = 0xFE; +inline constexpr std::uint8_t TwoByteNopModRm = 0x1F; + +inline constexpr std::size_t ImmSizeNone = 0; +inline constexpr std::size_t ImmSize8 = 1; +inline constexpr std::size_t ImmSize16 = 2; +inline constexpr std::size_t ImmSize32 = 4; +inline constexpr std::size_t ImmSize64 = 8; + +inline constexpr std::uint8_t ModRmModShift = 6; +inline constexpr std::uint8_t ModRmModMask = 0x03; +inline constexpr std::uint8_t ModRmRmMask = 0x07; +inline constexpr std::uint8_t ModRmModIndirect = 0x00; +inline constexpr std::uint8_t ModRmModDisp8 = 0x01; +inline constexpr std::uint8_t ModRmModDisp32 = 0x02; +inline constexpr std::uint8_t ModRmModRegister = 0x03; +inline constexpr std::uint8_t ModRmRmSibPresent = 0x04; +inline constexpr std::uint8_t ModRmRmRipRelative = 0x05; + +inline constexpr std::uint8_t SibBaseMask = 0x07; +inline constexpr std::uint8_t SibBaseDisp32 = 0x05; + +inline constexpr std::size_t Disp8Size = 1; +inline constexpr std::size_t Disp32Size = 4; + +inline constexpr std::size_t Rel32InstructionLength = 5; + +} + +#endif diff --git a/core/codegen/src/x86/X64InstructionDecoder.cpp b/core/codegen/src/x86/X64InstructionDecoder.cpp index b3f88ae0e..99a774361 100644 --- a/core/codegen/src/x86/X64InstructionDecoder.cpp +++ b/core/codegen/src/x86/X64InstructionDecoder.cpp @@ -1,8 +1,11 @@ #include +#include #include namespace Codegen { +using namespace X64OpcodeConstants; + std::size_t X64InstructionDecoder::Decode(const std::uint8_t* data, std::size_t available) const { std::size_t pos = 0; bool rexPresent = false; @@ -12,20 +15,20 @@ std::size_t X64InstructionDecoder::Decode(const std::uint8_t* data, std::size_t while (pos < available) { const std::uint8_t b = data[pos]; - if (b == 0xF0 || b == 0xF2 || b == 0xF3 || - b == 0x2E || b == 0x36 || b == 0x3E || b == 0x26 || - b == 0x64 || b == 0x65) { + if (b == PrefixLock || b == PrefixRepne || b == PrefixRep || + b == PrefixSegCs || b == PrefixSegSs || b == PrefixSegDs || b == PrefixSegEs || + b == PrefixSegFs || b == PrefixSegGs) { pos += 1; continue; } - if (b == 0x66) { + if (b == PrefixOperandSize) { operandSizeOverride = true; pos += 1; continue; } - if (b == 0x67) { + if (b == PrefixAddressSize) { pos += 1; continue; } @@ -33,7 +36,7 @@ std::size_t X64InstructionDecoder::Decode(const std::uint8_t* data, std::size_t break; } - if (pos < available && data[pos] >= 0x40 && data[pos] <= 0x4F) { + if (pos < available && data[pos] >= RexMin && data[pos] <= RexMax) { rexPresent = true; rex = data[pos]; pos += 1; @@ -47,7 +50,7 @@ std::size_t X64InstructionDecoder::Decode(const std::uint8_t* data, std::size_t pos += 1; bool twoByteOpcode = false; - if (opcode == 0x0F) { + if (opcode == TwoByteOpcodeEscape) { if (pos >= available) { throw CodegenException("Instruction truncated after two-byte opcode escape"); } @@ -57,79 +60,86 @@ std::size_t X64InstructionDecoder::Decode(const std::uint8_t* data, std::size_t } bool hasModRm = false; - std::size_t immediateSize = 0; + std::size_t immediateSize = ImmSizeNone; if (!twoByteOpcode) { - if ((opcode >= 0x00 && opcode <= 0x03) || (opcode >= 0x08 && opcode <= 0x0B) || - (opcode >= 0x10 && opcode <= 0x13) || (opcode >= 0x18 && opcode <= 0x1B) || - (opcode >= 0x20 && opcode <= 0x23) || (opcode >= 0x28 && opcode <= 0x2B) || - (opcode >= 0x30 && opcode <= 0x33) || (opcode >= 0x38 && opcode <= 0x3B) || - opcode == 0x62 || opcode == 0x63 || - (opcode >= 0x84 && opcode <= 0x8F) || - opcode == 0xC0 || opcode == 0xC1 || - opcode == 0xC4 || opcode == 0xC5 || opcode == 0xC6 || opcode == 0xC7 || - opcode == 0xD0 || opcode == 0xD1 || opcode == 0xD2 || opcode == 0xD3 || - opcode == 0xF6 || opcode == 0xF7 || - opcode == 0xFE || opcode == 0xFF || - (opcode >= 0x88 && opcode <= 0x8B)) { + if ((opcode >= OneByteModRmRangeAMin && opcode <= OneByteModRmRangeAMax) || + (opcode >= OneByteModRmRangeBMin && opcode <= OneByteModRmRangeBMax) || + (opcode >= OneByteModRmRangeCMin && opcode <= OneByteModRmRangeCMax) || + (opcode >= OneByteModRmRangeDMin && opcode <= OneByteModRmRangeDMax) || + (opcode >= OneByteModRmRangeEMin && opcode <= OneByteModRmRangeEMax) || + (opcode >= OneByteModRmRangeFMin && opcode <= OneByteModRmRangeFMax) || + (opcode >= OneByteModRmRangeGMin && opcode <= OneByteModRmRangeGMax) || + (opcode >= OneByteModRmRangeHMin && opcode <= OneByteModRmRangeHMax) || + opcode == OneByteArpl || opcode == OneByteMovsxd || + (opcode >= OneByteModRmRangeIMin && opcode <= OneByteModRmRangeIMax) || + opcode == OneByteGrp2Rm8Imm8 || opcode == OneByteGrp2RmImm8 || + opcode == OneByteVex3 || opcode == OneByteVex2 || + opcode == OneByteMovImm8 || opcode == OneByteMovImm32 || + opcode == OneByteShiftRm8By1 || opcode == OneByteShiftRmBy1 || + opcode == OneByteShiftRm8ByCl || opcode == OneByteShiftRmByCl || + opcode == OneByteTestGrp3Rm8 || opcode == OneByteTestGrp3Rm || + opcode == OneByteIncDecRm8 || opcode == OneByteGrp5Rm || + (opcode >= OneByteModRmRangeJMin && opcode <= OneByteModRmRangeJMax)) { hasModRm = true; } - if (opcode == 0xC6 || opcode == 0x80 || - opcode == 0x04 || opcode == 0x0C || - opcode == 0x14 || opcode == 0x1C || - opcode == 0x24 || opcode == 0x2C || - opcode == 0x34 || opcode == 0x3C || - (opcode >= 0xB0 && opcode <= 0xB7) || - opcode == 0x6A || - opcode == 0xA8) { - immediateSize = 1; - } else if (opcode == 0xC7 || opcode == 0x81 || - opcode == 0x05 || opcode == 0x0D || - opcode == 0x15 || opcode == 0x1D || - opcode == 0x25 || opcode == 0x2D || - opcode == 0x35 || opcode == 0x3D || - opcode == 0x68 || - opcode == 0xA9 || - (opcode >= 0xB8 && opcode <= 0xBF)) { - if (opcode >= 0xB8 && opcode <= 0xBF) { - immediateSize = (rexPresent && (rex & 0x08) != 0) ? 8 : (operandSizeOverride ? 2 : 4); + if (opcode == OneByteImm8AluOrGrp3 || opcode == OneByteImm8AluCmp || + opcode == OneByteImm8AddAl || opcode == OneByteImm8OrAl || + opcode == OneByteImm8AdcAl || opcode == OneByteImm8SbbAl || + opcode == OneByteImm8AndAl || opcode == OneByteImm8SubAl || + opcode == OneByteImm8XorAl || opcode == OneByteImm8CmpAl || + (opcode >= OneByteMovImm8RegMin && opcode <= OneByteMovImm8RegMax) || + opcode == OneBytePushImm8 || + opcode == OneByteTestAlImm8) { + immediateSize = ImmSize8; + } else if (opcode == OneByteImm32AluCmp || + opcode == OneByteImm32AddEax || opcode == OneByteImm32OrEax || + opcode == OneByteImm32AdcEax || opcode == OneByteImm32SbbEax || + opcode == OneByteImm32AndEax || opcode == OneByteImm32SubEax || + opcode == OneByteImm32XorEax || opcode == OneByteImm32CmpEax || + opcode == OneBytePushImm32 || + opcode == OneByteTestEaxImm32 || + (opcode >= OneByteMovImm32RegMin && opcode <= OneByteMovImm32RegMax)) { + if (opcode >= OneByteMovImm32RegMin && opcode <= OneByteMovImm32RegMax) { + immediateSize = (rexPresent && (rex & RexWBit) != 0) ? ImmSize64 : + (operandSizeOverride ? ImmSize16 : ImmSize32); } else { - immediateSize = operandSizeOverride ? 2 : 4; + immediateSize = operandSizeOverride ? ImmSize16 : ImmSize32; } - } else if (opcode == 0x83) { - immediateSize = 1; + } else if (opcode == OneByteImm8Grp1) { + immediateSize = ImmSize8; } - if (opcode >= 0x70 && opcode <= 0x7F) { - immediateSize = 1; + if (opcode >= OneByteJccRel8Min && opcode <= OneByteJccRel8Max) { + immediateSize = ImmSize8; } - if (opcode == 0xE8 || opcode == 0xE9) { - immediateSize = 4; + if (opcode == OneByteCallRel32 || opcode == OneByteJmpRel32) { + immediateSize = ImmSize32; } - if (opcode == 0xEB) { - immediateSize = 1; + if (opcode == OneByteJmpRel8) { + immediateSize = ImmSize8; } } else { - if (opcode >= 0x80 && opcode <= 0x8F) { - immediateSize = 4; - } else if (opcode == 0xBA) { + if (opcode >= TwoByteJccRel32Min && opcode <= TwoByteJccRel32Max) { + immediateSize = ImmSize32; + } else if (opcode == TwoByteMovImm8ModRm) { hasModRm = true; - immediateSize = 1; - } else if (opcode == 0xA4 || opcode == 0xAC) { - immediateSize = 1; - } else if ((opcode >= 0x40 && opcode <= 0x4F) || - (opcode >= 0xA3 && opcode <= 0xAB) || - (opcode >= 0xB0 && opcode <= 0xB7) || - (opcode >= 0xBC && opcode <= 0xBF) || - (opcode >= 0x10 && opcode <= 0x17) || - (opcode >= 0x28 && opcode <= 0x2F) || - (opcode >= 0x38 && opcode <= 0x3A) || - (opcode >= 0x54 && opcode <= 0x77) || - (opcode >= 0xD0 && opcode <= 0xFE) || - opcode == 0x1F) { + immediateSize = ImmSize8; + } else if (opcode == TwoByteStringOpMovs || opcode == TwoByteStringOpCmps) { + immediateSize = ImmSize8; + } else if ((opcode >= TwoByteCmovRangeMin && opcode <= TwoByteCmovRangeMax) || + (opcode >= TwoByteModRmRangeAMin && opcode <= TwoByteModRmRangeAMax) || + (opcode >= TwoByteModRmRangeBMin && opcode <= TwoByteModRmRangeBMax) || + (opcode >= TwoByteModRmRangeCMin && opcode <= TwoByteModRmRangeCMax) || + (opcode >= TwoByteModRmRangeDMin && opcode <= TwoByteModRmRangeDMax) || + (opcode >= TwoByteModRmRangeEMin && opcode <= TwoByteModRmRangeEMax) || + (opcode >= TwoByteModRmRangeFMin && opcode <= TwoByteModRmRangeFMax) || + (opcode >= TwoByteModRmRangeGMin && opcode <= TwoByteModRmRangeGMax) || + (opcode >= TwoByteModRmRangeHMin && opcode <= TwoByteModRmRangeHMax) || + opcode == TwoByteNopModRm) { hasModRm = true; } } @@ -148,28 +158,28 @@ std::size_t X64InstructionDecoder::Decode(const std::uint8_t* data, std::size_t const std::uint8_t modrm = data[pos]; pos += 1; - const std::uint8_t mod = static_cast((modrm >> 6) & 0x03); - const std::uint8_t rm = static_cast(modrm & 0x07); + const std::uint8_t mod = static_cast((modrm >> ModRmModShift) & ModRmModMask); + const std::uint8_t rm = static_cast(modrm & ModRmRmMask); - if (mod != 0x03 && rm == 0x04) { + if (mod != ModRmModRegister && rm == ModRmRmSibPresent) { if (pos >= available) { throw CodegenException("Instruction truncated before SIB byte"); } const std::uint8_t sib = data[pos]; - const std::uint8_t base = static_cast(sib & 0x07); + const std::uint8_t base = static_cast(sib & SibBaseMask); pos += 1; - if (mod == 0x00 && base == 0x05) { - pos += 4; + if (mod == ModRmModIndirect && base == SibBaseDisp32) { + pos += Disp32Size; } } - if (mod == 0x01) { - pos += 1; - } else if (mod == 0x02) { - pos += 4; - } else if (mod == 0x00 && rm == 0x05) { - pos += 4; + if (mod == ModRmModDisp8) { + pos += Disp8Size; + } else if (mod == ModRmModDisp32) { + pos += Disp32Size; + } else if (mod == ModRmModIndirect && rm == ModRmRmRipRelative) { + pos += Disp32Size; } pos += immediateSize; diff --git a/core/codegen/src/x86/X64InstructionRewriter.cpp b/core/codegen/src/x86/X64InstructionRewriter.cpp index 55022cc38..623bdca1a 100644 --- a/core/codegen/src/x86/X64InstructionRewriter.cpp +++ b/core/codegen/src/x86/X64InstructionRewriter.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -7,6 +8,8 @@ namespace Codegen { +using namespace X64OpcodeConstants; + X64InstructionRewriter::ReferenceSite X64InstructionRewriter::ClassifyInstruction( const std::uint8_t* data, std::size_t length @@ -15,10 +18,10 @@ X64InstructionRewriter::ReferenceSite X64InstructionRewriter::ClassifyInstructio while (pos < length) { const std::uint8_t b = data[pos]; - if (b == OpcodePrefixLock || b == OpcodePrefixRepne || b == OpcodePrefixRep || - b == OpcodePrefixSegCs || b == OpcodePrefixSegSs || b == OpcodePrefixSegDs || - b == OpcodePrefixSegEs || b == OpcodePrefixSegFs || b == OpcodePrefixSegGs || - b == OpcodePrefixOperandSize || b == OpcodePrefixAddressSize) { + if (b == PrefixLock || b == PrefixRepne || b == PrefixRep || + b == PrefixSegCs || b == PrefixSegSs || b == PrefixSegDs || + b == PrefixSegEs || b == PrefixSegFs || b == PrefixSegGs || + b == PrefixOperandSize || b == PrefixAddressSize) { pos += 1; continue; } @@ -48,22 +51,22 @@ X64InstructionRewriter::ReferenceSite X64InstructionRewriter::ClassifyInstructio } if (!twoByteOpcode) { - if (opcode == OpcodeCallRel32 || opcode == OpcodeJmpRel32) { + if (opcode == OneByteCallRel32 || opcode == OneByteJmpRel32) { if (length >= opcodeOffset + Rel32InstructionLength) { return {ReferenceKind::Rel32Branch, pos}; } return {ReferenceKind::None, 0}; } - if (opcode == OpcodeJmpRel8 || (opcode >= OpcodeJccRel8Min && opcode <= OpcodeJccRel8Max)) { - if (length >= pos + Rel8FieldSize) { + if (opcode == OneByteJmpRel8 || (opcode >= OneByteJccRel8Min && opcode <= OneByteJccRel8Max)) { + if (length >= pos + Disp8Size) { return {ReferenceKind::Rel8Branch, pos}; } return {ReferenceKind::None, 0}; } } else { - if (opcode >= OpcodeJccRel32Min && opcode <= OpcodeJccRel32Max) { - if (length >= pos + Rel32FieldSize) { + if (opcode >= TwoByteJccRel32Min && opcode <= TwoByteJccRel32Max) { + if (length >= pos + Disp32Size) { return {ReferenceKind::Rel32Branch, pos}; } return {ReferenceKind::None, 0}; @@ -80,7 +83,7 @@ X64InstructionRewriter::ReferenceSite X64InstructionRewriter::ClassifyInstructio if (mod == ModRmModIndirect && rm == ModRmRmRipRelative) { const std::size_t dispOffset = pos + 1; - if (length >= dispOffset + Disp32FieldSize) { + if (length >= dispOffset + Disp32Size) { return {ReferenceKind::RipRelativeDisp32, dispOffset}; } }