diff --git a/include/Zydis/Formatter.h b/include/Zydis/Formatter.h index f54348b..3406f2c 100644 --- a/include/Zydis/Formatter.h +++ b/include/Zydis/Formatter.h @@ -246,12 +246,17 @@ enum ZydisFormatterHookTypes * Replacing this function might indirectly disable some specific calls to the * @c ZYDIS_FORMATTER_PRINT_ADDRESS function. */ - ZYDIS_FORMATTER_HOOK_FORMAT_OPERAND_IMM, + ZYDIS_FORMATTER_HOOK_FORMAT_OPERAND_IMM, /** * @brief This function is called right before formatting an memory operand to print the * optional size-specifier. */ ZYDIS_FORMATTER_HOOK_PRINT_OPERANDSIZE, + /** + * @brief This function is called right before formatting an memory operand to print the + * optional segment-register. + */ + ZYDIS_FORMATTER_HOOK_PRINT_SEGMENT, /** * @brief This function is called right after formatting an operand to print the optional * avx-512 operand decorator. @@ -279,7 +284,7 @@ typedef struct ZydisInstructionFormatter_ ZydisInstructionFormatter; * This function type is used for the @c ZYDIS_FORMATTER_HOOK_PRE and * @c ZYDIS_FORMATTER_HOOK_POST hook-types. */ -typedef ZydisStatus (*ZydisFormatterNotifyFunc)(ZydisInstructionFormatter* fornatter, +typedef ZydisStatus (*ZydisFormatterNotifyFunc)(ZydisInstructionFormatter* formatter, ZydisInstructionInfo* info); /** @@ -299,7 +304,7 @@ typedef ZydisStatus (*ZydisFormatterNotifyFunc)(ZydisInstructionFormatter* forna * 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. */ -typedef ZydisStatus (*ZydisFormatterFormatFunc)(ZydisInstructionFormatter* fornatter, +typedef ZydisStatus (*ZydisFormatterFormatFunc)(ZydisInstructionFormatter* formatter, char** buffer, size_t bufferLen, ZydisInstructionInfo* info); /** @@ -321,18 +326,19 @@ typedef ZydisStatus (*ZydisFormatterFormatFunc)(ZydisInstructionFormatter* forna * without increasing the buffer-pointer is valid and will cause the formatter to omit the current * operand. * - * Returning @c ZYDIS_STATUS_SUCCESS in @c ZYDIS_FORMATTER_HOOK_PRINT_OPERANDSIZE or - * @c ZYDIS_FORMATTER_HOOK_PRINT_DECORATOR without increasing the buffer-pointer is valid and - * signals that no operand-size or decorator should be printed for the current operand. + * Returning @c ZYDIS_STATUS_SUCCESS in @c ZYDIS_FORMATTER_HOOK_PRINT_OPERANDSIZE, + * @c ZYDIS_FORMATTER_HOOK_PRINT_SEGMENT or @c ZYDIS_FORMATTER_HOOK_PRINT_DECORATOR without + * increasing the buffer-pointer is valid and signals that the corresponding element should not be + * printed for the current operand. * * 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, * @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 and - * @c ZYDIS_FORMATTER_HOOK_PRINT_DECORATOR hook-types. + * @c ZYDIS_FORMATTER_HOOK_FORMAT_OPERAND_IMM, @c ZYDIS_FORMATTER_HOOK_PRINT_OPERANDSIZE, + * @c ZYDIS_FORMATTER_HOOK_PRINT_SEGMENT and @c ZYDIS_FORMATTER_HOOK_PRINT_DECORATOR hook-types. */ -typedef ZydisStatus (*ZydisFormatterFormatOperandFunc)(ZydisInstructionFormatter* fornatter, +typedef ZydisStatus (*ZydisFormatterFormatOperandFunc)(ZydisInstructionFormatter* formatter, char** buffer, size_t bufferLen, ZydisInstructionInfo* info, ZydisOperandInfo* operand); /** @@ -353,7 +359,7 @@ typedef ZydisStatus (*ZydisFormatterFormatOperandFunc)(ZydisInstructionFormatter * * This function type is used for the @c ZYDIS_FORMATTER_HOOK_PRINT_ADDRESS hook-type. */ -typedef ZydisStatus (*ZydisFormatterFormatAddressFunc)(ZydisInstructionFormatter* fornatter, +typedef ZydisStatus (*ZydisFormatterFormatAddressFunc)(ZydisInstructionFormatter* formatter, char** buffer, size_t bufferLen, ZydisInstructionInfo* info, ZydisOperandInfo* operand, uint64_t address); @@ -376,6 +382,7 @@ typedef struct ZydisInstructionFormatter_ ZydisFormatterFormatOperandFunc funcFormatOperandPtr; ZydisFormatterFormatOperandFunc funcFormatOperandImm; ZydisFormatterFormatOperandFunc funcPrintOperandSize; + ZydisFormatterFormatOperandFunc funcPrintSegment; ZydisFormatterFormatOperandFunc funcPrintDecorator; ZydisFormatterFormatAddressFunc funcPrintAddress; const char* prefixHEX; diff --git a/src/Formatter.c b/src/Formatter.c index d4c93a0..ca50f72 100644 --- a/src/Formatter.c +++ b/src/Formatter.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -283,36 +284,6 @@ static ZydisStatus ZydisFormatterFormatOperandMemIntel(ZydisInstructionFormatter char* bufEnd = *buffer + bufferLen; - // Display memory segment - switch (operand->mem.segment) - { - case ZYDIS_REGISTER_ES: - case ZYDIS_REGISTER_SS: - case ZYDIS_REGISTER_FS: - case ZYDIS_REGISTER_GS: - ZYDIS_CHECK(ZydisStringBufferAppendFormat(buffer, bufEnd - *buffer, ZYDIS_APPENDMODE, - "%s:", ZydisRegisterGetString(operand->mem.segment))); - break; - case ZYDIS_REGISTER_CS: - if ((formatter->flags & ZYDIS_FMTFLAG_FORCE_SEGMENTS) || - (info->prefixFlags & ZYDIS_PREFIXFLAG_HAS_SEGMENT_CS)) - { - ZYDIS_CHECK(ZydisStringBufferAppendFormat(buffer, bufEnd - *buffer, ZYDIS_APPENDMODE, - "%s:", ZydisRegisterGetString(operand->mem.segment))); - } - break; - case ZYDIS_REGISTER_DS: - if ((formatter->flags & ZYDIS_FMTFLAG_FORCE_SEGMENTS) || - (info->prefixFlags & ZYDIS_PREFIXFLAG_HAS_SEGMENT_DS)) - { - ZYDIS_CHECK(ZydisStringBufferAppendFormat(buffer, bufEnd - *buffer, ZYDIS_APPENDMODE, - "%s:", ZydisRegisterGetString(operand->mem.segment))); - } - break; - default: - return ZYDIS_STATUS_INVALID_PARAMETER; - } - ZYDIS_CHECK( ZydisStringBufferAppend(buffer, bufEnd - *buffer, ZYDIS_STRBUF_APPEND_MODE_DEFAULT, "[")); @@ -328,7 +299,7 @@ static ZydisStatus ZydisFormatterFormatOperandMemIntel(ZydisInstructionFormatter address = (uint64_t)operand->mem.disp.value.sqword; } else { - // EIP/RIP-relative address + // EIP/RIP-relative ZYDIS_CHECK(ZydisUtilsCalcAbsoluteTargetAddress(info, operand, &address)); } ZYDIS_CHECK(formatter->funcPrintAddress(formatter, buffer, bufEnd - *buffer, @@ -372,7 +343,8 @@ static ZydisStatus ZydisFormatterFormatOperandMemIntel(ZydisInstructionFormatter (operand->mem.index != ZYDIS_REGISTER_NONE))) { ZYDIS_CHECK(ZydisStringBufferAppendFormat(buffer, bufEnd - *buffer, - ZYDIS_STRBUF_APPEND_MODE_DEFAULT, "-0x%02lX", -operand->mem.disp.value.sdword)); + ZYDIS_STRBUF_APPEND_MODE_DEFAULT, + "-0x%02"PRIX32, -operand->mem.disp.value.sdword)); } else { const char* sign = @@ -380,7 +352,7 @@ static ZydisStatus ZydisFormatterFormatOperandMemIntel(ZydisInstructionFormatter (operand->mem.index == ZYDIS_REGISTER_NONE)) ? "" : "+"; ZYDIS_CHECK(ZydisStringBufferAppendFormat(buffer, bufEnd - *buffer, ZYDIS_STRBUF_APPEND_MODE_DEFAULT, - "%s0x%02lX", sign, operand->mem.disp.value.sdword)); + "%s0x%02"PRIX32, sign, operand->mem.disp.value.sdword)); } } } @@ -397,7 +369,7 @@ static ZydisStatus ZydisFormatterFormatOperandPtrIntel(ZydisInstructionFormatter } return ZydisStringBufferAppendFormat(buffer, bufferLen, ZYDIS_STRBUF_APPEND_MODE_DEFAULT, - "0x%04X:0x%08lX", operand->ptr.segment, operand->ptr.offset); + "0x%04"PRIX16":0x%08"PRIX32, operand->ptr.segment, operand->ptr.offset); } static ZydisStatus ZydisFormatterFormatOperandImmIntel(ZydisInstructionFormatter* formatter, @@ -433,10 +405,10 @@ static ZydisStatus ZydisFormatterFormatOperandImmIntel(ZydisInstructionFormatter if (printSignedHEX && (operand->imm.value.sqword < 0)) { return ZydisStringBufferAppendFormat(buffer, bufferLen, - ZYDIS_STRBUF_APPEND_MODE_DEFAULT, "-0x%02lX", -operand->imm.value.sdword); + ZYDIS_STRBUF_APPEND_MODE_DEFAULT, "-0x%02"PRIX32, -operand->imm.value.sdword); } return ZydisStringBufferAppendFormat(buffer, bufferLen, ZYDIS_STRBUF_APPEND_MODE_DEFAULT, - "0x%02lX", operand->imm.value.sdword); + "0x%02"PRIX32, operand->imm.value.sdword); } // The immediate operand contains an actual ordinal value @@ -500,10 +472,10 @@ static ZydisStatus ZydisFormatterPrintAddressIntel(ZydisInstructionFormatter* fo case ZYDIS_DISASSEMBLER_MODE_16BIT: case ZYDIS_DISASSEMBLER_MODE_32BIT: return ZydisStringBufferAppendFormat(buffer, bufferLen, ZYDIS_STRBUF_APPEND_MODE_DEFAULT, - "0x%08lX", address); + "0x%08"PRIX64, address); case ZYDIS_DISASSEMBLER_MODE_64BIT: return ZydisStringBufferAppendFormat(buffer, bufferLen, ZYDIS_STRBUF_APPEND_MODE_DEFAULT, - "0x%016llX", address); + "0x%016"PRIX64, address); default: return ZYDIS_STATUS_INVALID_PARAMETER; } @@ -601,6 +573,44 @@ static ZydisStatus ZydisFormatterPrintOperandSizeIntel(ZydisInstructionFormatter return ZYDIS_STATUS_SUCCESS; } +static ZydisStatus ZydisFormatterPrintSegmentIntel(ZydisInstructionFormatter* formatter, + char** buffer, size_t bufferLen, ZydisInstructionInfo* info, ZydisOperandInfo* operand) +{ + if (!formatter || !buffer || !*buffer || (bufferLen <= 0) || !info || !operand) + { + return ZYDIS_STATUS_INVALID_PARAMETER; + } + + switch (operand->mem.segment) + { + case ZYDIS_REGISTER_ES: + case ZYDIS_REGISTER_SS: + case ZYDIS_REGISTER_FS: + case ZYDIS_REGISTER_GS: + return ZydisStringBufferAppendFormat(buffer, bufferLen, ZYDIS_APPENDMODE, "%s:", + ZydisRegisterGetString(operand->mem.segment)); + case ZYDIS_REGISTER_CS: + if ((formatter->flags & ZYDIS_FMTFLAG_FORCE_SEGMENTS) || + (info->prefixFlags & ZYDIS_PREFIXFLAG_HAS_SEGMENT_CS)) + { + return ZydisStringBufferAppendFormat(buffer, bufferLen, ZYDIS_APPENDMODE, "%s:", + ZydisRegisterGetString(operand->mem.segment)); + } + break; + case ZYDIS_REGISTER_DS: + if ((formatter->flags & ZYDIS_FMTFLAG_FORCE_SEGMENTS) || + (info->prefixFlags & ZYDIS_PREFIXFLAG_HAS_SEGMENT_DS)) + { + return ZydisStringBufferAppendFormat(buffer, bufferLen, ZYDIS_APPENDMODE, "%s:", + ZydisRegisterGetString(operand->mem.segment)); + } + break; + default: + break; + } + return ZYDIS_STATUS_INVALID_PARAMETER; +} + static ZydisStatus ZydisFormatterPrintDecoratorIntel(ZydisInstructionFormatter* formatter, char** buffer, size_t bufferLen, ZydisInstructionInfo* info, ZydisOperandInfo* operand) { @@ -734,6 +744,8 @@ static ZydisStatus ZydisFormatterFormatInstrIntel(ZydisInstructionFormatter* for { ZYDIS_CHECK(formatter->funcPrintOperandSize(formatter, buffer, bufEnd - *buffer, info, &info->operand[i])); + ZYDIS_CHECK(formatter->funcPrintSegment(formatter, buffer, bufEnd - *buffer, + info, &info->operand[i])); const char* bufTemp = *buffer; ZYDIS_CHECK(formatter->funcFormatOperandMem(formatter, buffer, bufEnd - *buffer, info, &info->operand[i])); @@ -821,6 +833,7 @@ ZydisStatus ZydisFormatterInitInstructionFormatterEx( formatter->funcFormatOperandPtr = &ZydisFormatterFormatOperandPtrIntel; formatter->funcFormatOperandImm = &ZydisFormatterFormatOperandImmIntel; formatter->funcPrintOperandSize = &ZydisFormatterPrintOperandSizeIntel; + formatter->funcPrintSegment = &ZydisFormatterPrintSegmentIntel; formatter->funcPrintDecorator = &ZydisFormatterPrintDecoratorIntel; formatter->funcPrintAddress = &ZydisFormatterPrintAddressIntel; break; @@ -874,6 +887,9 @@ ZydisStatus ZydisFormatterSetHook(ZydisInstructionFormatter* formatter, case ZYDIS_FORMATTER_HOOK_PRINT_OPERANDSIZE: *callback = *(const void**)&formatter->funcPrintOperandSize; break; + case ZYDIS_FORMATTER_HOOK_PRINT_SEGMENT: + *callback = *(const void**)&formatter->funcPrintSegment; + break; case ZYDIS_FORMATTER_HOOK_PRINT_DECORATOR: *callback = *(const void**)&formatter->funcPrintDecorator; break; @@ -923,6 +939,9 @@ ZydisStatus ZydisFormatterSetHook(ZydisInstructionFormatter* formatter, case ZYDIS_FORMATTER_HOOK_PRINT_OPERANDSIZE: formatter->funcPrintOperandSize = *(ZydisFormatterFormatOperandFunc*)&temp; break; + case ZYDIS_FORMATTER_HOOK_PRINT_SEGMENT: + formatter->funcPrintSegment = *(ZydisFormatterFormatOperandFunc*)&temp; + break; case ZYDIS_FORMATTER_HOOK_PRINT_DECORATOR: formatter->funcPrintDecorator = *(ZydisFormatterFormatOperandFunc*)&temp; break;