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

@ -252,6 +252,11 @@ enum ZydisFormatterHookTypes
* optional size-specifier. * optional size-specifier.
*/ */
ZYDIS_FORMATTER_HOOK_PRINT_OPERANDSIZE, 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 * @brief This function is called right after formatting an operand to print the optional
* avx-512 operand decorator. * 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 * This function type is used for the @c ZYDIS_FORMATTER_HOOK_PRE and
* @c ZYDIS_FORMATTER_HOOK_POST hook-types. * @c ZYDIS_FORMATTER_HOOK_POST hook-types.
*/ */
typedef ZydisStatus (*ZydisFormatterNotifyFunc)(ZydisInstructionFormatter* fornatter, typedef ZydisStatus (*ZydisFormatterNotifyFunc)(ZydisInstructionFormatter* formatter,
ZydisInstructionInfo* info); ZydisInstructionInfo* info);
/** /**
@ -299,7 +304,7 @@ typedef ZydisStatus (*ZydisFormatterNotifyFunc)(ZydisInstructionFormatter* forna
* This function type is used for the @c ZYDIS_FORMATTER_HOOK_FORMAT_INSTRUCTION, * 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. * @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); 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 * without increasing the buffer-pointer is valid and will cause the formatter to omit the current
* operand. * operand.
* *
* Returning @c ZYDIS_STATUS_SUCCESS in @c ZYDIS_FORMATTER_HOOK_PRINT_OPERANDSIZE or * Returning @c ZYDIS_STATUS_SUCCESS in @c ZYDIS_FORMATTER_HOOK_PRINT_OPERANDSIZE,
* @c ZYDIS_FORMATTER_HOOK_PRINT_DECORATOR without increasing the buffer-pointer is valid and * @c ZYDIS_FORMATTER_HOOK_PRINT_SEGMENT or @c ZYDIS_FORMATTER_HOOK_PRINT_DECORATOR without
* signals that no operand-size or decorator should be printed for the current operand. * 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. * 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_FORMAT_OPERAND_REG,
* @c ZYDIS_FORMATTER_HOOK_FORMAT_OPERAND_MEM, @c ZYDIS_FORMATTER_HOOK_FORMAT_OPERAND_PTR, * @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_FORMAT_OPERAND_IMM, @c ZYDIS_FORMATTER_HOOK_PRINT_OPERANDSIZE,
* @c ZYDIS_FORMATTER_HOOK_PRINT_DECORATOR hook-types. * @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); 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. * 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, char** buffer, size_t bufferLen, ZydisInstructionInfo* info, ZydisOperandInfo* operand,
uint64_t address); uint64_t address);
@ -376,6 +382,7 @@ typedef struct ZydisInstructionFormatter_
ZydisFormatterFormatOperandFunc funcFormatOperandPtr; ZydisFormatterFormatOperandFunc funcFormatOperandPtr;
ZydisFormatterFormatOperandFunc funcFormatOperandImm; ZydisFormatterFormatOperandFunc funcFormatOperandImm;
ZydisFormatterFormatOperandFunc funcPrintOperandSize; ZydisFormatterFormatOperandFunc funcPrintOperandSize;
ZydisFormatterFormatOperandFunc funcPrintSegment;
ZydisFormatterFormatOperandFunc funcPrintDecorator; ZydisFormatterFormatOperandFunc funcPrintDecorator;
ZydisFormatterFormatAddressFunc funcPrintAddress; ZydisFormatterFormatAddressFunc funcPrintAddress;
const char* prefixHEX; const char* prefixHEX;

View File

@ -29,6 +29,7 @@
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
#include <inttypes.h>
#include <assert.h> #include <assert.h>
#include <Zydis/Status.h> #include <Zydis/Status.h>
#include <Zydis/Formatter.h> #include <Zydis/Formatter.h>
@ -283,36 +284,6 @@ static ZydisStatus ZydisFormatterFormatOperandMemIntel(ZydisInstructionFormatter
char* bufEnd = *buffer + bufferLen; 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( ZYDIS_CHECK(
ZydisStringBufferAppend(buffer, bufEnd - *buffer, ZYDIS_STRBUF_APPEND_MODE_DEFAULT, "[")); 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; address = (uint64_t)operand->mem.disp.value.sqword;
} else } else
{ {
// EIP/RIP-relative address // EIP/RIP-relative
ZYDIS_CHECK(ZydisUtilsCalcAbsoluteTargetAddress(info, operand, &address)); ZYDIS_CHECK(ZydisUtilsCalcAbsoluteTargetAddress(info, operand, &address));
} }
ZYDIS_CHECK(formatter->funcPrintAddress(formatter, buffer, bufEnd - *buffer, ZYDIS_CHECK(formatter->funcPrintAddress(formatter, buffer, bufEnd - *buffer,
@ -372,7 +343,8 @@ static ZydisStatus ZydisFormatterFormatOperandMemIntel(ZydisInstructionFormatter
(operand->mem.index != ZYDIS_REGISTER_NONE))) (operand->mem.index != ZYDIS_REGISTER_NONE)))
{ {
ZYDIS_CHECK(ZydisStringBufferAppendFormat(buffer, bufEnd - *buffer, 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 } else
{ {
const char* sign = const char* sign =
@ -380,7 +352,7 @@ static ZydisStatus ZydisFormatterFormatOperandMemIntel(ZydisInstructionFormatter
(operand->mem.index == ZYDIS_REGISTER_NONE)) ? "" : "+"; (operand->mem.index == ZYDIS_REGISTER_NONE)) ? "" : "+";
ZYDIS_CHECK(ZydisStringBufferAppendFormat(buffer, bufEnd - *buffer, ZYDIS_CHECK(ZydisStringBufferAppendFormat(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, 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, 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, static ZydisStatus ZydisFormatterFormatOperandImmIntel(ZydisInstructionFormatter* formatter,
@ -433,10 +405,10 @@ static ZydisStatus ZydisFormatterFormatOperandImmIntel(ZydisInstructionFormatter
if (printSignedHEX && (operand->imm.value.sqword < 0)) if (printSignedHEX && (operand->imm.value.sqword < 0))
{ {
return ZydisStringBufferAppendFormat(buffer, bufferLen, 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, 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 // 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_16BIT:
case ZYDIS_DISASSEMBLER_MODE_32BIT: case ZYDIS_DISASSEMBLER_MODE_32BIT:
return ZydisStringBufferAppendFormat(buffer, bufferLen, ZYDIS_STRBUF_APPEND_MODE_DEFAULT, return ZydisStringBufferAppendFormat(buffer, bufferLen, ZYDIS_STRBUF_APPEND_MODE_DEFAULT,
"0x%08lX", address); "0x%08"PRIX64, address);
case ZYDIS_DISASSEMBLER_MODE_64BIT: case ZYDIS_DISASSEMBLER_MODE_64BIT:
return ZydisStringBufferAppendFormat(buffer, bufferLen, ZYDIS_STRBUF_APPEND_MODE_DEFAULT, return ZydisStringBufferAppendFormat(buffer, bufferLen, ZYDIS_STRBUF_APPEND_MODE_DEFAULT,
"0x%016llX", address); "0x%016"PRIX64, address);
default: default:
return ZYDIS_STATUS_INVALID_PARAMETER; return ZYDIS_STATUS_INVALID_PARAMETER;
} }
@ -601,6 +573,44 @@ static ZydisStatus ZydisFormatterPrintOperandSizeIntel(ZydisInstructionFormatter
return ZYDIS_STATUS_SUCCESS; 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, static ZydisStatus ZydisFormatterPrintDecoratorIntel(ZydisInstructionFormatter* formatter,
char** buffer, size_t bufferLen, ZydisInstructionInfo* info, ZydisOperandInfo* operand) 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, ZYDIS_CHECK(formatter->funcPrintOperandSize(formatter, buffer, bufEnd - *buffer,
info, &info->operand[i])); info, &info->operand[i]));
ZYDIS_CHECK(formatter->funcPrintSegment(formatter, buffer, bufEnd - *buffer,
info, &info->operand[i]));
const char* bufTemp = *buffer; const char* bufTemp = *buffer;
ZYDIS_CHECK(formatter->funcFormatOperandMem(formatter, buffer, bufEnd - *buffer, ZYDIS_CHECK(formatter->funcFormatOperandMem(formatter, buffer, bufEnd - *buffer,
info, &info->operand[i])); info, &info->operand[i]));
@ -821,6 +833,7 @@ ZydisStatus ZydisFormatterInitInstructionFormatterEx(
formatter->funcFormatOperandPtr = &ZydisFormatterFormatOperandPtrIntel; formatter->funcFormatOperandPtr = &ZydisFormatterFormatOperandPtrIntel;
formatter->funcFormatOperandImm = &ZydisFormatterFormatOperandImmIntel; formatter->funcFormatOperandImm = &ZydisFormatterFormatOperandImmIntel;
formatter->funcPrintOperandSize = &ZydisFormatterPrintOperandSizeIntel; formatter->funcPrintOperandSize = &ZydisFormatterPrintOperandSizeIntel;
formatter->funcPrintSegment = &ZydisFormatterPrintSegmentIntel;
formatter->funcPrintDecorator = &ZydisFormatterPrintDecoratorIntel; formatter->funcPrintDecorator = &ZydisFormatterPrintDecoratorIntel;
formatter->funcPrintAddress = &ZydisFormatterPrintAddressIntel; formatter->funcPrintAddress = &ZydisFormatterPrintAddressIntel;
break; break;
@ -874,6 +887,9 @@ ZydisStatus ZydisFormatterSetHook(ZydisInstructionFormatter* formatter,
case ZYDIS_FORMATTER_HOOK_PRINT_OPERANDSIZE: case ZYDIS_FORMATTER_HOOK_PRINT_OPERANDSIZE:
*callback = *(const void**)&formatter->funcPrintOperandSize; *callback = *(const void**)&formatter->funcPrintOperandSize;
break; break;
case ZYDIS_FORMATTER_HOOK_PRINT_SEGMENT:
*callback = *(const void**)&formatter->funcPrintSegment;
break;
case ZYDIS_FORMATTER_HOOK_PRINT_DECORATOR: case ZYDIS_FORMATTER_HOOK_PRINT_DECORATOR:
*callback = *(const void**)&formatter->funcPrintDecorator; *callback = *(const void**)&formatter->funcPrintDecorator;
break; break;
@ -923,6 +939,9 @@ ZydisStatus ZydisFormatterSetHook(ZydisInstructionFormatter* formatter,
case ZYDIS_FORMATTER_HOOK_PRINT_OPERANDSIZE: case ZYDIS_FORMATTER_HOOK_PRINT_OPERANDSIZE:
formatter->funcPrintOperandSize = *(ZydisFormatterFormatOperandFunc*)&temp; formatter->funcPrintOperandSize = *(ZydisFormatterFormatOperandFunc*)&temp;
break; break;
case ZYDIS_FORMATTER_HOOK_PRINT_SEGMENT:
formatter->funcPrintSegment = *(ZydisFormatterFormatOperandFunc*)&temp;
break;
case ZYDIS_FORMATTER_HOOK_PRINT_DECORATOR: case ZYDIS_FORMATTER_HOOK_PRINT_DECORATOR:
formatter->funcPrintDecorator = *(ZydisFormatterFormatOperandFunc*)&temp; formatter->funcPrintDecorator = *(ZydisFormatterFormatOperandFunc*)&temp;
break; break;