Added formatter properties to set a custom hex-prefix/suffix

This commit is contained in:
flobernd 2017-11-13 13:52:02 +01:00
parent 9ccc096232
commit 5c634f71ad
4 changed files with 128 additions and 81 deletions

View File

@ -129,28 +129,40 @@ enum ZydisFormatterProperties
ZYDIS_FORMATTER_PROP_IMM_FORMAT,
/**
* @brief Controls the padding (minimum number of chars) of address values.
* @brief Sets the prefix for hexadecimal values.
*
* The default value is `2`.
* The default value is `0x`.
*/
ZYDIS_FORMATTER_PROP_ADDR_PADDING,
ZYDIS_FORMATTER_PROP_HEX_PREFIX,
/**
* @brief Controls the padding (minimum number of chars) of displacement values.
* @brief Sets the suffix for hexadecimal values.
*
* The default value is `2`.
* The default value is `NULL`.
*/
ZYDIS_FORMATTER_PROP_DISP_PADDING,
ZYDIS_FORMATTER_PROP_HEX_SUFFIX,
/**
* @brief Controls the padding (minimum number of chars) of immediate values.
* @brief Controls the padding (minimum number of chars) of hexadecimal address values.
*
* The default value is `2`.
*/
ZYDIS_FORMATTER_PROP_IMM_PADDING,
ZYDIS_FORMATTER_PROP_HEX_PADDING_ADDR,
/**
* @brief Controls the padding (minimum number of chars) of hexadecimal displacement values.
*
* The default value is `2`.
*/
ZYDIS_FORMATTER_PROP_HEX_PADDING_DISP,
/**
* @brief Controls the padding (minimum number of chars) of hexadecimal immediate values.
*
* The default value is `2`.
*/
ZYDIS_FORMATTER_PROP_HEX_PADDING_IMM,
/**
* @brief Maximum value of this enum.
*/
ZYDIS_FORMATTER_PROP_MAX_VALUE = ZYDIS_FORMATTER_PROP_IMM_PADDING
ZYDIS_FORMATTER_PROP_MAX_VALUE = ZYDIS_FORMATTER_PROP_HEX_PADDING_IMM
};
/* ---------------------------------------------------------------------------------------------- */
@ -518,9 +530,11 @@ struct ZydisFormatter_
uint8_t addressFormat;
uint8_t displacementFormat;
uint8_t immediateFormat;
uint8_t addressPadding;
uint8_t displacementPadding;
uint8_t immediatePadding;
char* hexPrefix;
char* hexSuffix;
uint8_t hexPaddingAddress;
uint8_t hexPaddingDisplacement;
uint8_t hexPaddingImmediate;
ZydisFormatterNotifyFunc funcPre;
ZydisFormatterNotifyFunc funcPost;
ZydisFormatterFormatFunc funcFormatInstruction;

View File

@ -138,15 +138,16 @@ ZydisStatus ZydisPrintDecU32(char** buffer, size_t bufferLen, uint32_t value, ui
}
ZydisStatus ZydisPrintHexU32(char** buffer, size_t bufferLen, uint32_t value, uint8_t paddingLength,
ZydisBool uppercase, ZydisBool prefix)
ZydisBool uppercase, const char* prefix, const char* suffix)
{
ZYDIS_ASSERT(buffer);
ZYDIS_ASSERT(bufferLen);
if (prefix)
{
ZYDIS_CHECK(ZydisPrintStr(buffer, bufferLen, "0x", ZYDIS_LETTER_CASE_DEFAULT));
bufferLen -= 2;
const char* bufEnd = *buffer + bufferLen;
ZYDIS_CHECK(ZydisPrintStr(buffer, bufferLen, prefix, ZYDIS_LETTER_CASE_DEFAULT));
bufferLen = bufEnd - *buffer;
}
if (bufferLen < (size_t)(paddingLength + 1))
{
@ -197,9 +198,13 @@ ZydisStatus ZydisPrintHexU32(char** buffer, size_t bufferLen, uint32_t value, ui
}
}
(*buffer)[n] = '\0';
*buffer += n;
if (suffix)
{
ZYDIS_CHECK(ZydisPrintStr(buffer, bufferLen - n, suffix, ZYDIS_LETTER_CASE_DEFAULT));
}
return ZYDIS_STATUS_SUCCESS;
}
#endif
@ -242,15 +247,16 @@ ZydisStatus ZydisPrintDecU64(char** buffer, size_t bufferLen, uint64_t value, ui
}
ZydisStatus ZydisPrintHexU64(char** buffer, size_t bufferLen, uint64_t value, uint8_t paddingLength,
ZydisBool uppercase, ZydisBool prefix)
ZydisBool uppercase, const char* prefix, const char* suffix)
{
ZYDIS_ASSERT(buffer);
ZYDIS_ASSERT(bufferLen);
if (prefix)
{
ZYDIS_CHECK(ZydisPrintStr(buffer, bufferLen, "0x", ZYDIS_LETTER_CASE_DEFAULT));
bufferLen -= 2;
const char* bufEnd = *buffer + bufferLen;
ZYDIS_CHECK(ZydisPrintStr(buffer, bufferLen, prefix, ZYDIS_LETTER_CASE_DEFAULT));
bufferLen = bufEnd - *buffer;
}
if (bufferLen < (size_t)(paddingLength + 1))
{
@ -302,9 +308,13 @@ ZydisStatus ZydisPrintHexU64(char** buffer, size_t bufferLen, uint64_t value, ui
}
}
(*buffer)[n] = '\0';
*buffer += n;
if (suffix)
{
ZYDIS_CHECK(ZydisPrintStr(buffer, bufferLen - n, suffix, ZYDIS_LETTER_CASE_DEFAULT));
}
return ZYDIS_STATUS_SUCCESS;
}
@ -369,39 +379,37 @@ ZydisStatus ZydisPrintDecS(char** buffer, size_t bufferLen, int64_t value, uint8
}
ZydisStatus ZydisPrintHexU(char** buffer, size_t bufferLen, uint64_t value, uint8_t paddingLength,
ZydisBool uppercase, ZydisBool prefix)
ZydisBool uppercase, const char* prefix, const char* suffix)
{
#ifdef ZYDIS_X64
return ZydisPrintHexU64(buffer, bufferLen, value, paddingLength, uppercase, prefix);
return ZydisPrintHexU64(buffer, bufferLen, value, paddingLength, uppercase, prefix, suffix);
#else
if (value & 0xFFFFFFFF00000000)
{
return ZydisPrintHexU64(buffer, bufferLen, value, paddingLength, uppercase, prefix);
return ZydisPrintHexU64(buffer, bufferLen, value, paddingLength, uppercase, prefix, suffix);
} else
{
return ZydisPrintHexU32(
buffer, bufferLen, (uint32_t)value, paddingLength, uppercase, prefix);
return ZydisPrintHexU32(buffer, bufferLen, (uint32_t)value, paddingLength, uppercase,
prefix, suffix);
}
#endif
}
ZydisStatus ZydisPrintHexS(char** buffer, size_t bufferLen, int64_t value, uint8_t paddingLength,
ZydisBool uppercase, ZydisBool prefix)
ZydisBool uppercase, const char* prefix, const char* suffix)
{
if (value < 0)
{
const char* bufEnd = *buffer + bufferLen;
ZYDIS_CHECK(ZydisPrintStr(buffer, bufferLen, "-", ZYDIS_LETTER_CASE_DEFAULT));
if (prefix)
{
ZYDIS_CHECK(ZydisPrintStr(buffer, bufferLen, "-0x", ZYDIS_LETTER_CASE_DEFAULT));
bufferLen -= 3;
} else
{
ZYDIS_CHECK(ZydisPrintStr(buffer, bufferLen, "-", ZYDIS_LETTER_CASE_DEFAULT));
--bufferLen;
ZYDIS_CHECK(ZydisPrintStr(buffer, bufEnd - *buffer, prefix, ZYDIS_LETTER_CASE_DEFAULT));
}
return ZydisPrintHexU(buffer, bufferLen, -value, paddingLength, uppercase, ZYDIS_FALSE);
return ZydisPrintHexU(buffer, bufEnd - *buffer, -value, paddingLength, uppercase,
NULL, suffix);
}
return ZydisPrintHexU(buffer, bufferLen, value, paddingLength, uppercase, prefix);
return ZydisPrintHexU(buffer, bufferLen, value, paddingLength, uppercase, prefix, suffix);
}
/* ---------------------------------------------------------------------------------------------- */

View File

@ -153,7 +153,8 @@ ZYDIS_NO_EXPORT ZydisStatus ZydisPrintDecS(char** buffer, size_t bufferLen, int6
* less than the @c paddingLength.
* @param uppercase Set @c TRUE to print the hexadecimal value in uppercase letters instead
* of lowercase ones.
* @param prefix Set @c TRUE to add the "0x" prefix to the hexadecimal value.
* @param prefix The string to use as prefix or `NULL`, if not needed.
* @param suffix The string to use as suffix or `NULL`, if not needed.
*
* @return @c ZYDIS_STATUS_SUCCESS, if the function succeeded, or
* @c ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE, if the size of the buffer was not
@ -163,7 +164,7 @@ ZYDIS_NO_EXPORT ZydisStatus ZydisPrintDecS(char** buffer, size_t bufferLen, int6
* successfull.
*/
ZYDIS_NO_EXPORT ZydisStatus ZydisPrintHexU(char** buffer, size_t bufferLen, uint64_t value,
uint8_t paddingLength, ZydisBool uppercase, ZydisBool prefix);
uint8_t paddingLength, ZydisBool uppercase, const char* prefix, const char* suffix);
/**
* @brief Formats the given signed ordinal @c value to its hexadecimal text-representation and
@ -176,7 +177,8 @@ ZYDIS_NO_EXPORT ZydisStatus ZydisPrintHexU(char** buffer, size_t bufferLen, uint
* less than the @c paddingLength (the sign char is ignored).
* @param uppercase Set @c TRUE to print the hexadecimal value in uppercase letters instead
* of lowercase ones.
* @param prefix Set @c TRUE to add the "0x" prefix to the hexadecimal value.
* @param prefix The string to use as prefix or `NULL`, if not needed.
* @param suffix The string to use as suffix or `NULL`, if not needed.
*
* @return @c ZYDIS_STATUS_SUCCESS, if the function succeeded, or
* @c ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE, if the size of the buffer was not
@ -186,7 +188,7 @@ ZYDIS_NO_EXPORT ZydisStatus ZydisPrintHexU(char** buffer, size_t bufferLen, uint
* successfull.
*/
ZYDIS_NO_EXPORT ZydisStatus ZydisPrintHexS(char** buffer, size_t bufferLen, int64_t value,
uint8_t paddingLength, ZydisBool uppercase, ZydisBool prefix);
uint8_t paddingLength, ZydisBool uppercase, const char* prefix, const char* suffix);
/* ---------------------------------------------------------------------------------------------- */

View File

@ -222,11 +222,11 @@ static ZydisStatus ZydisFormatterFormatOperandPtrIntel(const ZydisFormatter* for
}
char* bufEnd = *buffer + bufferLen;
ZYDIS_CHECK(ZydisPrintHexU(
buffer, bufEnd - *buffer, operand->ptr.segment, 4, ZYDIS_TRUE, ZYDIS_TRUE));
ZYDIS_CHECK(ZydisPrintHexU(buffer, bufEnd - *buffer, operand->ptr.segment, 4, ZYDIS_TRUE,
formatter->hexPrefix, formatter->hexSuffix));
ZYDIS_CHECK(ZydisPrintStr(buffer, bufEnd - *buffer, ":", ZYDIS_LETTER_CASE_DEFAULT));
return ZydisPrintHexU(
buffer, bufEnd - *buffer, operand->ptr.offset, 8, ZYDIS_TRUE, ZYDIS_TRUE);
return ZydisPrintHexU(buffer, bufEnd - *buffer, operand->ptr.offset, 8, ZYDIS_TRUE,
formatter->hexPrefix, formatter->hexSuffix);
}
static ZydisStatus ZydisFormatterFormatOperandImmIntel(const ZydisFormatter* formatter,
@ -263,10 +263,12 @@ static ZydisStatus ZydisFormatterFormatOperandImmIntel(const ZydisFormatter* for
if (printSignedHEX)
{
return ZydisPrintHexS(buffer, bufferLen, (int32_t)operand->imm.value.s,
formatter->addressPadding, ZYDIS_TRUE, ZYDIS_TRUE);
formatter->hexPaddingAddress, ZYDIS_TRUE, formatter->hexPrefix,
formatter->hexSuffix);
}
return ZydisPrintHexU(buffer, bufferLen, operand->imm.value.u, formatter->addressPadding,
ZYDIS_TRUE, ZYDIS_TRUE);
return ZydisPrintHexU(buffer, bufferLen, operand->imm.value.u,
formatter->hexPaddingAddress, ZYDIS_TRUE, formatter->hexPrefix,
formatter->hexSuffix);
}
// The immediate operand contains an actual ordinal value
@ -290,11 +292,14 @@ static ZydisStatus ZydisFormatterPrintAddressIntel(const ZydisFormatter* formatt
switch (instruction->stackWidth)
{
case 16:
return ZydisPrintHexU(buffer, bufferLen, (uint16_t)address, 4, ZYDIS_TRUE, ZYDIS_TRUE);
return ZydisPrintHexU(buffer, bufferLen, (uint16_t)address, 4, ZYDIS_TRUE,
formatter->hexPrefix, formatter->hexSuffix);
case 32:
return ZydisPrintHexU(buffer, bufferLen, (uint32_t)address, 8, ZYDIS_TRUE, ZYDIS_TRUE);
return ZydisPrintHexU(buffer, bufferLen, (uint32_t)address, 8, ZYDIS_TRUE,
formatter->hexPrefix, formatter->hexSuffix);
case 64:
return ZydisPrintHexU(buffer, bufferLen, address, 16, ZYDIS_TRUE, ZYDIS_TRUE);
return ZydisPrintHexU(buffer, bufferLen, address, 16, ZYDIS_TRUE,
formatter->hexPrefix, formatter->hexSuffix);
default:
return ZYDIS_STATUS_INVALID_PARAMETER;
}
@ -322,7 +327,8 @@ static ZydisStatus ZydisFormatterPrintDisplacementIntel(const ZydisFormatter* fo
(operand->mem.index != ZYDIS_REGISTER_NONE)))
{
return ZydisPrintHexS(buffer, bufferLen, operand->mem.disp.value,
formatter->displacementPadding, ZYDIS_TRUE, ZYDIS_TRUE);
formatter->hexPaddingDisplacement, ZYDIS_TRUE, formatter->hexPrefix,
formatter->hexSuffix);
}
char* bufEnd = *buffer + bufferLen;
if ((operand->mem.base != ZYDIS_REGISTER_NONE) ||
@ -331,7 +337,8 @@ static ZydisStatus ZydisFormatterPrintDisplacementIntel(const ZydisFormatter* fo
ZYDIS_CHECK(ZydisPrintStr(buffer, bufferLen, "+", ZYDIS_LETTER_CASE_DEFAULT));
}
return ZydisPrintHexU(buffer, bufEnd - *buffer, (uint64_t)operand->mem.disp.value,
formatter->displacementPadding, ZYDIS_TRUE, ZYDIS_TRUE);
formatter->hexPaddingDisplacement, ZYDIS_TRUE, formatter->hexPrefix,
formatter->hexSuffix);
}
return ZYDIS_STATUS_SUCCESS;
}
@ -359,16 +366,20 @@ static ZydisStatus ZydisFormatterPrintImmediateIntel(const ZydisFormatter* forma
{
case 8:
return ZydisPrintHexS(buffer, bufferLen, (int8_t)operand->imm.value.s,
formatter->immediatePadding, ZYDIS_TRUE, ZYDIS_TRUE);
formatter->hexPaddingImmediate, ZYDIS_TRUE, formatter->hexPrefix,
formatter->hexSuffix);
case 16:
return ZydisPrintHexS(buffer, bufferLen, (int16_t)operand->imm.value.s,
formatter->immediatePadding, ZYDIS_TRUE, ZYDIS_TRUE);
formatter->hexPaddingImmediate, ZYDIS_TRUE, formatter->hexPrefix,
formatter->hexSuffix);
case 32:
return ZydisPrintHexS(buffer, bufferLen, (int32_t)operand->imm.value.s,
formatter->immediatePadding, ZYDIS_TRUE, ZYDIS_TRUE);
formatter->hexPaddingImmediate, ZYDIS_TRUE, formatter->hexPrefix,
formatter->hexSuffix);
case 64:
return ZydisPrintHexS(buffer, bufferLen, operand->imm.value.s,
formatter->immediatePadding, ZYDIS_TRUE, ZYDIS_TRUE);
formatter->hexPaddingImmediate, ZYDIS_TRUE, formatter->hexPrefix,
formatter->hexSuffix);
default:
return ZYDIS_STATUS_INVALID_PARAMETER;
}
@ -377,16 +388,20 @@ static ZydisStatus ZydisFormatterPrintImmediateIntel(const ZydisFormatter* forma
{
case 8:
return ZydisPrintHexU(buffer, bufferLen, (uint8_t)operand->imm.value.u,
formatter->immediatePadding, ZYDIS_TRUE, ZYDIS_TRUE);
formatter->hexPaddingImmediate, ZYDIS_TRUE, formatter->hexPrefix,
formatter->hexSuffix);
case 16:
return ZydisPrintHexU(buffer, bufferLen, (uint16_t)operand->imm.value.u,
formatter->immediatePadding, ZYDIS_TRUE, ZYDIS_TRUE);
formatter->hexPaddingImmediate, ZYDIS_TRUE, formatter->hexPrefix,
formatter->hexSuffix);
case 32:
return ZydisPrintHexU(buffer, bufferLen, (uint32_t)operand->imm.value.u,
formatter->immediatePadding, ZYDIS_TRUE, ZYDIS_TRUE);
formatter->hexPaddingImmediate, ZYDIS_TRUE, formatter->hexPrefix,
formatter->hexSuffix);
case 64:
return ZydisPrintHexU(buffer, bufferLen, operand->imm.value.u,
formatter->immediatePadding, ZYDIS_TRUE, ZYDIS_TRUE);
formatter->hexPaddingImmediate, ZYDIS_TRUE, formatter->hexPrefix,
formatter->hexSuffix);
default:
return ZYDIS_STATUS_INVALID_PARAMETER;
}
@ -895,15 +910,17 @@ ZydisStatus ZydisFormatterInit(ZydisFormatter* formatter, ZydisFormatterStyle st
}
memset(formatter, 0, sizeof(ZydisFormatter));
formatter->letterCase = ZYDIS_LETTER_CASE_DEFAULT;
formatter->forceSegments = ZYDIS_FALSE;
formatter->forceOperandSize = ZYDIS_FALSE;
formatter->addressFormat = ZYDIS_ADDR_FORMAT_ABSOLUTE;
formatter->displacementFormat = ZYDIS_DISP_FORMAT_HEX_SIGNED;
formatter->immediateFormat = ZYDIS_IMM_FORMAT_HEX_UNSIGNED;
formatter->addressPadding = 2;
formatter->displacementPadding = 2;
formatter->immediatePadding = 2;
formatter->letterCase = ZYDIS_LETTER_CASE_DEFAULT;
formatter->forceSegments = ZYDIS_FALSE;
formatter->forceOperandSize = ZYDIS_FALSE;
formatter->addressFormat = ZYDIS_ADDR_FORMAT_ABSOLUTE;
formatter->displacementFormat = ZYDIS_DISP_FORMAT_HEX_SIGNED;
formatter->immediateFormat = ZYDIS_IMM_FORMAT_HEX_UNSIGNED;
formatter->hexPrefix = "0x";
formatter->hexSuffix = NULL;
formatter->hexPaddingAddress = 2;
formatter->hexPaddingDisplacement = 2;
formatter->hexPaddingImmediate = 2;
switch (style)
{
@ -999,26 +1016,32 @@ ZydisStatus ZydisFormatterSetProperty(ZydisFormatter* formatter,
}
formatter->immediateFormat = (uint8_t)value;
break;
case ZYDIS_FORMATTER_PROP_ADDR_PADDING:
if (value > 20)
{
return ZYDIS_STATUS_INVALID_PARAMETER;
}
formatter->addressPadding = (uint8_t)value;
case ZYDIS_FORMATTER_PROP_HEX_PREFIX:
formatter->hexPrefix = (char*)value;
break;
case ZYDIS_FORMATTER_PROP_DISP_PADDING:
if (value > 20)
{
return ZYDIS_STATUS_INVALID_PARAMETER;
}
formatter->displacementPadding = (uint8_t)value;
case ZYDIS_FORMATTER_PROP_HEX_SUFFIX:
formatter->hexSuffix = (char*)value;
break;
case ZYDIS_FORMATTER_PROP_IMM_PADDING:
case ZYDIS_FORMATTER_PROP_HEX_PADDING_ADDR:
if (value > 20)
{
return ZYDIS_STATUS_INVALID_PARAMETER;
}
formatter->immediatePadding = (uint8_t)value;
formatter->hexPaddingAddress = (uint8_t)value;
break;
case ZYDIS_FORMATTER_PROP_HEX_PADDING_DISP:
if (value > 20)
{
return ZYDIS_STATUS_INVALID_PARAMETER;
}
formatter->hexPaddingDisplacement = (uint8_t)value;
break;
case ZYDIS_FORMATTER_PROP_HEX_PADDING_IMM:
if (value > 20)
{
return ZYDIS_STATUS_INVALID_PARAMETER;
}
formatter->hexPaddingImmediate = (uint8_t)value;
break;
default:
return ZYDIS_STATUS_INVALID_PARAMETER;