Added semantic element-information for operands

This commit is contained in:
flobernd 2017-06-16 23:19:57 +02:00
parent 44792f2338
commit ad35e81eee
6 changed files with 6133 additions and 5879 deletions

View File

@ -220,7 +220,7 @@ enum ZydisOperandActions
};
/* ---------------------------------------------------------------------------------------------- */
/* Element type */
/* Elements */
/* ---------------------------------------------------------------------------------------------- */
/**
@ -245,6 +245,11 @@ enum ZydisElementTypes
ZYDIS_ELEMENT_TYPE_LONGBCD
};
/**
* @brief Defines the @c ZydisElementSize datatype.
*/
typedef uint16_t ZydisElementSize;
/* ---------------------------------------------------------------------------------------------- */
/* Operand info */
/* ---------------------------------------------------------------------------------------------- */
@ -285,7 +290,7 @@ typedef struct ZydisOperandInfo_
/**
* @brief The size of a single element.
*/
uint16_t elementSize;
ZydisElementSize elementSize;
/**
* @brief The number of elements.
*/

View File

@ -203,6 +203,39 @@ enum ZydisSemanticOperandTypes
ZYDIS_SEMANTIC_OPTYPE_MOFFS
};
/**
* @brief Defines the @c ZydisInternalElementType datatype.
*/
typedef uint8_t ZydisInternalElementType;
/**
* @brief Values that represent internal element-types.
*/
enum ZydisInternalElementTypes
{
ZYDIS_IELEMENT_TYPE_INVALID,
ZYDIS_IELEMENT_TYPE_VARIABLE, // TODO: Remove
ZYDIS_IELEMENT_TYPE_STRUCT,
ZYDIS_IELEMENT_TYPE_INT,
ZYDIS_IELEMENT_TYPE_UINT,
ZYDIS_IELEMENT_TYPE_INT1,
ZYDIS_IELEMENT_TYPE_INT8,
ZYDIS_IELEMENT_TYPE_INT16,
ZYDIS_IELEMENT_TYPE_INT32,
ZYDIS_IELEMENT_TYPE_INT64,
ZYDIS_IELEMENT_TYPE_UINT8,
ZYDIS_IELEMENT_TYPE_UINT16,
ZYDIS_IELEMENT_TYPE_UINT32,
ZYDIS_IELEMENT_TYPE_UINT64,
ZYDIS_IELEMENT_TYPE_UINT128,
ZYDIS_IELEMENT_TYPE_UINT256,
ZYDIS_IELEMENT_TYPE_FLOAT16,
ZYDIS_IELEMENT_TYPE_FLOAT32,
ZYDIS_IELEMENT_TYPE_FLOAT64,
ZYDIS_IELEMENT_TYPE_FLOAT80,
ZYDIS_IELEMENT_TYPE_BCD80
};
/**
* @brief Defines the @c ZydisOperandDefinition struct.
*/
@ -212,8 +245,7 @@ typedef struct ZydisOperandDefinition_
ZydisOperandVisibility visibility : 2;
ZydisOperandAction action : 3;
uint16_t size[3];
uint8_t elementType : 4;
uint16_t elementSize : 12;
ZydisInternalElementType elementType : 5;
union
{
uint8_t encoding;
@ -222,7 +254,7 @@ typedef struct ZydisOperandDefinition_
uint8_t type : 3;
union
{
ZydisRegister reg : 8;
ZydisRegister reg;
uint8_t id : 6;
} reg;
} reg;
@ -448,6 +480,10 @@ typedef struct ZydisInstructionParts_
/* Functions */
/* ============================================================================================== */
/* ---------------------------------------------------------------------------------------------- */
/* Instruction tree */
/* ---------------------------------------------------------------------------------------------- */
/**
* @brief Returns the root node of the instruction tree.
*
@ -466,6 +502,10 @@ ZYDIS_NO_EXPORT const ZydisInstructionTreeNode* ZydisInstructionTreeGetRootNode(
ZYDIS_NO_EXPORT const ZydisInstructionTreeNode* ZydisInstructionTreeGetChildNode(
const ZydisInstructionTreeNode* parent, uint16_t index);
/* ---------------------------------------------------------------------------------------------- */
/* Instruction definition */
/* ---------------------------------------------------------------------------------------------- */
/**
* @brief Returns the instruction- and operand-definition that is linked to the given @c node.
*
@ -476,8 +516,8 @@ ZYDIS_NO_EXPORT void ZydisGetInstructionDefinition(const ZydisInstructionTreeNod
const ZydisInstructionDefinition** definition);
/**
* @brief Returns information about optional instruction parts for the instruction that is linked
* to the given @c node.
* @brief Returns information about optional instruction parts (like modrm, displacement or
* immediates) for the instruction that is linked to the given @c node.
*
* @param node The instruction definition node.
* @param info A pointer to the @c ZydisInstructionParts struct.
@ -485,6 +525,10 @@ ZYDIS_NO_EXPORT void ZydisGetInstructionDefinition(const ZydisInstructionTreeNod
ZYDIS_NO_EXPORT void ZydisGetOptionalInstructionParts(const ZydisInstructionTreeNode* node,
const ZydisInstructionParts** info);
/* ---------------------------------------------------------------------------------------------- */
/* Operand definition */
/* ---------------------------------------------------------------------------------------------- */
/**
* @brief Returns the instruction- and operand-definition that is linked to the given @c node.
*
@ -497,6 +541,22 @@ ZYDIS_NO_EXPORT void ZydisGetOptionalInstructionParts(const ZydisInstructionTree
ZYDIS_NO_EXPORT uint8_t ZydisGetOperandDefinitions(const ZydisInstructionDefinition* definition,
const ZydisOperandDefinition** operands);
/* ---------------------------------------------------------------------------------------------- */
/* Element info */
/* ---------------------------------------------------------------------------------------------- */
/**
* @brief Returns the actual type and size of an internal element-type.
*
* @param element The internal element type.
* @param type The actual element type.
* @param size The element size.
*/
ZYDIS_NO_EXPORT void ZydisGetElementInfo(ZydisInternalElementType element, ZydisElementType* type,
ZydisElementSize* size);
/* ---------------------------------------------------------------------------------------------- */
/* ============================================================================================== */
#ifdef __cplusplus

File diff suppressed because it is too large Load Diff

View File

@ -901,6 +901,111 @@ static ZydisStatus ZydisDecodeOptionalInstructionParts(ZydisDecoderContext* cont
/* ---------------------------------------------------------------------------------------------- */
/**
* @brief Sets the operand-size and element-specific information for the given operand.
*
* @param context A pointer to the @c ZydisDecoderContext instance.
* @param info A pointer to the @c ZydisInstructionInfo struct.
* @param operand A pointer to the @c ZydisOperandInfo struct.
* @param definition A pointer to the @c ZydisOperandDefinition struct.
*/
static void ZydisSetOperandSizeAndElementInfo(ZydisDecoderContext* context,
ZydisInstructionInfo* info, ZydisOperandInfo* operand, const ZydisOperandDefinition* definition)
{
ZYDIS_ASSERT(context);
ZYDIS_ASSERT(info);
ZYDIS_ASSERT(operand);
ZYDIS_ASSERT(definition);
// Operand size
switch (operand->type)
{
case ZYDIS_OPERAND_TYPE_REGISTER:
{
operand->size = (context->decoder->machineMode == 64) ?
ZydisRegisterGetWidth64(operand->reg) : ZydisRegisterGetWidth(operand->reg);
operand->elementType = ZYDIS_ELEMENT_TYPE_INT;
operand->elementSize = operand->size;
break;
}
case ZYDIS_OPERAND_TYPE_MEMORY:
switch (info->encoding)
{
case ZYDIS_INSTRUCTION_ENCODING_DEFAULT:
case ZYDIS_INSTRUCTION_ENCODING_3DNOW:
case ZYDIS_INSTRUCTION_ENCODING_XOP:
case ZYDIS_INSTRUCTION_ENCODING_VEX:
operand->size = definition->size[context->eoszIndex] * 8;
break;
case ZYDIS_INSTRUCTION_ENCODING_EVEX:
if (definition->size[context->eoszIndex])
{
// Operand size is hardcoded
operand->size = definition->size[context->eoszIndex] * 8;
} else
{
// Operand size depends on the tuple-type, the element-size and the number of
// elements
ZYDIS_ASSERT(info->encoding == ZYDIS_INSTRUCTION_ENCODING_EVEX);
ZYDIS_ASSERT(info->avx.tupleType);
switch (info->avx.tupleType)
{
case ZYDIS_TUPLETYPE_FV:
if (info->avx.broadcastMode)
{
operand->size = info->avx.elementSize;
} else
{
operand->size = info->avx.vectorLength;
}
break;
case ZYDIS_TUPLETYPE_HV:
if (info->avx.broadcastMode)
{
operand->size = info->avx.elementSize;
} else
{
operand->size = info->avx.vectorLength / 2;
}
break;
default:
ZYDIS_UNREACHABLE;
}
}
break;
case ZYDIS_INSTRUCTION_ENCODING_MVEX:
// TODO:
break;
default:
ZYDIS_UNREACHABLE;
}
break;
case ZYDIS_OPERAND_TYPE_POINTER:
case ZYDIS_OPERAND_TYPE_IMMEDIATE:
operand->size = definition->size[context->eoszIndex] * 8;
ZYDIS_ASSERT(operand->size);
break;
default:
ZYDIS_UNREACHABLE;
}
// Element info
if (definition->elementType)
{
ZydisGetElementInfo(definition->elementType, &operand->elementType, &operand->elementSize);
if (!operand->elementSize)
{
// The element size is the same as the operand size. This is used for single element
// scaling operands
operand->elementSize = operand->size;
}
}
if (operand->elementSize && operand->size)
{
operand->elementCount = operand->size / operand->elementSize;
}
}
/**
* @brief Decodes an register-operand.
*
@ -1243,15 +1348,13 @@ static void ZydisDecodeOperandImplicitRegister(ZydisDecoderContext* context,
* @brief Decodes an implicit memory operand.
*
* @param context A pointer to the @c ZydisDecoderContext instance.
* @param info A pointer to the @c ZydisInstructionInfo struct.
* @param operand A pointer to the @c ZydisOperandInfo struct.
* @param definition A pointer to the @c ZydisOperandDefinition struct.
*/
static void ZydisDecodeOperandImplicitMemory(ZydisDecoderContext* context,
ZydisInstructionInfo* info, ZydisOperandInfo* operand, const ZydisOperandDefinition* definition)
ZydisOperandInfo* operand, const ZydisOperandDefinition* definition)
{
ZYDIS_ASSERT(context);
ZYDIS_ASSERT(info);
ZYDIS_ASSERT(operand);
ZYDIS_ASSERT(definition);
@ -1323,20 +1426,14 @@ static ZydisStatus ZydisDecodeOperands(ZydisDecoderContext* context, ZydisInstru
ZydisDecodeOperandImplicitRegister(context, info, &info->operands[i], operand);
break;
case ZYDIS_SEMANTIC_OPTYPE_IMPLICIT_MEM:
ZydisDecodeOperandImplicitMemory(context, info, &info->operands[i], operand);
ZydisDecodeOperandImplicitMemory(context, &info->operands[i], operand);
break;
default:
break;
}
if (info->operands[i].type)
{
if (info->operands[i].type == ZYDIS_OPERAND_TYPE_MEMORY)
{
//ZYDIS_ASSERT(operand->size[context->eoszIndex]);
info->operands[i].size = operand->size[context->eoszIndex] * 8;
}
++operand;
continue;
goto FinalizeOperand;
}
// Register operands
@ -1494,20 +1591,8 @@ static ZydisStatus ZydisDecodeOperands(ZydisDecoderContext* context, ZydisInstru
default:
ZYDIS_UNREACHABLE;
}
if (!operand->size[context->eoszIndex])
{
info->operands[i].size = (context->decoder->machineMode == 64) ?
ZydisRegisterGetWidth64(info->operands[i].reg) :
ZydisRegisterGetWidth(info->operands[i].reg);
} else
{
// TODO: Always override size for register operands?
info->operands[i].size = operand->size[context->eoszIndex] * 8;
}
++operand;
continue;
goto FinalizeOperand;
}
// Memory operands
@ -1542,7 +1627,7 @@ static ZydisStatus ZydisDecodeOperands(ZydisDecoderContext* context, ZydisInstru
default:
break;
}
if (info->operands[i].type == ZYDIS_OPERAND_TYPE_MEMORY)
if (info->operands[i].type)
{
if (vsibBaseRegister)
{
@ -1603,9 +1688,6 @@ static ZydisStatus ZydisDecodeOperands(ZydisDecoderContext* context, ZydisInstru
};
}
//ZYDIS_ASSERT(operand->size[context->eoszIndex]);
info->operands[i].size = operand->size[context->eoszIndex] * 8;
// Handle compressed 8-bit displacement
if (((info->encoding == ZYDIS_INSTRUCTION_ENCODING_EVEX) ||
(info->encoding == ZYDIS_INSTRUCTION_ENCODING_MVEX)) &&
@ -1614,8 +1696,7 @@ static ZydisStatus ZydisDecodeOperands(ZydisDecoderContext* context, ZydisInstru
info->operands[i].mem.disp.value.sqword *= info->avx.compressedDisp8Scale;
}
++operand;
continue;
goto FinalizeOperand;
}
// Immediate operands
@ -1638,6 +1719,8 @@ static ZydisStatus ZydisDecodeOperands(ZydisDecoderContext* context, ZydisInstru
}
ZYDIS_ASSERT(info->operands[i].type == ZYDIS_OPERAND_TYPE_IMMEDIATE);
FinalizeOperand:
ZydisSetOperandSizeAndElementInfo(context, info, &info->operands[i], operand);
++operand;
}
@ -2106,6 +2189,20 @@ static void ZydisSetAVXInformation(ZydisDecoderContext* context,
break;
case 1:
info->avx.compressedDisp8Scale = 4;
switch (info->avx.vectorLength)
{
case 128:
info->avx.broadcastMode = ZYDIS_BCSTMODE_1_TO_2;
break;
case 256:
info->avx.broadcastMode = ZYDIS_BCSTMODE_1_TO_4;
break;
case 512:
info->avx.broadcastMode = ZYDIS_BCSTMODE_1_TO_8;
break;
default:
ZYDIS_UNREACHABLE;
}
break;
default:
ZYDIS_UNREACHABLE;
@ -2167,7 +2264,8 @@ static void ZydisSetAVXInformation(ZydisDecoderContext* context,
break;
case 1:
ZYDIS_ASSERT(info->avx.elementSize == 64);
ZYDIS_ASSERT((info->avx.vectorLength == 256) || (info->avx.vectorLength == 512));
ZYDIS_ASSERT((info->avx.vectorLength == 256) ||
(info->avx.vectorLength == 512));
info->avx.compressedDisp8Scale = 16;
break;
default:
@ -2179,7 +2277,8 @@ static void ZydisSetAVXInformation(ZydisDecoderContext* context,
{
case 0:
ZYDIS_ASSERT(info->avx.elementSize == 32);
ZYDIS_ASSERT((info->avx.vectorLength == 256) || (info->avx.vectorLength == 512));
ZYDIS_ASSERT((info->avx.vectorLength == 256) ||
(info->avx.vectorLength == 512));
info->avx.compressedDisp8Scale = 16;
break;
case 1:
@ -2269,7 +2368,7 @@ static void ZydisSetAVXInformation(ZydisDecoderContext* context,
}
} else
{
// TODO: Add tuple type to register-only definitions
// TODO: Add tuple type to register-only definitions or remove it from the info struct
ZYDIS_ASSERT(info->details.modrm.mod == 3);
}

View File

@ -328,6 +328,10 @@ extern const ZydisInstructionDefinitionMVEX instructionDefinitionsMVEX[];
/* Functions */
/* ============================================================================================== */
/* ---------------------------------------------------------------------------------------------- */
/* Instruction tree */
/* ---------------------------------------------------------------------------------------------- */
const ZydisInstructionTreeNode* ZydisInstructionTreeGetRootNode()
{
static const ZydisInstructionTreeNode root = { ZYDIS_NODETYPE_FILTER_OPCODE, 0x00000000 };
@ -403,6 +407,10 @@ const ZydisInstructionTreeNode* ZydisInstructionTreeGetChildNode(
return &invalid;
}
/* ---------------------------------------------------------------------------------------------- */
/* Instruction definition */
/* ---------------------------------------------------------------------------------------------- */
void ZydisGetInstructionDefinition(const ZydisInstructionTreeNode* node,
const ZydisInstructionDefinition** definition)
{
@ -447,6 +455,10 @@ void ZydisGetOptionalInstructionParts(const ZydisInstructionTreeNode* node,
*info = &instructionClassMap[class];
}
/* ---------------------------------------------------------------------------------------------- */
/* Operand definition */
/* ---------------------------------------------------------------------------------------------- */
uint8_t ZydisGetOperandDefinitions(const ZydisInstructionDefinition* definition,
const ZydisOperandDefinition** operands)
{
@ -460,4 +472,48 @@ uint8_t ZydisGetOperandDefinitions(const ZydisInstructionDefinition* definition,
return definition->operandCount;
}
/* ---------------------------------------------------------------------------------------------- */
/* Element info */
/* ---------------------------------------------------------------------------------------------- */
void ZydisGetElementInfo(ZydisInternalElementType element, ZydisElementType* type,
ZydisElementSize* size)
{
static const struct
{
ZydisElementType type;
ZydisElementSize size;
} lookup[21] =
{
{ ZYDIS_ELEMENT_TYPE_INVALID , 0 },
{ ZYDIS_ELEMENT_TYPE_VARIABLE , 0 },
{ ZYDIS_ELEMENT_TYPE_STRUCT , 0 },
{ ZYDIS_ELEMENT_TYPE_INT , 0 },
{ ZYDIS_ELEMENT_TYPE_UINT , 0 },
{ ZYDIS_ELEMENT_TYPE_INT , 1 },
{ ZYDIS_ELEMENT_TYPE_INT , 8 },
{ ZYDIS_ELEMENT_TYPE_INT , 16 },
{ ZYDIS_ELEMENT_TYPE_INT , 32 },
{ ZYDIS_ELEMENT_TYPE_INT , 64 },
{ ZYDIS_ELEMENT_TYPE_UINT , 8 },
{ ZYDIS_ELEMENT_TYPE_UINT , 16 },
{ ZYDIS_ELEMENT_TYPE_UINT , 32 },
{ ZYDIS_ELEMENT_TYPE_UINT , 64 },
{ ZYDIS_ELEMENT_TYPE_UINT , 128 },
{ ZYDIS_ELEMENT_TYPE_UINT , 256 },
{ ZYDIS_ELEMENT_TYPE_FLOAT16 , 16 },
{ ZYDIS_ELEMENT_TYPE_FLOAT32 , 32 },
{ ZYDIS_ELEMENT_TYPE_FLOAT64 , 64 },
{ ZYDIS_ELEMENT_TYPE_FLOAT80 , 80 },
{ ZYDIS_ELEMENT_TYPE_LONGBCD , 80 }
};
ZYDIS_ASSERT((element >= 0) && (element < ZYDIS_ARRAY_SIZE(lookup)));
*type = lookup[element].type;
*size = lookup[element].size;
}
/* ---------------------------------------------------------------------------------------------- */
/* ============================================================================================== */

View File

@ -210,6 +210,23 @@ ZydisRegisterClass ZydisRegisterGetClass(ZydisRegister reg)
ZydisRegisterWidth ZydisRegisterGetWidth(ZydisRegister reg)
{
// Special cases
switch (reg)
{
case ZYDIS_REGISTER_IP:
case ZYDIS_REGISTER_FLAGS:
return 16;
case ZYDIS_REGISTER_EIP:
case ZYDIS_REGISTER_EFLAGS:
return 32;
case ZYDIS_REGISTER_RIP:
case ZYDIS_REGISTER_RFLAGS:
return 64;
default:
break;
}
// Register classes
for (unsigned i = 0; i < registerMapCount; ++i)
{
if ((reg >= registerMap[i].lo) && (reg <= registerMap[i].hi))
@ -222,6 +239,23 @@ ZydisRegisterWidth ZydisRegisterGetWidth(ZydisRegister reg)
ZydisRegisterWidth ZydisRegisterGetWidth64(ZydisRegister reg)
{
// Special cases
switch (reg)
{
case ZYDIS_REGISTER_IP:
case ZYDIS_REGISTER_FLAGS:
return 16;
case ZYDIS_REGISTER_EIP:
case ZYDIS_REGISTER_EFLAGS:
return 32;
case ZYDIS_REGISTER_RIP:
case ZYDIS_REGISTER_RFLAGS:
return 64;
default:
break;
}
// Register classes
for (unsigned i = 0; i < registerMapCount; ++i)
{
if ((reg >= registerMap[i].lo) && (reg <= registerMap[i].hi))