mirror of https://github.com/x64dbg/zydis
Major rework of encoder context design
- Split into various smaller structs - Only hand functions parts they actually need
This commit is contained in:
parent
9152714865
commit
5ac595eb72
272
src/Encoder.c
272
src/Encoder.c
|
@ -37,46 +37,43 @@
|
||||||
|
|
||||||
typedef uint32_t ZydisSemanticOperandTypeMask;
|
typedef uint32_t ZydisSemanticOperandTypeMask;
|
||||||
|
|
||||||
/**
|
typedef struct ZydisInstructionQuery_
|
||||||
* @brief The encoder context struct.
|
|
||||||
*/
|
|
||||||
typedef struct ZydisEncoderContext_
|
|
||||||
{
|
{
|
||||||
// Input parameters.
|
|
||||||
uint8_t* buffer;
|
|
||||||
size_t bufferLen;
|
|
||||||
size_t writeOffs;
|
|
||||||
const ZydisEncoderRequest* req;
|
|
||||||
|
|
||||||
// Definition requirements (filled by `ZydisAnalyzeRequirements`)
|
|
||||||
ZydisSemanticOperandTypeMask semOperandTypeMasks[ZYDIS_ENCODER_MAX_OPERANDS];
|
ZydisSemanticOperandTypeMask semOperandTypeMasks[ZYDIS_ENCODER_MAX_OPERANDS];
|
||||||
uint8_t derivedImmSize[ZYDIS_ENCODER_MAX_OPERANDS];
|
|
||||||
ZydisBool require66;
|
ZydisBool require66;
|
||||||
ZydisBool require67;
|
ZydisBool require67;
|
||||||
ZydisBool requireREXW;
|
ZydisBool requireREXW;
|
||||||
uint8_t eosz;
|
uint8_t eosz;
|
||||||
uint8_t easz;
|
uint8_t easz;
|
||||||
|
} ZydisInstructionQuery;
|
||||||
|
|
||||||
// Found matching definition info (filled by `ZydisFindMatchingDef`)
|
typedef struct ZydisInstructionMatch_
|
||||||
const ZydisEncodableInstruction* matchingInsn;
|
{
|
||||||
const ZydisInstructionDefinition* matchingDef;
|
const ZydisEncodableInstruction* insn;
|
||||||
uint8_t matchingOperandCount;
|
const ZydisInstructionDefinition* def;
|
||||||
const ZydisOperandDefinition* matchingOperands;
|
uint8_t operandCount;
|
||||||
|
const ZydisOperandDefinition* operands;
|
||||||
|
uint8_t derivedImmSizes[ZYDIS_ENCODER_MAX_OPERANDS];
|
||||||
|
} ZydisInstructionMatch;
|
||||||
|
|
||||||
|
typedef struct ZydisRawInstruction_
|
||||||
|
{
|
||||||
ZydisInstructionAttributes derivedAttrs;
|
ZydisInstructionAttributes derivedAttrs;
|
||||||
ZydisBool emitMandatoryPrefix;
|
uint8_t mandatoryPrefix; // 0 = not present
|
||||||
uint8_t mandatoryPrefix;
|
|
||||||
uint8_t dispBitSize;
|
|
||||||
uint64_t disp;
|
|
||||||
uint8_t immBitSizes[2];
|
|
||||||
uint64_t imms[2];
|
|
||||||
uint8_t opcodeMapPrefixLen;
|
uint8_t opcodeMapPrefixLen;
|
||||||
uint8_t opcodeMapPrefix[3];
|
uint8_t opcodeMapPrefix[3];
|
||||||
|
uint8_t opcode;
|
||||||
|
|
||||||
// Prepared, raw instruction data (filled by `ZydisPrepare*` funcs)
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
uint8_t opcode;
|
int64_t val;
|
||||||
|
uint8_t size;
|
||||||
|
} disp;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint64_t val;
|
||||||
|
uint8_t size;
|
||||||
|
} imms[2];
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
uint8_t W;
|
uint8_t W;
|
||||||
|
@ -150,7 +147,17 @@ typedef struct ZydisEncoderContext_
|
||||||
uint8_t index;
|
uint8_t index;
|
||||||
uint8_t base;
|
uint8_t base;
|
||||||
} sib;
|
} sib;
|
||||||
} raw;
|
} ZydisRawInstruction;
|
||||||
|
|
||||||
|
typedef struct ZydisEncoderContext_
|
||||||
|
{
|
||||||
|
// Input parameters.
|
||||||
|
uint8_t* buffer;
|
||||||
|
size_t bufferLen;
|
||||||
|
size_t writeOffs;
|
||||||
|
const ZydisEncoderRequest* req;
|
||||||
|
|
||||||
|
ZydisRawInstruction raw;
|
||||||
} ZydisEncoderContext;
|
} ZydisEncoderContext;
|
||||||
|
|
||||||
/* ============================================================================================== */
|
/* ============================================================================================== */
|
||||||
|
@ -646,29 +653,28 @@ static ZydisBool ZydisSemanticTypeIsImplicit(ZydisSemanticOperandType type)
|
||||||
/* Preparation functions. Parse encoder request, determine required bytes and prefixes. */
|
/* Preparation functions. Parse encoder request, determine required bytes and prefixes. */
|
||||||
/* ---------------------------------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
static ZydisStatus ZydisPrepareOpcode(ZydisEncoderContext* ctx)
|
static ZydisStatus ZydisPrepareOpcode(ZydisEncoderContext* ctx, const ZydisInstructionMatch* match)
|
||||||
{
|
{
|
||||||
ZYDIS_ASSERT(ctx);
|
ZYDIS_ASSERT(ctx);
|
||||||
ZYDIS_ASSERT(ctx->matchingDef);
|
ZYDIS_ASSERT(match);
|
||||||
ZYDIS_ASSERT(ctx->req);
|
|
||||||
|
|
||||||
// Put opcode map prefix(es), if required.
|
// Put opcode map prefix(es), if required.
|
||||||
switch (ctx->req->encoding)
|
switch (ctx->req->encoding)
|
||||||
{
|
{
|
||||||
case ZYDIS_INSTRUCTION_ENCODING_DEFAULT:
|
case ZYDIS_INSTRUCTION_ENCODING_DEFAULT:
|
||||||
case ZYDIS_INSTRUCTION_ENCODING_3DNOW:
|
case ZYDIS_INSTRUCTION_ENCODING_3DNOW:
|
||||||
switch (ctx->matchingInsn->opcodeMap)
|
switch (match->insn->opcodeMap)
|
||||||
{
|
{
|
||||||
case ZYDIS_OPCODE_MAP_0F:
|
case ZYDIS_OPCODE_MAP_0F:
|
||||||
ctx->opcodeMapPrefix[ctx->opcodeMapPrefixLen++] = 0x0F;
|
ctx->raw.opcodeMapPrefix[ctx->raw.opcodeMapPrefixLen++] = 0x0F;
|
||||||
break;
|
break;
|
||||||
case ZYDIS_OPCODE_MAP_0F38:
|
case ZYDIS_OPCODE_MAP_0F38:
|
||||||
ctx->opcodeMapPrefix[ctx->opcodeMapPrefixLen++] = 0x0F;
|
ctx->raw.opcodeMapPrefix[ctx->raw.opcodeMapPrefixLen++] = 0x0F;
|
||||||
ctx->opcodeMapPrefix[ctx->opcodeMapPrefixLen++] = 0x38;
|
ctx->raw.opcodeMapPrefix[ctx->raw.opcodeMapPrefixLen++] = 0x38;
|
||||||
break;
|
break;
|
||||||
case ZYDIS_OPCODE_MAP_0F3A:
|
case ZYDIS_OPCODE_MAP_0F3A:
|
||||||
ctx->opcodeMapPrefix[ctx->opcodeMapPrefixLen++] = 0x0F;
|
ctx->raw.opcodeMapPrefix[ctx->raw.opcodeMapPrefixLen++] = 0x0F;
|
||||||
ctx->opcodeMapPrefix[ctx->opcodeMapPrefixLen++] = 0x3A;
|
ctx->raw.opcodeMapPrefix[ctx->raw.opcodeMapPrefixLen++] = 0x3A;
|
||||||
break;
|
break;
|
||||||
case ZYDIS_OPCODE_MAP_DEFAULT:
|
case ZYDIS_OPCODE_MAP_DEFAULT:
|
||||||
break; // Nothing to do.
|
break; // Nothing to do.
|
||||||
|
@ -677,16 +683,16 @@ static ZydisStatus ZydisPrepareOpcode(ZydisEncoderContext* ctx)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ZYDIS_INSTRUCTION_ENCODING_VEX:
|
case ZYDIS_INSTRUCTION_ENCODING_VEX:
|
||||||
ctx->raw.vex.m_mmmm = ctx->matchingInsn->opcodeMap;
|
ctx->raw.vex.m_mmmm = match->insn->opcodeMap;
|
||||||
ZYDIS_ASSERT(ctx->raw.vex.m_mmmm <= 0x03);
|
ZYDIS_ASSERT(ctx->raw.vex.m_mmmm <= 0x03);
|
||||||
break;
|
break;
|
||||||
case ZYDIS_INSTRUCTION_ENCODING_EVEX:
|
case ZYDIS_INSTRUCTION_ENCODING_EVEX:
|
||||||
ctx->raw.evex.mm = ctx->matchingInsn->opcodeMap;
|
ctx->raw.evex.mm = match->insn->opcodeMap;
|
||||||
ZYDIS_ASSERT(ctx->raw.evex.mm <= 0x03);
|
ZYDIS_ASSERT(ctx->raw.evex.mm <= 0x03);
|
||||||
break;
|
break;
|
||||||
case ZYDIS_INSTRUCTION_ENCODING_XOP:
|
case ZYDIS_INSTRUCTION_ENCODING_XOP:
|
||||||
ctx->raw.xop.m_mmmm =
|
ctx->raw.xop.m_mmmm =
|
||||||
ctx->matchingInsn->opcodeMap - ZYDIS_OPCODE_MAP_XOP8 + 0x08;
|
match->insn->opcodeMap - ZYDIS_OPCODE_MAP_XOP8 + 0x08;
|
||||||
ZYDIS_ASSERT(ctx->raw.xop.m_mmmm >= 0x08);
|
ZYDIS_ASSERT(ctx->raw.xop.m_mmmm >= 0x08);
|
||||||
ZYDIS_ASSERT(ctx->raw.xop.m_mmmm <= 0x0B);
|
ZYDIS_ASSERT(ctx->raw.xop.m_mmmm <= 0x0B);
|
||||||
break;
|
break;
|
||||||
|
@ -730,7 +736,7 @@ static ZydisStatus ZydisPrepareRegOperand(ZydisEncoderContext* ctx,
|
||||||
case 'X': ctx->raw.rex.X = topBit; break;
|
case 'X': ctx->raw.rex.X = topBit; break;
|
||||||
default: ZYDIS_UNREACHABLE;
|
default: ZYDIS_UNREACHABLE;
|
||||||
}
|
}
|
||||||
if (topBit) ctx->derivedAttrs |= ZYDIS_ATTRIB_HAS_REX;
|
if (topBit) ctx->raw.derivedAttrs |= ZYDIS_ATTRIB_HAS_REX;
|
||||||
break;
|
break;
|
||||||
case ZYDIS_INSTRUCTION_ENCODING_VEX:
|
case ZYDIS_INSTRUCTION_ENCODING_VEX:
|
||||||
switch (topBitLoc)
|
switch (topBitLoc)
|
||||||
|
@ -773,28 +779,28 @@ static ZydisStatus ZydisPrepareSegmentPrefix(ZydisEncoderContext* ctx,
|
||||||
switch (segment)
|
switch (segment)
|
||||||
{
|
{
|
||||||
case ZYDIS_REGISTER_ES:
|
case ZYDIS_REGISTER_ES:
|
||||||
ctx->derivedAttrs |= ZYDIS_ATTRIB_HAS_SEGMENT_ES;
|
ctx->raw.derivedAttrs |= ZYDIS_ATTRIB_HAS_SEGMENT_ES;
|
||||||
break;
|
break;
|
||||||
case ZYDIS_REGISTER_SS:
|
case ZYDIS_REGISTER_SS:
|
||||||
if (!ZydisRegIsStack(base))
|
if (!ZydisRegIsStack(base))
|
||||||
{
|
{
|
||||||
ctx->derivedAttrs |= ZYDIS_ATTRIB_HAS_SEGMENT_SS;
|
ctx->raw.derivedAttrs |= ZYDIS_ATTRIB_HAS_SEGMENT_SS;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ZYDIS_REGISTER_CS:
|
case ZYDIS_REGISTER_CS:
|
||||||
ctx->derivedAttrs |= ZYDIS_ATTRIB_HAS_SEGMENT_CS;
|
ctx->raw.derivedAttrs |= ZYDIS_ATTRIB_HAS_SEGMENT_CS;
|
||||||
break;
|
break;
|
||||||
case ZYDIS_REGISTER_DS:
|
case ZYDIS_REGISTER_DS:
|
||||||
if (ZydisRegIsStack(base))
|
if (ZydisRegIsStack(base))
|
||||||
{
|
{
|
||||||
ctx->derivedAttrs |= ZYDIS_ATTRIB_HAS_SEGMENT_DS;
|
ctx->raw.derivedAttrs |= ZYDIS_ATTRIB_HAS_SEGMENT_DS;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ZYDIS_REGISTER_FS:
|
case ZYDIS_REGISTER_FS:
|
||||||
ctx->derivedAttrs |= ZYDIS_ATTRIB_HAS_SEGMENT_FS;
|
ctx->raw.derivedAttrs |= ZYDIS_ATTRIB_HAS_SEGMENT_FS;
|
||||||
break;
|
break;
|
||||||
case ZYDIS_REGISTER_GS:
|
case ZYDIS_REGISTER_GS:
|
||||||
ctx->derivedAttrs |= ZYDIS_ATTRIB_HAS_SEGMENT_GS;
|
ctx->raw.derivedAttrs |= ZYDIS_ATTRIB_HAS_SEGMENT_GS;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION; // TODO: Better status.
|
return ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION; // TODO: Better status.
|
||||||
|
@ -815,8 +821,8 @@ static ZydisStatus ZydisPrepareMemoryOperand(ZydisEncoderContext* ctx,
|
||||||
// Absolute memory access? Special case.
|
// Absolute memory access? Special case.
|
||||||
if (operand->mem.base == ZYDIS_REGISTER_NONE)
|
if (operand->mem.base == ZYDIS_REGISTER_NONE)
|
||||||
{
|
{
|
||||||
ctx->disp = operand->mem.disp;
|
ctx->raw.disp.val = operand->mem.disp;
|
||||||
ctx->dispBitSize = 32;
|
ctx->raw.disp.size = 32;
|
||||||
|
|
||||||
// In 32 bit mode, ModRM allows for a shortcut here.
|
// In 32 bit mode, ModRM allows for a shortcut here.
|
||||||
if (ctx->req->machineMode == 32)
|
if (ctx->req->machineMode == 32)
|
||||||
|
@ -832,7 +838,7 @@ static ZydisStatus ZydisPrepareMemoryOperand(ZydisEncoderContext* ctx,
|
||||||
ctx->raw.sib.index = 0x04 /* none */;
|
ctx->raw.sib.index = 0x04 /* none */;
|
||||||
ctx->raw.sib.scale = 0x00 /* * 1 */;
|
ctx->raw.sib.scale = 0x00 /* * 1 */;
|
||||||
ctx->raw.sib.base = 0x05;
|
ctx->raw.sib.base = 0x05;
|
||||||
ctx->derivedAttrs |= ZYDIS_ATTRIB_HAS_SIB;
|
ctx->raw.derivedAttrs |= ZYDIS_ATTRIB_HAS_SIB;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ZYDIS_STATUS_SUCCESS;
|
return ZYDIS_STATUS_SUCCESS;
|
||||||
|
@ -853,14 +859,14 @@ static ZydisStatus ZydisPrepareMemoryOperand(ZydisEncoderContext* ctx,
|
||||||
return ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION; // TODO
|
return ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION; // TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx->disp = operand->mem.disp;
|
ctx->raw.disp.val = operand->mem.disp;
|
||||||
ctx->dispBitSize = 32;
|
ctx->raw.disp.size = 32;
|
||||||
ctx->raw.modrm.mod = 0x00;
|
ctx->raw.modrm.mod = 0x00;
|
||||||
ctx->raw.modrm.rm = 0x05 /* RIP relative mem */;
|
ctx->raw.modrm.rm = 0x05 /* RIP relative mem */;
|
||||||
|
|
||||||
if (operand->mem.base == ZYDIS_REGISTER_EIP)
|
if (operand->mem.base == ZYDIS_REGISTER_EIP)
|
||||||
{
|
{
|
||||||
ctx->derivedAttrs |= ZYDIS_ATTRIB_HAS_ADDRESSSIZE;
|
ctx->raw.derivedAttrs |= ZYDIS_ATTRIB_HAS_ADDRESSSIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ZYDIS_STATUS_SUCCESS;
|
return ZYDIS_STATUS_SUCCESS;
|
||||||
|
@ -879,7 +885,7 @@ static ZydisStatus ZydisPrepareMemoryOperand(ZydisEncoderContext* ctx,
|
||||||
case 16:
|
case 16:
|
||||||
break; // Nothing to do.
|
break; // Nothing to do.
|
||||||
case 32:
|
case 32:
|
||||||
ctx->derivedAttrs |= ZYDIS_ATTRIB_HAS_ADDRESSSIZE;
|
ctx->raw.derivedAttrs |= ZYDIS_ATTRIB_HAS_ADDRESSSIZE;
|
||||||
break;
|
break;
|
||||||
case 64:
|
case 64:
|
||||||
// AMD64 doesn't allow for 16 bit addressing.
|
// AMD64 doesn't allow for 16 bit addressing.
|
||||||
|
@ -896,7 +902,7 @@ static ZydisStatus ZydisPrepareMemoryOperand(ZydisEncoderContext* ctx,
|
||||||
case 32:
|
case 32:
|
||||||
break; // Nothing to do.
|
break; // Nothing to do.
|
||||||
case 64:
|
case 64:
|
||||||
ctx->derivedAttrs |= ZYDIS_ATTRIB_HAS_ADDRESSSIZE;
|
ctx->raw.derivedAttrs |= ZYDIS_ATTRIB_HAS_ADDRESSSIZE;
|
||||||
default:
|
default:
|
||||||
return ZYDIS_STATUS_INVALID_PARAMETER; // TODO
|
return ZYDIS_STATUS_INVALID_PARAMETER; // TODO
|
||||||
}
|
}
|
||||||
|
@ -944,7 +950,7 @@ static ZydisStatus ZydisPrepareMemoryOperand(ZydisEncoderContext* ctx,
|
||||||
ctx->raw.sib.index = 0x04 /* no index */;
|
ctx->raw.sib.index = 0x04 /* no index */;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx->derivedAttrs |= ZYDIS_ATTRIB_HAS_SIB;
|
ctx->raw.derivedAttrs |= ZYDIS_ATTRIB_HAS_SIB;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Has displacement or is rBP and we have no SIB?
|
// Has displacement or is rBP and we have no SIB?
|
||||||
|
@ -952,9 +958,9 @@ static ZydisStatus ZydisPrepareMemoryOperand(ZydisEncoderContext* ctx,
|
||||||
if (operand->mem.disp || (!(ctx->req->attributes & ZYDIS_ATTRIB_HAS_SIB)
|
if (operand->mem.disp || (!(ctx->req->attributes & ZYDIS_ATTRIB_HAS_SIB)
|
||||||
&& ZydisRegIsBP(operand->mem.base)))
|
&& ZydisRegIsBP(operand->mem.base)))
|
||||||
{
|
{
|
||||||
ctx->dispBitSize = 32;
|
ctx->raw.disp.size = 32;
|
||||||
ctx->raw.modrm.mod = 0x02 /* 32 bit disp */;
|
ctx->raw.modrm.mod = 0x02 /* 32 bit disp */;
|
||||||
ctx->disp = operand->mem.disp;
|
ctx->raw.disp.val = operand->mem.disp;
|
||||||
}
|
}
|
||||||
// No displacement.
|
// No displacement.
|
||||||
else
|
else
|
||||||
|
@ -965,11 +971,12 @@ static ZydisStatus ZydisPrepareMemoryOperand(ZydisEncoderContext* ctx,
|
||||||
return ZYDIS_STATUS_SUCCESS;
|
return ZYDIS_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ZydisStatus ZydisPrepareOperand(ZydisEncoderContext* ctx, uint8_t n)
|
static ZydisStatus ZydisPrepareOperand(ZydisEncoderContext* ctx,
|
||||||
|
ZydisInstructionMatch* match, uint8_t n)
|
||||||
{
|
{
|
||||||
ZYDIS_ASSERT(ctx);
|
ZYDIS_ASSERT(ctx);
|
||||||
const ZydisEncoderOperand* reqOperand = ctx->req->operands + n;
|
const ZydisEncoderOperand* reqOperand = ctx->req->operands + n;
|
||||||
const ZydisOperandDefinition* operandDef = ctx->matchingOperands + n;
|
const ZydisOperandDefinition* operandDef = match->operands + n;
|
||||||
//ZYDIS_ASSERT(!ZydisSemanticTypeIsImplicit(operandDef->type));
|
//ZYDIS_ASSERT(!ZydisSemanticTypeIsImplicit(operandDef->type));
|
||||||
|
|
||||||
switch (operandDef->op.encoding)
|
switch (operandDef->op.encoding)
|
||||||
|
@ -982,8 +989,8 @@ static ZydisStatus ZydisPrepareOperand(ZydisEncoderContext* ctx, uint8_t n)
|
||||||
ZYDIS_CHECK(ZydisPrepareSegmentPrefix(
|
ZYDIS_CHECK(ZydisPrepareSegmentPrefix(
|
||||||
ctx, reqOperand->mem.segment, ZYDIS_REGISTER_NONE
|
ctx, reqOperand->mem.segment, ZYDIS_REGISTER_NONE
|
||||||
));
|
));
|
||||||
ctx->imms[0] = reqOperand->mem.disp;
|
ctx->raw.imms[0].val = reqOperand->mem.disp;
|
||||||
ctx->immBitSizes[0] = reqOperand->mem.dispSize;
|
ctx->raw.imms[0].size = reqOperand->mem.dispSize;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case ZYDIS_OPERAND_ENCODING_MODRM_REG:
|
case ZYDIS_OPERAND_ENCODING_MODRM_REG:
|
||||||
|
@ -1011,7 +1018,7 @@ static ZydisStatus ZydisPrepareOperand(ZydisEncoderContext* ctx, uint8_t n)
|
||||||
ctx->raw.modrm.mod = 0x03 /* reg */;
|
ctx->raw.modrm.mod = 0x03 /* reg */;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx->derivedAttrs |= ZYDIS_ATTRIB_HAS_MODRM;
|
ctx->raw.derivedAttrs |= ZYDIS_ATTRIB_HAS_MODRM;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ZYDIS_OPERAND_ENCODING_OPCODE:
|
case ZYDIS_OPERAND_ENCODING_OPCODE:
|
||||||
|
@ -1020,7 +1027,7 @@ static ZydisStatus ZydisPrepareOperand(ZydisEncoderContext* ctx, uint8_t n)
|
||||||
if (reg == -1) return ZYDIS_STATUS_INVALID_PARAMETER;
|
if (reg == -1) return ZYDIS_STATUS_INVALID_PARAMETER;
|
||||||
ctx->raw.opcode += reg & 0x07;
|
ctx->raw.opcode += reg & 0x07;
|
||||||
ctx->raw.rex.B = (reg & 0x08) >> 3;
|
ctx->raw.rex.B = (reg & 0x08) >> 3;
|
||||||
if (ctx->raw.rex.B) ctx->derivedAttrs |= ZYDIS_ATTRIB_HAS_REX;
|
if (ctx->raw.rex.B) ctx->raw.derivedAttrs |= ZYDIS_ATTRIB_HAS_REX;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ZYDIS_OPERAND_ENCODING_NDSNDD:
|
case ZYDIS_OPERAND_ENCODING_NDSNDD:
|
||||||
|
@ -1035,8 +1042,8 @@ static ZydisStatus ZydisPrepareOperand(ZydisEncoderContext* ctx, uint8_t n)
|
||||||
break; // TODO
|
break; // TODO
|
||||||
case ZYDIS_OPERAND_ENCODING_IS4:
|
case ZYDIS_OPERAND_ENCODING_IS4:
|
||||||
{
|
{
|
||||||
ctx->immBitSizes[0] = 8;
|
ctx->raw.imms[0].size = 8;
|
||||||
ctx->imms[0] |= reqOperand->imm.u & 0x0F;
|
ctx->raw.imms[0].val |= reqOperand->imm.u & 0x0F;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// TODO
|
// TODO
|
||||||
|
@ -1059,9 +1066,9 @@ static ZydisStatus ZydisPrepareOperand(ZydisEncoderContext* ctx, uint8_t n)
|
||||||
case ZYDIS_OPERAND_ENCODING_SIMM64:
|
case ZYDIS_OPERAND_ENCODING_SIMM64:
|
||||||
case ZYDIS_OPERAND_ENCODING_JIMM64:
|
case ZYDIS_OPERAND_ENCODING_JIMM64:
|
||||||
{
|
{
|
||||||
uint8_t immIdx = ctx->immBitSizes[0] ? 1 : 0;
|
uint8_t immIdx = ctx->raw.imms[0].size ? 1 : 0;
|
||||||
ctx->immBitSizes[immIdx] = ctx->derivedImmSize[n];
|
ctx->raw.imms[immIdx].val = reqOperand->imm.u;
|
||||||
ctx->imms[immIdx] = reqOperand->imm.u;
|
ctx->raw.imms[immIdx].size = match->derivedImmSizes[n];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -1071,20 +1078,21 @@ static ZydisStatus ZydisPrepareOperand(ZydisEncoderContext* ctx, uint8_t n)
|
||||||
return ZYDIS_STATUS_SUCCESS;
|
return ZYDIS_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ZydisStatus ZydisPrepareMandatoryPrefixes(ZydisEncoderContext* ctx)
|
static ZydisStatus ZydisPrepareMandatoryPrefixes(ZydisEncoderContext* ctx,
|
||||||
|
ZydisInstructionMatch* match)
|
||||||
{
|
{
|
||||||
ZYDIS_ASSERT(ctx);
|
ZYDIS_ASSERT(ctx);
|
||||||
|
ZYDIS_ASSERT(match);
|
||||||
|
|
||||||
// Is a prefix mandatory? 0x00 is a sentinel value for `None` in the table.
|
// Is a prefix mandatory? 0x00 is a sentinel value for `None` in the table.
|
||||||
uint8_t prefix = ctx->matchingInsn->mandatoryPrefix;
|
uint8_t prefix = match->insn->mandatoryPrefix;
|
||||||
if (prefix != 0x00)
|
if (prefix != 0x00)
|
||||||
{
|
{
|
||||||
switch (ctx->req->encoding)
|
switch (ctx->req->encoding)
|
||||||
{
|
{
|
||||||
case ZYDIS_INSTRUCTION_ENCODING_DEFAULT:
|
case ZYDIS_INSTRUCTION_ENCODING_DEFAULT:
|
||||||
case ZYDIS_INSTRUCTION_ENCODING_3DNOW:
|
case ZYDIS_INSTRUCTION_ENCODING_3DNOW:
|
||||||
ctx->emitMandatoryPrefix = ZYDIS_TRUE;
|
ctx->raw.mandatoryPrefix = prefix;
|
||||||
ctx->mandatoryPrefix = prefix;
|
|
||||||
break;
|
break;
|
||||||
case ZYDIS_INSTRUCTION_ENCODING_VEX:
|
case ZYDIS_INSTRUCTION_ENCODING_VEX:
|
||||||
ctx->raw.vex.pp = prefix;
|
ctx->raw.vex.pp = prefix;
|
||||||
|
@ -1104,18 +1112,19 @@ static ZydisStatus ZydisPrepareMandatoryPrefixes(ZydisEncoderContext* ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
static ZydisStatus ZydisAnalyzeRequirements(
|
static ZydisStatus ZydisAnalyzeRequirements(
|
||||||
ZydisEncoderContext* ctx, const ZydisEncoderRequest* req)
|
ZydisEncoderContext* ctx, const ZydisEncoderRequest* req, ZydisInstructionQuery* q)
|
||||||
{
|
{
|
||||||
ZYDIS_ASSERT(ctx);
|
ZYDIS_ASSERT(ctx);
|
||||||
ZYDIS_ASSERT(req);
|
ZYDIS_ASSERT(req);
|
||||||
|
ZYDIS_ASSERT(q);
|
||||||
|
|
||||||
// Walk list of requested operands, derive possible encodings
|
// Walk list of requested operands, derive possible encodings
|
||||||
// and perform additional sanity checks.
|
// and perform additional sanity checks.
|
||||||
ctx->require66 = ZYDIS_FALSE;
|
q->require66 = ZYDIS_FALSE;
|
||||||
ctx->require67 = ZYDIS_FALSE;
|
q->require67 = ZYDIS_FALSE;
|
||||||
ctx->requireREXW = ZYDIS_FALSE;
|
q->requireREXW = ZYDIS_FALSE;
|
||||||
ctx->eosz = req->machineMode;
|
q->eosz = req->machineMode;
|
||||||
ctx->easz = req->machineMode;
|
q->easz = req->machineMode;
|
||||||
for (uint8_t i = 0; i < req->operandCount; ++i)
|
for (uint8_t i = 0; i < req->operandCount; ++i)
|
||||||
{
|
{
|
||||||
const ZydisEncoderOperand* curReqOperand = req->operands + i;
|
const ZydisEncoderOperand* curReqOperand = req->operands + i;
|
||||||
|
@ -1126,32 +1135,32 @@ static ZydisStatus ZydisAnalyzeRequirements(
|
||||||
switch (ZydisRegisterGetClass(curReqOperand->reg))
|
switch (ZydisRegisterGetClass(curReqOperand->reg))
|
||||||
{
|
{
|
||||||
case ZYDIS_REGCLASS_GPR16:
|
case ZYDIS_REGCLASS_GPR16:
|
||||||
ctx->eosz = 16;
|
q->eosz = 16;
|
||||||
switch (req->machineMode)
|
switch (req->machineMode)
|
||||||
{
|
{
|
||||||
case 16: break; // Default mode.
|
case 16: break; // Default mode.
|
||||||
case 32:
|
case 32:
|
||||||
case 64: ctx->require66 = ZYDIS_TRUE; break;
|
case 64: q->require66 = ZYDIS_TRUE; break;
|
||||||
default: return ZYDIS_STATUS_INVALID_PARAMETER;
|
default: return ZYDIS_STATUS_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ZYDIS_REGCLASS_GPR32:
|
case ZYDIS_REGCLASS_GPR32:
|
||||||
ctx->eosz = 32;
|
q->eosz = 32;
|
||||||
switch (req->machineMode)
|
switch (req->machineMode)
|
||||||
{
|
{
|
||||||
case 16: ctx->require66 = ZYDIS_TRUE; break;
|
case 16: q->require66 = ZYDIS_TRUE; break;
|
||||||
case 32:
|
case 32:
|
||||||
case 64: break; // Default mode.
|
case 64: break; // Default mode.
|
||||||
default: return ZYDIS_STATUS_INVALID_PARAMETER;
|
default: return ZYDIS_STATUS_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ZYDIS_REGCLASS_GPR64:
|
case ZYDIS_REGCLASS_GPR64:
|
||||||
ctx->eosz = 64;
|
q->eosz = 64;
|
||||||
switch (req->machineMode)
|
switch (req->machineMode)
|
||||||
{
|
{
|
||||||
case 16:
|
case 16:
|
||||||
case 32: return ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION;
|
case 32: return ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION;
|
||||||
case 64: ctx->requireREXW = ZYDIS_TRUE; break;
|
case 64: q->requireREXW = ZYDIS_TRUE; break;
|
||||||
default: return ZYDIS_STATUS_INVALID_PARAMETER;
|
default: return ZYDIS_STATUS_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1175,27 +1184,27 @@ static ZydisStatus ZydisAnalyzeRequirements(
|
||||||
// Address size prefix required?
|
// Address size prefix required?
|
||||||
switch (baseRegClass)
|
switch (baseRegClass)
|
||||||
{
|
{
|
||||||
case ZYDIS_REGCLASS_GPR16: ctx->easz = 16; break;
|
case ZYDIS_REGCLASS_GPR16: q->easz = 16; break;
|
||||||
case ZYDIS_REGCLASS_GPR32: ctx->easz = 32; break;
|
case ZYDIS_REGCLASS_GPR32: q->easz = 32; break;
|
||||||
case ZYDIS_REGCLASS_GPR64: ctx->easz = 64; break;
|
case ZYDIS_REGCLASS_GPR64: q->easz = 64; break;
|
||||||
default:
|
default:
|
||||||
switch (baseRegClass)
|
switch (baseRegClass)
|
||||||
{
|
{
|
||||||
case ZYDIS_REGISTER_IP: ctx->easz = 16; break;
|
case ZYDIS_REGISTER_IP: q->easz = 16; break;
|
||||||
case ZYDIS_REGISTER_EIP: ctx->easz = 32; break;
|
case ZYDIS_REGISTER_EIP: q->easz = 32; break;
|
||||||
case ZYDIS_REGISTER_RIP: ctx->easz = 64; break;
|
case ZYDIS_REGISTER_RIP: q->easz = 64; break;
|
||||||
default:
|
default:
|
||||||
; // Other registers can't be address-scaled.
|
; // Other registers can't be address-scaled.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (ctx->easz)
|
switch (q->easz)
|
||||||
{
|
{
|
||||||
case 16:
|
case 16:
|
||||||
switch (ctx->req->machineMode)
|
switch (ctx->req->machineMode)
|
||||||
{
|
{
|
||||||
case 16: break; // Default mode.
|
case 16: break; // Default mode.
|
||||||
case 32: ctx->require67 = ZYDIS_TRUE; break;
|
case 32: q->require67 = ZYDIS_TRUE; break;
|
||||||
case 64: return ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION; // TODO
|
case 64: return ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION; // TODO
|
||||||
default: return ZYDIS_STATUS_INVALID_PARAMETER;
|
default: return ZYDIS_STATUS_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
@ -1203,9 +1212,9 @@ static ZydisStatus ZydisAnalyzeRequirements(
|
||||||
case 32:
|
case 32:
|
||||||
switch (ctx->req->machineMode)
|
switch (ctx->req->machineMode)
|
||||||
{
|
{
|
||||||
case 16: ctx->require67 = ZYDIS_TRUE; break;
|
case 16: q->require67 = ZYDIS_TRUE; break;
|
||||||
case 32: break; // Default mode.
|
case 32: break; // Default mode.
|
||||||
case 64: ctx->require67 = ZYDIS_TRUE; break;
|
case 64: q->require67 = ZYDIS_TRUE; break;
|
||||||
default: return ZYDIS_STATUS_INVALID_PARAMETER;
|
default: return ZYDIS_STATUS_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1221,7 +1230,7 @@ static ZydisStatus ZydisAnalyzeRequirements(
|
||||||
}
|
}
|
||||||
|
|
||||||
ZYDIS_CHECK(ZydisSemanticOperandTypeDeriveMask(
|
ZYDIS_CHECK(ZydisSemanticOperandTypeDeriveMask(
|
||||||
req->operands + i, ctx->semOperandTypeMasks + i
|
req->operands + i, q->semOperandTypeMasks + i
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1229,13 +1238,15 @@ static ZydisStatus ZydisAnalyzeRequirements(
|
||||||
}
|
}
|
||||||
|
|
||||||
static ZydisStatus ZydisFindMatchingDef(
|
static ZydisStatus ZydisFindMatchingDef(
|
||||||
ZydisEncoderContext* ctx, const ZydisEncoderRequest* req)
|
ZydisEncoderContext* ctx, const ZydisEncoderRequest* req, ZydisInstructionMatch* match)
|
||||||
{
|
{
|
||||||
ZYDIS_ASSERT(ctx);
|
ZYDIS_ASSERT(ctx);
|
||||||
ZYDIS_ASSERT(req);
|
ZYDIS_ASSERT(req);
|
||||||
|
ZYDIS_ASSERT(match);
|
||||||
|
|
||||||
// Evaluate request.
|
// Evaluate request.
|
||||||
ZYDIS_CHECK(ZydisAnalyzeRequirements(ctx, req));
|
ZydisInstructionQuery q;
|
||||||
|
ZYDIS_CHECK(ZydisAnalyzeRequirements(ctx, req, &q));
|
||||||
|
|
||||||
// Translate requested mode to flags.
|
// Translate requested mode to flags.
|
||||||
uint8_t modeFlag;
|
uint8_t modeFlag;
|
||||||
|
@ -1280,7 +1291,7 @@ static ZydisStatus ZydisFindMatchingDef(
|
||||||
if (curDefOperand->visibility == ZYDIS_OPERAND_VISIBILITY_HIDDEN) goto _nextInsn;
|
if (curDefOperand->visibility == ZYDIS_OPERAND_VISIBILITY_HIDDEN) goto _nextInsn;
|
||||||
|
|
||||||
// Is the type one of those we permit for the given operand?
|
// Is the type one of those we permit for the given operand?
|
||||||
if (!(1 << curDefOperand->type & ctx->semOperandTypeMasks[k])) goto _nextInsn;
|
if (!(1 << curDefOperand->type & q.semOperandTypeMasks[k])) goto _nextInsn;
|
||||||
|
|
||||||
// For some operand types, additional checks are required.
|
// For some operand types, additional checks are required.
|
||||||
switch (curDefOperand->type)
|
switch (curDefOperand->type)
|
||||||
|
@ -1352,7 +1363,7 @@ static ZydisStatus ZydisFindMatchingDef(
|
||||||
curDefOperand->op.encoding, req->machineMode, &eisz
|
curDefOperand->op.encoding, req->machineMode, &eisz
|
||||||
));
|
));
|
||||||
if (eisz < minSize) goto _nextInsn;
|
if (eisz < minSize) goto _nextInsn;
|
||||||
ctx->derivedImmSize[k] = eisz;
|
match->derivedImmSizes[k] = eisz;
|
||||||
} break;
|
} break;
|
||||||
default:
|
default:
|
||||||
; // No further checks required.
|
; // No further checks required.
|
||||||
|
@ -1367,10 +1378,10 @@ static ZydisStatus ZydisFindMatchingDef(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Still here? Looks like we found our instruction, then!
|
// Still here? Looks like we found our instruction, then!
|
||||||
ctx->matchingInsn = candidateInsn;
|
match->insn = candidateInsn;
|
||||||
ctx->matchingDef = candidateDef;
|
match->def = candidateDef;
|
||||||
ctx->matchingOperands = candidateOperands;
|
match->operands = candidateOperands;
|
||||||
ctx->matchingOperandCount = req->operandCount;
|
match->operandCount = req->operandCount;
|
||||||
return ZYDIS_STATUS_SUCCESS;
|
return ZYDIS_STATUS_SUCCESS;
|
||||||
|
|
||||||
_nextInsn:
|
_nextInsn:
|
||||||
|
@ -1462,34 +1473,35 @@ ZydisStatus ZydisEncoderEncodeInstruction(void* buffer, size_t* bufferLen,
|
||||||
|
|
||||||
// Mask out attributes that can't be set explicitly by user.
|
// Mask out attributes that can't be set explicitly by user.
|
||||||
// TODO: We should probably rather error on unsupported attrs.
|
// TODO: We should probably rather error on unsupported attrs.
|
||||||
ctx.derivedAttrs = request->attributes & ZYDIS_USER_ENCODABLE_ATTRIB_MASK;
|
ctx.raw.derivedAttrs = request->attributes & ZYDIS_USER_ENCODABLE_ATTRIB_MASK;
|
||||||
|
|
||||||
// Search matching instruction, collect information about what needs to be
|
// Search matching instruction, collect information about what needs to be
|
||||||
// encoded, what prefixes are required, etc.
|
// encoded, what prefixes are required, etc.
|
||||||
ZYDIS_CHECK(ZydisFindMatchingDef(&ctx, request));
|
ZydisInstructionMatch match;
|
||||||
ctx.raw.opcode = ctx.matchingInsn->opcode;
|
ZYDIS_CHECK(ZydisFindMatchingDef(&ctx, request, &match));
|
||||||
|
ctx.raw.opcode = match.insn->opcode;
|
||||||
|
|
||||||
// TODO: Check compatibility of requested prefixes to found instruction.
|
// TODO: Check compatibility of requested prefixes to found instruction.
|
||||||
|
|
||||||
// Prepare prefix bits.
|
// Prepare prefix bits.
|
||||||
ctx.raw.evex.B = ctx.matchingInsn->evexB;
|
ctx.raw.evex.B = match.insn->evexB;
|
||||||
ctx.raw.evex.L = ctx.matchingInsn->vectorLength & 0x01;
|
ctx.raw.evex.L = match.insn->vectorLength & 0x01;
|
||||||
ctx.raw.evex.L2 = ctx.matchingInsn->vectorLength & 0x02;
|
ctx.raw.evex.L2 = match.insn->vectorLength & 0x02;
|
||||||
ctx.raw.vex.L = ctx.matchingInsn->vectorLength & 0x01;
|
ctx.raw.vex.L = match.insn->vectorLength & 0x01;
|
||||||
if (ctx.matchingInsn->rexW)
|
if (match.insn->rexW)
|
||||||
{
|
{
|
||||||
ctx.raw.rex.W = 1;
|
ctx.raw.rex.W = 1;
|
||||||
ctx.derivedAttrs |= ZYDIS_ATTRIB_HAS_REX;
|
ctx.raw.derivedAttrs |= ZYDIS_ATTRIB_HAS_REX;
|
||||||
}
|
}
|
||||||
ZYDIS_CHECK(ZydisPrepareMandatoryPrefixes(&ctx));
|
ZYDIS_CHECK(ZydisPrepareMandatoryPrefixes(&ctx, &match));
|
||||||
|
|
||||||
// Prepare opcode.
|
// Prepare opcode.
|
||||||
ZYDIS_CHECK(ZydisPrepareOpcode(&ctx));
|
ZYDIS_CHECK(ZydisPrepareOpcode(&ctx, &match));
|
||||||
|
|
||||||
// Some instructions have additional opcode bits encoded in ModRM.reg.
|
// Some instructions have additional opcode bits encoded in ModRM.reg.
|
||||||
if (ctx.matchingInsn->modrmReg != 0xFF)
|
if (match.insn->modrmReg != 0xFF)
|
||||||
{
|
{
|
||||||
ctx.raw.modrm.reg = ctx.matchingInsn->modrmReg;
|
ctx.raw.modrm.reg = match.insn->modrmReg;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Analyze and prepare operands.
|
// Analyze and prepare operands.
|
||||||
|
@ -1499,16 +1511,16 @@ ZydisStatus ZydisEncoderEncodeInstruction(void* buffer, size_t* bufferLen,
|
||||||
return ZYDIS_STATUS_INVALID_PARAMETER;
|
return ZYDIS_STATUS_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint8_t i = 0; i < ctx.matchingDef->operandCount; ++i)
|
for (uint8_t i = 0; i < match.def->operandCount; ++i)
|
||||||
{
|
{
|
||||||
ZYDIS_CHECK(ZydisPrepareOperand(&ctx, i));
|
ZYDIS_CHECK(ZydisPrepareOperand(&ctx, &match, i));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do actual encoding work.
|
// Emit prepared raw instruction to bytestream.
|
||||||
ZYDIS_CHECK(ZydisEmitLegacyPrefixes(&ctx));
|
ZYDIS_CHECK(ZydisEmitLegacyPrefixes(&ctx));
|
||||||
if (ctx.derivedAttrs & ZYDIS_ATTRIB_HAS_REX) ZYDIS_CHECK(ZydisEmitREX(&ctx));
|
if (ctx.raw.derivedAttrs & ZYDIS_ATTRIB_HAS_REX) ZYDIS_CHECK(ZydisEmitREX(&ctx));
|
||||||
|
|
||||||
switch (ctx.matchingInsn->encoding)
|
switch (match.insn->encoding)
|
||||||
{
|
{
|
||||||
case ZYDIS_INSTRUCTION_ENCODING_EVEX: ZYDIS_CHECK(ZydisEmitEVEX(&ctx)); break;
|
case ZYDIS_INSTRUCTION_ENCODING_EVEX: ZYDIS_CHECK(ZydisEmitEVEX(&ctx)); break;
|
||||||
case ZYDIS_INSTRUCTION_ENCODING_VEX: ZYDIS_CHECK(ZydisEmitVEX (&ctx)); break;
|
case ZYDIS_INSTRUCTION_ENCODING_VEX: ZYDIS_CHECK(ZydisEmitVEX (&ctx)); break;
|
||||||
|
@ -1516,21 +1528,25 @@ ZydisStatus ZydisEncoderEncodeInstruction(void* buffer, size_t* bufferLen,
|
||||||
default:; // Shut up linter.
|
default:; // Shut up linter.
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx.emitMandatoryPrefix) ZYDIS_CHECK(ZydisEmitByte(&ctx, ctx.mandatoryPrefix));
|
if (ctx.raw.mandatoryPrefix) ZYDIS_CHECK(ZydisEmitByte(&ctx, ctx.raw.mandatoryPrefix));
|
||||||
|
|
||||||
for (uint8_t i = 0; i < ctx.opcodeMapPrefixLen; ++i)
|
for (uint8_t i = 0; i < ctx.raw.opcodeMapPrefixLen; ++i)
|
||||||
{
|
{
|
||||||
ZYDIS_CHECK(ZydisEmitByte(&ctx, ctx.opcodeMapPrefix[i]));
|
ZYDIS_CHECK(ZydisEmitByte(&ctx, ctx.raw.opcodeMapPrefix[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
ZYDIS_CHECK(ZydisEmitByte(&ctx, ctx.raw.opcode));
|
ZYDIS_CHECK(ZydisEmitByte(&ctx, ctx.raw.opcode));
|
||||||
|
|
||||||
if (ctx.derivedAttrs & ZYDIS_ATTRIB_HAS_MODRM) ZYDIS_CHECK(ZydisEmitModRM(&ctx));
|
if (ctx.raw.derivedAttrs & ZYDIS_ATTRIB_HAS_MODRM) ZYDIS_CHECK(ZydisEmitModRM(&ctx));
|
||||||
if (ctx.derivedAttrs & ZYDIS_ATTRIB_HAS_SIB ) ZYDIS_CHECK(ZydisEmitSIB (&ctx));
|
if (ctx.raw.derivedAttrs & ZYDIS_ATTRIB_HAS_SIB) ZYDIS_CHECK(ZydisEmitSIB(&ctx));
|
||||||
|
if (ctx.raw.disp.size) ZYDIS_CHECK(ZydisEmitImm(&ctx, ctx.raw.disp.val, ctx.raw.disp.size));
|
||||||
|
|
||||||
if (ctx.dispBitSize ) ZYDIS_CHECK(ZydisEmitImm(&ctx, ctx.disp, ctx.dispBitSize ));
|
for (uint8_t i = 0
|
||||||
if (ctx.immBitSizes[0]) ZYDIS_CHECK(ZydisEmitImm(&ctx, ctx.imms[0], ctx.immBitSizes[0]));
|
; i < ZYDIS_ARRAY_SIZE(ctx.raw.imms) && ctx.raw.imms[i].size
|
||||||
if (ctx.immBitSizes[1]) ZYDIS_CHECK(ZydisEmitImm(&ctx, ctx.imms[1], ctx.immBitSizes[1]));
|
; ++i)
|
||||||
|
{
|
||||||
|
ZYDIS_CHECK(ZydisEmitImm(&ctx, ctx.raw.imms[i].val, ctx.raw.imms[i].size));
|
||||||
|
}
|
||||||
|
|
||||||
*bufferLen = ctx.writeOffs;
|
*bufferLen = ctx.writeOffs;
|
||||||
return ZYDIS_STATUS_SUCCESS;
|
return ZYDIS_STATUS_SUCCESS;
|
||||||
|
|
Loading…
Reference in New Issue