Minor refactorings and changes to the instruction-formatter

- The formatter now makes use of the format-macros in inttypes.h for better portability
- Added formatter-hook ZYDIS_FORMATTER_HOOK_PRINT_SEGMENT
This commit is contained in:
flobernd 2016-11-26 18:41:58 +01:00
parent 83f41f0f55
commit e481c3e401
2 changed files with 74 additions and 48 deletions

View File

@ -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;

View File

@ -29,6 +29,7 @@
#include <stdint.h>
#include <string.h>
#include <ctype.h>
#include <inttypes.h>
#include <assert.h>
#include <Zydis/Status.h>
#include <Zydis/Formatter.h>
@ -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;