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_RM,
ZYDIS_OPERAND_ENCODING_OPCODE,
ZYDIS_OPERAND_ENCODING_NDS,
ZYDIS_OPERAND_ENCODING_NDSNDD,
ZYDIS_OPERAND_ENCODING_IS4,
ZYDIS_OPERAND_ENCODING_MASK,
ZYDIS_OPERAND_ENCODING_UIMM8_LO,
ZYDIS_OPERAND_ENCODING_UIMM8_HI,
ZYDIS_OPERAND_ENCODING_DISP8,
ZYDIS_OPERAND_ENCODING_DISP16,
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; \
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.
*/
@ -689,7 +693,7 @@ typedef struct ZydisInstructionDefinitionVEX_
typedef struct ZydisInstructionDefinitionEVEX_
{
ZYDIS_INSTRUCTION_DEFINITION_BASE_VECTOR;
ZYDIS_INSTRUCTION_DEFINITION_BASE_VECTOR_EX;
ZydisInternalVectorLength vectorLength ZYDIS_BITFIELD(2);
ZydisEVEXTupleType tupleType ZYDIS_BITFIELD(4);
ZydisInternalElementSize elementSize ZYDIS_BITFIELD(4);
@ -700,7 +704,7 @@ typedef struct ZydisInstructionDefinitionEVEX_
typedef struct ZydisInstructionDefinitionMVEX_
{
ZYDIS_INSTRUCTION_DEFINITION_BASE_VECTOR;
ZYDIS_INSTRUCTION_DEFINITION_BASE_VECTOR_EX;
ZydisMVEXFunctionality functionality ZYDIS_BITFIELD(5);
ZydisMaskPolicy maskPolicy ZYDIS_BITFIELD(2);
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,
ZydisCalcRegisterId(context, info, ZYDIS_REG_ENCODING_OPCODE, registerClass)));
break;
case ZYDIS_OPERAND_ENCODING_NDS:
case ZYDIS_OPERAND_ENCODING_NDSNDD:
ZYDIS_CHECK(
ZydisDecodeOperandRegister(info, &info->operands[i], 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,
ZydisCalcRegisterId(context, info, ZYDIS_REG_ENCODING_MASK, registerClass)));
break;
case ZYDIS_OPERAND_ENCODING_UIMM8_HI:
case ZYDIS_OPERAND_ENCODING_IS4:
ZYDIS_CHECK(
ZydisDecodeOperandRegister(info, &info->operands[i], 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));
info->operands[i].type = ZYDIS_OPERAND_TYPE_IMMEDIATE;
info->operands[i].size = operand->size[context->eoszIndex] * 8;
info->operands[i].imm.value.uqword = info->details.imm[immId].value.uqword;
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.isSigned = info->details.imm[immId].isSigned;
info->operands[i].imm.isRelative = info->details.imm[immId].isRelative;
++immId;
@ -4017,6 +4025,7 @@ static ZydisStatus ZydisDecodeInstruction(ZydisDecoderContext* context, ZydisIns
ZYDIS_CHECK(ZydisDecodeOptionalInstructionParts(context, info, optionalParts));
ZydisBool hasNDSNDDOperand = ZYDIS_FALSE;
ZydisBool hasVSIB = ZYDIS_FALSE;
ZydisMaskPolicy maskPolicy = ZYDIS_MASK_POLICY_INVALID;
switch (info->encoding)
{
@ -4059,6 +4068,7 @@ static ZydisStatus ZydisDecodeInstruction(ZydisDecoderContext* context, ZydisIns
const ZydisInstructionDefinitionEVEX* def =
(const ZydisInstructionDefinitionEVEX*)definition;
hasNDSNDDOperand = def->hasNDSNDDOperand;
hasVSIB = def->hasVSIB;
maskPolicy = def->maskPolicy;
break;
}
@ -4067,6 +4077,7 @@ static ZydisStatus ZydisDecodeInstruction(ZydisDecoderContext* context, ZydisIns
const ZydisInstructionDefinitionMVEX* def =
(const ZydisInstructionDefinitionMVEX*)definition;
hasNDSNDDOperand = def->hasNDSNDDOperand;
hasVSIB = def->hasVSIB;
maskPolicy = def->maskPolicy;
// Check for invalid MVEX.SSS values
@ -4135,14 +4146,18 @@ static ZydisStatus ZydisDecodeInstruction(ZydisDecoderContext* context, ZydisIns
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))
{
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
switch (maskPolicy)
{