mirror of https://github.com/x64dbg/zydis
Implemented encoding for XOP, VEX and EVEX
This commit is contained in:
parent
46077709f8
commit
0a50bb9daa
246
src/Encoder.c
246
src/Encoder.c
|
@ -58,6 +58,17 @@ enum ZydisModeConstraints
|
||||||
ZYDIS_MODE_CONSTR_REQUIRE64,
|
ZYDIS_MODE_CONSTR_REQUIRE64,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef uint8_t ZydisPrefixBit;
|
||||||
|
|
||||||
|
enum ZydisPrefixBits
|
||||||
|
{
|
||||||
|
// TODO: Use defines instead?
|
||||||
|
ZYDIS_PREFBIT_VEX_L = 0x01,
|
||||||
|
ZYDIS_PREFBIT_REX_W = 0x02,
|
||||||
|
ZYDIS_PREFBIT_EVEX_L2 = 0x04,
|
||||||
|
ZYDIS_PREFBIT_EVEX_B = 0x08,
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct ZydisEncoderTableEntry_
|
typedef struct ZydisEncoderTableEntry_
|
||||||
{
|
{
|
||||||
uint16_t mnemonic;
|
uint16_t mnemonic;
|
||||||
|
@ -69,6 +80,7 @@ typedef struct ZydisEncoderTableEntry_
|
||||||
ZydisInstructionAttributes mandatoryAttribs;
|
ZydisInstructionAttributes mandatoryAttribs;
|
||||||
ZydisModRMMod modRmMod;
|
ZydisModRMMod modRmMod;
|
||||||
ZydisModeConstraint modeConstraint;
|
ZydisModeConstraint modeConstraint;
|
||||||
|
ZydisPrefixBit prefixBits;
|
||||||
} ZydisEncoderTableEntry;
|
} ZydisEncoderTableEntry;
|
||||||
|
|
||||||
#include <Zydis/Internal/EncoderTable.inc>
|
#include <Zydis/Internal/EncoderTable.inc>
|
||||||
|
@ -87,6 +99,8 @@ typedef struct ZydisEncoderContext_
|
||||||
uint64_t disp;
|
uint64_t disp;
|
||||||
uint8_t immBitSizes[2];
|
uint8_t immBitSizes[2];
|
||||||
uint64_t imms[2];
|
uint64_t imms[2];
|
||||||
|
uint8_t opcodeMapPrefixLen;
|
||||||
|
uint8_t opcodeMapPrefix[3];
|
||||||
} ZydisEncoderContext;
|
} ZydisEncoderContext;
|
||||||
|
|
||||||
/* ============================================================================================== */
|
/* ============================================================================================== */
|
||||||
|
@ -199,40 +213,39 @@ static ZydisStatus ZydisEmitVEX(ZydisEncoderContext* ctx)
|
||||||
{
|
{
|
||||||
ZYDIS_ASSERT(ctx);
|
ZYDIS_ASSERT(ctx);
|
||||||
|
|
||||||
// Write opcode.
|
// Can we use short 2-byte VEX encoding?
|
||||||
uint8_t opcode = ctx->info->details.vex.data[0];
|
if (ctx->info->details.vex.X == 1 &&
|
||||||
ZYDIS_CHECK(ZydisEmitByte(ctx, opcode));
|
ctx->info->details.vex.B == 1 &&
|
||||||
|
ctx->info->details.vex.W == 0 &&
|
||||||
// Write prefix' "operands".
|
ctx->info->details.vex.m_mmmm == 1)
|
||||||
switch (opcode)
|
|
||||||
{
|
{
|
||||||
case 0xC4:
|
ZYDIS_CHECK(ZydisEmitByte(ctx, 0xC5));
|
||||||
ZYDIS_CHECK(ZydisEmitByte(
|
ZYDIS_CHECK(ZydisEmitByte(
|
||||||
ctx,
|
ctx,
|
||||||
(ctx->info->details.vex.R & 0x01) << 7 |
|
(~ctx->info->details.vex.R & 0x01) << 7 |
|
||||||
(ctx->info->details.vex.X & 0x01) << 6 |
|
(~ctx->info->details.vex.vvvv & 0x0F) << 3 |
|
||||||
(ctx->info->details.vex.B & 0x01) << 5 |
|
( ctx->info->details.vex.L & 0x01) << 2 |
|
||||||
(ctx->info->details.vex.m_mmmm & 0x1F) << 0
|
( ctx->info->details.vex.pp & 0x03) << 0
|
||||||
|
));
|
||||||
|
}
|
||||||
|
// Nope, use 3-byte VEX.
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ZYDIS_CHECK(ZydisEmitByte(ctx, 0xC4));
|
||||||
|
ZYDIS_CHECK(ZydisEmitByte(
|
||||||
|
ctx,
|
||||||
|
(~ctx->info->details.vex.R & 0x01) << 7 |
|
||||||
|
(~ctx->info->details.vex.X & 0x01) << 6 |
|
||||||
|
(~ctx->info->details.vex.B & 0x01) << 5 |
|
||||||
|
( ctx->info->details.vex.m_mmmm & 0x1F) << 0
|
||||||
));
|
));
|
||||||
ZYDIS_CHECK(ZydisEmitByte(
|
ZYDIS_CHECK(ZydisEmitByte(
|
||||||
ctx,
|
ctx,
|
||||||
(ctx->info->details.vex.W & 0x01) << 7 |
|
( ctx->info->details.vex.W & 0x01) << 7 |
|
||||||
(ctx->info->details.vex.vvvv & 0x0F) << 3 |
|
(~ctx->info->details.vex.vvvv & 0x0F) << 3 |
|
||||||
(ctx->info->details.vex.L & 0x01) << 2 |
|
( ctx->info->details.vex.L & 0x01) << 2 |
|
||||||
(ctx->info->details.vex.pp & 0x03) << 0
|
( ctx->info->details.vex.pp & 0x03) << 0
|
||||||
));
|
));
|
||||||
break;
|
|
||||||
case 0xC5:
|
|
||||||
ZYDIS_CHECK(ZydisEmitByte(
|
|
||||||
ctx,
|
|
||||||
(ctx->info->details.vex.R & 0x01) << 7 |
|
|
||||||
(ctx->info->details.vex.vvvv & 0x0F) << 3 |
|
|
||||||
(ctx->info->details.vex.L & 0x01) << 2 |
|
|
||||||
(ctx->info->details.vex.pp & 0x03) << 0
|
|
||||||
));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ZYDIS_UNREACHABLE; // TODO: return error instead
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ZYDIS_STATUS_SUCCESS;
|
return ZYDIS_STATUS_SUCCESS;
|
||||||
|
@ -313,39 +326,53 @@ static ZydisStatus ZydisEmitSIB(ZydisEncoderContext* ctx)
|
||||||
return ZYDIS_STATUS_SUCCESS;
|
return ZYDIS_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ZydisStatus ZydisEmitOpcode(ZydisEncoderContext* ctx)
|
static ZydisStatus ZydisPrepareOpcode(ZydisEncoderContext* ctx)
|
||||||
{
|
{
|
||||||
ZYDIS_ASSERT(ctx);
|
ZYDIS_ASSERT(ctx);
|
||||||
ZYDIS_ASSERT(ctx->matchingEntry);
|
ZYDIS_ASSERT(ctx->matchingEntry);
|
||||||
|
|
||||||
// Put opcode extension prefix(es), if required.
|
// Put opcode map prefix(es), if required.
|
||||||
switch (ctx->matchingEntry->map)
|
switch (ctx->info->encoding)
|
||||||
{
|
{
|
||||||
case ZYDIS_OPCODE_MAP_0F:
|
case ZYDIS_INSTRUCTION_ENCODING_DEFAULT:
|
||||||
ZYDIS_CHECK(ZydisEmitByte(ctx, 0x0F));
|
case ZYDIS_INSTRUCTION_ENCODING_3DNOW:
|
||||||
|
switch (ctx->matchingEntry->map)
|
||||||
|
{
|
||||||
|
case ZYDIS_OPCODE_MAP_0F:
|
||||||
|
ctx->opcodeMapPrefix[ctx->opcodeMapPrefixLen++] = 0x0F;
|
||||||
|
break;
|
||||||
|
case ZYDIS_OPCODE_MAP_0F38:
|
||||||
|
ctx->opcodeMapPrefix[ctx->opcodeMapPrefixLen++] = 0x0F;
|
||||||
|
ctx->opcodeMapPrefix[ctx->opcodeMapPrefixLen++] = 0x38;
|
||||||
|
break;
|
||||||
|
case ZYDIS_OPCODE_MAP_0F3A:
|
||||||
|
ctx->opcodeMapPrefix[ctx->opcodeMapPrefixLen++] = 0x0F;
|
||||||
|
ctx->opcodeMapPrefix[ctx->opcodeMapPrefixLen++] = 0x3A;
|
||||||
|
break;
|
||||||
|
case ZYDIS_OPCODE_MAP_DEFAULT:
|
||||||
|
break; // Nothing to do.
|
||||||
|
default:
|
||||||
|
ZYDIS_UNREACHABLE;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case ZYDIS_OPCODE_MAP_0F38:
|
case ZYDIS_INSTRUCTION_ENCODING_VEX:
|
||||||
ZYDIS_CHECK(ZydisEmitByte(ctx, 0x0F));
|
ctx->info->details.vex.m_mmmm = ctx->matchingEntry->map;
|
||||||
ZYDIS_CHECK(ZydisEmitByte(ctx, 0x38));
|
ZYDIS_ASSERT(ctx->info->details.vex.m_mmmm <= 0x03);
|
||||||
break;
|
break;
|
||||||
case ZYDIS_OPCODE_MAP_0F3A:
|
case ZYDIS_INSTRUCTION_ENCODING_EVEX:
|
||||||
ZYDIS_CHECK(ZydisEmitByte(ctx, 0x0F));
|
ctx->info->details.evex.mm = ctx->matchingEntry->map;
|
||||||
ZYDIS_CHECK(ZydisEmitByte(ctx, 0x3A));
|
ZYDIS_ASSERT(ctx->info->details.evex.mm <= 0x03);
|
||||||
break;
|
break;
|
||||||
case ZYDIS_OPCODE_MAP_XOP8:
|
case ZYDIS_INSTRUCTION_ENCODING_XOP:
|
||||||
case ZYDIS_OPCODE_MAP_XOP9:
|
ctx->info->details.xop.m_mmmm =
|
||||||
case ZYDIS_OPCODE_MAP_XOPA:
|
ctx->matchingEntry->map - ZYDIS_OPCODE_MAP_XOP8 + 0x08;
|
||||||
return ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION; // TODO
|
ZYDIS_ASSERT(ctx->info->details.xop.m_mmmm >= 0x08);
|
||||||
|
ZYDIS_ASSERT(ctx->info->details.xop.m_mmmm <= 0x0B);
|
||||||
break;
|
break;
|
||||||
case ZYDIS_OPCODE_MAP_DEFAULT:
|
|
||||||
break; // Nothing to do.
|
|
||||||
default:
|
default:
|
||||||
ZYDIS_UNREACHABLE;
|
ZYDIS_UNREACHABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Emit actual opcode.
|
|
||||||
ZYDIS_CHECK(ZydisEmitByte(ctx, ctx->info->opcode));
|
|
||||||
|
|
||||||
return ZYDIS_STATUS_SUCCESS;
|
return ZYDIS_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -395,9 +422,9 @@ static ZydisStatus ZydisPrepareRegOperand(ZydisEncoderContext* ctx,
|
||||||
|
|
||||||
switch (topBitLoc)
|
switch (topBitLoc)
|
||||||
{
|
{
|
||||||
case 'B': ctx->info->details.modrm.rm = lowerBits;
|
case 'B': ctx->info->details.modrm.rm = lowerBits; break;
|
||||||
case 'R': ctx->info->details.modrm.reg = lowerBits;
|
case 'R': ctx->info->details.modrm.reg = lowerBits; break;
|
||||||
case 'X': ctx->info->details.sib.index = lowerBits;
|
case 'X': ctx->info->details.sib.index = lowerBits; break;
|
||||||
default: ZYDIS_UNREACHABLE;
|
default: ZYDIS_UNREACHABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -424,7 +451,6 @@ static ZydisStatus ZydisPrepareRegOperand(ZydisEncoderContext* ctx,
|
||||||
case 'X': topBitDst = &ctx->info->details.vex.X; break;
|
case 'X': topBitDst = &ctx->info->details.vex.X; break;
|
||||||
default: ZYDIS_UNREACHABLE;
|
default: ZYDIS_UNREACHABLE;
|
||||||
}
|
}
|
||||||
topBit = ~topBit;
|
|
||||||
break;
|
break;
|
||||||
case ZYDIS_INSTRUCTION_ENCODING_XOP:
|
case ZYDIS_INSTRUCTION_ENCODING_XOP:
|
||||||
switch (topBitLoc)
|
switch (topBitLoc)
|
||||||
|
@ -434,7 +460,6 @@ static ZydisStatus ZydisPrepareRegOperand(ZydisEncoderContext* ctx,
|
||||||
case 'X': topBitDst = &ctx->info->details.xop.X; break;
|
case 'X': topBitDst = &ctx->info->details.xop.X; break;
|
||||||
default: ZYDIS_UNREACHABLE;
|
default: ZYDIS_UNREACHABLE;
|
||||||
}
|
}
|
||||||
topBit = ~topBit;
|
|
||||||
break;
|
break;
|
||||||
case ZYDIS_INSTRUCTION_ENCODING_EVEX:
|
case ZYDIS_INSTRUCTION_ENCODING_EVEX:
|
||||||
switch (topBitLoc)
|
switch (topBitLoc)
|
||||||
|
@ -444,7 +469,6 @@ static ZydisStatus ZydisPrepareRegOperand(ZydisEncoderContext* ctx,
|
||||||
case 'X': topBitDst = &ctx->info->details.evex.X; break;
|
case 'X': topBitDst = &ctx->info->details.evex.X; break;
|
||||||
default: ZYDIS_UNREACHABLE;
|
default: ZYDIS_UNREACHABLE;
|
||||||
}
|
}
|
||||||
topBit = ~topBit;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION; // TODO
|
return ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION; // TODO
|
||||||
|
@ -474,34 +498,56 @@ static ZydisStatus ZydisPrepareOperand(ZydisEncoderContext* ctx,
|
||||||
case ZYDIS_OPERAND_ENCODING_RM_CD32:
|
case ZYDIS_OPERAND_ENCODING_RM_CD32:
|
||||||
case ZYDIS_OPERAND_ENCODING_RM_CD64:
|
case ZYDIS_OPERAND_ENCODING_RM_CD64:
|
||||||
{
|
{
|
||||||
|
// TODO: MMX registers
|
||||||
|
// TODO: rBP
|
||||||
|
// TODO: RIP relative addressing
|
||||||
|
|
||||||
// Memory operand?
|
// Memory operand?
|
||||||
if (operand->type == ZYDIS_OPERAND_TYPE_MEMORY)
|
if (operand->type == ZYDIS_OPERAND_TYPE_MEMORY)
|
||||||
{
|
{
|
||||||
// Has base register?
|
// Absolute memory access?
|
||||||
if (operand->mem.base != ZYDIS_REGISTER_NONE)
|
if (operand->mem.base == ZYDIS_REGISTER_NONE)
|
||||||
{
|
{
|
||||||
ZYDIS_CHECK(ZydisPrepareRegOperand(ctx, operand->mem.base, 'B'));
|
ctx->disp = operand->mem.disp.value.sdword;
|
||||||
}
|
ctx->dispBitSize = 32;
|
||||||
else
|
|
||||||
{
|
// In 32 bit mode, ModRM allows for a shortcut here.
|
||||||
// TODO: Does rm=0x05 work with sbyte disps?
|
if (ctx->info->mode == ZYDIS_DISASSEMBLER_MODE_32BIT)
|
||||||
ctx->info->details.modrm.rm = 0x05 /* memory */;
|
{
|
||||||
|
ctx->info->details.modrm.mod = 0x00;
|
||||||
|
ctx->info->details.modrm.rm = 0x05 /* memory */;
|
||||||
|
}
|
||||||
|
// In AMD64 mode, we have to build a SIB.
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ctx->info->details.modrm.mod = 0x00;
|
||||||
|
ctx->info->details.modrm.rm = 0x04 /* SIB */;
|
||||||
|
ctx->info->details.sib.index = 0x04 /* none */;
|
||||||
|
ctx->info->details.sib.scale = 0x00 /* * 1 */;
|
||||||
|
ctx->info->details.sib.base = 0x05;
|
||||||
|
ctx->info->attributes |= ZYDIS_ATTRIB_HAS_SIB;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->info->attributes |= ZYDIS_ATTRIB_HAS_MODRM;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Base register?
|
||||||
|
ZYDIS_CHECK(ZydisPrepareRegOperand(ctx, operand->mem.base, 'B'));
|
||||||
|
|
||||||
// SIB byte required?
|
// SIB byte required?
|
||||||
if (operand->mem.index || operand->mem.scale)
|
if (operand->mem.index || operand->mem.scale)
|
||||||
{
|
{
|
||||||
switch (operand->mem.scale)
|
switch (operand->mem.scale)
|
||||||
{
|
{
|
||||||
case 1: ctx->info->details.sib.index = 0x01; break;
|
case 1: ctx->info->details.sib.index = 0x00; break;
|
||||||
case 2: ctx->info->details.sib.index = 0x02; break;
|
case 2: ctx->info->details.sib.index = 0x01; break;
|
||||||
case 4: ctx->info->details.sib.index = 0x03; break;
|
case 4: ctx->info->details.sib.index = 0x02; break;
|
||||||
case 8: ctx->info->details.sib.index = 0x04; break;
|
case 8: ctx->info->details.sib.index = 0x03; break;
|
||||||
default: return ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION; // TODO
|
default: return ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION; // TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
// Base & index register.
|
// Base & index register.
|
||||||
ZYDIS_CHECK(ZydisPrepareRegOperand(ctx, operand->mem.base, 'B'));
|
|
||||||
ctx->info->details.sib.base = ctx->info->details.modrm.rm;
|
ctx->info->details.sib.base = ctx->info->details.modrm.rm;
|
||||||
ZYDIS_CHECK(ZydisPrepareRegOperand(ctx, operand->mem.index, 'X'));
|
ZYDIS_CHECK(ZydisPrepareRegOperand(ctx, operand->mem.index, 'X'));
|
||||||
|
|
||||||
|
@ -515,14 +561,14 @@ static ZydisStatus ZydisPrepareOperand(ZydisEncoderContext* ctx,
|
||||||
int32_t divisor = 1;
|
int32_t divisor = 1;
|
||||||
switch (tableEntry->encoding)
|
switch (tableEntry->encoding)
|
||||||
{
|
{
|
||||||
case ZYDIS_OPERAND_ENCODING_RM: break;
|
case ZYDIS_OPERAND_ENCODING_RM: break;
|
||||||
case ZYDIS_OPERAND_ENCODING_RM_CD2: divisor = 2; break;
|
case ZYDIS_OPERAND_ENCODING_RM_CD2: divisor = 2; break;
|
||||||
case ZYDIS_OPERAND_ENCODING_RM_CD4: divisor = 4; break;
|
case ZYDIS_OPERAND_ENCODING_RM_CD4: divisor = 4; break;
|
||||||
case ZYDIS_OPERAND_ENCODING_RM_CD8: divisor = 8; break;
|
case ZYDIS_OPERAND_ENCODING_RM_CD8: divisor = 8; break;
|
||||||
case ZYDIS_OPERAND_ENCODING_RM_CD16: divisor = 16; break;
|
case ZYDIS_OPERAND_ENCODING_RM_CD16: divisor = 16; break;
|
||||||
case ZYDIS_OPERAND_ENCODING_RM_CD32: divisor = 32; break;
|
case ZYDIS_OPERAND_ENCODING_RM_CD32: divisor = 32; break;
|
||||||
case ZYDIS_OPERAND_ENCODING_RM_CD64: divisor = 64; break;
|
case ZYDIS_OPERAND_ENCODING_RM_CD64: divisor = 64; break;
|
||||||
default: ZYDIS_UNREACHABLE;
|
default: ZYDIS_UNREACHABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Has compressed disp encoding and is compression possible?
|
// Has compressed disp encoding and is compression possible?
|
||||||
|
@ -577,8 +623,16 @@ static ZydisStatus ZydisPrepareOperand(ZydisEncoderContext* ctx,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ZYDIS_OPERAND_ENCODING_VVVV:
|
case ZYDIS_OPERAND_ENCODING_VVVV:
|
||||||
break; // TODO
|
{
|
||||||
|
int16_t reg = ZydisRegisterGetId(operand->reg);
|
||||||
|
if (reg == -1) return ZYDIS_STATUS_INVALID_PARAMETER;
|
||||||
|
// TODO: Conditional assignment instead?
|
||||||
|
ctx->info->details.vex.vvvv = (reg & 0x0F);
|
||||||
|
ctx->info->details.evex.vvvv = (reg & 0x0F);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case ZYDIS_OPERAND_ENCODING_AAA:
|
case ZYDIS_OPERAND_ENCODING_AAA:
|
||||||
|
return ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION;
|
||||||
break; // TODO
|
break; // TODO
|
||||||
case ZYDIS_OPERAND_ENCODING_IMM8_LO:
|
case ZYDIS_OPERAND_ENCODING_IMM8_LO:
|
||||||
{
|
{
|
||||||
|
@ -627,7 +681,7 @@ static ZydisStatus ZydisFindMatchingDef(const ZydisInstructionInfo* info,
|
||||||
ZYDIS_ASSERT(matchingEntry);
|
ZYDIS_ASSERT(matchingEntry);
|
||||||
|
|
||||||
// Locate entries with matching mnemonic.
|
// Locate entries with matching mnemonic.
|
||||||
// TODO: do binary search / hash based lookup instead
|
// TODO: Do binary search / hash based lookup instead.
|
||||||
for (size_t i = 0; i < ZYDIS_ARRAY_SIZE(kEncoderTable); ++i)
|
for (size_t i = 0; i < ZYDIS_ARRAY_SIZE(kEncoderTable); ++i)
|
||||||
{
|
{
|
||||||
const ZydisEncoderTableEntry* curEntry = &kEncoderTable[i];
|
const ZydisEncoderTableEntry* curEntry = &kEncoderTable[i];
|
||||||
|
@ -645,6 +699,7 @@ static ZydisStatus ZydisFindMatchingDef(const ZydisInstructionInfo* info,
|
||||||
// Check operands.
|
// Check operands.
|
||||||
for (size_t k = 0; k < curEntry->operandCount; ++k)
|
for (size_t k = 0; k < curEntry->operandCount; ++k)
|
||||||
{
|
{
|
||||||
|
// TODO: Match operand size.
|
||||||
const ZydisEncoderTableOperand* curEncoderOp = &curEntry->operands[k];
|
const ZydisEncoderTableOperand* curEncoderOp = &curEntry->operands[k];
|
||||||
const ZydisOperandInfo* curReqOp = &info->operands[k];
|
const ZydisOperandInfo* curReqOp = &info->operands[k];
|
||||||
if (curReqOp->encoding != curEncoderOp->encoding) goto continueTopLevel;
|
if (curReqOp->encoding != curEncoderOp->encoding) goto continueTopLevel;
|
||||||
|
@ -692,6 +747,32 @@ ZydisStatus ZydisEncoderEncodeInstruction(void* buffer, size_t* bufferLen,
|
||||||
info->opcode = ctx.matchingEntry->opcode;
|
info->opcode = ctx.matchingEntry->opcode;
|
||||||
info->attributes |= ctx.matchingEntry->mandatoryAttribs;
|
info->attributes |= ctx.matchingEntry->mandatoryAttribs;
|
||||||
|
|
||||||
|
// TODO: Check compatibility of requested prefixes to found instruction.
|
||||||
|
|
||||||
|
// Determine required prefixes.
|
||||||
|
switch (ctx.matchingEntry->encoding)
|
||||||
|
{
|
||||||
|
case ZYDIS_INSTRUCTION_ENCODING_EVEX:
|
||||||
|
info->attributes |= ZYDIS_ATTRIB_HAS_EVEX;
|
||||||
|
break;
|
||||||
|
case ZYDIS_INSTRUCTION_ENCODING_VEX:
|
||||||
|
info->attributes |= ZYDIS_ATTRIB_HAS_VEX;
|
||||||
|
break;
|
||||||
|
case ZYDIS_INSTRUCTION_ENCODING_XOP:
|
||||||
|
info->attributes |= ZYDIS_ATTRIB_HAS_XOP;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare prefix bits.
|
||||||
|
ZydisPrefixBit pb = ctx.matchingEntry->prefixBits;
|
||||||
|
info->details.evex.B = (pb & ZYDIS_PREFBIT_EVEX_B ) ? 1 : 0;
|
||||||
|
info->details.evex.L2 = (pb & ZYDIS_PREFBIT_EVEX_L2) ? 1 : 0;
|
||||||
|
info->details.vex.L = (pb & ZYDIS_PREFBIT_VEX_L ) ? 1 : 0;
|
||||||
|
info->details.rex.W = (pb & ZYDIS_PREFBIT_REX_W ) ? 1 : 0;
|
||||||
|
|
||||||
|
// Prepare opcode.
|
||||||
|
ZYDIS_CHECK(ZydisPrepareOpcode(&ctx));
|
||||||
|
|
||||||
// Analyze and prepare operands.
|
// Analyze and prepare operands.
|
||||||
if (info->operandCount > ZYDIS_ARRAY_SIZE(info->operands))
|
if (info->operandCount > ZYDIS_ARRAY_SIZE(info->operands))
|
||||||
{
|
{
|
||||||
|
@ -713,7 +794,14 @@ ZydisStatus ZydisEncoderEncodeInstruction(void* buffer, size_t* bufferLen,
|
||||||
if (info->attributes & ZYDIS_ATTRIB_HAS_VEX ) ZYDIS_CHECK(ZydisEmitVEX (&ctx));
|
if (info->attributes & ZYDIS_ATTRIB_HAS_VEX ) ZYDIS_CHECK(ZydisEmitVEX (&ctx));
|
||||||
if (info->attributes & ZYDIS_ATTRIB_HAS_EVEX ) ZYDIS_CHECK(ZydisEmitEVEX (&ctx));
|
if (info->attributes & ZYDIS_ATTRIB_HAS_EVEX ) ZYDIS_CHECK(ZydisEmitEVEX (&ctx));
|
||||||
if (info->attributes & ZYDIS_ATTRIB_HAS_XOP ) ZYDIS_CHECK(ZydisEmitXOP (&ctx));
|
if (info->attributes & ZYDIS_ATTRIB_HAS_XOP ) ZYDIS_CHECK(ZydisEmitXOP (&ctx));
|
||||||
ZYDIS_CHECK(ZydisEmitOpcode(&ctx));
|
|
||||||
|
for (uint8_t i = 0; i < ctx.opcodeMapPrefixLen; ++i)
|
||||||
|
{
|
||||||
|
ZYDIS_CHECK(ZydisEmitByte(&ctx, ctx.opcodeMapPrefix[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
ZYDIS_CHECK(ZydisEmitByte(&ctx, info->opcode));
|
||||||
|
|
||||||
if (info->attributes & ZYDIS_ATTRIB_HAS_MODRM) ZYDIS_CHECK(ZydisEmitModRM(&ctx));
|
if (info->attributes & ZYDIS_ATTRIB_HAS_MODRM) ZYDIS_CHECK(ZydisEmitModRM(&ctx));
|
||||||
if (info->attributes & ZYDIS_ATTRIB_HAS_SIB ) ZYDIS_CHECK(ZydisEmitSIB (&ctx));
|
if (info->attributes & ZYDIS_ATTRIB_HAS_SIB ) ZYDIS_CHECK(ZydisEmitSIB (&ctx));
|
||||||
|
|
||||||
|
|
|
@ -96,6 +96,12 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
// TODO: Remove
|
// TODO: Remove
|
||||||
// DEBUG CODE START
|
// DEBUG CODE START
|
||||||
|
for (size_t i = 0; i < info.length; ++i)
|
||||||
|
{
|
||||||
|
printf("%02X ", *(readBuf + readOffs + i));
|
||||||
|
}
|
||||||
|
putchar('\n');
|
||||||
|
|
||||||
uint8_t encBuffer[15];
|
uint8_t encBuffer[15];
|
||||||
size_t encBufferSize = sizeof(encBuffer);
|
size_t encBufferSize = sizeof(encBuffer);
|
||||||
ZydisStatus encStatus = ZydisEncoderEncodeInstruction(
|
ZydisStatus encStatus = ZydisEncoderEncodeInstruction(
|
||||||
|
|
Loading…
Reference in New Issue