From 8a626388ae57f185546375df36f3a1ace164e51d Mon Sep 17 00:00:00 2001 From: flobernd Date: Tue, 4 Jul 2017 19:02:11 +0200 Subject: [PATCH] Improved formatting of decorators --- include/Zydis/Decoder.h | 11 +- include/Zydis/Formatter.h | 64 ++++++- src/Decoder.c | 8 +- src/Formatter.c | 392 ++++++++++++++++++++++---------------- src/InstructionTable.h | 10 +- 5 files changed, 299 insertions(+), 186 deletions(-) diff --git a/include/Zydis/Decoder.h b/include/Zydis/Decoder.h index 723d2f1..63fd67e 100644 --- a/include/Zydis/Decoder.h +++ b/include/Zydis/Decoder.h @@ -50,20 +50,23 @@ typedef uint32_t ZydisDecodeGranularity; */ enum ZydisDecodeGranularities { + /** + * @brief Defaults to `ZYDIS_DECODE_GRANULARITY_FULL`. + */ ZYDIS_DECODE_GRANULARITY_DEFAULT, /** * @brief Minimal instruction decoding without semantic analysis. * - * This mode should be sufficient, if you plan to analyse code for pure relocation purposes, - * as it gives you access to the mnemonic, the instruction-length, displacements, immediates - * and the `ZYDIS_ATTRIB_IS_RELATIVE` attribute. + * This mode provides access to the mnemonic, the instruction-length, the effective + * operand-size, the effective address-width, some attributes (e.g. `ZYDIS_ATTRIB_IS_RELATIVE`) + * 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 * accessible in this mode. */ ZYDIS_DECODE_GRANULARITY_MINIMAL, /** - * @brief Full physical and semantical instruction-decoding. + * @brief Full physical and semantic instruction-decoding. */ ZYDIS_DECODE_GRANULARITY_FULL }; diff --git a/include/Zydis/Formatter.h b/include/Zydis/Formatter.h index 4501089..076a44f 100644 --- a/include/Zydis/Formatter.h +++ b/include/Zydis/Formatter.h @@ -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; /** @@ -373,6 +393,32 @@ typedef ZydisStatus (*ZydisFormatterFormatAddressFunc)(const ZydisFormatter* for char** buffer, size_t bufferLen, ZydisDecodedInstruction* instruction, 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. */ @@ -393,15 +439,10 @@ struct ZydisFormatter_ ZydisFormatterFormatOperandFunc funcFormatOperandImm; ZydisFormatterFormatOperandFunc funcPrintOperandSize; ZydisFormatterFormatOperandFunc funcPrintSegment; - ZydisFormatterFormatOperandFunc funcPrintDecorator; + ZydisFormatterFormatDecoratorFunc funcPrintDecorator; ZydisFormatterFormatAddressFunc funcPrintAddress; ZydisFormatterFormatOperandFunc funcPrintDisplacement; - ZydisFormatterFormatOperandFunc funcPrintImmediate; - const char* prefixHEX; - const char* prefixOCT; - const char* delimMnemonic; - const char* delimOperands; - const char* fmtDecorator; // TODO: + ZydisFormatterFormatOperandFunc funcPrintImmediate; }; /* ============================================================================================== */ @@ -435,13 +476,18 @@ ZYDIS_EXPORT ZydisStatus ZydisFormatterInitEx(ZydisFormatter* formatter, ZydisFo 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 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. + * + * 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, ZydisFormatterHookType hook, const void** callback); diff --git a/src/Decoder.c b/src/Decoder.c index dcfbc0b..6c23c8b 100644 --- a/src/Decoder.c +++ b/src/Decoder.c @@ -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 instruction A pointer to the @c ZydisDecodedInstruction struct. * @param definition A pointer to the @c ZydisInstructionDefinition struct. */ -static void ZydisSetPrefixRelatedAttributes(ZydisDecoderContext* context, - ZydisDecodedInstruction* instruction, const ZydisInstructionDefinition* definition) +static void ZydisSetAttributes(ZydisDecoderContext* context, ZydisDecodedInstruction* instruction, + const ZydisInstructionDefinition* definition) { ZYDIS_ASSERT(context); ZYDIS_ASSERT(instruction); @@ -4294,7 +4294,7 @@ static ZydisStatus ZydisDecodeInstruction(ZydisDecoderContext* context, if (context->decoder->decodeGranularity == ZYDIS_DECODE_GRANULARITY_FULL) { - ZydisSetPrefixRelatedAttributes(context, instruction, definition); + ZydisSetAttributes(context, instruction, definition); switch (instruction->encoding) { case ZYDIS_INSTRUCTION_ENCODING_XOP: diff --git a/src/Formatter.c b/src/Formatter.c index 032510f..0b47c0f 100644 --- a/src/Formatter.c +++ b/src/Formatter.c @@ -251,6 +251,11 @@ static ZydisStatus ZydisFormatterFormatOperandRegIntel(const ZydisFormatter* for 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); if (!reg) { @@ -514,9 +519,11 @@ static ZydisStatus ZydisFormatterPrintOperandSizeIntel(const ZydisFormatter* for switch (operand->id) { case 0: - typecast = ((instruction->operands[1].type == ZYDIS_OPERAND_TYPE_UNUSED) || - (instruction->operands[1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE) || - (instruction->operands[0].size != instruction->operands[1].size)) ? instruction->operands[0].size : 0; + typecast = + ((instruction->operands[1].type == ZYDIS_OPERAND_TYPE_UNUSED) || + (instruction->operands[1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE) || + (instruction->operands[0].size != instruction->operands[1].size)) ? + instruction->operands[0].size : 0; if (!typecast && (instruction->operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER) && (instruction->operands[1].reg == ZYDIS_REGISTER_CL)) @@ -539,8 +546,9 @@ static ZydisStatus ZydisFormatterPrintOperandSizeIntel(const ZydisFormatter* for case 1: case 2: typecast = - (instruction->operands[operand->id - 1].size != instruction->operands[operand->id].size) ? - instruction->operands[operand->id].size : 0; + (instruction->operands[operand->id - 1].size != + instruction->operands[operand->id].size) ? + instruction->operands[operand->id].size : 0; break; default: break; @@ -627,7 +635,7 @@ static ZydisStatus ZydisFormatterPrintSegmentIntel(const ZydisFormatter* formatt static ZydisStatus ZydisFormatterPrintDecoratorIntel(const ZydisFormatter* formatter, char** buffer, size_t bufferLen, ZydisDecodedInstruction* instruction, - ZydisDecodedOperand* operand) + ZydisDecodedOperand* operand, ZydisDecoratorType type, ZydisRegister mask) { if (!formatter || !buffer || !*buffer || (bufferLen <= 0) || !instruction || !operand) { @@ -635,194 +643,197 @@ static ZydisStatus ZydisFormatterPrintDecoratorIntel(const ZydisFormatter* forma } const char* bufEnd = *buffer + bufferLen; - - if (operand->id == 1) + switch (type) { - if ((operand->type == ZYDIS_OPERAND_TYPE_REGISTER) && - (operand->encoding == ZYDIS_OPERAND_ENCODING_MASK) && - (operand->reg != ZYDIS_REGISTER_K0)) + case ZYDIS_DECORATOR_TYPE_MASK: + { + if (mask != ZYDIS_REGISTER_K0) { - const char* reg = ZydisRegisterGetString(operand->reg); + const char* reg = ZydisRegisterGetString(mask); if (!reg) { return ZYDIS_STATUS_INVALID_PARAMETER; } - ZYDIS_CHECK(ZydisStringBufferAppendFormat(buffer, bufEnd - *buffer, ZYDIS_APPENDMODE, - " {%s}", reg)); + ZYDIS_CHECK(ZydisStringBufferAppendFormat( + buffer, bufEnd - *buffer, ZYDIS_APPENDMODE, " {%s}", reg)); if (instruction->avx.maskMode == ZYDIS_MASK_MODE_ZERO) { ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer, 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}")); - } + } } - - if ((operand->id == (instruction->operandCount - 1)) || - ((operand->id != (instruction->operandCount - 1)) && - (instruction->operands[operand->id + 1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE))) + break; + } + case ZYDIS_DECORATOR_TYPE_BROADCAST: + if (!instruction->avx.broadcast.isStatic) { - if (instruction->avx.hasSAE) + switch (instruction->avx.broadcast.mode) { - switch (instruction->avx.roundingMode) - { - 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}")); + case ZYDIS_BROADCAST_MODE_INVALID: break; - case ZYDIS_SWIZZLE_MODE_BADC: + case ZYDIS_BROADCAST_MODE_1_TO_2: ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer, - ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {badc}")); + ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {1to2}")); break; - case ZYDIS_SWIZZLE_MODE_DACB: + case ZYDIS_BROADCAST_MODE_1_TO_4: ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer, - ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {dacb}")); + ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {1to4}")); break; - case ZYDIS_SWIZZLE_MODE_AAAA: + case ZYDIS_BROADCAST_MODE_1_TO_8: ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer, - ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {aaaa}")); + ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {1to8}")); break; - case ZYDIS_SWIZZLE_MODE_BBBB: + case ZYDIS_BROADCAST_MODE_1_TO_16: ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer, - ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {bbbb}")); + ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {1to16}")); break; - case ZYDIS_SWIZZLE_MODE_CCCC: + case ZYDIS_BROADCAST_MODE_4_TO_8: ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer, - ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {cccc}")); + ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {4to8}")); break; - case ZYDIS_SWIZZLE_MODE_DDDD: + case ZYDIS_BROADCAST_MODE_4_TO_16: ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer, - ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {dddd}")); + ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {4to16}")); break; default: 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; @@ -903,8 +914,55 @@ static ZydisStatus ZydisFormatterFormatInstrIntel(const ZydisFormatter* formatte if ((instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_EVEX) || (instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_MVEX)) { - ZYDIS_CHECK(formatter->funcPrintDecorator(formatter, buffer, bufEnd - *buffer, - instruction, &instruction->operands[i])); + if (i == 0) + { + 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; break; case ZYDIS_FORMATTER_HOOK_PRINT_DECORATOR: - formatter->funcPrintDecorator = *(ZydisFormatterFormatOperandFunc*)&temp; + formatter->funcPrintDecorator = *(ZydisFormatterFormatDecoratorFunc*)&temp; break; case ZYDIS_FORMATTER_HOOK_PRINT_ADDRESS: formatter->funcPrintAddress = *(ZydisFormatterFormatAddressFunc*)&temp; diff --git a/src/InstructionTable.h b/src/InstructionTable.h index 2a54273..af09b54 100644 --- a/src/InstructionTable.h +++ b/src/InstructionTable.h @@ -217,7 +217,7 @@ typedef uint8_t ZydisInternalElementType; enum ZydisInternalElementTypes { ZYDIS_IELEMENT_TYPE_INVALID, - ZYDIS_IELEMENT_TYPE_VARIABLE, // TODO: Remove + ZYDIS_IELEMENT_TYPE_VARIABLE, ZYDIS_IELEMENT_TYPE_STRUCT, ZYDIS_IELEMENT_TYPE_INT, ZYDIS_IELEMENT_TYPE_UINT, @@ -270,6 +270,9 @@ typedef struct ZydisOperandDefinition_ } op; } ZydisOperandDefinition; +/** + * @brief Values that represent implicit-register types. + */ enum ZydisImplicitRegisterType { ZYDIS_IMPLREG_TYPE_STATIC, @@ -281,6 +284,9 @@ enum ZydisImplicitRegisterType ZYDIS_IMPLREG_TYPE_FLAGS_SSZ }; +/** + * @brief Values that represent implicit-memory base-registers. + */ enum ZydisImplicitMemBase { ZYDIS_IMPLMEM_BASE_ABX, @@ -657,7 +663,7 @@ enum ZydisMaskPolicies #define ZYDIS_INSTRUCTION_DEFINITION_BASE_VECTOR_EX \ ZYDIS_INSTRUCTION_DEFINITION_BASE_VECTOR; \ - ZydisBool hasVSIB ZYDIS_BITFIELD( 1) + ZydisBool hasVSIB ZYDIS_BITFIELD( 1) /** * @brief Defines the @c ZydisInstructionDefinition struct.