Decoder improvements

- Instructions which are only valid in protected-mode are now rejected, if `ZYDIS_MACHINE_MODE_REAL_16` is used
- The `scale` of memory-operands is now correctly set to `1` in 16-bit mode, if an index register was specified
This commit is contained in:
flobernd 2017-11-13 19:43:19 +01:00
parent ac3a01bd57
commit df101d0fe0
4 changed files with 7123 additions and 7105 deletions

View File

@ -69,35 +69,35 @@ typedef uint8_t ZydisMachineMode;
*/
enum ZydisMachineModes
{
ZYDIS_MACHINE_MODE_INVALID = 0,
ZYDIS_MACHINE_MODE_INVALID,
/**
* @brief 64 bit mode.
*/
ZYDIS_MACHINE_MODE_LONG_64 = 64,
ZYDIS_MACHINE_MODE_LONG_64,
/**
* @brief 32 bit protected mode.
*/
ZYDIS_MACHINE_MODE_LONG_COMPAT_32 = 32,
ZYDIS_MACHINE_MODE_LONG_COMPAT_32,
/**
* @brief 16 bit protected mode.
*/
ZYDIS_MACHINE_MODE_LONG_COMPAT_16 = 16,
ZYDIS_MACHINE_MODE_LONG_COMPAT_16,
/**
* @brief 32 bit protected mode.
*/
ZYDIS_MACHINE_MODE_LEGACY_32 = 32,
ZYDIS_MACHINE_MODE_LEGACY_32,
/**
* @brief 16 bit protected mode.
*/
ZYDIS_MACHINE_MODE_LEGACY_16 = 16,
ZYDIS_MACHINE_MODE_LEGACY_16,
/**
* @brief 16 bit real mode.
*/
ZYDIS_MACHINE_MODE_REAL_16 = 16,
ZYDIS_MACHINE_MODE_REAL_16,
/**
* @brief Maximum value of this enum.
*/
ZYDIS_MACHINE_MODE_MAX_VALUE = ZYDIS_MACHINE_MODE_LONG_64
ZYDIS_MACHINE_MODE_MAX_VALUE = ZYDIS_MACHINE_MODE_REAL_16
};
/* ---------------------------------------------------------------------------------------------- */

View File

@ -564,7 +564,7 @@ static ZydisStatus ZydisDecodeEVEX(ZydisDecoderContext* context,
((0x01 & ~instruction->raw.evex.V2) << 4) | (0x0F & ~instruction->raw.evex.vvvv);
context->cache.mask = instruction->raw.evex.aaa;
if (!instruction->raw.evex.V2 && (context->decoder->machineMode != 64))
if (!instruction->raw.evex.V2 && (context->decoder->machineMode != ZYDIS_MACHINE_MODE_LONG_64))
{
return ZYDIS_STATUS_MALFORMED_EVEX;
}
@ -846,8 +846,11 @@ static uint8_t ZydisCalcRegisterId(ZydisDecoderContext* context,
{
switch (context->decoder->machineMode)
{
case 16:
case 32:
case ZYDIS_MACHINE_MODE_LONG_COMPAT_16:
case ZYDIS_MACHINE_MODE_LEGACY_16:
case ZYDIS_MACHINE_MODE_REAL_16:
case ZYDIS_MACHINE_MODE_LONG_COMPAT_32:
case ZYDIS_MACHINE_MODE_LEGACY_32:
switch (encoding)
{
case ZYDIS_REG_ENCODING_OPCODE:
@ -900,7 +903,7 @@ static uint8_t ZydisCalcRegisterId(ZydisDecoderContext* context,
default:
ZYDIS_UNREACHABLE;
}
case 64:
case ZYDIS_MACHINE_MODE_LONG_64:
switch (encoding)
{
case ZYDIS_REG_ENCODING_OPCODE:
@ -1081,7 +1084,7 @@ static void ZydisSetOperandSizeAndElementInfo(ZydisDecoderContext* context,
operand->size = definition->size[context->eoszIndex] * 8;
} else
{
operand->size = (context->decoder->machineMode == 64) ?
operand->size = (context->decoder->machineMode == ZYDIS_MACHINE_MODE_LONG_64) ?
ZydisRegisterGetWidth64(operand->reg.value) :
ZydisRegisterGetWidth(operand->reg.value);
}
@ -1385,7 +1388,7 @@ static ZydisStatus ZydisDecodeOperandMemory(ZydisDecoderContext* context,
};
operand->mem.base = bases[modrm_rm];
operand->mem.index = indices[modrm_rm];
operand->mem.scale = 0;
operand->mem.scale = (operand->mem.index == ZYDIS_REGISTER_NONE) ? 0 : 1;
switch (instruction->raw.modrm.mod)
{
case 0:
@ -3224,7 +3227,7 @@ static ZydisStatus ZydisDecodeOptionalInstructionParts(ZydisDecoderContext* cont
case 0:
if (instruction->raw.modrm.rm == 5)
{
if (context->decoder->machineMode == 64)
if (context->decoder->machineMode == ZYDIS_MACHINE_MODE_LONG_64)
{
instruction->attributes |= ZYDIS_ATTRIB_IS_RELATIVE;
}
@ -3401,13 +3404,16 @@ static void ZydisSetEffectiveOperandSize(ZydisDecoderContext* context,
uint8_t index = (instruction->attributes & ZYDIS_ATTRIB_HAS_OPERANDSIZE) ? 1 : 0;
switch (context->decoder->machineMode)
{
case 16:
case ZYDIS_MACHINE_MODE_LONG_COMPAT_16:
case ZYDIS_MACHINE_MODE_LEGACY_16:
case ZYDIS_MACHINE_MODE_REAL_16:
index += 0;
break;
case 32:
case ZYDIS_MACHINE_MODE_LONG_COMPAT_32:
case ZYDIS_MACHINE_MODE_LEGACY_32:
index += 2;
break;
case 64:
case ZYDIS_MACHINE_MODE_LONG_64:
index += 4;
index += (context->cache.W & 0x01) << 1;
break;
@ -3738,13 +3744,16 @@ static ZydisStatus ZydisNodeHandlerMode(ZydisDecoderContext* context, uint16_t*
switch (context->decoder->machineMode)
{
case 16:
case ZYDIS_MACHINE_MODE_LONG_COMPAT_16:
case ZYDIS_MACHINE_MODE_LEGACY_16:
case ZYDIS_MACHINE_MODE_REAL_16:
*index = 0;
break;
case 32:
case ZYDIS_MACHINE_MODE_LONG_COMPAT_32:
case ZYDIS_MACHINE_MODE_LEGACY_32:
*index = 1;
break;
case 64:
case ZYDIS_MACHINE_MODE_LONG_64:
*index = 2;
break;
default:
@ -3856,18 +3865,21 @@ static ZydisStatus ZydisNodeHandlerOperandSize(ZydisDecoderContext* context,
ZYDIS_ASSERT(instruction);
ZYDIS_ASSERT(index);
if ((context->decoder->machineMode == 64) && (context->cache.W))
if ((context->decoder->machineMode == ZYDIS_MACHINE_MODE_LONG_64) && (context->cache.W))
{
*index = 2;
} else
{
switch (context->decoder->machineMode)
{
case 16:
case ZYDIS_MACHINE_MODE_LONG_COMPAT_16:
case ZYDIS_MACHINE_MODE_LEGACY_16:
case ZYDIS_MACHINE_MODE_REAL_16:
*index = (instruction->attributes & ZYDIS_ATTRIB_HAS_OPERANDSIZE) ? 1 : 0;
break;
case 32:
case 64:
case ZYDIS_MACHINE_MODE_LONG_COMPAT_32:
case ZYDIS_MACHINE_MODE_LEGACY_32:
case ZYDIS_MACHINE_MODE_LONG_64:
*index = (instruction->attributes & ZYDIS_ATTRIB_HAS_OPERANDSIZE) ? 0 : 1;
break;
default:
@ -4044,6 +4056,11 @@ static ZydisStatus ZydisCheckErrorConditions(ZydisDecoderContext* context,
{
const ZydisInstructionDefinitionDEFAULT* def =
(const ZydisInstructionDefinitionDEFAULT*)definition;
if (def->requiresProtectedMode &&
(context->decoder->machineMode == ZYDIS_MACHINE_MODE_REAL_16))
{
return ZYDIS_STATUS_DECODING_ERROR;
}
acceptsLock = def->acceptsLock;
break;
}
@ -4319,6 +4336,7 @@ static ZydisStatus ZydisDecodeInstruction(ZydisDecoderContext* context,
{
const ZydisInstructionDefinition* definition;
ZydisGetInstructionDefinition(instruction->encoding, node->value, &definition);
ZYDIS_CHECK(ZydisCheckErrorConditions(context, instruction, definition));
ZydisSetEffectiveOperandSize(context, instruction, definition);
ZydisSetEffectiveAddressWidth(context, instruction, definition);
@ -4345,8 +4363,6 @@ static ZydisStatus ZydisDecodeInstruction(ZydisDecoderContext* context,
ZydisGetInstructionDefinition(instruction->encoding, node->value, &definition);
}
ZYDIS_CHECK(ZydisCheckErrorConditions(context, instruction, definition));
instruction->mnemonic = definition->mnemonic;
instruction->meta.category = definition->category;
instruction->meta.isaSet = definition->isaSet;
@ -4406,11 +4422,12 @@ ZydisStatus ZydisDecoderInit(ZydisDecoder* decoder, ZydisMachineMode machineMode
ZYDIS_TRUE // ZYDIS_DECODER_MODE_TZCNT
};
if (!decoder || ((machineMode != 16) && (machineMode != 32) && (machineMode != 64)))
if (!decoder ||
(machineMode == ZYDIS_MACHINE_MODE_INVALID) || (machineMode > ZYDIS_MACHINE_MODE_MAX_VALUE))
{
return ZYDIS_STATUS_INVALID_PARAMETER;
}
if (machineMode == 64)
if (machineMode == ZYDIS_MACHINE_MODE_LONG_64)
{
if (addressWidth != 64)
{

File diff suppressed because it is too large Load Diff

View File

@ -548,6 +548,7 @@ enum ZydisMaskPolicies
uint16_t operandReference ZYDIS_BITFIELD(15); \
uint8_t operandSizeMap ZYDIS_BITFIELD( 3); \
uint8_t flagsReference ZYDIS_BITFIELD( 7); \
ZydisBool requiresProtectedMode ZYDIS_BITFIELD( 1); \
ZydisBool acceptsAddressSizeOverride ZYDIS_BITFIELD( 1); \
ZydisInstructionCategory category ZYDIS_BITFIELD(ZYDIS_CATEGORY_MAX_BITS); \
ZydisISASet isaSet ZYDIS_BITFIELD(ZYDIS_ISA_SET_MAX_BITS); \