mirror of https://github.com/x64dbg/zydis
More encoder progress
This commit is contained in:
parent
3498a33944
commit
743048852c
|
@ -61,6 +61,8 @@ extern "C" {
|
||||||
/* Structs */
|
/* Structs */
|
||||||
/* ============================================================================================== */
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
#define ZYDIS_ENCODER_MAX_OPERANDS (5)
|
||||||
|
|
||||||
typedef struct ZydisEncoderOperand_
|
typedef struct ZydisEncoderOperand_
|
||||||
{
|
{
|
||||||
ZydisOperandType type;
|
ZydisOperandType type;
|
||||||
|
@ -94,7 +96,7 @@ typedef struct ZydisEncoderRequest_
|
||||||
ZydisInstructionAttributes attributes;
|
ZydisInstructionAttributes attributes;
|
||||||
ZydisInstructionEncoding encoding;
|
ZydisInstructionEncoding encoding;
|
||||||
uint8_t operandCount;
|
uint8_t operandCount;
|
||||||
ZydisEncoderOperand operands[5];
|
ZydisEncoderOperand operands[ZYDIS_ENCODER_MAX_OPERANDS];
|
||||||
|
|
||||||
// TODO: AVX stuff
|
// TODO: AVX stuff
|
||||||
// TODO: MVEX stuff
|
// TODO: MVEX stuff
|
||||||
|
@ -119,7 +121,7 @@ ZYDIS_EXPORT ZydisStatus ZydisEncoderDecodedInstructionToRequest(
|
||||||
* @return A zydis status code.
|
* @return A zydis status code.
|
||||||
*/
|
*/
|
||||||
ZYDIS_EXPORT ZydisStatus ZydisEncoderEncodeInstruction(void* buffer, size_t* bufferLen,
|
ZYDIS_EXPORT ZydisStatus ZydisEncoderEncodeInstruction(void* buffer, size_t* bufferLen,
|
||||||
ZydisEncoderRequest* request);
|
const ZydisEncoderRequest* request);
|
||||||
|
|
||||||
/* ============================================================================================== */
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
|
256
src/Encoder.c
256
src/Encoder.c
|
@ -35,6 +35,8 @@
|
||||||
/* Internal context and table types */
|
/* Internal context and table types */
|
||||||
/* ============================================================================================== */
|
/* ============================================================================================== */
|
||||||
|
|
||||||
|
typedef uint32_t ZydisSemanticOperandTypeMask;
|
||||||
|
|
||||||
struct ZydisPrefixAcceptMapping
|
struct ZydisPrefixAcceptMapping
|
||||||
{
|
{
|
||||||
uint64_t has;
|
uint64_t has;
|
||||||
|
@ -71,11 +73,13 @@ typedef struct ZydisEncoderContext_
|
||||||
uint8_t* buffer;
|
uint8_t* buffer;
|
||||||
size_t bufferLen;
|
size_t bufferLen;
|
||||||
size_t writeOffs;
|
size_t writeOffs;
|
||||||
ZydisEncoderRequest* req;
|
const ZydisEncoderRequest* req;
|
||||||
const ZydisEncodableInstruction* matchingInsn;
|
const ZydisEncodableInstruction* matchingInsn;
|
||||||
const ZydisInstructionDefinition* matchingDef;
|
const ZydisInstructionDefinition* matchingDef;
|
||||||
uint8_t matchingOperandCount;
|
uint8_t matchingOperandCount;
|
||||||
const ZydisOperandDefinition* matchingOperands;
|
const ZydisOperandDefinition* matchingOperands;
|
||||||
|
|
||||||
|
ZydisInstructionAttributes derivedAttrs;
|
||||||
ZydisBool emitMandatoryPrefix;
|
ZydisBool emitMandatoryPrefix;
|
||||||
uint8_t mandatoryPrefix;
|
uint8_t mandatoryPrefix;
|
||||||
uint8_t dispBitSize;
|
uint8_t dispBitSize;
|
||||||
|
@ -498,7 +502,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->req->attributes |= ZYDIS_ATTRIB_HAS_REX;
|
if (topBit) ctx->derivedAttrs |= ZYDIS_ATTRIB_HAS_REX;
|
||||||
break;
|
break;
|
||||||
case ZYDIS_INSTRUCTION_ENCODING_VEX:
|
case ZYDIS_INSTRUCTION_ENCODING_VEX:
|
||||||
switch (topBitLoc)
|
switch (topBitLoc)
|
||||||
|
@ -569,28 +573,28 @@ static ZydisStatus ZydisPrepareSegmentPrefix(ZydisEncoderContext* ctx,
|
||||||
switch (segment)
|
switch (segment)
|
||||||
{
|
{
|
||||||
case ZYDIS_REGISTER_ES:
|
case ZYDIS_REGISTER_ES:
|
||||||
ctx->req->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_ES;
|
ctx->derivedAttrs |= ZYDIS_ATTRIB_HAS_SEGMENT_ES;
|
||||||
break;
|
break;
|
||||||
case ZYDIS_REGISTER_SS:
|
case ZYDIS_REGISTER_SS:
|
||||||
if (!ZydisIsStackReg(base))
|
if (!ZydisIsStackReg(base))
|
||||||
{
|
{
|
||||||
ctx->req->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_SS;
|
ctx->derivedAttrs |= ZYDIS_ATTRIB_HAS_SEGMENT_SS;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ZYDIS_REGISTER_CS:
|
case ZYDIS_REGISTER_CS:
|
||||||
ctx->req->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_CS;
|
ctx->derivedAttrs |= ZYDIS_ATTRIB_HAS_SEGMENT_CS;
|
||||||
break;
|
break;
|
||||||
case ZYDIS_REGISTER_DS:
|
case ZYDIS_REGISTER_DS:
|
||||||
if (ZydisIsStackReg(base))
|
if (ZydisIsStackReg(base))
|
||||||
{
|
{
|
||||||
ctx->req->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_DS;
|
ctx->derivedAttrs |= ZYDIS_ATTRIB_HAS_SEGMENT_DS;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ZYDIS_REGISTER_FS:
|
case ZYDIS_REGISTER_FS:
|
||||||
ctx->req->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_FS;
|
ctx->derivedAttrs |= ZYDIS_ATTRIB_HAS_SEGMENT_FS;
|
||||||
break;
|
break;
|
||||||
case ZYDIS_REGISTER_GS:
|
case ZYDIS_REGISTER_GS:
|
||||||
ctx->req->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_GS;
|
ctx->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.
|
||||||
|
@ -629,7 +633,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->req->attributes |= ZYDIS_ATTRIB_HAS_SIB;
|
ctx->derivedAttrs |= ZYDIS_ATTRIB_HAS_SIB;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ZYDIS_STATUS_SUCCESS;
|
return ZYDIS_STATUS_SUCCESS;
|
||||||
|
@ -657,7 +661,7 @@ static ZydisStatus ZydisPrepareMemoryOperand(ZydisEncoderContext* ctx,
|
||||||
|
|
||||||
if (operand->mem.base == ZYDIS_REGISTER_EIP)
|
if (operand->mem.base == ZYDIS_REGISTER_EIP)
|
||||||
{
|
{
|
||||||
ctx->req->attributes |= ZYDIS_ATTRIB_HAS_ADDRESSSIZE;
|
ctx->derivedAttrs |= ZYDIS_ATTRIB_HAS_ADDRESSSIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ZYDIS_STATUS_SUCCESS;
|
return ZYDIS_STATUS_SUCCESS;
|
||||||
|
@ -676,7 +680,7 @@ static ZydisStatus ZydisPrepareMemoryOperand(ZydisEncoderContext* ctx,
|
||||||
case 16:
|
case 16:
|
||||||
break; // Nothing to do.
|
break; // Nothing to do.
|
||||||
case 32:
|
case 32:
|
||||||
ctx->req->attributes |= ZYDIS_ATTRIB_HAS_ADDRESSSIZE;
|
ctx->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.
|
||||||
|
@ -693,7 +697,7 @@ static ZydisStatus ZydisPrepareMemoryOperand(ZydisEncoderContext* ctx,
|
||||||
case 32:
|
case 32:
|
||||||
break; // Nothing to do.
|
break; // Nothing to do.
|
||||||
case 64:
|
case 64:
|
||||||
ctx->req->attributes |= ZYDIS_ATTRIB_HAS_ADDRESSSIZE;
|
ctx->derivedAttrs |= ZYDIS_ATTRIB_HAS_ADDRESSSIZE;
|
||||||
default:
|
default:
|
||||||
return ZYDIS_STATUS_INVALID_PARAMETER; // TODO
|
return ZYDIS_STATUS_INVALID_PARAMETER; // TODO
|
||||||
}
|
}
|
||||||
|
@ -741,7 +745,7 @@ static ZydisStatus ZydisPrepareMemoryOperand(ZydisEncoderContext* ctx,
|
||||||
ctx->raw.sib.index = 0x04 /* no index */;
|
ctx->raw.sib.index = 0x04 /* no index */;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx->req->attributes |= ZYDIS_ATTRIB_HAS_SIB;
|
ctx->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?
|
||||||
|
@ -811,7 +815,7 @@ static ZydisStatus ZydisPrepareOperand(ZydisEncoderContext* ctx,
|
||||||
ctx->raw.modrm.mod = 0x03 /* reg */;
|
ctx->raw.modrm.mod = 0x03 /* reg */;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx->req->attributes |= ZYDIS_ATTRIB_HAS_MODRM;
|
ctx->derivedAttrs |= ZYDIS_ATTRIB_HAS_MODRM;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ZYDIS_OPERAND_ENCODING_OPCODE:
|
case ZYDIS_OPERAND_ENCODING_OPCODE:
|
||||||
|
@ -820,7 +824,7 @@ static ZydisStatus ZydisPrepareOperand(ZydisEncoderContext* ctx,
|
||||||
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->req->attributes |= ZYDIS_ATTRIB_HAS_REX;
|
if (ctx->raw.rex.B) ctx->derivedAttrs |= ZYDIS_ATTRIB_HAS_REX;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ZYDIS_OPERAND_ENCODING_NDSNDD:
|
case ZYDIS_OPERAND_ENCODING_NDSNDD:
|
||||||
|
@ -902,16 +906,95 @@ static ZydisStatus ZydisPrepareMandatoryPrefixes(ZydisEncoderContext* ctx)
|
||||||
return ZYDIS_STATUS_SUCCESS;
|
return ZYDIS_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ZydisStatus ZydisDetermineInstructionEncoding(ZydisEncoderRequest* ctx)
|
static ZydisStatus ZydisDeriveSemanticOperandTypeMask(
|
||||||
|
ZydisEncoderContext* ctx, const ZydisEncoderOperand* op,
|
||||||
|
ZydisSemanticOperandTypeMask* mask)
|
||||||
{
|
{
|
||||||
|
ZYDIS_ASSERT(op);
|
||||||
ZYDIS_ASSERT(ctx);
|
ZYDIS_ASSERT(ctx);
|
||||||
|
ZYDIS_ASSERT(mask);
|
||||||
|
|
||||||
for (const ZydisEncoderOperand *op = ctx->operands,
|
switch (op->type)
|
||||||
*end = ctx->operands + ctx->operandCount
|
|
||||||
; op < end
|
|
||||||
; ++op)
|
|
||||||
{
|
{
|
||||||
|
case ZYDIS_OPERAND_TYPE_REGISTER:
|
||||||
|
switch (ZydisRegisterGetClass(op->reg))
|
||||||
|
{
|
||||||
|
case ZYDIS_REGCLASS_GPR8:
|
||||||
|
*mask = 1 << ZYDIS_SEMANTIC_OPTYPE_GPR8;
|
||||||
|
break;
|
||||||
|
case ZYDIS_REGCLASS_GPR16:
|
||||||
|
*mask = 1 << ZYDIS_SEMANTIC_OPTYPE_GPR16 |
|
||||||
|
1 << ZYDIS_SEMANTIC_OPTYPE_GPR16_32_32 |
|
||||||
|
1 << ZYDIS_SEMANTIC_OPTYPE_GPR16_32_32;
|
||||||
|
break;
|
||||||
|
case ZYDIS_REGCLASS_GPR32:
|
||||||
|
*mask = 1 << ZYDIS_SEMANTIC_OPTYPE_GPR32 |
|
||||||
|
1 << ZYDIS_SEMANTIC_OPTYPE_GPR16_32_64 |
|
||||||
|
1 << ZYDIS_SEMANTIC_OPTYPE_GPR32_32_64 |
|
||||||
|
1 << ZYDIS_SEMANTIC_OPTYPE_GPR16_32_32;
|
||||||
|
break;
|
||||||
|
case ZYDIS_REGCLASS_GPR64:
|
||||||
|
*mask = 1 << ZYDIS_SEMANTIC_OPTYPE_GPR64 |
|
||||||
|
1 << ZYDIS_SEMANTIC_OPTYPE_GPR16_32_64 |
|
||||||
|
1 << ZYDIS_SEMANTIC_OPTYPE_GPR32_32_64;
|
||||||
|
break;
|
||||||
|
case ZYDIS_REGCLASS_X87:
|
||||||
|
*mask = 1 << ZYDIS_SEMANTIC_OPTYPE_FPR;
|
||||||
|
break;
|
||||||
|
case ZYDIS_REGCLASS_MMX:
|
||||||
|
*mask = 1 << ZYDIS_SEMANTIC_OPTYPE_MMX;
|
||||||
|
break;
|
||||||
|
case ZYDIS_REGCLASS_XMM:
|
||||||
|
*mask = 1 << ZYDIS_SEMANTIC_OPTYPE_XMM;
|
||||||
|
break;
|
||||||
|
case ZYDIS_REGCLASS_YMM:
|
||||||
|
*mask = 1 << ZYDIS_SEMANTIC_OPTYPE_YMM;
|
||||||
|
break;
|
||||||
|
case ZYDIS_REGCLASS_ZMM:
|
||||||
|
*mask = 1 << ZYDIS_SEMANTIC_OPTYPE_ZMM;
|
||||||
|
break;
|
||||||
|
case ZYDIS_REGCLASS_FLAGS:
|
||||||
|
case ZYDIS_REGCLASS_IP:
|
||||||
|
return ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION; // TODO
|
||||||
|
case ZYDIS_REGCLASS_SEGMENT:
|
||||||
|
*mask = 1 << ZYDIS_SEMANTIC_OPTYPE_SREG;
|
||||||
|
break;
|
||||||
|
case ZYDIS_REGCLASS_TEST:
|
||||||
|
// TODO
|
||||||
|
ZYDIS_UNREACHABLE;
|
||||||
|
case ZYDIS_REGCLASS_CONTROL:
|
||||||
|
*mask = 1 << ZYDIS_SEMANTIC_OPTYPE_CR;
|
||||||
|
break;
|
||||||
|
case ZYDIS_REGCLASS_DEBUG:
|
||||||
|
*mask = 1 << ZYDIS_SEMANTIC_OPTYPE_DR;
|
||||||
|
break;
|
||||||
|
case ZYDIS_REGCLASS_MASK:
|
||||||
|
*mask = 1 << ZYDIS_SEMANTIC_OPTYPE_MASK;
|
||||||
|
break;
|
||||||
|
case ZYDIS_REGCLASS_BOUND:
|
||||||
|
*mask = 1 << ZYDIS_SEMANTIC_OPTYPE_BND;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ZYDIS_UNREACHABLE;
|
||||||
|
}
|
||||||
|
*mask |= ZYDIS_SEMANTIC_OPTYPE_IMPLICIT_REG;
|
||||||
|
break;
|
||||||
|
case ZYDIS_OPERAND_TYPE_MEMORY:
|
||||||
|
*mask = 1 << ZYDIS_SEMANTIC_OPTYPE_MEM |
|
||||||
|
1 << ZYDIS_SEMANTIC_OPTYPE_MEM_VSIBX |
|
||||||
|
1 << ZYDIS_SEMANTIC_OPTYPE_MEM_VSIBY |
|
||||||
|
1 << ZYDIS_SEMANTIC_OPTYPE_MEM_VSIBZ |
|
||||||
|
1 << ZYDIS_SEMANTIC_OPTYPE_IMPLICIT_MEM;
|
||||||
|
break;
|
||||||
|
case ZYDIS_OPERAND_TYPE_POINTER:
|
||||||
|
*mask = 1 << ZYDIS_SEMANTIC_OPTYPE_PTR;
|
||||||
|
break;
|
||||||
|
case ZYDIS_OPERAND_TYPE_IMMEDIATE:
|
||||||
|
*mask = 1 << ZYDIS_SEMANTIC_OPTYPE_IMM |
|
||||||
|
1 << ZYDIS_SEMANTIC_OPTYPE_IMPLICIT_IMM1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return ZYDIS_STATUS_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ZYDIS_STATUS_SUCCESS;
|
return ZYDIS_STATUS_SUCCESS;
|
||||||
|
@ -933,15 +1016,66 @@ static ZydisStatus ZydisFindMatchingDef(
|
||||||
default: return ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION; // TODO
|
default: return ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION; // TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Walk list of requested operands, derive possible encodings
|
||||||
|
// and perform additional sanity checks.
|
||||||
|
ZydisSemanticOperandTypeMask semOperandTypeMasks[ZYDIS_ENCODER_MAX_OPERANDS];
|
||||||
|
ZydisBool requireOperandSizeOverride = ZYDIS_FALSE;
|
||||||
|
//ZydisBool requireAddressSizeOverride = ZYDIS_FALSE;
|
||||||
|
for (uint8_t i = 0; i < req->operandCount; ++i)
|
||||||
|
{
|
||||||
|
const ZydisEncoderOperand* curReqOperand = req->operands + i;
|
||||||
|
if (curReqOperand->type == ZYDIS_OPERAND_TYPE_REGISTER)
|
||||||
|
{
|
||||||
|
switch (ZydisRegisterGetClass(curReqOperand->reg))
|
||||||
|
{
|
||||||
|
case ZYDIS_REGCLASS_GPR16:
|
||||||
|
switch (req->machineMode)
|
||||||
|
{
|
||||||
|
case 16: break; // Nothing to do.
|
||||||
|
case 32:
|
||||||
|
case 64: requireOperandSizeOverride = ZYDIS_TRUE; break;
|
||||||
|
default: return ZYDIS_STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ZYDIS_REGCLASS_GPR32:
|
||||||
|
switch (req->machineMode)
|
||||||
|
{
|
||||||
|
case 16: return ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION;
|
||||||
|
case 32:
|
||||||
|
case 64: break; // Nothing to do.
|
||||||
|
default: return ZYDIS_STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ZYDIS_REGCLASS_GPR64:
|
||||||
|
switch (req->machineMode)
|
||||||
|
{
|
||||||
|
case 16:
|
||||||
|
case 32: return ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION;
|
||||||
|
case 64: break;
|
||||||
|
default: return ZYDIS_STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
; // Don't care.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ZYDIS_CHECK(ZydisDeriveSemanticOperandTypeMask(
|
||||||
|
ctx, req->operands + i, semOperandTypeMasks + i
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
// Walk list of candidates.
|
// Walk list of candidates.
|
||||||
const ZydisEncodableInstruction* insns = NULL;
|
const ZydisEncodableInstruction* insns = NULL;
|
||||||
uint8_t insnCount = ZydisGetEncodableInstructions(req->mnemonic, &insns);
|
uint8_t insnCount = ZydisGetEncodableInstructions(req->mnemonic, &insns);
|
||||||
if (!insnCount) return ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION; // TODO
|
if (!insnCount) return ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION; // TODO
|
||||||
ZYDIS_ASSERT(insns);
|
ZYDIS_ASSERT(insns);
|
||||||
|
|
||||||
for (uint8_t i = 0; i < insnCount; ++i)
|
for (const ZydisEncodableInstruction *candidateInsn = insns,
|
||||||
|
*insnsEnd = insns + insnCount
|
||||||
|
; candidateInsn < insnsEnd
|
||||||
|
; ++candidateInsn)
|
||||||
{
|
{
|
||||||
const ZydisEncodableInstruction* candidateInsn = insns + i;
|
|
||||||
if (!(candidateInsn->mode & modeFlag)) goto _nextInsn;
|
if (!(candidateInsn->mode & modeFlag)) goto _nextInsn;
|
||||||
|
|
||||||
const ZydisInstructionDefinition* candidateDef = NULL;
|
const ZydisInstructionDefinition* candidateDef = NULL;
|
||||||
|
@ -999,11 +1133,53 @@ static ZydisStatus ZydisFindMatchingDef(
|
||||||
ZydisStatus ZydisEncoderDecodedInstructionToRequest(
|
ZydisStatus ZydisEncoderDecodedInstructionToRequest(
|
||||||
const ZydisDecodedInstruction* in, ZydisEncoderRequest* out)
|
const ZydisDecodedInstruction* in, ZydisEncoderRequest* out)
|
||||||
{
|
{
|
||||||
ZYDIS_ASSERT(in);
|
if (!in || !out || in->operandCount > ZYDIS_ARRAY_SIZE(in->operands))
|
||||||
ZYDIS_ASSERT(out);
|
{
|
||||||
|
return ZYDIS_STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
(void) in; (void) out;
|
out->machineMode = in->machineMode;
|
||||||
// TODO
|
out->mnemonic = in->mnemonic;
|
||||||
|
out->attributes = in->attributes;
|
||||||
|
out->encoding = in->encoding;
|
||||||
|
out->operandCount = 0;
|
||||||
|
|
||||||
|
for (uint8_t iIn = 0
|
||||||
|
; iIn < in->operandCount && out->operandCount < ZYDIS_ARRAY_SIZE(out->operands)
|
||||||
|
; ++iIn)
|
||||||
|
{
|
||||||
|
const ZydisDecodedOperand* inOp = in->operands + iIn;
|
||||||
|
ZydisEncoderOperand* outOp = out->operands + out->operandCount;
|
||||||
|
if (inOp->visibility == ZYDIS_OPERAND_VISIBILITY_HIDDEN) continue;
|
||||||
|
|
||||||
|
outOp->type = inOp->type;
|
||||||
|
switch (inOp->type)
|
||||||
|
{
|
||||||
|
case ZYDIS_OPERAND_TYPE_REGISTER:
|
||||||
|
outOp->reg = inOp->reg;
|
||||||
|
break;
|
||||||
|
case ZYDIS_OPERAND_TYPE_MEMORY:
|
||||||
|
outOp->mem.segment = inOp->mem.segment;
|
||||||
|
outOp->mem.base = inOp->mem.base;
|
||||||
|
outOp->mem.index = inOp->mem.index;
|
||||||
|
outOp->mem.scale = inOp->mem.scale;
|
||||||
|
outOp->mem.disp = inOp->mem.disp.value;
|
||||||
|
outOp->mem.dispSize = in->raw.disp.size;
|
||||||
|
break;
|
||||||
|
case ZYDIS_OPERAND_TYPE_POINTER:
|
||||||
|
outOp->ptr.segment = inOp->ptr.segment;
|
||||||
|
outOp->ptr.offset = inOp->ptr.offset;
|
||||||
|
break;
|
||||||
|
case ZYDIS_OPERAND_TYPE_IMMEDIATE:
|
||||||
|
outOp->imm.u = inOp->imm.value.u;
|
||||||
|
outOp->immSize = in->raw.imm->size;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return ZYDIS_STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
++out->operandCount;
|
||||||
|
}
|
||||||
|
|
||||||
return ZYDIS_STATUS_SUCCESS;
|
return ZYDIS_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -1011,7 +1187,7 @@ ZydisStatus ZydisEncoderDecodedInstructionToRequest(
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ZydisStatus ZydisEncoderEncodeInstruction(void* buffer, size_t* bufferLen,
|
ZydisStatus ZydisEncoderEncodeInstruction(void* buffer, size_t* bufferLen,
|
||||||
ZydisEncoderRequest* request)
|
const ZydisEncoderRequest* request)
|
||||||
{
|
{
|
||||||
if (!request || !bufferLen || request->operandCount > ZYDIS_ARRAY_SIZE(request->operands))
|
if (!request || !bufferLen || request->operandCount > ZYDIS_ARRAY_SIZE(request->operands))
|
||||||
{
|
{
|
||||||
|
@ -1028,7 +1204,7 @@ ZydisStatus ZydisEncoderEncodeInstruction(void* buffer, size_t* bufferLen,
|
||||||
*bufferLen = 0;
|
*bufferLen = 0;
|
||||||
|
|
||||||
// Mask out attributes that can't be set explicitly by user.
|
// Mask out attributes that can't be set explicitly by user.
|
||||||
request->attributes &= ZYDIS_USER_ENCODABLE_ATTRIB_MASK;
|
ctx.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.
|
||||||
|
@ -1054,13 +1230,13 @@ ZydisStatus ZydisEncoderEncodeInstruction(void* buffer, size_t* bufferLen,
|
||||||
switch (ctx.matchingInsn->encoding)
|
switch (ctx.matchingInsn->encoding)
|
||||||
{
|
{
|
||||||
case ZYDIS_INSTRUCTION_ENCODING_EVEX:
|
case ZYDIS_INSTRUCTION_ENCODING_EVEX:
|
||||||
request->attributes |= ZYDIS_ATTRIB_HAS_EVEX;
|
ctx.derivedAttrs |= ZYDIS_ATTRIB_HAS_EVEX;
|
||||||
break;
|
break;
|
||||||
case ZYDIS_INSTRUCTION_ENCODING_VEX:
|
case ZYDIS_INSTRUCTION_ENCODING_VEX:
|
||||||
request->attributes |= ZYDIS_ATTRIB_HAS_VEX;
|
ctx.derivedAttrs |= ZYDIS_ATTRIB_HAS_VEX;
|
||||||
break;
|
break;
|
||||||
case ZYDIS_INSTRUCTION_ENCODING_XOP:
|
case ZYDIS_INSTRUCTION_ENCODING_XOP:
|
||||||
request->attributes |= ZYDIS_ATTRIB_HAS_XOP;
|
ctx.derivedAttrs |= ZYDIS_ATTRIB_HAS_XOP;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ZYDIS_UNREACHABLE;
|
ZYDIS_UNREACHABLE;
|
||||||
|
@ -1074,7 +1250,7 @@ ZydisStatus ZydisEncoderEncodeInstruction(void* buffer, size_t* bufferLen,
|
||||||
if (ctx.matchingInsn->rexW)
|
if (ctx.matchingInsn->rexW)
|
||||||
{
|
{
|
||||||
ctx.raw.rex.W = 1;
|
ctx.raw.rex.W = 1;
|
||||||
request->attributes |= ZYDIS_ATTRIB_HAS_REX;
|
ctx.derivedAttrs |= ZYDIS_ATTRIB_HAS_REX;
|
||||||
}
|
}
|
||||||
ZYDIS_CHECK(ZydisPrepareMandatoryPrefixes(&ctx));
|
ZYDIS_CHECK(ZydisPrepareMandatoryPrefixes(&ctx));
|
||||||
|
|
||||||
|
@ -1101,13 +1277,13 @@ ZydisStatus ZydisEncoderEncodeInstruction(void* buffer, size_t* bufferLen,
|
||||||
// &ctx.matchingDef->operands[i]
|
// &ctx.matchingDef->operands[i]
|
||||||
// ));
|
// ));
|
||||||
//}
|
//}
|
||||||
//
|
|
||||||
// Do actual encoding work.
|
// Do actual encoding work.
|
||||||
ZYDIS_CHECK(ZydisEmitLegacyPrefixes(&ctx));
|
ZYDIS_CHECK(ZydisEmitLegacyPrefixes(&ctx));
|
||||||
if (request->attributes & ZYDIS_ATTRIB_HAS_REX ) ZYDIS_CHECK(ZydisEmitREX (&ctx));
|
if (ctx.derivedAttrs & ZYDIS_ATTRIB_HAS_REX ) ZYDIS_CHECK(ZydisEmitREX (&ctx));
|
||||||
if (request->attributes & ZYDIS_ATTRIB_HAS_VEX ) ZYDIS_CHECK(ZydisEmitVEX (&ctx));
|
if (ctx.derivedAttrs & ZYDIS_ATTRIB_HAS_VEX ) ZYDIS_CHECK(ZydisEmitVEX (&ctx));
|
||||||
if (request->attributes & ZYDIS_ATTRIB_HAS_EVEX ) ZYDIS_CHECK(ZydisEmitEVEX (&ctx));
|
if (ctx.derivedAttrs & ZYDIS_ATTRIB_HAS_EVEX ) ZYDIS_CHECK(ZydisEmitEVEX (&ctx));
|
||||||
if (request->attributes & ZYDIS_ATTRIB_HAS_XOP ) ZYDIS_CHECK(ZydisEmitXOP (&ctx));
|
if (ctx.derivedAttrs & ZYDIS_ATTRIB_HAS_XOP ) ZYDIS_CHECK(ZydisEmitXOP (&ctx));
|
||||||
|
|
||||||
if (ctx.emitMandatoryPrefix) ZYDIS_CHECK(ZydisEmitByte(&ctx, ctx.mandatoryPrefix));
|
if (ctx.emitMandatoryPrefix) ZYDIS_CHECK(ZydisEmitByte(&ctx, ctx.mandatoryPrefix));
|
||||||
|
|
||||||
|
@ -1118,8 +1294,8 @@ ZydisStatus ZydisEncoderEncodeInstruction(void* buffer, size_t* bufferLen,
|
||||||
|
|
||||||
ZYDIS_CHECK(ZydisEmitByte(&ctx, ctx.raw.opcode));
|
ZYDIS_CHECK(ZydisEmitByte(&ctx, ctx.raw.opcode));
|
||||||
|
|
||||||
if (request->attributes & ZYDIS_ATTRIB_HAS_MODRM) ZYDIS_CHECK(ZydisEmitModRM(&ctx));
|
if (ctx.derivedAttrs & ZYDIS_ATTRIB_HAS_MODRM) ZYDIS_CHECK(ZydisEmitModRM(&ctx));
|
||||||
if (request->attributes & ZYDIS_ATTRIB_HAS_SIB ) ZYDIS_CHECK(ZydisEmitSIB (&ctx));
|
if (ctx.derivedAttrs & ZYDIS_ATTRIB_HAS_SIB ) ZYDIS_CHECK(ZydisEmitSIB (&ctx));
|
||||||
|
|
||||||
if (ctx.dispBitSize ) ZYDIS_CHECK(ZydisEmitImm(&ctx, ctx.disp, ctx.dispBitSize ));
|
if (ctx.dispBitSize ) ZYDIS_CHECK(ZydisEmitImm(&ctx, ctx.disp, ctx.dispBitSize ));
|
||||||
if (ctx.immBitSizes[0]) ZYDIS_CHECK(ZydisEmitImm(&ctx, ctx.imms[0], ctx.immBitSizes[0]));
|
if (ctx.immBitSizes[0]) ZYDIS_CHECK(ZydisEmitImm(&ctx, ctx.imms[0], ctx.immBitSizes[0]));
|
||||||
|
|
Loading…
Reference in New Issue