Improved formatting of decorators

This commit is contained in:
flobernd 2017-07-04 19:02:11 +02:00
parent 9f735b0f51
commit 8a626388ae
5 changed files with 299 additions and 186 deletions

View File

@ -50,20 +50,23 @@ typedef uint32_t ZydisDecodeGranularity;
*/ */
enum ZydisDecodeGranularities enum ZydisDecodeGranularities
{ {
/**
* @brief Defaults to `ZYDIS_DECODE_GRANULARITY_FULL`.
*/
ZYDIS_DECODE_GRANULARITY_DEFAULT, ZYDIS_DECODE_GRANULARITY_DEFAULT,
/** /**
* @brief Minimal instruction decoding without semantic analysis. * @brief Minimal instruction decoding without semantic analysis.
* *
* This mode should be sufficient, if you plan to analyse code for pure relocation purposes, * This mode provides access to the mnemonic, the instruction-length, the effective
* as it gives you access to the mnemonic, the instruction-length, displacements, immediates * operand-size, the effective address-width, some attributes (e.g. `ZYDIS_ATTRIB_IS_RELATIVE`)
* and the `ZYDIS_ATTRIB_IS_RELATIVE` attribute. * and all of the information in the `raw` field of the `ZydisDecodedInstruction` struct.
* *
* Operands, most attributes and other specific information (like AVX info) are not * Operands, most attributes and other specific information (like AVX info) are not
* accessible in this mode. * accessible in this mode.
*/ */
ZYDIS_DECODE_GRANULARITY_MINIMAL, ZYDIS_DECODE_GRANULARITY_MINIMAL,
/** /**
* @brief Full physical and semantical instruction-decoding. * @brief Full physical and semantic instruction-decoding.
*/ */
ZYDIS_DECODE_GRANULARITY_FULL ZYDIS_DECODE_GRANULARITY_FULL
}; };

View File

@ -277,6 +277,26 @@ enum ZydisFormatterHookTypes
/* ---------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------- */
/**
* @brief Defines the @c ZydisDecoratorType datatype.
*/
typedef uint8_t ZydisDecoratorType;
/**
* @brief Values that represent decorator-types.
*/
enum ZydisDecoratorTypes
{
ZYDIS_DECORATOR_TYPE_INVALID,
ZYDIS_DECORATOR_TYPE_MASK,
ZYDIS_DECORATOR_TYPE_BROADCAST,
ZYDIS_DECORATOR_TYPE_ROUNDING_CONTROL,
ZYDIS_DECORATOR_TYPE_SAE,
ZYDIS_DECORATOR_TYPE_SWIZZLE,
ZYDIS_DECORATOR_TYPE_CONVERSION,
ZYDIS_DECORATOR_TYPE_EVICTION_HINT
};
typedef struct ZydisFormatter_ ZydisFormatter; typedef struct ZydisFormatter_ ZydisFormatter;
/** /**
@ -373,6 +393,32 @@ typedef ZydisStatus (*ZydisFormatterFormatAddressFunc)(const ZydisFormatter* for
char** buffer, size_t bufferLen, ZydisDecodedInstruction* instruction, char** buffer, size_t bufferLen, ZydisDecodedInstruction* instruction,
ZydisDecodedOperand* operand, uint64_t address); ZydisDecodedOperand* operand, uint64_t address);
/**
* @brief Defines the @c ZydisFormatterFormatDecoratorFunc function pointer.
*
* @param formatter A pointer to the @c ZydisFormatter instance.
* @param buffer A pointer to the string-buffer.
* @param bufferLen The length of the string-buffer.
* @param instruction A pointer to the @c ZydisDecodedInstruction struct.
* @param operand A pointer to the @c ZydisDecodedOperand struct.
* @param type The decorator type.
* @param mask The embedded-mask register (`ZYDIS_DECORATOR_TYPE_MASK` only).
*
* @return Returning a status code other than @c ZYDIS_STATUS_SUCCESS will immediately cause the
* formatting process to fail.
*
* After appending text to the @c buffer you MUST increase the buffer-pointer by the size of the
* number of chars written.
*
* Returning @c ZYDIS_STATUS_SUCCESS without increasing the buffer-pointer is valid and will cause
* the formatter to omit the current decorator.
*
* This function type is used for the @c ZYDIS_FORMATTER_HOOK_PRINT_DECORATOR hook-type.
*/
typedef ZydisStatus (*ZydisFormatterFormatDecoratorFunc)(const ZydisFormatter* formatter,
char** buffer, size_t bufferLen, ZydisDecodedInstruction* instruction,
ZydisDecodedOperand* operand, ZydisDecoratorType type, ZydisRegister mask);
/** /**
* @brief Defines the @c ZydisFormatter struct. * @brief Defines the @c ZydisFormatter struct.
*/ */
@ -393,15 +439,10 @@ struct ZydisFormatter_
ZydisFormatterFormatOperandFunc funcFormatOperandImm; ZydisFormatterFormatOperandFunc funcFormatOperandImm;
ZydisFormatterFormatOperandFunc funcPrintOperandSize; ZydisFormatterFormatOperandFunc funcPrintOperandSize;
ZydisFormatterFormatOperandFunc funcPrintSegment; ZydisFormatterFormatOperandFunc funcPrintSegment;
ZydisFormatterFormatOperandFunc funcPrintDecorator; ZydisFormatterFormatDecoratorFunc funcPrintDecorator;
ZydisFormatterFormatAddressFunc funcPrintAddress; ZydisFormatterFormatAddressFunc funcPrintAddress;
ZydisFormatterFormatOperandFunc funcPrintDisplacement; ZydisFormatterFormatOperandFunc funcPrintDisplacement;
ZydisFormatterFormatOperandFunc funcPrintImmediate; ZydisFormatterFormatOperandFunc funcPrintImmediate;
const char* prefixHEX;
const char* prefixOCT;
const char* delimMnemonic;
const char* delimOperands;
const char* fmtDecorator; // TODO:
}; };
/* ============================================================================================== */ /* ============================================================================================== */
@ -435,13 +476,18 @@ ZYDIS_EXPORT ZydisStatus ZydisFormatterInitEx(ZydisFormatter* formatter, ZydisFo
ZydisFormatterImmediateFormat immmediateFormat); ZydisFormatterImmediateFormat immmediateFormat);
/** /**
* @brief TODO: * @brief Replaces a formatter function with a custom callback and/or retrieves the currently
* used function.
* *
* @param formatter A pointer to the @c ZydisFormatter instance. * @param formatter A pointer to the @c ZydisFormatter instance.
* @param hook The formatter hook-type. * @param hook The formatter hook-type.
* @param callback TODO: In Out * @param callback A pointer to a variable that contains the pointer of the callback function
* and receives the pointer of the currently used function.
* *
* @return A zydis status code. * @return A zydis status code.
*
* Call this function with `callback` pointing to a `NULL` value to retrieve the currently used
* function without replacing it.
*/ */
ZYDIS_EXPORT ZydisStatus ZydisFormatterSetHook(ZydisFormatter* formatter, ZYDIS_EXPORT ZydisStatus ZydisFormatterSetHook(ZydisFormatter* formatter,
ZydisFormatterHookType hook, const void** callback); ZydisFormatterHookType hook, const void** callback);

View File

@ -2026,14 +2026,14 @@ FinalizeOperand:
/* ---------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------- */
/** /**
* @brief Sets prefix-related attributes for the given instruction. * @brief Sets attributes for the given instruction.
* *
* @param context A pointer to the @c ZydisDecoderContext struct. * @param context A pointer to the @c ZydisDecoderContext struct.
* @param instruction A pointer to the @c ZydisDecodedInstruction struct. * @param instruction A pointer to the @c ZydisDecodedInstruction struct.
* @param definition A pointer to the @c ZydisInstructionDefinition struct. * @param definition A pointer to the @c ZydisInstructionDefinition struct.
*/ */
static void ZydisSetPrefixRelatedAttributes(ZydisDecoderContext* context, static void ZydisSetAttributes(ZydisDecoderContext* context, ZydisDecodedInstruction* instruction,
ZydisDecodedInstruction* instruction, const ZydisInstructionDefinition* definition) const ZydisInstructionDefinition* definition)
{ {
ZYDIS_ASSERT(context); ZYDIS_ASSERT(context);
ZYDIS_ASSERT(instruction); ZYDIS_ASSERT(instruction);
@ -4294,7 +4294,7 @@ static ZydisStatus ZydisDecodeInstruction(ZydisDecoderContext* context,
if (context->decoder->decodeGranularity == ZYDIS_DECODE_GRANULARITY_FULL) if (context->decoder->decodeGranularity == ZYDIS_DECODE_GRANULARITY_FULL)
{ {
ZydisSetPrefixRelatedAttributes(context, instruction, definition); ZydisSetAttributes(context, instruction, definition);
switch (instruction->encoding) switch (instruction->encoding)
{ {
case ZYDIS_INSTRUCTION_ENCODING_XOP: case ZYDIS_INSTRUCTION_ENCODING_XOP:

View File

@ -251,6 +251,11 @@ static ZydisStatus ZydisFormatterFormatOperandRegIntel(const ZydisFormatter* for
return ZYDIS_STATUS_INVALID_PARAMETER; return ZYDIS_STATUS_INVALID_PARAMETER;
} }
if ((operand->id == 1) && (operand->encoding == ZYDIS_OPERAND_ENCODING_MASK))
{
return ZYDIS_STATUS_SUCCESS;
}
const char* reg = ZydisRegisterGetString(operand->reg); const char* reg = ZydisRegisterGetString(operand->reg);
if (!reg) if (!reg)
{ {
@ -514,9 +519,11 @@ static ZydisStatus ZydisFormatterPrintOperandSizeIntel(const ZydisFormatter* for
switch (operand->id) switch (operand->id)
{ {
case 0: case 0:
typecast = ((instruction->operands[1].type == ZYDIS_OPERAND_TYPE_UNUSED) || typecast =
(instruction->operands[1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE) || ((instruction->operands[1].type == ZYDIS_OPERAND_TYPE_UNUSED) ||
(instruction->operands[0].size != instruction->operands[1].size)) ? instruction->operands[0].size : 0; (instruction->operands[1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE) ||
(instruction->operands[0].size != instruction->operands[1].size)) ?
instruction->operands[0].size : 0;
if (!typecast && if (!typecast &&
(instruction->operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER) && (instruction->operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER) &&
(instruction->operands[1].reg == ZYDIS_REGISTER_CL)) (instruction->operands[1].reg == ZYDIS_REGISTER_CL))
@ -539,8 +546,9 @@ static ZydisStatus ZydisFormatterPrintOperandSizeIntel(const ZydisFormatter* for
case 1: case 1:
case 2: case 2:
typecast = typecast =
(instruction->operands[operand->id - 1].size != instruction->operands[operand->id].size) ? (instruction->operands[operand->id - 1].size !=
instruction->operands[operand->id].size : 0; instruction->operands[operand->id].size) ?
instruction->operands[operand->id].size : 0;
break; break;
default: default:
break; break;
@ -627,7 +635,7 @@ static ZydisStatus ZydisFormatterPrintSegmentIntel(const ZydisFormatter* formatt
static ZydisStatus ZydisFormatterPrintDecoratorIntel(const ZydisFormatter* formatter, static ZydisStatus ZydisFormatterPrintDecoratorIntel(const ZydisFormatter* formatter,
char** buffer, size_t bufferLen, ZydisDecodedInstruction* instruction, char** buffer, size_t bufferLen, ZydisDecodedInstruction* instruction,
ZydisDecodedOperand* operand) ZydisDecodedOperand* operand, ZydisDecoratorType type, ZydisRegister mask)
{ {
if (!formatter || !buffer || !*buffer || (bufferLen <= 0) || !instruction || !operand) if (!formatter || !buffer || !*buffer || (bufferLen <= 0) || !instruction || !operand)
{ {
@ -635,194 +643,197 @@ static ZydisStatus ZydisFormatterPrintDecoratorIntel(const ZydisFormatter* forma
} }
const char* bufEnd = *buffer + bufferLen; const char* bufEnd = *buffer + bufferLen;
switch (type)
if (operand->id == 1)
{ {
if ((operand->type == ZYDIS_OPERAND_TYPE_REGISTER) && case ZYDIS_DECORATOR_TYPE_MASK:
(operand->encoding == ZYDIS_OPERAND_ENCODING_MASK) && {
(operand->reg != ZYDIS_REGISTER_K0)) if (mask != ZYDIS_REGISTER_K0)
{ {
const char* reg = ZydisRegisterGetString(operand->reg); const char* reg = ZydisRegisterGetString(mask);
if (!reg) if (!reg)
{ {
return ZYDIS_STATUS_INVALID_PARAMETER; return ZYDIS_STATUS_INVALID_PARAMETER;
} }
ZYDIS_CHECK(ZydisStringBufferAppendFormat(buffer, bufEnd - *buffer, ZYDIS_APPENDMODE, ZYDIS_CHECK(ZydisStringBufferAppendFormat(
" {%s}", reg)); buffer, bufEnd - *buffer, ZYDIS_APPENDMODE, " {%s}", reg));
if (instruction->avx.maskMode == ZYDIS_MASK_MODE_ZERO) if (instruction->avx.maskMode == ZYDIS_MASK_MODE_ZERO)
{ {
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer, ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {z}")); ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {z}"));
} }
}
} else
{
if (instruction->operands[operand->id].type == ZYDIS_OPERAND_TYPE_MEMORY)
{
if (!instruction->avx.broadcast.isStatic)
{
switch (instruction->avx.broadcast.mode)
{
case ZYDIS_BROADCAST_MODE_INVALID:
break;
case ZYDIS_BROADCAST_MODE_1_TO_2:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {1to2}"));
break;
case ZYDIS_BROADCAST_MODE_1_TO_4:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {1to4}"));
break;
case ZYDIS_BROADCAST_MODE_1_TO_8:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {1to8}"));
break;
case ZYDIS_BROADCAST_MODE_1_TO_16:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {1to16}"));
break;
case ZYDIS_BROADCAST_MODE_4_TO_8:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {4to8}"));
break;
case ZYDIS_BROADCAST_MODE_4_TO_16:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {4to16}"));
break;
default:
return ZYDIS_STATUS_INVALID_PARAMETER;
}
}
switch (instruction->avx.conversionMode)
{
case ZYDIS_CONVERSION_MODE_INVALID:
break;
case ZYDIS_CONVERSION_MODE_FLOAT16:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {float16}"));
break;
case ZYDIS_CONVERSION_MODE_SINT8:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {sint8}"));
break;
case ZYDIS_CONVERSION_MODE_UINT8:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {uint8}"));
break;
case ZYDIS_CONVERSION_MODE_SINT16:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {sint16}"));
break;
case ZYDIS_CONVERSION_MODE_UINT16:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {uint16}"));
break;
default:
return ZYDIS_STATUS_INVALID_PARAMETER;
}
if (instruction->avx.hasEvictionHint)
{
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {eh}"));
}
} }
break;
if ((operand->id == (instruction->operandCount - 1)) || }
((operand->id != (instruction->operandCount - 1)) && case ZYDIS_DECORATOR_TYPE_BROADCAST:
(instruction->operands[operand->id + 1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE))) if (!instruction->avx.broadcast.isStatic)
{ {
if (instruction->avx.hasSAE) switch (instruction->avx.broadcast.mode)
{ {
switch (instruction->avx.roundingMode) case ZYDIS_BROADCAST_MODE_INVALID:
{
case ZYDIS_ROUNDING_MODE_INVALID:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {sae}"));
break;
case ZYDIS_ROUNDING_MODE_RN:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {rn-sae}"));
break;
case ZYDIS_ROUNDING_MODE_RD:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {rd-sae}"));
break;
case ZYDIS_ROUNDING_MODE_RU:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {ru-sae}"));
break;
case ZYDIS_ROUNDING_MODE_RZ:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {rz-sae}"));
break;
default:
return ZYDIS_STATUS_INVALID_PARAMETER;
}
} else
{
switch (instruction->avx.roundingMode)
{
case ZYDIS_ROUNDING_MODE_INVALID:
break;
case ZYDIS_ROUNDING_MODE_RN:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {rn}"));
break;
case ZYDIS_ROUNDING_MODE_RD:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {rd}"));
break;
case ZYDIS_ROUNDING_MODE_RU:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {ru}"));
break;
case ZYDIS_ROUNDING_MODE_RZ:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {rz}"));
break;
default:
return ZYDIS_STATUS_INVALID_PARAMETER;
}
}
switch (instruction->avx.swizzleMode)
{
case ZYDIS_SWIZZLE_MODE_INVALID:
case ZYDIS_SWIZZLE_MODE_DCBA:
// Nothing to do here
break;
case ZYDIS_SWIZZLE_MODE_CDAB:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {cdab}"));
break; break;
case ZYDIS_SWIZZLE_MODE_BADC: case ZYDIS_BROADCAST_MODE_1_TO_2:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer, ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {badc}")); ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {1to2}"));
break; break;
case ZYDIS_SWIZZLE_MODE_DACB: case ZYDIS_BROADCAST_MODE_1_TO_4:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer, ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {dacb}")); ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {1to4}"));
break; break;
case ZYDIS_SWIZZLE_MODE_AAAA: case ZYDIS_BROADCAST_MODE_1_TO_8:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer, ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {aaaa}")); ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {1to8}"));
break; break;
case ZYDIS_SWIZZLE_MODE_BBBB: case ZYDIS_BROADCAST_MODE_1_TO_16:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer, ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {bbbb}")); ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {1to16}"));
break; break;
case ZYDIS_SWIZZLE_MODE_CCCC: case ZYDIS_BROADCAST_MODE_4_TO_8:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer, ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {cccc}")); ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {4to8}"));
break; break;
case ZYDIS_SWIZZLE_MODE_DDDD: case ZYDIS_BROADCAST_MODE_4_TO_16:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer, ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {dddd}")); ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {4to16}"));
break; break;
default: default:
return ZYDIS_STATUS_INVALID_PARAMETER; return ZYDIS_STATUS_INVALID_PARAMETER;
} }
} }
break;
case ZYDIS_DECORATOR_TYPE_ROUNDING_CONTROL:
if (instruction->avx.hasSAE)
{
switch (instruction->avx.roundingMode)
{
case ZYDIS_ROUNDING_MODE_INVALID:
break;
case ZYDIS_ROUNDING_MODE_RN:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {rn-sae}"));
break;
case ZYDIS_ROUNDING_MODE_RD:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {rd-sae}"));
break;
case ZYDIS_ROUNDING_MODE_RU:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {ru-sae}"));
break;
case ZYDIS_ROUNDING_MODE_RZ:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {rz-sae}"));
break;
default:
return ZYDIS_STATUS_INVALID_PARAMETER;
}
} else
{
switch (instruction->avx.roundingMode)
{
case ZYDIS_ROUNDING_MODE_INVALID:
break;
case ZYDIS_ROUNDING_MODE_RN:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {rn}"));
break;
case ZYDIS_ROUNDING_MODE_RD:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {rd}"));
break;
case ZYDIS_ROUNDING_MODE_RU:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {ru}"));
break;
case ZYDIS_ROUNDING_MODE_RZ:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {rz}"));
break;
default:
return ZYDIS_STATUS_INVALID_PARAMETER;
}
}
break;
case ZYDIS_DECORATOR_TYPE_SAE:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {sae}"));
break;
case ZYDIS_DECORATOR_TYPE_SWIZZLE:
switch (instruction->avx.swizzleMode)
{
case ZYDIS_SWIZZLE_MODE_INVALID:
case ZYDIS_SWIZZLE_MODE_DCBA:
// Nothing to do here
break;
case ZYDIS_SWIZZLE_MODE_CDAB:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {cdab}"));
break;
case ZYDIS_SWIZZLE_MODE_BADC:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {badc}"));
break;
case ZYDIS_SWIZZLE_MODE_DACB:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {dacb}"));
break;
case ZYDIS_SWIZZLE_MODE_AAAA:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {aaaa}"));
break;
case ZYDIS_SWIZZLE_MODE_BBBB:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {bbbb}"));
break;
case ZYDIS_SWIZZLE_MODE_CCCC:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {cccc}"));
break;
case ZYDIS_SWIZZLE_MODE_DDDD:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {dddd}"));
break;
default:
return ZYDIS_STATUS_INVALID_PARAMETER;
}
break;
case ZYDIS_DECORATOR_TYPE_CONVERSION:
switch (instruction->avx.conversionMode)
{
case ZYDIS_CONVERSION_MODE_INVALID:
break;
case ZYDIS_CONVERSION_MODE_FLOAT16:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {float16}"));
break;
case ZYDIS_CONVERSION_MODE_SINT8:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {sint8}"));
break;
case ZYDIS_CONVERSION_MODE_UINT8:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {uint8}"));
break;
case ZYDIS_CONVERSION_MODE_SINT16:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {sint16}"));
break;
case ZYDIS_CONVERSION_MODE_UINT16:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {uint16}"));
break;
default:
return ZYDIS_STATUS_INVALID_PARAMETER;
}
break;
case ZYDIS_DECORATOR_TYPE_EVICTION_HINT:
if (instruction->avx.hasEvictionHint)
{
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {eh}"));
}
break;
default:
return ZYDIS_STATUS_INVALID_PARAMETER;
} }
return ZYDIS_STATUS_SUCCESS; return ZYDIS_STATUS_SUCCESS;
@ -903,8 +914,55 @@ static ZydisStatus ZydisFormatterFormatInstrIntel(const ZydisFormatter* formatte
if ((instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_EVEX) || if ((instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_EVEX) ||
(instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_MVEX)) (instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_MVEX))
{ {
ZYDIS_CHECK(formatter->funcPrintDecorator(formatter, buffer, bufEnd - *buffer, if (i == 0)
instruction, &instruction->operands[i])); {
if (instruction->operands[i + 1].encoding == ZYDIS_OPERAND_ENCODING_MASK)
{
ZYDIS_CHECK(formatter->funcPrintDecorator(formatter, buffer,
bufEnd - *buffer, instruction, &instruction->operands[i],
ZYDIS_DECORATOR_TYPE_MASK, instruction->operands[i + 1].reg));
}
} else
{
if (instruction->operands[i].type == ZYDIS_OPERAND_TYPE_MEMORY)
{
ZYDIS_CHECK(formatter->funcPrintDecorator(formatter, buffer,
bufEnd - *buffer, instruction, &instruction->operands[i],
ZYDIS_DECORATOR_TYPE_BROADCAST, ZYDIS_REGISTER_NONE));
if (instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_MVEX)
{
ZYDIS_CHECK(formatter->funcPrintDecorator(formatter, buffer,
bufEnd - *buffer, instruction, &instruction->operands[i],
ZYDIS_DECORATOR_TYPE_CONVERSION, ZYDIS_REGISTER_NONE));
ZYDIS_CHECK(formatter->funcPrintDecorator(formatter, buffer,
bufEnd - *buffer, instruction, &instruction->operands[i],
ZYDIS_DECORATOR_TYPE_EVICTION_HINT, ZYDIS_REGISTER_NONE));
}
} else
{
if ((i == (instruction->operandCount - 1)) ||
(instruction->operands[i + 1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE))
{
if (instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_MVEX)
{
ZYDIS_CHECK(formatter->funcPrintDecorator(formatter, buffer,
bufEnd - *buffer, instruction, &instruction->operands[i],
ZYDIS_DECORATOR_TYPE_SWIZZLE, ZYDIS_REGISTER_NONE));
}
if (instruction->avx.roundingMode)
{
ZYDIS_CHECK(formatter->funcPrintDecorator(formatter, buffer,
bufEnd - *buffer, instruction, &instruction->operands[i],
ZYDIS_DECORATOR_TYPE_ROUNDING_CONTROL, ZYDIS_REGISTER_NONE));
} else
{
ZYDIS_CHECK(formatter->funcPrintDecorator(formatter, buffer,
bufEnd - *buffer, instruction, &instruction->operands[i],
ZYDIS_DECORATOR_TYPE_SAE, ZYDIS_REGISTER_NONE));
}
}
}
}
} }
} }
} }
@ -1079,7 +1137,7 @@ ZydisStatus ZydisFormatterSetHook(ZydisFormatter* formatter, ZydisFormatterHookT
formatter->funcPrintSegment = *(ZydisFormatterFormatOperandFunc*)&temp; formatter->funcPrintSegment = *(ZydisFormatterFormatOperandFunc*)&temp;
break; break;
case ZYDIS_FORMATTER_HOOK_PRINT_DECORATOR: case ZYDIS_FORMATTER_HOOK_PRINT_DECORATOR:
formatter->funcPrintDecorator = *(ZydisFormatterFormatOperandFunc*)&temp; formatter->funcPrintDecorator = *(ZydisFormatterFormatDecoratorFunc*)&temp;
break; break;
case ZYDIS_FORMATTER_HOOK_PRINT_ADDRESS: case ZYDIS_FORMATTER_HOOK_PRINT_ADDRESS:
formatter->funcPrintAddress = *(ZydisFormatterFormatAddressFunc*)&temp; formatter->funcPrintAddress = *(ZydisFormatterFormatAddressFunc*)&temp;

View File

@ -217,7 +217,7 @@ typedef uint8_t ZydisInternalElementType;
enum ZydisInternalElementTypes enum ZydisInternalElementTypes
{ {
ZYDIS_IELEMENT_TYPE_INVALID, ZYDIS_IELEMENT_TYPE_INVALID,
ZYDIS_IELEMENT_TYPE_VARIABLE, // TODO: Remove ZYDIS_IELEMENT_TYPE_VARIABLE,
ZYDIS_IELEMENT_TYPE_STRUCT, ZYDIS_IELEMENT_TYPE_STRUCT,
ZYDIS_IELEMENT_TYPE_INT, ZYDIS_IELEMENT_TYPE_INT,
ZYDIS_IELEMENT_TYPE_UINT, ZYDIS_IELEMENT_TYPE_UINT,
@ -270,6 +270,9 @@ typedef struct ZydisOperandDefinition_
} op; } op;
} ZydisOperandDefinition; } ZydisOperandDefinition;
/**
* @brief Values that represent implicit-register types.
*/
enum ZydisImplicitRegisterType enum ZydisImplicitRegisterType
{ {
ZYDIS_IMPLREG_TYPE_STATIC, ZYDIS_IMPLREG_TYPE_STATIC,
@ -281,6 +284,9 @@ enum ZydisImplicitRegisterType
ZYDIS_IMPLREG_TYPE_FLAGS_SSZ ZYDIS_IMPLREG_TYPE_FLAGS_SSZ
}; };
/**
* @brief Values that represent implicit-memory base-registers.
*/
enum ZydisImplicitMemBase enum ZydisImplicitMemBase
{ {
ZYDIS_IMPLMEM_BASE_ABX, ZYDIS_IMPLMEM_BASE_ABX,
@ -657,7 +663,7 @@ enum ZydisMaskPolicies
#define ZYDIS_INSTRUCTION_DEFINITION_BASE_VECTOR_EX \ #define ZYDIS_INSTRUCTION_DEFINITION_BASE_VECTOR_EX \
ZYDIS_INSTRUCTION_DEFINITION_BASE_VECTOR; \ ZYDIS_INSTRUCTION_DEFINITION_BASE_VECTOR; \
ZydisBool hasVSIB ZYDIS_BITFIELD( 1) ZydisBool hasVSIB ZYDIS_BITFIELD( 1)
/** /**
* @brief Defines the @c ZydisInstructionDefinition struct. * @brief Defines the @c ZydisInstructionDefinition struct.