diff --git a/include/Zydis/Formatter.h b/include/Zydis/Formatter.h index 3f07918..955f2e7 100644 --- a/include/Zydis/Formatter.h +++ b/include/Zydis/Formatter.h @@ -363,10 +363,14 @@ enum ZydisFormatterHookTypes * @brief This function is called to print an immediate value. */ ZYDIS_FORMATTER_HOOK_PRINT_IMMEDIATE, + /** + * @brief This function is called before each operand is formatted, to print a separator. + */ + ZYDIS_FORMATTER_HOOK_PRINT_OPERAND_SEPARATOR, /** * @brief Maximum value of this enum. */ - ZYDIS_FORMATTER_HOOK_MAX_VALUE = ZYDIS_FORMATTER_HOOK_PRINT_IMMEDIATE + ZYDIS_FORMATTER_HOOK_MAX_VALUE = ZYDIS_FORMATTER_HOOK_PRINT_OPERAND_SEPARATOR }; /* ---------------------------------------------------------------------------------------------- */ @@ -523,6 +527,29 @@ typedef ZydisStatus (*ZydisFormatterFormatDecoratorFunc)(const ZydisFormatter* f char** buffer, ZydisUSize bufferLen, const ZydisDecodedInstruction* instruction, const ZydisDecodedOperand* operand, ZydisDecoratorType type, void* userData); +/** + * @brief Defines the @c ZydisFormatterPrintOperandSeparatorFunc 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 index The current index of the operand. + * @param userData A pointer to user-defined data. + * + * @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 separator. + * + * This function type is used for the @c ZYDIS_FORMATTER_HOOK_PRINT_OPERAND_SEPARATOR hook-type. + */ +typedef ZydisStatus(*ZydisFormatterPrintOperandSeparatorFunc)(const ZydisFormatter* formatter, + char** buffer, ZydisUSize bufferLen, ZydisU8 index, void* userData); + /* ---------------------------------------------------------------------------------------------- */ /* Formatter struct */ /* ---------------------------------------------------------------------------------------------- */ @@ -558,7 +585,8 @@ struct ZydisFormatter_ ZydisFormatterFormatDecoratorFunc funcPrintDecorator; ZydisFormatterFormatAddressFunc funcPrintAddress; ZydisFormatterFormatOperandFunc funcPrintDisplacement; - ZydisFormatterFormatOperandFunc funcPrintImmediate; + ZydisFormatterFormatOperandFunc funcPrintImmediate; + ZydisFormatterPrintOperandSeparatorFunc funcPrintOperandSeparator; }; /* ---------------------------------------------------------------------------------------------- */ diff --git a/src/Formatter.c b/src/Formatter.c index 75e9454..654e591 100644 --- a/src/Formatter.c +++ b/src/Formatter.c @@ -776,6 +776,21 @@ static ZydisStatus ZydisFormatterPrintDecoratorIntel(const ZydisFormatter* forma return ZYDIS_STATUS_SUCCESS; } +static ZydisStatus ZydisFormatterPrintOperandSeparatorIntel(const ZydisFormatter* formatter, + char** buffer, ZydisUSize bufferLen, ZydisU8 index, void* userData) +{ + const char* bufEnd = *buffer + bufferLen; + if (index == 0) + { + ZYDIS_CHECK(ZydisPrintStr(buffer, bufEnd - *buffer, " ", ZYDIS_LETTER_CASE_DEFAULT)); + } + else + { + ZYDIS_CHECK(ZydisPrintStr(buffer, bufEnd - *buffer, ", ", ZYDIS_LETTER_CASE_DEFAULT)); + } + return ZYDIS_STATUS_SUCCESS; +} + static ZydisStatus ZydisFormatterFormatInstrIntel(const ZydisFormatter* formatter, char** buffer, ZydisUSize bufferLen, const ZydisDecodedInstruction* instruction, void* userData) { @@ -790,7 +805,7 @@ static ZydisStatus ZydisFormatterFormatInstrIntel(const ZydisFormatter* formatte ZYDIS_CHECK( formatter->funcPrintMnemonic(formatter, buffer, bufEnd - *buffer, instruction, userData)); - char* bufRestore = *buffer; + char* bufRestore; for (ZydisU8 i = 0; i < instruction->operandCount; ++i) { if (instruction->operands[i].visibility == ZYDIS_OPERAND_VISIBILITY_HIDDEN) @@ -798,14 +813,8 @@ static ZydisStatus ZydisFormatterFormatInstrIntel(const ZydisFormatter* formatte break; } - if (i == 0) - { - ZYDIS_CHECK(ZydisPrintStr(buffer, bufEnd - *buffer, " ", ZYDIS_LETTER_CASE_DEFAULT)); - } else - { - bufRestore = *buffer; - ZYDIS_CHECK(ZydisPrintStr(buffer, bufEnd - *buffer, ", ", ZYDIS_LETTER_CASE_DEFAULT)); - } + bufRestore = *buffer; + ZYDIS_CHECK(formatter->funcPrintOperandSeparator(formatter, buffer, bufEnd - *buffer, i, userData)); const char* bufPreOperand = *buffer; switch (instruction->operands[i].type) @@ -926,19 +935,20 @@ ZydisStatus ZydisFormatterInit(ZydisFormatter* formatter, ZydisFormatterStyle st switch (style) { case ZYDIS_FORMATTER_STYLE_INTEL: - formatter->funcFormatInstruction = &ZydisFormatterFormatInstrIntel; - formatter->funcPrintPrefixes = &ZydisFormatterPrintPrefixesIntel; - formatter->funcPrintMnemonic = &ZydisFormatterPrintMnemonicIntel; - formatter->funcFormatOperandReg = &ZydisFormatterFormatOperandRegIntel; - formatter->funcFormatOperandMem = &ZydisFormatterFormatOperandMemIntel; - formatter->funcFormatOperandPtr = &ZydisFormatterFormatOperandPtrIntel; - formatter->funcFormatOperandImm = &ZydisFormatterFormatOperandImmIntel; - formatter->funcPrintOperandSize = &ZydisFormatterPrintOperandSizeIntel; - formatter->funcPrintSegment = &ZydisFormatterPrintSegmentIntel; - formatter->funcPrintDecorator = &ZydisFormatterPrintDecoratorIntel; - formatter->funcPrintAddress = &ZydisFormatterPrintAddressIntel; - formatter->funcPrintDisplacement = &ZydisFormatterPrintDisplacementIntel; - formatter->funcPrintImmediate = &ZydisFormatterPrintImmediateIntel; + formatter->funcFormatInstruction = &ZydisFormatterFormatInstrIntel; + formatter->funcPrintPrefixes = &ZydisFormatterPrintPrefixesIntel; + formatter->funcPrintMnemonic = &ZydisFormatterPrintMnemonicIntel; + formatter->funcFormatOperandReg = &ZydisFormatterFormatOperandRegIntel; + formatter->funcFormatOperandMem = &ZydisFormatterFormatOperandMemIntel; + formatter->funcFormatOperandPtr = &ZydisFormatterFormatOperandPtrIntel; + formatter->funcFormatOperandImm = &ZydisFormatterFormatOperandImmIntel; + formatter->funcPrintOperandSize = &ZydisFormatterPrintOperandSizeIntel; + formatter->funcPrintSegment = &ZydisFormatterPrintSegmentIntel; + formatter->funcPrintDecorator = &ZydisFormatterPrintDecoratorIntel; + formatter->funcPrintAddress = &ZydisFormatterPrintAddressIntel; + formatter->funcPrintDisplacement = &ZydisFormatterPrintDisplacementIntel; + formatter->funcPrintImmediate = &ZydisFormatterPrintImmediateIntel; + formatter->funcPrintOperandSeparator = &ZydisFormatterPrintOperandSeparatorIntel; break; default: return ZYDIS_STATUS_INVALID_PARAMETER; @@ -1082,6 +1092,9 @@ ZydisStatus ZydisFormatterSetHook(ZydisFormatter* formatter, ZydisFormatterHookT case ZYDIS_FORMATTER_HOOK_PRINT_IMMEDIATE: *callback = *(const void**)&formatter->funcPrintImmediate; break; + case ZYDIS_FORMATTER_HOOK_PRINT_OPERAND_SEPARATOR: + *callback = *(const void**)&formatter->funcPrintOperandSeparator; + break; default: return ZYDIS_STATUS_INVALID_PARAMETER; } @@ -1140,6 +1153,9 @@ ZydisStatus ZydisFormatterSetHook(ZydisFormatter* formatter, ZydisFormatterHookT case ZYDIS_FORMATTER_HOOK_PRINT_IMMEDIATE: formatter->funcPrintImmediate = *(ZydisFormatterFormatOperandFunc*)&temp; break; + case ZYDIS_FORMATTER_HOOK_PRINT_OPERAND_SEPARATOR: + formatter->funcPrintOperandSeparator = *(ZydisFormatterPrintOperandSeparatorFunc*)&temp; + break; default: return ZYDIS_STATUS_INVALID_PARAMETER; }