mirror of https://github.com/x64dbg/zydis
Merge branch 'develop' of github.com:zyantific/zyan-disassembler-engine into develop
This commit is contained in:
commit
9e15ecc5f1
175
src/Encoder.c
175
src/Encoder.c
|
@ -538,7 +538,7 @@ static ZydisStatus ZydisPrepareRegOperand(ZydisEncoderContext* ctx,
|
||||||
return ZYDIS_STATUS_SUCCESS;
|
return ZYDIS_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ZydisBool ZydisIsBPReg(ZydisRegister reg)
|
static ZydisBool ZydisRegIsBP(ZydisRegister reg)
|
||||||
{
|
{
|
||||||
return reg == ZYDIS_REGISTER_BPL ||
|
return reg == ZYDIS_REGISTER_BPL ||
|
||||||
reg == ZYDIS_REGISTER_BP ||
|
reg == ZYDIS_REGISTER_BP ||
|
||||||
|
@ -546,7 +546,7 @@ static ZydisBool ZydisIsBPReg(ZydisRegister reg)
|
||||||
reg == ZYDIS_REGISTER_RBP;
|
reg == ZYDIS_REGISTER_RBP;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ZydisBool ZydisIsSPReg(ZydisRegister reg)
|
static ZydisBool ZydisRegIsSP(ZydisRegister reg)
|
||||||
{
|
{
|
||||||
return reg == ZYDIS_REGISTER_SPL ||
|
return reg == ZYDIS_REGISTER_SPL ||
|
||||||
reg == ZYDIS_REGISTER_SP ||
|
reg == ZYDIS_REGISTER_SP ||
|
||||||
|
@ -554,16 +554,23 @@ static ZydisBool ZydisIsSPReg(ZydisRegister reg)
|
||||||
reg == ZYDIS_REGISTER_RSP;
|
reg == ZYDIS_REGISTER_RSP;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ZydisBool ZydisIsIPReg(ZydisRegister reg)
|
static ZydisBool ZydisRegIsIP(ZydisRegister reg)
|
||||||
{
|
{
|
||||||
return reg == ZYDIS_REGISTER_IP ||
|
return reg == ZYDIS_REGISTER_IP ||
|
||||||
reg == ZYDIS_REGISTER_EIP ||
|
reg == ZYDIS_REGISTER_EIP ||
|
||||||
reg == ZYDIS_REGISTER_RIP;
|
reg == ZYDIS_REGISTER_RIP;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ZydisBool ZydisIsStackReg(ZydisRegister reg)
|
static ZydisBool ZydisRegIsStack(ZydisRegister reg)
|
||||||
{
|
{
|
||||||
return ZydisIsSPReg(reg) || ZydisIsBPReg(reg);
|
return ZydisRegIsSP(reg) || ZydisRegIsBP(reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ZydisBool ZydisSemanticTypeIsImplicit(ZydisSemanticOperandType type)
|
||||||
|
{
|
||||||
|
return type == ZYDIS_SEMANTIC_OPTYPE_IMPLICIT_REG ||
|
||||||
|
type == ZYDIS_SEMANTIC_OPTYPE_IMPLICIT_MEM ||
|
||||||
|
type == ZYDIS_SEMANTIC_OPTYPE_IMPLICIT_IMM1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ZydisStatus ZydisPrepareSegmentPrefix(ZydisEncoderContext* ctx,
|
static ZydisStatus ZydisPrepareSegmentPrefix(ZydisEncoderContext* ctx,
|
||||||
|
@ -576,7 +583,7 @@ static ZydisStatus ZydisPrepareSegmentPrefix(ZydisEncoderContext* ctx,
|
||||||
ctx->derivedAttrs |= 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 (!ZydisRegIsStack(base))
|
||||||
{
|
{
|
||||||
ctx->derivedAttrs |= ZYDIS_ATTRIB_HAS_SEGMENT_SS;
|
ctx->derivedAttrs |= ZYDIS_ATTRIB_HAS_SEGMENT_SS;
|
||||||
}
|
}
|
||||||
|
@ -585,7 +592,7 @@ static ZydisStatus ZydisPrepareSegmentPrefix(ZydisEncoderContext* ctx,
|
||||||
ctx->derivedAttrs |= 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 (ZydisRegIsStack(base))
|
||||||
{
|
{
|
||||||
ctx->derivedAttrs |= ZYDIS_ATTRIB_HAS_SEGMENT_DS;
|
ctx->derivedAttrs |= ZYDIS_ATTRIB_HAS_SEGMENT_DS;
|
||||||
}
|
}
|
||||||
|
@ -604,12 +611,11 @@ static ZydisStatus ZydisPrepareSegmentPrefix(ZydisEncoderContext* ctx,
|
||||||
}
|
}
|
||||||
|
|
||||||
static ZydisStatus ZydisPrepareMemoryOperand(ZydisEncoderContext* ctx,
|
static ZydisStatus ZydisPrepareMemoryOperand(ZydisEncoderContext* ctx,
|
||||||
ZydisEncoderOperand* operand, const ZydisOperandDefinition* operandDef)
|
ZydisEncoderOperand* operand)
|
||||||
{
|
{
|
||||||
ZYDIS_ASSERT(ctx);
|
ZYDIS_ASSERT(ctx);
|
||||||
ZYDIS_ASSERT(ctx->req);
|
ZYDIS_ASSERT(ctx->req);
|
||||||
ZYDIS_ASSERT(operand);
|
ZYDIS_ASSERT(operand);
|
||||||
ZYDIS_ASSERT(operandDef);
|
|
||||||
|
|
||||||
ZYDIS_CHECK(ZydisPrepareSegmentPrefix(ctx, operand->mem.segment, operand->mem.base));
|
ZYDIS_CHECK(ZydisPrepareSegmentPrefix(ctx, operand->mem.segment, operand->mem.base));
|
||||||
|
|
||||||
|
@ -640,7 +646,7 @@ static ZydisStatus ZydisPrepareMemoryOperand(ZydisEncoderContext* ctx,
|
||||||
}
|
}
|
||||||
|
|
||||||
// rIP relative addressing? Special case.
|
// rIP relative addressing? Special case.
|
||||||
if (ZydisIsIPReg(operand->mem.base))
|
if (ZydisRegIsIP(operand->mem.base))
|
||||||
{
|
{
|
||||||
// rIP addressing is only available since AMD64.
|
// rIP addressing is only available since AMD64.
|
||||||
if (ctx->req->machineMode != 64)
|
if (ctx->req->machineMode != 64)
|
||||||
|
@ -713,7 +719,7 @@ static ZydisStatus ZydisPrepareMemoryOperand(ZydisEncoderContext* ctx,
|
||||||
}
|
}
|
||||||
|
|
||||||
// SIB byte required? rSP can only be encoded with SIB.
|
// SIB byte required? rSP can only be encoded with SIB.
|
||||||
if (operand->mem.index || operand->mem.scale || ZydisIsSPReg(operand->mem.base))
|
if (operand->mem.index || operand->mem.scale || ZydisRegIsSP(operand->mem.base))
|
||||||
{
|
{
|
||||||
// Translate scale to SIB format.
|
// Translate scale to SIB format.
|
||||||
switch (operand->mem.scale)
|
switch (operand->mem.scale)
|
||||||
|
@ -751,7 +757,7 @@ static ZydisStatus ZydisPrepareMemoryOperand(ZydisEncoderContext* ctx,
|
||||||
// Has displacement or is rBP and we have no SIB?
|
// Has displacement or is rBP and we have no SIB?
|
||||||
// rBP can't be ModRM-encoded without a disp.
|
// rBP can't be ModRM-encoded without a disp.
|
||||||
if (operand->mem.disp || (!(ctx->req->attributes & ZYDIS_ATTRIB_HAS_SIB)
|
if (operand->mem.disp || (!(ctx->req->attributes & ZYDIS_ATTRIB_HAS_SIB)
|
||||||
&& ZydisIsBPReg(operand->mem.base)))
|
&& ZydisRegIsBP(operand->mem.base)))
|
||||||
{
|
{
|
||||||
ctx->dispBitSize = 32;
|
ctx->dispBitSize = 32;
|
||||||
ctx->raw.modrm.mod = 0x02 /* 32 bit disp */;
|
ctx->raw.modrm.mod = 0x02 /* 32 bit disp */;
|
||||||
|
@ -772,9 +778,7 @@ static ZydisStatus ZydisPrepareOperand(ZydisEncoderContext* ctx,
|
||||||
ZYDIS_ASSERT(ctx);
|
ZYDIS_ASSERT(ctx);
|
||||||
ZYDIS_ASSERT(operand);
|
ZYDIS_ASSERT(operand);
|
||||||
ZYDIS_ASSERT(operandDef);
|
ZYDIS_ASSERT(operandDef);
|
||||||
ZYDIS_ASSERT(operandDef->type != ZYDIS_SEMANTIC_OPTYPE_IMPLICIT_REG);
|
ZYDIS_ASSERT(!ZydisSemanticTypeIsImplicit(operandDef->type));
|
||||||
ZYDIS_ASSERT(operandDef->type != ZYDIS_SEMANTIC_OPTYPE_IMPLICIT_MEM);
|
|
||||||
ZYDIS_ASSERT(operandDef->type != ZYDIS_SEMANTIC_OPTYPE_IMPLICIT_IMM1);
|
|
||||||
|
|
||||||
switch (operandDef->op.encoding)
|
switch (operandDef->op.encoding)
|
||||||
{
|
{
|
||||||
|
@ -806,7 +810,7 @@ static ZydisStatus ZydisPrepareOperand(ZydisEncoderContext* ctx,
|
||||||
// Memory operand?
|
// Memory operand?
|
||||||
if (operand->type == ZYDIS_OPERAND_TYPE_MEMORY)
|
if (operand->type == ZYDIS_OPERAND_TYPE_MEMORY)
|
||||||
{
|
{
|
||||||
ZYDIS_CHECK(ZydisPrepareMemoryOperand(ctx, operand, operandDef));
|
ZYDIS_CHECK(ZydisPrepareMemoryOperand(ctx, operand));
|
||||||
}
|
}
|
||||||
// Nope, register.
|
// Nope, register.
|
||||||
else if (operand->type == ZYDIS_OPERAND_TYPE_REGISTER)
|
else if (operand->type == ZYDIS_OPERAND_TYPE_REGISTER)
|
||||||
|
@ -907,11 +911,9 @@ static ZydisStatus ZydisPrepareMandatoryPrefixes(ZydisEncoderContext* ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
static ZydisStatus ZydisDeriveSemanticOperandTypeMask(
|
static ZydisStatus ZydisDeriveSemanticOperandTypeMask(
|
||||||
ZydisEncoderContext* ctx, const ZydisEncoderOperand* op,
|
const ZydisEncoderOperand* op, ZydisSemanticOperandTypeMask* mask)
|
||||||
ZydisSemanticOperandTypeMask* mask)
|
|
||||||
{
|
{
|
||||||
ZYDIS_ASSERT(op);
|
ZYDIS_ASSERT(op);
|
||||||
ZYDIS_ASSERT(ctx);
|
|
||||||
ZYDIS_ASSERT(mask);
|
ZYDIS_ASSERT(mask);
|
||||||
|
|
||||||
switch (op->type)
|
switch (op->type)
|
||||||
|
@ -1019,49 +1021,117 @@ static ZydisStatus ZydisFindMatchingDef(
|
||||||
// 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.
|
||||||
ZydisSemanticOperandTypeMask semOperandTypeMasks[ZYDIS_ENCODER_MAX_OPERANDS];
|
ZydisSemanticOperandTypeMask semOperandTypeMasks[ZYDIS_ENCODER_MAX_OPERANDS];
|
||||||
ZydisBool requireOperandSizeOverride = ZYDIS_FALSE;
|
ZydisBool require66 = ZYDIS_FALSE;
|
||||||
//ZydisBool requireAddressSizeOverride = ZYDIS_FALSE;
|
ZydisBool require67 = ZYDIS_FALSE;
|
||||||
|
ZydisBool requireREXW = ZYDIS_FALSE;
|
||||||
|
uint8_t eosz = req->machineMode;
|
||||||
|
uint8_t 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;
|
||||||
|
|
||||||
|
// Do we need any operand size overrides?
|
||||||
if (curReqOperand->type == ZYDIS_OPERAND_TYPE_REGISTER)
|
if (curReqOperand->type == ZYDIS_OPERAND_TYPE_REGISTER)
|
||||||
{
|
{
|
||||||
switch (ZydisRegisterGetClass(curReqOperand->reg))
|
switch (ZydisRegisterGetClass(curReqOperand->reg))
|
||||||
{
|
{
|
||||||
case ZYDIS_REGCLASS_GPR16:
|
case ZYDIS_REGCLASS_GPR16:
|
||||||
|
eosz = 16;
|
||||||
switch (req->machineMode)
|
switch (req->machineMode)
|
||||||
{
|
{
|
||||||
case 16: break; // Nothing to do.
|
case 16: break; // Default mode.
|
||||||
case 32:
|
case 32:
|
||||||
case 64: requireOperandSizeOverride = ZYDIS_TRUE; break;
|
case 64: 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:
|
||||||
|
eosz = 32;
|
||||||
switch (req->machineMode)
|
switch (req->machineMode)
|
||||||
{
|
{
|
||||||
case 16: return ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION;
|
case 16: require66 = ZYDIS_TRUE; break;
|
||||||
case 32:
|
case 32:
|
||||||
case 64: break; // Nothing to do.
|
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:
|
||||||
|
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: break;
|
case 64: requireREXW = ZYDIS_TRUE; break;
|
||||||
default: return ZYDIS_STATUS_INVALID_PARAMETER;
|
default: return ZYDIS_STATUS_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
; // Other registers can't be operand-scaled.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Address size overrides?
|
||||||
|
if (curReqOperand->type == ZYDIS_OPERAND_TYPE_MEMORY)
|
||||||
|
{
|
||||||
|
// Verify base and index have the same register class, if present.
|
||||||
|
ZydisRegisterClass baseRegClass = ZydisRegisterGetClass(curReqOperand->mem.base);
|
||||||
|
if (curReqOperand->mem.base != ZYDIS_REGISTER_NONE &&
|
||||||
|
curReqOperand->mem.base != ZYDIS_REGISTER_NONE &&
|
||||||
|
baseRegClass != ZydisRegisterGetClass(curReqOperand->mem.index))
|
||||||
|
{
|
||||||
|
return ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION; // TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
// Address size prefix required?
|
||||||
|
switch (baseRegClass)
|
||||||
|
{
|
||||||
|
case ZYDIS_REGCLASS_GPR16: easz = 16; break;
|
||||||
|
case ZYDIS_REGCLASS_GPR32: easz = 32; break;
|
||||||
|
case ZYDIS_REGCLASS_GPR64: easz = 64; break;
|
||||||
|
default:
|
||||||
|
switch (baseRegClass)
|
||||||
|
{
|
||||||
|
case ZYDIS_REGISTER_IP: easz = 16; break;
|
||||||
|
case ZYDIS_REGISTER_EIP: easz = 32; break;
|
||||||
|
case ZYDIS_REGISTER_RIP: easz = 64; break;
|
||||||
|
default:
|
||||||
|
; // Other registers can't be address-scaled.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (easz)
|
||||||
|
{
|
||||||
|
case 16:
|
||||||
|
switch (ctx->req->machineMode)
|
||||||
|
{
|
||||||
|
case 16: break; // Default mode.
|
||||||
|
case 32: require67 = ZYDIS_TRUE; break;
|
||||||
|
case 64: return ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION; // TODO
|
||||||
|
default: return ZYDIS_STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 32:
|
||||||
|
switch (ctx->req->machineMode)
|
||||||
|
{
|
||||||
|
case 16: require67 = ZYDIS_TRUE; break;
|
||||||
|
case 32: break; // Default mode.
|
||||||
|
case 64: require67 = ZYDIS_TRUE; break;
|
||||||
|
default: return ZYDIS_STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 64:
|
||||||
|
if (ctx->req->machineMode != 64)
|
||||||
|
{
|
||||||
|
return ZYDIS_STATUS_IMPOSSIBLE_INSTRUCTION; // TODO
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
; // Don't care.
|
; // Don't care.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ZYDIS_CHECK(ZydisDeriveSemanticOperandTypeMask(
|
ZYDIS_CHECK(ZydisDeriveSemanticOperandTypeMask(
|
||||||
ctx, req->operands + i, semOperandTypeMasks + i
|
req->operands + i, semOperandTypeMasks + i
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1097,9 +1167,56 @@ static ZydisStatus ZydisFindMatchingDef(
|
||||||
// it's safe to assume this isn't the instruction we're looking for.
|
// it's safe to assume this isn't the instruction we're looking for.
|
||||||
if (curDefOperand->visibility == ZYDIS_OPERAND_VISIBILITY_HIDDEN) goto _nextInsn;
|
if (curDefOperand->visibility == ZYDIS_OPERAND_VISIBILITY_HIDDEN) goto _nextInsn;
|
||||||
|
|
||||||
if (curDefOperand->type != curReqOperand->type) continue;
|
// Is the type one of those we permit for the given operand?
|
||||||
|
if (!(1 << curDefOperand->type & semOperandTypeMasks[k])) goto _nextInsn;
|
||||||
|
|
||||||
// blah blah more checks
|
// For implicit operands, check if the implicit value is what we're looking for.
|
||||||
|
switch (curDefOperand->type)
|
||||||
|
{
|
||||||
|
case ZYDIS_SEMANTIC_OPTYPE_IMPLICIT_REG:
|
||||||
|
{
|
||||||
|
switch (curDefOperand->op.reg.type)
|
||||||
|
{
|
||||||
|
case ZYDIS_IMPLREG_TYPE_STATIC:
|
||||||
|
// reg reg reg banaaanaa phooone!
|
||||||
|
if (curDefOperand->op.reg.reg.reg != curReqOperand->reg) goto _nextInsn;
|
||||||
|
break;
|
||||||
|
case ZYDIS_IMPLREG_TYPE_GPR_OSZ:
|
||||||
|
|
||||||
|
break;
|
||||||
|
case ZYDIS_IMPLREG_TYPE_GPR_ASZ: break; // TODO
|
||||||
|
case ZYDIS_IMPLREG_TYPE_GPR_SSZ: break; // TODO
|
||||||
|
case ZYDIS_IMPLREG_TYPE_IP_ASZ: break; // TODO
|
||||||
|
case ZYDIS_IMPLREG_TYPE_IP_SSZ: break; // TODO
|
||||||
|
case ZYDIS_IMPLREG_TYPE_FLAGS_SSZ: break; // TODO
|
||||||
|
default: ZYDIS_UNREACHABLE;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case ZYDIS_SEMANTIC_OPTYPE_IMPLICIT_MEM:
|
||||||
|
{
|
||||||
|
// TODO: Can those be scaled using 67?
|
||||||
|
ZydisRegisterClass regClass;
|
||||||
|
switch (req->machineMode)
|
||||||
|
{
|
||||||
|
case 16: regClass = ZYDIS_REGCLASS_GPR16; break;
|
||||||
|
case 32: regClass = ZYDIS_REGCLASS_GPR32; break;
|
||||||
|
case 64: regClass = ZYDIS_REGCLASS_GPR64; break;
|
||||||
|
default: return ZYDIS_STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
static const uint8_t regIdxLookup[4] = {3, 5, 6, 7};
|
||||||
|
ZYDIS_ASSERT(curDefOperand->op.mem.base < ZYDIS_ARRAY_SIZE(regIdxLookup));
|
||||||
|
uint8_t regIdx = regIdxLookup[curDefOperand->op.mem.base];
|
||||||
|
ZydisRegister derivedReg = ZydisRegisterEncode(regClass, regIdx);
|
||||||
|
|
||||||
|
if (curReqOperand->mem.base != derivedReg) goto _nextInsn;
|
||||||
|
} break;
|
||||||
|
case ZYDIS_SEMANTIC_OPTYPE_IMPLICIT_IMM1:
|
||||||
|
{
|
||||||
|
if (curReqOperand->imm.u != 1) goto _nextInsn;
|
||||||
|
} break;
|
||||||
|
default:
|
||||||
|
; // Shut up linter.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure we compared either all operands or the remaining operands are hidden.
|
// Make sure we compared either all operands or the remaining operands are hidden.
|
||||||
|
|
Loading…
Reference in New Issue