Improved instruction decoding

- Decoding of EVEX/MVEX instructions without a NDS/NDD-operand encoded in `.vvvv` and without a VSIB-operand will now fail, if `.v'` is != 1b
- Added information about XACQUIRE, XRELEASE and BOUND prefixes to the instruction definitions
- Fixed immediate-decoding of the `vpermil2pd` / `vpermil2ps` instruction
This commit is contained in:
flobernd 2017-06-29 18:09:42 +02:00
parent 73b02f6d12
commit 65fe4a4e6c
5 changed files with 3964 additions and 3946 deletions

View File

@ -110,10 +110,9 @@ enum ZydisOperandEncodings
ZYDIS_OPERAND_ENCODING_MODRM_REG, ZYDIS_OPERAND_ENCODING_MODRM_REG,
ZYDIS_OPERAND_ENCODING_MODRM_RM, ZYDIS_OPERAND_ENCODING_MODRM_RM,
ZYDIS_OPERAND_ENCODING_OPCODE, ZYDIS_OPERAND_ENCODING_OPCODE,
ZYDIS_OPERAND_ENCODING_NDS, ZYDIS_OPERAND_ENCODING_NDSNDD,
ZYDIS_OPERAND_ENCODING_IS4,
ZYDIS_OPERAND_ENCODING_MASK, ZYDIS_OPERAND_ENCODING_MASK,
ZYDIS_OPERAND_ENCODING_UIMM8_LO,
ZYDIS_OPERAND_ENCODING_UIMM8_HI,
ZYDIS_OPERAND_ENCODING_DISP8, ZYDIS_OPERAND_ENCODING_DISP8,
ZYDIS_OPERAND_ENCODING_DISP16, ZYDIS_OPERAND_ENCODING_DISP16,
ZYDIS_OPERAND_ENCODING_DISP32, ZYDIS_OPERAND_ENCODING_DISP32,

File diff suppressed because it is too large Load Diff

View File

@ -648,6 +648,10 @@ enum ZydisMaskPolicies
ZYDIS_INSTRUCTION_DEFINITION_BASE; \ ZYDIS_INSTRUCTION_DEFINITION_BASE; \
ZydisBool hasNDSNDDOperand ZYDIS_BITFIELD( 1) ZydisBool hasNDSNDDOperand ZYDIS_BITFIELD( 1)
#define ZYDIS_INSTRUCTION_DEFINITION_BASE_VECTOR_EX \
ZYDIS_INSTRUCTION_DEFINITION_BASE_VECTOR; \
ZydisBool hasVSIB ZYDIS_BITFIELD( 1)
/** /**
* @brief Defines the @c ZydisInstructionDefinition struct. * @brief Defines the @c ZydisInstructionDefinition struct.
*/ */
@ -689,7 +693,7 @@ typedef struct ZydisInstructionDefinitionVEX_
typedef struct ZydisInstructionDefinitionEVEX_ typedef struct ZydisInstructionDefinitionEVEX_
{ {
ZYDIS_INSTRUCTION_DEFINITION_BASE_VECTOR; ZYDIS_INSTRUCTION_DEFINITION_BASE_VECTOR_EX;
ZydisInternalVectorLength vectorLength ZYDIS_BITFIELD(2); ZydisInternalVectorLength vectorLength ZYDIS_BITFIELD(2);
ZydisEVEXTupleType tupleType ZYDIS_BITFIELD(4); ZydisEVEXTupleType tupleType ZYDIS_BITFIELD(4);
ZydisInternalElementSize elementSize ZYDIS_BITFIELD(4); ZydisInternalElementSize elementSize ZYDIS_BITFIELD(4);
@ -700,7 +704,7 @@ typedef struct ZydisInstructionDefinitionEVEX_
typedef struct ZydisInstructionDefinitionMVEX_ typedef struct ZydisInstructionDefinitionMVEX_
{ {
ZYDIS_INSTRUCTION_DEFINITION_BASE_VECTOR; ZYDIS_INSTRUCTION_DEFINITION_BASE_VECTOR_EX;
ZydisMVEXFunctionality functionality ZYDIS_BITFIELD(5); ZydisMVEXFunctionality functionality ZYDIS_BITFIELD(5);
ZydisMaskPolicy maskPolicy ZYDIS_BITFIELD(2); ZydisMaskPolicy maskPolicy ZYDIS_BITFIELD(2);
ZydisBool hasElementGranularity ZYDIS_BITFIELD(1); ZydisBool hasElementGranularity ZYDIS_BITFIELD(1);

File diff suppressed because it is too large Load Diff

View File

@ -1780,7 +1780,7 @@ static ZydisStatus ZydisDecodeOperands(ZydisDecoderContext* context, ZydisInstru
ZydisDecodeOperandRegister(info, &info->operands[i], registerClass, ZydisDecodeOperandRegister(info, &info->operands[i], registerClass,
ZydisCalcRegisterId(context, info, ZYDIS_REG_ENCODING_OPCODE, registerClass))); ZydisCalcRegisterId(context, info, ZYDIS_REG_ENCODING_OPCODE, registerClass)));
break; break;
case ZYDIS_OPERAND_ENCODING_NDS: case ZYDIS_OPERAND_ENCODING_NDSNDD:
ZYDIS_CHECK( ZYDIS_CHECK(
ZydisDecodeOperandRegister(info, &info->operands[i], registerClass, ZydisDecodeOperandRegister(info, &info->operands[i], registerClass,
ZydisCalcRegisterId(context, info, ZYDIS_REG_ENCODING_NDSNDD, registerClass))); ZydisCalcRegisterId(context, info, ZYDIS_REG_ENCODING_NDSNDD, registerClass)));
@ -1790,7 +1790,7 @@ static ZydisStatus ZydisDecodeOperands(ZydisDecoderContext* context, ZydisInstru
ZydisDecodeOperandRegister(info, &info->operands[i], registerClass, ZydisDecodeOperandRegister(info, &info->operands[i], registerClass,
ZydisCalcRegisterId(context, info, ZYDIS_REG_ENCODING_MASK, registerClass))); ZydisCalcRegisterId(context, info, ZYDIS_REG_ENCODING_MASK, registerClass)));
break; break;
case ZYDIS_OPERAND_ENCODING_UIMM8_HI: case ZYDIS_OPERAND_ENCODING_IS4:
ZYDIS_CHECK( ZYDIS_CHECK(
ZydisDecodeOperandRegister(info, &info->operands[i], registerClass, ZydisDecodeOperandRegister(info, &info->operands[i], registerClass,
ZydisCalcRegisterId(context, info, ZYDIS_REG_ENCODING_IS4, registerClass))); ZydisCalcRegisterId(context, info, ZYDIS_REG_ENCODING_IS4, registerClass)));
@ -1866,7 +1866,15 @@ static ZydisStatus ZydisDecodeOperands(ZydisDecoderContext* context, ZydisInstru
ZYDIS_ASSERT((immId == 0) || (immId == 1)); ZYDIS_ASSERT((immId == 0) || (immId == 1));
info->operands[i].type = ZYDIS_OPERAND_TYPE_IMMEDIATE; info->operands[i].type = ZYDIS_OPERAND_TYPE_IMMEDIATE;
info->operands[i].size = operand->size[context->eoszIndex] * 8; info->operands[i].size = operand->size[context->eoszIndex] * 8;
if (operand->op.encoding == ZYDIS_OPERAND_ENCODING_IS4)
{
// The upper half of the 8-bit immediate is used to encode a register specifier
ZYDIS_ASSERT(info->details.imm[immId].dataSize == 8);
info->operands[i].imm.value.ubyte = info->details.imm[immId].value.ubyte & 0x0F;
} else
{
info->operands[i].imm.value.uqword = info->details.imm[immId].value.uqword; info->operands[i].imm.value.uqword = info->details.imm[immId].value.uqword;
}
info->operands[i].imm.isSigned = info->details.imm[immId].isSigned; info->operands[i].imm.isSigned = info->details.imm[immId].isSigned;
info->operands[i].imm.isRelative = info->details.imm[immId].isRelative; info->operands[i].imm.isRelative = info->details.imm[immId].isRelative;
++immId; ++immId;
@ -4017,6 +4025,7 @@ static ZydisStatus ZydisDecodeInstruction(ZydisDecoderContext* context, ZydisIns
ZYDIS_CHECK(ZydisDecodeOptionalInstructionParts(context, info, optionalParts)); ZYDIS_CHECK(ZydisDecodeOptionalInstructionParts(context, info, optionalParts));
ZydisBool hasNDSNDDOperand = ZYDIS_FALSE; ZydisBool hasNDSNDDOperand = ZYDIS_FALSE;
ZydisBool hasVSIB = ZYDIS_FALSE;
ZydisMaskPolicy maskPolicy = ZYDIS_MASK_POLICY_INVALID; ZydisMaskPolicy maskPolicy = ZYDIS_MASK_POLICY_INVALID;
switch (info->encoding) switch (info->encoding)
{ {
@ -4059,6 +4068,7 @@ static ZydisStatus ZydisDecodeInstruction(ZydisDecoderContext* context, ZydisIns
const ZydisInstructionDefinitionEVEX* def = const ZydisInstructionDefinitionEVEX* def =
(const ZydisInstructionDefinitionEVEX*)definition; (const ZydisInstructionDefinitionEVEX*)definition;
hasNDSNDDOperand = def->hasNDSNDDOperand; hasNDSNDDOperand = def->hasNDSNDDOperand;
hasVSIB = def->hasVSIB;
maskPolicy = def->maskPolicy; maskPolicy = def->maskPolicy;
break; break;
} }
@ -4067,6 +4077,7 @@ static ZydisStatus ZydisDecodeInstruction(ZydisDecoderContext* context, ZydisIns
const ZydisInstructionDefinitionMVEX* def = const ZydisInstructionDefinitionMVEX* def =
(const ZydisInstructionDefinitionMVEX*)definition; (const ZydisInstructionDefinitionMVEX*)definition;
hasNDSNDDOperand = def->hasNDSNDDOperand; hasNDSNDDOperand = def->hasNDSNDDOperand;
hasVSIB = def->hasVSIB;
maskPolicy = def->maskPolicy; maskPolicy = def->maskPolicy;
// Check for invalid MVEX.SSS values // Check for invalid MVEX.SSS values
@ -4135,14 +4146,18 @@ static ZydisStatus ZydisDecodeInstruction(ZydisDecoderContext* context, ZydisIns
ZYDIS_UNREACHABLE; ZYDIS_UNREACHABLE;
} }
// TODO: Add check for invalid .V` // Check for invalid `XOP/VEX/EVEX/MVEX.vvvv` value
// Check for invalid XOP/VEX/EVEX/MVEX.vvvv value
if (!hasNDSNDDOperand && (context->cache.v_vvvv & 0x0F)) if (!hasNDSNDDOperand && (context->cache.v_vvvv & 0x0F))
{ {
return ZYDIS_STATUS_DECODING_ERROR; return ZYDIS_STATUS_DECODING_ERROR;
} }
// Check for invalid `EVEX/MVEX.v'` value
if (!hasNDSNDDOperand && !hasVSIB && context->cache.V2)
{
return ZYDIS_STATUS_DECODING_ERROR;
}
// Check for invalid MASK registers // Check for invalid MASK registers
switch (maskPolicy) switch (maskPolicy)
{ {