Merge branch 'develop' of github.com:zyantific/zyan-disassembler-engine into develop

This commit is contained in:
flobernd 2017-07-14 22:56:06 +02:00
commit 9e15ecc5f1
1 changed files with 146 additions and 29 deletions

View File

@ -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.