diff --git a/examples/FormatterHooks.c b/examples/FormatterHooks.c index 0faa231..6336492 100644 --- a/examples/FormatterHooks.c +++ b/examples/FormatterHooks.c @@ -97,7 +97,7 @@ typedef struct ZydisCustomUserData_ /* Hook callbacks */ /* ============================================================================================== */ -ZydisFormatterFormatFunc defaultPrintMnemonic; +ZydisFormatterFunc defaultPrintMnemonic; static ZydisStatus ZydisFormatterPrintMnemonic(const ZydisFormatter* formatter, char** buffer, size_t bufferLen, const ZydisDecodedInstruction* instruction, @@ -160,7 +160,7 @@ static ZydisStatus ZydisFormatterPrintMnemonic(const ZydisFormatter* formatter, /* ---------------------------------------------------------------------------------------------- */ -ZydisFormatterFormatOperandFunc defaultFormatOperandImm; +ZydisFormatterOperandFunc defaultFormatOperandImm; static ZydisStatus ZydisFormatterFormatOperandImm(const ZydisFormatter* formatter, char** buffer, size_t bufferLen, const ZydisDecodedInstruction* instruction, @@ -194,10 +194,10 @@ void disassembleBuffer(ZydisDecoder* decoder, uint8_t* data, size_t length, Zydi if (installHooks) { - defaultPrintMnemonic = (ZydisFormatterFormatFunc)&ZydisFormatterPrintMnemonic; + defaultPrintMnemonic = (ZydisFormatterFunc)&ZydisFormatterPrintMnemonic; ZydisFormatterSetHook(&formatter, ZYDIS_FORMATTER_HOOK_PRINT_MNEMONIC, (const void**)&defaultPrintMnemonic); - defaultFormatOperandImm = (ZydisFormatterFormatOperandFunc)&ZydisFormatterFormatOperandImm; + defaultFormatOperandImm = (ZydisFormatterOperandFunc)&ZydisFormatterFormatOperandImm; ZydisFormatterSetHook(&formatter, ZYDIS_FORMATTER_HOOK_FORMAT_OPERAND_IMM, (const void**)&defaultFormatOperandImm); } diff --git a/include/Zydis/Formatter.h b/include/Zydis/Formatter.h index 955f2e7..6bc084d 100644 --- a/include/Zydis/Formatter.h +++ b/include/Zydis/Formatter.h @@ -294,7 +294,7 @@ enum ZydisFormatterHookTypes */ ZYDIS_FORMATTER_HOOK_PRE, /** - * @brief This function is called before the formatter finished formatting an instruction. + * @brief This function is called after the formatter finished formatting an instruction. */ ZYDIS_FORMATTER_HOOK_POST, /** @@ -314,6 +314,14 @@ enum ZydisFormatterHookTypes * @brief This function is called to print the instruction mnemonic. */ ZYDIS_FORMATTER_HOOK_PRINT_MNEMONIC, + /** + * @brief This function is called before the formatter starts formatting an operand. + */ + ZYDIS_FORMATTER_HOOK_PRE_OPERAND, + /** + * @brief This function is called after the formatter finished formatting an operand. + */ + ZYDIS_FORMATTER_HOOK_POST_OPERAND, /** * @brief This function is called to format an register operand. */ @@ -363,14 +371,11 @@ 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_OPERAND_SEPARATOR + ZYDIS_FORMATTER_HOOK_MAX_VALUE = ZYDIS_FORMATTER_HOOK_PRINT_IMMEDIATE }; /* ---------------------------------------------------------------------------------------------- */ @@ -404,23 +409,7 @@ enum ZydisDecoratorTypes typedef struct ZydisFormatter_ ZydisFormatter; /** - * @brief Defines the @c ZydisFormatterNotifyFunc function pointer. - * - * @param formatter A pointer to the @c ZydisFormatter instance. - * @param instruction A pointer to the @c ZydisDecodedInstruction struct. - * @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. - * - * This function type is used for the @c ZYDIS_FORMATTER_HOOK_PRE and - * @c ZYDIS_FORMATTER_HOOK_POST hook-types. - */ -typedef ZydisStatus (*ZydisFormatterNotifyFunc)(const ZydisFormatter* formatter, - const ZydisDecodedInstruction* instruction, void* userData); - -/** - * @brief Defines the @c ZydisFormatterFormatFunc function pointer. + * @brief Defines the @c ZydisFormatterFunc function pointer. * * @param formatter A pointer to the @c ZydisFormatter instance. * @param buffer A pointer to the string-buffer. @@ -434,14 +423,15 @@ typedef ZydisStatus (*ZydisFormatterNotifyFunc)(const ZydisFormatter* formatter, * After appending text to the @c buffer you MUST increase the buffer-pointer by the size of the * number of chars written. Not increasing the buffer-pointer will cause unexpected behavior. * - * This function type is used for the @c ZYDIS_FORMATTER_HOOK_FORMAT_INSTRUCTION, - * @c ZYDIS_FORMATTER_HOOK_PRINT_PREFIXES and @c ZYDIS_FORMATTER_HOOK_PRINT_MNEMONIC hook-types. + * This function type is used for the @c ZYDIS_FORMATTER_HOOK_PRE, @c ZYDIS_FORMATTER_HOOK_POST, + * @c ZYDIS_FORMATTER_HOOK_FORMAT_INSTRUCTION, @c ZYDIS_FORMATTER_HOOK_PRINT_PREFIXES and + * @c ZYDIS_FORMATTER_HOOK_PRINT_MNEMONIC hook-types. */ -typedef ZydisStatus (*ZydisFormatterFormatFunc)(const ZydisFormatter* formatter, - char** buffer, ZydisUSize bufferLen, const ZydisDecodedInstruction* instruction, void* userData); +typedef ZydisStatus (*ZydisFormatterFunc)(const ZydisFormatter* formatter, char** buffer, + ZydisUSize bufferLen, const ZydisDecodedInstruction* instruction, void* userData); /** - * @brief Defines the @c ZydisFormatterFormatOperandFunc function pointer. + * @brief Defines the @c ZydisFormatterOperandFunc function pointer. * * @param formatter A pointer to the @c ZydisFormatter instance. * @param buffer A pointer to the string-buffer. @@ -467,19 +457,20 @@ typedef ZydisStatus (*ZydisFormatterFormatFunc)(const ZydisFormatter* formatter, * * Not increasing the buffer-pointer for any other hook-type will cause unexpected behavior. * - * This function type is used for the @c ZYDIS_FORMATTER_HOOK_FORMAT_OPERAND_REG, + * This function type is used for the @c ZYDIS_FORMATTER_HOOK_PRE_OPERAND, + * @c ZYDIS_FORMATTER_HOOK_POST_OPERAND, @c ZYDIS_FORMATTER_HOOK_FORMAT_OPERAND_REG * @c ZYDIS_FORMATTER_HOOK_FORMAT_OPERAND_MEM, @c ZYDIS_FORMATTER_HOOK_FORMAT_OPERAND_PTR, * @c ZYDIS_FORMATTER_HOOK_FORMAT_OPERAND_IMM, @c ZYDIS_FORMATTER_HOOK_PRINT_OPERANDSIZE, * @c ZYDIS_FORMATTER_HOOK_PRINT_SEGMENT, @c ZYDIS_FORMATTER_HOOK_PRINT_DECORATOR, * @c ZYDIS_FORMATTER_HOOK_PRINT_DISPLACEMENT and @c ZYDIS_FORMATTER_HOOK_PRINT_IMMEDIATE * hook-types. */ -typedef ZydisStatus (*ZydisFormatterFormatOperandFunc)(const ZydisFormatter* formatter, +typedef ZydisStatus (*ZydisFormatterOperandFunc)(const ZydisFormatter* formatter, char** buffer, ZydisUSize bufferLen, const ZydisDecodedInstruction* instruction, const ZydisDecodedOperand* operand, void* userData); /** - * @brief Defines the @c ZydisFormatterFormatAddressFunc function pointer. + * @brief Defines the @c ZydisFormatterAddressFunc function pointer. * * @param formatter A pointer to the @c ZydisFormatter instance. * @param buffer A pointer to the string-buffer. @@ -497,12 +488,12 @@ typedef ZydisStatus (*ZydisFormatterFormatOperandFunc)(const ZydisFormatter* for * * This function type is used for the @c ZYDIS_FORMATTER_HOOK_PRINT_ADDRESS hook-type. */ -typedef ZydisStatus (*ZydisFormatterFormatAddressFunc)(const ZydisFormatter* formatter, +typedef ZydisStatus (*ZydisFormatterAddressFunc)(const ZydisFormatter* formatter, char** buffer, ZydisUSize bufferLen, const ZydisDecodedInstruction* instruction, const ZydisDecodedOperand* operand, ZydisU64 address, void* userData); /** - * @brief Defines the @c ZydisFormatterFormatDecoratorFunc function pointer. + * @brief Defines the @c ZydisFormatterDecoratorFunc function pointer. * * @param formatter A pointer to the @c ZydisFormatter instance. * @param buffer A pointer to the string-buffer. @@ -523,33 +514,10 @@ typedef ZydisStatus (*ZydisFormatterFormatAddressFunc)(const ZydisFormatter* for * * This function type is used for the @c ZYDIS_FORMATTER_HOOK_PRINT_DECORATOR hook-type. */ -typedef ZydisStatus (*ZydisFormatterFormatDecoratorFunc)(const ZydisFormatter* formatter, +typedef ZydisStatus (*ZydisFormatterDecoratorFunc)(const ZydisFormatter* formatter, 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 */ /* ---------------------------------------------------------------------------------------------- */ @@ -571,22 +539,23 @@ struct ZydisFormatter_ ZydisU8 hexPaddingAddress; ZydisU8 hexPaddingDisplacement; ZydisU8 hexPaddingImmediate; - ZydisFormatterNotifyFunc funcPre; - ZydisFormatterNotifyFunc funcPost; - ZydisFormatterFormatFunc funcFormatInstruction; - ZydisFormatterFormatFunc funcPrintPrefixes; - ZydisFormatterFormatFunc funcPrintMnemonic; - ZydisFormatterFormatOperandFunc funcFormatOperandReg; - ZydisFormatterFormatOperandFunc funcFormatOperandMem; - ZydisFormatterFormatOperandFunc funcFormatOperandPtr; - ZydisFormatterFormatOperandFunc funcFormatOperandImm; - ZydisFormatterFormatOperandFunc funcPrintOperandSize; - ZydisFormatterFormatOperandFunc funcPrintSegment; - ZydisFormatterFormatDecoratorFunc funcPrintDecorator; - ZydisFormatterFormatAddressFunc funcPrintAddress; - ZydisFormatterFormatOperandFunc funcPrintDisplacement; - ZydisFormatterFormatOperandFunc funcPrintImmediate; - ZydisFormatterPrintOperandSeparatorFunc funcPrintOperandSeparator; + ZydisFormatterFunc funcPre; + ZydisFormatterFunc funcPost; + ZydisFormatterFunc funcFormatInstruction; + ZydisFormatterFunc funcPrintPrefixes; + ZydisFormatterFunc funcPrintMnemonic; + ZydisFormatterOperandFunc funcPreOperand; + ZydisFormatterOperandFunc funcPostOperand; + ZydisFormatterOperandFunc funcFormatOperandReg; + ZydisFormatterOperandFunc funcFormatOperandMem; + ZydisFormatterOperandFunc funcFormatOperandPtr; + ZydisFormatterOperandFunc funcFormatOperandImm; + ZydisFormatterOperandFunc funcPrintOperandSize; + ZydisFormatterOperandFunc funcPrintSegment; + ZydisFormatterDecoratorFunc funcPrintDecorator; + ZydisFormatterAddressFunc funcPrintAddress; + ZydisFormatterOperandFunc funcPrintDisplacement; + ZydisFormatterOperandFunc funcPrintImmediate; }; /* ---------------------------------------------------------------------------------------------- */ diff --git a/src/Formatter.c b/src/Formatter.c index 654e591..36e4d87 100644 --- a/src/Formatter.c +++ b/src/Formatter.c @@ -776,21 +776,6 @@ 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) { @@ -814,7 +799,20 @@ static ZydisStatus ZydisFormatterFormatInstrIntel(const ZydisFormatter* formatte } bufRestore = *buffer; - ZYDIS_CHECK(formatter->funcPrintOperandSeparator(formatter, buffer, bufEnd - *buffer, i, userData)); + if (i == 0) + { + ZYDIS_CHECK(ZydisPrintStr(buffer, bufEnd - *buffer, " ", ZYDIS_LETTER_CASE_DEFAULT)); + } + else + { + ZYDIS_CHECK(ZydisPrintStr(buffer, bufEnd - *buffer, ", ", ZYDIS_LETTER_CASE_DEFAULT)); + } + + if (formatter->funcPreOperand) + { + ZYDIS_CHECK(formatter->funcPreOperand(formatter, buffer, bufferLen, instruction, + &instruction->operands[i], userData)); + } const char* bufPreOperand = *buffer; switch (instruction->operands[i].type) @@ -850,6 +848,12 @@ static ZydisStatus ZydisFormatterFormatInstrIntel(const ZydisFormatter* formatte return ZYDIS_STATUS_INVALID_PARAMETER; } + if (formatter->funcPostOperand) + { + ZYDIS_CHECK(formatter->funcPostOperand(formatter, buffer, bufferLen, instruction, + &instruction->operands[i], userData)); + } + if (bufPreOperand == *buffer) { // Omit whole operand, if the buffer did not change during the formatting-callback @@ -948,7 +952,6 @@ ZydisStatus ZydisFormatterInit(ZydisFormatter* formatter, ZydisFormatterStyle st formatter->funcPrintAddress = &ZydisFormatterPrintAddressIntel; formatter->funcPrintDisplacement = &ZydisFormatterPrintDisplacementIntel; formatter->funcPrintImmediate = &ZydisFormatterPrintImmediateIntel; - formatter->funcPrintOperandSeparator = &ZydisFormatterPrintOperandSeparatorIntel; break; default: return ZYDIS_STATUS_INVALID_PARAMETER; @@ -1062,6 +1065,12 @@ ZydisStatus ZydisFormatterSetHook(ZydisFormatter* formatter, ZydisFormatterHookT case ZYDIS_FORMATTER_HOOK_PRINT_MNEMONIC: *callback = *(const void**)&formatter->funcPrintMnemonic; break; + case ZYDIS_FORMATTER_HOOK_PRE_OPERAND: + *callback = *(const void**)&formatter->funcPreOperand; + break; + case ZYDIS_FORMATTER_HOOK_POST_OPERAND: + *callback = *(const void**)&formatter->funcPostOperand; + break; case ZYDIS_FORMATTER_HOOK_FORMAT_OPERAND_REG: *callback = *(const void**)&formatter->funcFormatOperandReg; break; @@ -1092,9 +1101,6 @@ 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; } @@ -1109,52 +1115,55 @@ ZydisStatus ZydisFormatterSetHook(ZydisFormatter* formatter, ZydisFormatterHookT switch (hook) { case ZYDIS_FORMATTER_HOOK_PRE: - formatter->funcPre = *(ZydisFormatterNotifyFunc*)&temp; + formatter->funcPre = *(ZydisFormatterFunc*)&temp; break; case ZYDIS_FORMATTER_HOOK_POST: - formatter->funcPost = *(ZydisFormatterNotifyFunc*)&temp; + formatter->funcPost = *(ZydisFormatterFunc*)&temp; break; case ZYDIS_FORMATTER_HOOK_FORMAT_INSTRUCTION: - formatter->funcFormatInstruction = *(ZydisFormatterFormatFunc*)&temp; + formatter->funcFormatInstruction = *(ZydisFormatterFunc*)&temp; break; case ZYDIS_FORMATTER_HOOK_PRINT_PREFIXES: - formatter->funcPrintPrefixes = *(ZydisFormatterFormatFunc*)&temp; + formatter->funcPrintPrefixes = *(ZydisFormatterFunc*)&temp; break; case ZYDIS_FORMATTER_HOOK_PRINT_MNEMONIC: - formatter->funcPrintMnemonic = *(ZydisFormatterFormatFunc*)&temp; + formatter->funcPrintMnemonic = *(ZydisFormatterFunc*)&temp; + break; + case ZYDIS_FORMATTER_HOOK_PRE_OPERAND: + formatter->funcPreOperand = *(ZydisFormatterOperandFunc*)&temp; + break; + case ZYDIS_FORMATTER_HOOK_POST_OPERAND: + formatter->funcPostOperand = *(ZydisFormatterOperandFunc*)&temp; break; case ZYDIS_FORMATTER_HOOK_FORMAT_OPERAND_REG: - formatter->funcFormatOperandReg = *(ZydisFormatterFormatOperandFunc*)&temp; + formatter->funcFormatOperandReg = *(ZydisFormatterOperandFunc*)&temp; break; case ZYDIS_FORMATTER_HOOK_FORMAT_OPERAND_MEM: - formatter->funcFormatOperandMem = *(ZydisFormatterFormatOperandFunc*)&temp; + formatter->funcFormatOperandMem = *(ZydisFormatterOperandFunc*)&temp; break; case ZYDIS_FORMATTER_HOOK_FORMAT_OPERAND_PTR: - formatter->funcFormatOperandPtr = *(ZydisFormatterFormatOperandFunc*)&temp; + formatter->funcFormatOperandPtr = *(ZydisFormatterOperandFunc*)&temp; break; case ZYDIS_FORMATTER_HOOK_FORMAT_OPERAND_IMM: - formatter->funcFormatOperandImm = *(ZydisFormatterFormatOperandFunc*)&temp; + formatter->funcFormatOperandImm = *(ZydisFormatterOperandFunc*)&temp; break; case ZYDIS_FORMATTER_HOOK_PRINT_OPERANDSIZE: - formatter->funcPrintOperandSize = *(ZydisFormatterFormatOperandFunc*)&temp; + formatter->funcPrintOperandSize = *(ZydisFormatterOperandFunc*)&temp; break; case ZYDIS_FORMATTER_HOOK_PRINT_SEGMENT: - formatter->funcPrintSegment = *(ZydisFormatterFormatOperandFunc*)&temp; + formatter->funcPrintSegment = *(ZydisFormatterOperandFunc*)&temp; break; case ZYDIS_FORMATTER_HOOK_PRINT_DECORATOR: - formatter->funcPrintDecorator = *(ZydisFormatterFormatDecoratorFunc*)&temp; + formatter->funcPrintDecorator = *(ZydisFormatterDecoratorFunc*)&temp; break; case ZYDIS_FORMATTER_HOOK_PRINT_ADDRESS: - formatter->funcPrintAddress = *(ZydisFormatterFormatAddressFunc*)&temp; + formatter->funcPrintAddress = *(ZydisFormatterAddressFunc*)&temp; break; case ZYDIS_FORMATTER_HOOK_PRINT_DISPLACEMENT: - formatter->funcPrintDisplacement = *(ZydisFormatterFormatOperandFunc*)&temp; + formatter->funcPrintDisplacement = *(ZydisFormatterOperandFunc*)&temp; break; case ZYDIS_FORMATTER_HOOK_PRINT_IMMEDIATE: - formatter->funcPrintImmediate = *(ZydisFormatterFormatOperandFunc*)&temp; - break; - case ZYDIS_FORMATTER_HOOK_PRINT_OPERAND_SEPARATOR: - formatter->funcPrintOperandSeparator = *(ZydisFormatterPrintOperandSeparatorFunc*)&temp; + formatter->funcPrintImmediate = *(ZydisFormatterOperandFunc*)&temp; break; default: return ZYDIS_STATUS_INVALID_PARAMETER; @@ -1179,13 +1188,13 @@ ZydisStatus ZydisFormatterFormatInstructionEx(const ZydisFormatter* formatter, if (formatter->funcPre) { - ZYDIS_CHECK(formatter->funcPre(formatter, instruction, userData)); + ZYDIS_CHECK(formatter->funcPre(formatter, &buffer, bufferLen, instruction, userData)); } ZYDIS_CHECK( formatter->funcFormatInstruction(formatter, &buffer, bufferLen, instruction, userData)); if (formatter->funcPost) { - return formatter->funcPost(formatter, instruction, userData); + return formatter->funcPost(formatter, &buffer, bufferLen, instruction, userData); } return ZYDIS_STATUS_SUCCESS; }