Significantly improved formatter performance

- Exchanged `vsnprintf` by custom print functions
This commit is contained in:
flobernd 2017-09-14 00:59:23 +02:00
parent 30f15afe0a
commit 01dca38516
5 changed files with 985 additions and 282 deletions

View File

@ -127,9 +127,11 @@ if (ZYDIS_FEATURE_DECODER)
"${CMAKE_CURRENT_LIST_DIR}/include/Zydis/Formatter.h"
PRIVATE
"src/DecoderData.h"
"src/FormatHelper.h"
"src/Decoder.c"
"src/DecoderData.c"
"src/Formatter.c")
"src/Formatter.c"
"src/FormatHelper.c")
endif ()
if (ZYDIS_FEATURE_ENCODER)

View File

@ -323,7 +323,7 @@ int main(int argc, char** argv)
printf("Testing %s ...\n", tests[i].encoding);
testPerformance(buffer, length, ZYDIS_DECODE_GRANULARITY_MINIMAL, ZYDIS_FALSE);
testPerformance(buffer, length, ZYDIS_DECODE_GRANULARITY_FULL , ZYDIS_FALSE);
// testPerformance(buffer, length, ZYDIS_DECODE_GRANULARITY_FULL , ZYDIS_TRUE );
testPerformance(buffer, length, ZYDIS_DECODE_GRANULARITY_FULL , ZYDIS_TRUE );
puts("");
free(buffer);

451
src/FormatHelper.c Normal file
View File

@ -0,0 +1,451 @@
/***************************************************************************************************
Zyan Disassembler Library (Zydis)
Original Author : Florian Bernd
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
***************************************************************************************************/
#include <string.h>
#include <ctype.h>
#include <FormatHelper.h>
/* ============================================================================================== */
/* Constants */
/* ============================================================================================== */
/* ---------------------------------------------------------------------------------------------- */
/* Defines */
/* ---------------------------------------------------------------------------------------------- */
#define ZYDIS_MAXCHARS_DEC_32 10
#define ZYDIS_MAXCHARS_DEC_64 20
#define ZYDIS_MAXCHARS_HEX_32 8
#define ZYDIS_MAXCHARS_HEX_64 16
/* ---------------------------------------------------------------------------------------------- */
/* Lookup Tables */
/* ---------------------------------------------------------------------------------------------- */
static uint16_t const decimalLookup[100] =
{
0x3030, 0x3130, 0x3230, 0x3330, 0x3430, 0x3530, 0x3630, 0x3730, 0x3830, 0x3930,
0x3031, 0x3131, 0x3231, 0x3331, 0x3431, 0x3531, 0x3631, 0x3731, 0x3831, 0x3931,
0x3032, 0x3132, 0x3232, 0x3332, 0x3432, 0x3532, 0x3632, 0x3732, 0x3832, 0x3932,
0x3033, 0x3133, 0x3233, 0x3333, 0x3433, 0x3533, 0x3633, 0x3733, 0x3833, 0x3933,
0x3034, 0x3134, 0x3234, 0x3334, 0x3434, 0x3534, 0x3634, 0x3734, 0x3834, 0x3934,
0x3035, 0x3135, 0x3235, 0x3335, 0x3435, 0x3535, 0x3635, 0x3735, 0x3835, 0x3935,
0x3036, 0x3136, 0x3236, 0x3336, 0x3436, 0x3536, 0x3636, 0x3736, 0x3836, 0x3936,
0x3037, 0x3137, 0x3237, 0x3337, 0x3437, 0x3537, 0x3637, 0x3737, 0x3837, 0x3937,
0x3038, 0x3138, 0x3238, 0x3338, 0x3438, 0x3538, 0x3638, 0x3738, 0x3838, 0x3938,
0x3039, 0x3139, 0x3239, 0x3339, 0x3439, 0x3539, 0x3639, 0x3739, 0x3839, 0x3939
};
/* ---------------------------------------------------------------------------------------------- */
/* ============================================================================================== */
/* Functions */
/* ============================================================================================== */
/* ---------------------------------------------------------------------------------------------- */
/* Public Functions */
/* ---------------------------------------------------------------------------------------------- */
ZydisStatus ZydisPrintStr(char** buffer, size_t bufferLen, const char* text,
ZydisLetterCase letterCase)
{
ZYDIS_ASSERT(buffer);
ZYDIS_ASSERT(bufferLen > 0);
ZYDIS_ASSERT(text);
size_t strLen = strlen(text);
if (strLen >= bufferLen)
{
return ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE;
}
memcpy(*buffer, text, strLen + 1);
switch (letterCase)
{
case ZYDIS_LETTER_CASE_LOWER:
for (size_t i = 0; i < strLen; ++i)
{
(*buffer[i]) = (char)tolower((*buffer)[i]);
}
break;
case ZYDIS_LETTER_CASE_UPPER:
for (size_t i = 0; i < strLen; ++i)
{
(*buffer)[i] = (char)toupper((*buffer)[i]);
}
break;
default:
break;
}
*buffer += strLen;
return ZYDIS_STATUS_SUCCESS;
}
ZydisStatus ZydisPrintDec32U(char** buffer, size_t bufferLen, uint32_t value, uint8_t paddingLength)
{
#ifdef ZYDIS_X64
return ZydisPrintDec64U(buffer, bufferLen, value, paddingLength);
#else
ZYDIS_ASSERT(buffer);
ZYDIS_ASSERT(bufferLen > 0);
ZYDIS_ASSERT(paddingLength <= sizeof(ZYDIS_PADDING_STRING) / sizeof(ZYDIS_PADDING_STRING[0]));
char temp[ZYDIS_MAXCHARS_DEC_32 + 1];
char *p = &temp[ZYDIS_MAXCHARS_DEC_32];
*p = '\0';
while(value >= 100)
{
uint32_t const old = value;
p -= 2;
value /= 100;
memcpy(p, &decimalLookup[old - (value * 100)], sizeof(uint16_t));
}
p -= 2;
memcpy(p, &decimalLookup[value], sizeof(uint16_t));
size_t n = &temp[ZYDIS_MAXCHARS_DEC_32] - p;
if ((bufferLen < n + 1) || (bufferLen < paddingLength + 1))
{
return ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE;
}
uintptr_t offset = 0;
if (n <= paddingLength)
{
offset = paddingLength - n + 1;
memset((*buffer), '0', offset);
}
memcpy(&(*buffer)[offset], &p[value < 10], n + 1);
*buffer += n + offset - 1;
return ZYDIS_STATUS_SUCCESS;
#endif
}
ZydisStatus ZydisPrintDec64U(char** buffer, size_t bufferLen, uint64_t value, uint8_t paddingLength)
{
ZYDIS_ASSERT(buffer);
ZYDIS_ASSERT(bufferLen > 0);
ZYDIS_ASSERT(paddingLength <= sizeof(ZYDIS_PADDING_STRING) / sizeof(ZYDIS_PADDING_STRING[0]));
char temp[ZYDIS_MAXCHARS_DEC_64 + 1];
char *p = &temp[ZYDIS_MAXCHARS_DEC_64];
*p = '\0';
while(value >= 100)
{
uint64_t const old = value;
p -= 2;
value /= 100;
memcpy(p, &decimalLookup[old - (value * 100)], sizeof(uint16_t));
}
p -= 2;
memcpy(p, &decimalLookup[value], sizeof(uint16_t));
size_t n = &temp[ZYDIS_MAXCHARS_DEC_64] - p;
if ((bufferLen < n + 1) || (bufferLen < paddingLength + 1))
{
return ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE;
}
uintptr_t offset = 0;
if (n <= paddingLength)
{
offset = paddingLength - n + 1;
memset((*buffer), '0', offset);
}
memcpy(&(*buffer)[offset], &p[value < 20], n + 1);
*buffer += n + offset - 1;
return ZYDIS_STATUS_SUCCESS;
}
ZydisStatus ZydisPrintDec8S(char** buffer, size_t bufferLen, int8_t value, uint8_t paddingLength)
{
if (value < 0)
{
ZYDIS_CHECK(ZydisPrintStr(buffer, bufferLen, "-", ZYDIS_LETTER_CASE_DEFAULT));
return ZydisPrintDec32U(buffer, bufferLen - 1, -value, paddingLength);
}
return ZydisPrintDec32U(buffer, bufferLen, value, paddingLength);
}
ZydisStatus ZydisPrintDec16S(char** buffer, size_t bufferLen, int16_t value, uint8_t paddingLength)
{
if (value < 0)
{
ZYDIS_CHECK(ZydisPrintStr(buffer, bufferLen, "-", ZYDIS_LETTER_CASE_DEFAULT));
return ZydisPrintDec32U(buffer, bufferLen - 1, -value, paddingLength);
}
return ZydisPrintDec32U(buffer, bufferLen, value, paddingLength);
}
ZydisStatus ZydisPrintDec32S(char** buffer, size_t bufferLen, int32_t value, uint8_t paddingLength)
{
if (value < 0)
{
ZYDIS_CHECK(ZydisPrintStr(buffer, bufferLen, "-", ZYDIS_LETTER_CASE_DEFAULT));
return ZydisPrintDec32U(buffer, bufferLen - 1, -value, paddingLength);
}
return ZydisPrintDec32U(buffer, bufferLen, value, paddingLength);
}
ZydisStatus ZydisPrintDec64S(char** buffer, size_t bufferLen, int64_t value, uint8_t paddingLength)
{
if (value < 0)
{
ZYDIS_CHECK(ZydisPrintStr(buffer, bufferLen, "-", ZYDIS_LETTER_CASE_DEFAULT));
return ZydisPrintDec64U(buffer, bufferLen - 1, -value, paddingLength);
}
return ZydisPrintDec64U(buffer, bufferLen, value, paddingLength);
}
ZydisStatus ZydisPrintHex32U(char** buffer, size_t bufferLen, uint32_t value, uint8_t paddingLength,
ZydisBool uppercase, ZydisBool prefix)
{
#ifdef ZYDIS_X64
return ZydisPrintHex64U(buffer, bufferLen, value, paddingLength, uppercase, prefix);
#else
ZYDIS_ASSERT(buffer);
ZYDIS_ASSERT(bufferLen);
if (prefix)
{
ZYDIS_CHECK(ZydisPrintStr(buffer, bufferLen, "0x", ZYDIS_LETTER_CASE_DEFAULT));
bufferLen -= 2;
}
if (bufferLen < paddingLength + 1)
{
return ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE;
}
if (!value)
{
uint8_t n = (paddingLength ? paddingLength : 1);
if (bufferLen < n + 1)
{
return ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE;
}
memset((*buffer), '0', n);
(*buffer)[n] = '\0';
*buffer += n;
return ZYDIS_STATUS_SUCCESS;
}
char temp[ZYDIS_MAXCHARS_HEX_32];
uint8_t n = 0;
for (int8_t i = ZYDIS_MAXCHARS_HEX_32 - 1; i >= 0; --i)
{
uint8_t v = (value >> i * 4) & 0x0F;
if (!n)
{
if (!v)
{
continue;
}
if (bufferLen <= (uint8_t)(i + 1))
{
return ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE;
}
}
if (uppercase)
{
temp[n++] = "0123456789ABCDEF"[v];
} else
{
temp[n++] = "0123456789abcdef"[v];
}
}
uint8_t offset = 0;
if (paddingLength > n)
{
offset = paddingLength - n;
memset(*buffer, '0', offset);
}
memcpy(&(*buffer)[offset], temp, n);
(*buffer)[offset + n] = '\0';
*buffer += n + offset;
return ZYDIS_STATUS_SUCCESS;
#endif
}
ZydisStatus ZydisPrintHex64U(char** buffer, size_t bufferLen, uint64_t value, uint8_t paddingLength,
ZydisBool uppercase, ZydisBool prefix)
{
ZYDIS_ASSERT(buffer);
ZYDIS_ASSERT(bufferLen);
if (prefix)
{
ZYDIS_CHECK(ZydisPrintStr(buffer, bufferLen, "0x", ZYDIS_LETTER_CASE_DEFAULT));
bufferLen -= 2;
}
if (bufferLen < paddingLength + 1)
{
return ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE;
}
if (!value)
{
uint8_t n = (paddingLength ? paddingLength : 1);
if (bufferLen < n + 1)
{
return ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE;
}
memset((*buffer), '0', n);
(*buffer)[n] = '\0';
*buffer += n;
return ZYDIS_STATUS_SUCCESS;
}
char temp[ZYDIS_MAXCHARS_HEX_64];
uint8_t n = 0;
for (int8_t i =
((value & 0xFFFFFFFF00000000) ? ZYDIS_MAXCHARS_HEX_64 : ZYDIS_MAXCHARS_HEX_32) - 1;
i >= 0; --i)
{
uint8_t v = (value >> i * 4) & 0x0F;
if (!n)
{
if (!v)
{
continue;
}
if (bufferLen <= (uint8_t)(i + 1))
{
return ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE;
}
}
if (uppercase)
{
temp[n++] = "0123456789ABCDEF"[v];
} else
{
temp[n++] = "0123456789abcdef"[v];
}
}
uint8_t offset = 0;
if (paddingLength > n)
{
offset = paddingLength - n;
memset(*buffer, '0', offset);
}
memcpy(&(*buffer)[offset], temp, n);
(*buffer)[offset + n] = '\0';
*buffer += n + offset;
return ZYDIS_STATUS_SUCCESS;
}
ZydisStatus ZydisPrintHex8S(char** buffer, size_t bufferLen, int8_t value, uint8_t paddingLength,
ZydisBool uppercase, ZydisBool prefix)
{
if (value < 0)
{
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;
}
return ZydisPrintHex32U(buffer, bufferLen, -value, paddingLength, uppercase, ZYDIS_FALSE);
}
return ZydisPrintHex32U(buffer, bufferLen, value, paddingLength, uppercase, prefix);
}
ZydisStatus ZydisPrintHex16S(char** buffer, size_t bufferLen, int16_t value, uint8_t paddingLength,
ZydisBool uppercase, ZydisBool prefix)
{
if (value < 0)
{
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;
}
return ZydisPrintHex32U(buffer, bufferLen, -value, paddingLength, uppercase, ZYDIS_FALSE);
}
return ZydisPrintHex32U(buffer, bufferLen, value, paddingLength, uppercase, prefix);
}
ZydisStatus ZydisPrintHex32S(char** buffer, size_t bufferLen, int32_t value, uint8_t paddingLength,
ZydisBool uppercase, ZydisBool prefix)
{
if (value < 0)
{
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;
}
return ZydisPrintHex32U(buffer, bufferLen, -value, paddingLength, uppercase, ZYDIS_FALSE);
}
return ZydisPrintHex32U(buffer, bufferLen, value, paddingLength, uppercase, prefix);
}
ZydisStatus ZydisPrintHex64S(char** buffer, size_t bufferLen, int64_t value, uint8_t paddingLength,
ZydisBool uppercase, ZydisBool prefix)
{
if (value < 0)
{
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;
}
return ZydisPrintHex64U(buffer, bufferLen, -value, paddingLength, uppercase, ZYDIS_FALSE);
}
return ZydisPrintHex64U(buffer, bufferLen, value, paddingLength, uppercase, prefix);
}
/* ---------------------------------------------------------------------------------------------- */
/* ============================================================================================== */

371
src/FormatHelper.h Normal file
View File

@ -0,0 +1,371 @@
/***************************************************************************************************
Zyan Disassembler Library (Zydis)
Original Author : Florian Bernd
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
***************************************************************************************************/
#ifndef ZYDIS_FORMATHELPER_H
#define ZYDIS_FORMATHELPER_H
#include <Zydis/Defines.h>
#include <Zydis/Status.h>
#ifdef __cplusplus
extern "C" {
#endif
/* ============================================================================================== */
/* Enums and types */
/* ============================================================================================== */
/* ---------------------------------------------------------------------------------------------- */
/* Letter Case */
/* ---------------------------------------------------------------------------------------------- */
/**
* @brief Defines the `ZydisLetterCase` datatype.
*/
typedef uint8_t ZydisLetterCase;
/**
* @brief Values that represent letter cases.
*/
enum ZydisLetterCases
{
/**
* @brief Prints the given text "as it is".
*/
ZYDIS_LETTER_CASE_DEFAULT,
/**
* @brief Prints the given text in lowercase letters.
*/
ZYDIS_LETTER_CASE_LOWER,
/**
* @brief Prints the given text in uppercase letters.
*/
ZYDIS_LETTER_CASE_UPPER
};
/* ---------------------------------------------------------------------------------------------- */
/* ============================================================================================== */
/* Functions */
/* ============================================================================================== */
/* ---------------------------------------------------------------------------------------------- */
/* String */
/* ---------------------------------------------------------------------------------------------- */
/**
* @brief Appends the given @c text to the @c buffer.
*
* @param buffer A pointer to the string-buffer.
* @param bufferLen The length of the string-buffer.
* @param text The text to append.
* @param letterCase The desired letter-case.
*
* @return @c ZYDIS_STATUS_SUCCESS, if the function succeeded, or
* @c ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE, if the size of the buffer was not
* sufficient to append the given @c text.
*
* The string-buffer pointer is increased by the number of chars written, if the call was
* successfull.
*/
ZYDIS_NO_EXPORT ZydisStatus ZydisPrintStr(char** buffer, size_t bufferLen, const char* text,
ZydisLetterCase letterCase);
/* ---------------------------------------------------------------------------------------------- */
/* Decimal values */
/* ---------------------------------------------------------------------------------------------- */
/**
* @brief Formats the given unsigned 64-bit ordinal @c value to its decimal text-representation
* and appends it to the @c buffer.
*
* @param buffer A pointer to the string-buffer.
* @param bufferLen The length of the string-buffer.
* @param value The value.
* @param paddingLength Padds the converted value with leading zeros, if the number of chars is
* less than the @c paddingLength.
*
* @return @c ZYDIS_STATUS_SUCCESS, if the function succeeded, or
* @c ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE, if the size of the buffer was not
* sufficient to append the given @c value.
*
* The string-buffer pointer is increased by the number of chars written, if the call was
* successfull.
*/
ZYDIS_NO_EXPORT ZydisStatus ZydisPrintDec64U(char** buffer, size_t bufferLen, uint64_t value,
uint8_t paddingLength);
/**
* @brief Formats the given unsigned 32-bit ordinal @c value to its decimal text-representation
* and appends it to the @c buffer.
*
* @param buffer A pointer to the string-buffer.
* @param bufferLen The length of the string-buffer.
* @param value The value.
* @param paddingLength Padds the converted value with leading zeros, if the number of chars is
* less than the @c paddingLength.
*
* @return @c ZYDIS_STATUS_SUCCESS, if the function succeeded, or
* @c ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE, if the size of the buffer was not
* sufficient to append the given @c value.
*
* The string-buffer pointer is increased by the number of chars written, if the call was
* successfull.
*/
ZYDIS_NO_EXPORT ZydisStatus ZydisPrintDec32U(char** buffer, size_t bufferLen, uint32_t value,
uint8_t paddingLength);
/**
* @brief Formats the given signed 64-bit ordinal @c value to its decimal text-representation
* and appends it to the @c buffer.
*
* @param buffer A pointer to the string-buffer.
* @param bufferLen The length of the string-buffer.
* @param value The value.
* @param paddingLength Padds the converted value with leading zeros, if the number of chars is
* less than the @c paddingLength (the sign char is ignored).
*
* @return @c ZYDIS_STATUS_SUCCESS, if the function succeeded, or
* @c ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE, if the size of the buffer was not
* sufficient to append the given @c value.
*
* The string-buffer pointer is increased by the number of chars written, if the call was
* successfull.
*/
ZYDIS_NO_EXPORT ZydisStatus ZydisPrintDec64S(char** buffer, size_t bufferLen, int64_t value,
uint8_t paddingLength);
/**
* @brief Formats the given signed 32-bit ordinal @c value to its decimal text-representation
* and appends it to the @c buffer.
*
* @param buffer A pointer to the string-buffer.
* @param bufferLen The length of the string-buffer.
* @param value The value.
* @param paddingLength Padds the converted value with leading zeros, if the number of chars is
* less than the @c paddingLength (the sign char is ignored).
*
* @return @c ZYDIS_STATUS_SUCCESS, if the function succeeded, or
* @c ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE, if the size of the buffer was not
* sufficient to append the given @c value.
*
* The string-buffer pointer is increased by the number of chars written, if the call was
* successfull.
*/
ZYDIS_NO_EXPORT ZydisStatus ZydisPrintDec32S(char** buffer, size_t bufferLen, int32_t value,
uint8_t paddingLength);
/**
* @brief Formats the given signed 16-bit ordinal @c value to its decimal text-representation
* and appends it to the @c buffer.
*
* @param buffer A pointer to the string-buffer.
* @param bufferLen The length of the string-buffer.
* @param value The value.
* @param paddingLength Padds the converted value with leading zeros, if the number of chars is
* less than the @c paddingLength (the sign char is ignored).
*
* @return @c ZYDIS_STATUS_SUCCESS, if the function succeeded, or
* @c ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE, if the size of the buffer was not
* sufficient to append the given @c value.
*
* The string-buffer pointer is increased by the number of chars written, if the call was
* successfull.
*/
ZYDIS_NO_EXPORT ZydisStatus ZydisPrintDec16S(char** buffer, size_t bufferLen, int16_t value,
uint8_t paddingLength);
/**
* @brief Formats the given signed 8-bit ordinal @c value to its decimal text-representation
* and appends it to the @c buffer.
*
* @param buffer A pointer to the string-buffer.
* @param bufferLen The length of the string-buffer.
* @param value The value.
* @param paddingLength Padds the converted value with leading zeros, if the number of chars is
* less than the @c paddingLength (the sign char is ignored).
*
* @return @c ZYDIS_STATUS_SUCCESS, if the function succeeded, or
* @c ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE, if the size of the buffer was not
* sufficient to append the given @c value.
*
* The string-buffer pointer is increased by the number of chars written, if the call was
* successfull.
*/
ZYDIS_NO_EXPORT ZydisStatus ZydisPrintDec8S(char** buffer, size_t bufferLen, int8_t value,
uint8_t paddingLength);
/* ---------------------------------------------------------------------------------------------- */
/* Hexadecimal values */
/* ---------------------------------------------------------------------------------------------- */
/**
* @brief Formats the given unsigned 64-bit ordinal @c value to its hexadecimal text-
* representation and appends it to the @c buffer.
*
* @param buffer A pointer to the string-buffer.
* @param bufferLen The length of the string-buffer.
* @param value The value.
* @param paddingLength Padds the converted value with leading zeros, if the number of chars is
* 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.
*
* @return @c ZYDIS_STATUS_SUCCESS, if the function succeeded, or
* @c ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE, if the size of the buffer was not
* sufficient to append the given @c value.
*
* The string-buffer pointer is increased by the number of chars written, if the call was
* successfull.
*/
ZYDIS_NO_EXPORT ZydisStatus ZydisPrintHex64U(char** buffer, size_t bufferLen, uint64_t value,
uint8_t paddingLength, ZydisBool uppercase, ZydisBool prefix);
/**
* @brief Formats the given unsigned 32-bit ordinal @c value to its hexadecimal text-
* representation and appends it to the @c buffer.
*
* @param buffer A pointer to the string-buffer.
* @param bufferLen The length of the string-buffer.
* @param value The value.
* @param paddingLength Padds the converted value with leading zeros, if the number of chars is
* 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.
*
* @return @c ZYDIS_STATUS_SUCCESS, if the function succeeded, or
* @c ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE, if the size of the buffer was not
* sufficient to append the given @c value.
*
* The string-buffer pointer is increased by the number of chars written, if the call was
* successfull.
*/
ZYDIS_NO_EXPORT ZydisStatus ZydisPrintHex32U(char** buffer, size_t bufferLen, uint32_t value,
uint8_t paddingLength, ZydisBool uppercase, ZydisBool prefix);
/**
* @brief Formats the given signed 64-bit ordinal @c value to its hexadecimal text-
* representation and appends it to the @c buffer.
*
* @param buffer A pointer to the string-buffer.
* @param bufferLen The length of the string-buffer.
* @param value The value.
* @param paddingLength Padds the converted value with leading zeros, if the number of chars is
* 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.
*
* @return @c ZYDIS_STATUS_SUCCESS, if the function succeeded, or
* @c ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE, if the size of the buffer was not
* sufficient to append the given @c value.
*
* The string-buffer pointer is increased by the number of chars written, if the call was
* successfull.
*/
ZYDIS_NO_EXPORT ZydisStatus ZydisPrintHex64S(char** buffer, size_t bufferLen, int64_t value,
uint8_t paddingLength, ZydisBool uppercase, ZydisBool prefix);
/**
* @brief Formats the given signed 32-bit ordinal @c value to its hexadecimal text-
* representation and appends it to the @c buffer.
*
* @param buffer A pointer to the string-buffer.
* @param bufferLen The length of the string-buffer.
* @param value The value.
* @param paddingLength Padds the converted value with leading zeros, if the number of chars is
* 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.
*
* @return @c ZYDIS_STATUS_SUCCESS, if the function succeeded, or
* @c ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE, if the size of the buffer was not
* sufficient to append the given @c value.
*
* The string-buffer pointer is increased by the number of chars written, if the call was
* successfull.
*/
ZYDIS_NO_EXPORT ZydisStatus ZydisPrintHex32S(char** buffer, size_t bufferLen, int32_t value,
uint8_t paddingLength, ZydisBool uppercase, ZydisBool prefix);
/**
* @brief Formats the given signed 16-bit ordinal @c value to its hexadecimal text-
* representation and appends it to the @c buffer.
*
* @param buffer A pointer to the string-buffer.
* @param bufferLen The length of the string-buffer.
* @param value The value.
* @param paddingLength Padds the converted value with leading zeros, if the number of chars is
* 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.
*
* @return @c ZYDIS_STATUS_SUCCESS, if the function succeeded, or
* @c ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE, if the size of the buffer was not
* sufficient to append the given @c value.
*
* The string-buffer pointer is increased by the number of chars written, if the call was
* successfull.
*/
ZYDIS_NO_EXPORT ZydisStatus ZydisPrintHex16S(char** buffer, size_t bufferLen, int16_t value,
uint8_t paddingLength, ZydisBool uppercase, ZydisBool prefix);
/**
* @brief Formats the given signed 8-bit ordinal @c value to its hexadecimal text-
* representation and appends it to the @c buffer.
*
* @param buffer A pointer to the string-buffer.
* @param bufferLen The length of the string-buffer.
* @param value The value.
* @param paddingLength Padds the converted value with leading zeros, if the number of chars is
* 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.
*
* @return @c ZYDIS_STATUS_SUCCESS, if the function succeeded, or
* @c ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE, if the size of the buffer was not
* sufficient to append the given @c value.
*
* The string-buffer pointer is increased by the number of chars written, if the call was
* successfull.
*/
ZYDIS_NO_EXPORT ZydisStatus ZydisPrintHex8S(char** buffer, size_t bufferLen, int8_t value,
uint8_t paddingLength, ZydisBool uppercase, ZydisBool prefix);
/* ---------------------------------------------------------------------------------------------- */
/* ============================================================================================== */
#ifdef __cplusplus
}
#endif
#endif /* ZYDIS_FORMATHELPER_H */

View File

@ -24,169 +24,11 @@
***************************************************************************************************/
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include <Zydis/CommonTypes.h>
#include <Zydis/Formatter.h>
#include <Zydis/Utils.h>
#include <Zydis/CommonTypes.h>
#if defined(ZYDIS_WINKERNEL)
# include <ntddk.h>
# include <Ntstrsafe.h>
#endif
/* ============================================================================================== */
/* String formatting */
/* ============================================================================================== */
/* ---------------------------------------------------------------------------------------------- */
/* Enums and types */
/* ---------------------------------------------------------------------------------------------- */
/**
* @brief Defines the @c ZydisStringBufferAppendMode datatype.
*/
typedef uint8_t ZydisStringBufferAppendMode;
/**
* @brief Values that represent zydis string-buffer append-modes.
*/
enum ZydisStringBufferAppendModes
{
/**
* @brief Appends the string as it is.
*/
ZYDIS_STRBUF_APPEND_MODE_DEFAULT,
/**
* @brief Converts the string to lowercase characters.
*/
ZYDIS_STRBUF_APPEND_MODE_LOWERCASE,
/**
* @brief Converts the string to uppercase characters.
*/
ZYDIS_STRBUF_APPEND_MODE_UPPERCASE
};
/* ---------------------------------------------------------------------------------------------- */
/* Internal functions */
/* ---------------------------------------------------------------------------------------------- */
#if defined(ZYDIS_WINKERNEL)
static int ZydisVSNPrintF(char* s, size_t n, const char* format, va_list arg)
{
size_t bytesRemaining;
NTSTATUS ret = RtlStringCchVPrintfExA(
s, n, NULL, &bytesRemaining, 0, format, arg
);
if (!NT_SUCCESS(ret)) return -1;
return (int)(n - bytesRemaining);
}
#else
static int ZydisVSNPrintF(char* s, size_t n, const char* format, va_list arg)
{
return vsnprintf(s, n, format, arg);
}
#endif
/**
* @brief Appends the @c text to the given @c buffer and increases the string-buffer pointer by
* the number of chars written.
*
* @param buffer A pointer to the string-buffer.
* @param bufferLen The length of the string-buffer.
* @param mode The append-mode.
* @param text The text to append.
*
* @return @c ZYDIS_STATUS_SUCCESS, if the function succeeded, or
* @c ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE, if the size of the buffer was not
* sufficient to append the given @c text.
*/
static ZydisStatus ZydisStringBufferAppend(char** buffer, size_t bufferLen,
ZydisStringBufferAppendMode mode, const char* text)
{
ZYDIS_ASSERT(buffer);
ZYDIS_ASSERT(bufferLen != 0);
ZYDIS_ASSERT(text);
size_t strLen = strlen(text);
if (strLen >= bufferLen)
{
return ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE;
}
strncpy(*buffer, text, strLen + 1);
switch (mode)
{
case ZYDIS_STRBUF_APPEND_MODE_LOWERCASE:
for (size_t i = 0; i < strLen; ++i)
{
(*buffer[i]) = (char)tolower((*buffer)[i]);
}
break;
case ZYDIS_STRBUF_APPEND_MODE_UPPERCASE:
for (size_t i = 0; i < strLen; ++i)
{
(*buffer)[i] = (char)toupper((*buffer)[i]);
}
break;
default:
break;
}
*buffer += strLen;
return ZYDIS_STATUS_SUCCESS;
}
/**
* @brief Appends formatted text to the given @c buffer and increases the string-buffer pointer
* by the number of chars written.
*
* @param buffer A pointer to the string-buffer.
* @param bufferLen The length of the string-buffer.
* @param mode The append-mode.
* @param format The format string.
*
* @return @c ZYDIS_STATUS_SUCCESS, if the function succeeded, or
* @c ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE, if the size of the buffer was not
* sufficient to append the given text.
*/
static ZydisStatus ZydisStringBufferAppendFormat(char** buffer, size_t bufferLen,
ZydisStringBufferAppendMode mode, const char* format, ...)
{
ZYDIS_ASSERT(buffer);
ZYDIS_ASSERT(bufferLen != 0);
ZYDIS_ASSERT(format);
va_list arglist;
va_start(arglist, format);
int w = ZydisVSNPrintF(*buffer, bufferLen, format, arglist);
if ((w < 0) || ((size_t)w >= bufferLen))
{
va_end(arglist);
return ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE;
}
switch (mode)
{
case ZYDIS_STRBUF_APPEND_MODE_LOWERCASE:
for (size_t i = 0; i < (size_t)w; ++i)
{
(*buffer)[i] = (char)tolower((*buffer)[i]);
}
break;
case ZYDIS_STRBUF_APPEND_MODE_UPPERCASE:
for (size_t i = 0; i < (size_t)w; ++i)
{
(*buffer)[i] = (char)toupper((*buffer)[i]);
}
break;
default:
break;
}
*buffer += (size_t)w;
va_end(arglist);
return ZYDIS_STATUS_SUCCESS;
}
#include <FormatHelper.h>
/* ============================================================================================== */
/* Instruction formatter */
@ -196,9 +38,9 @@ static ZydisStatus ZydisStringBufferAppendFormat(char** buffer, size_t bufferLen
/* Internal macros */
/* ---------------------------------------------------------------------------------------------- */
#define ZYDIS_APPENDMODE \
#define ZYDIS_LETTER_CASE \
(formatter->flags & ZYDIS_FMTFLAG_UPPERCASE) ? \
ZYDIS_STRBUF_APPEND_MODE_UPPERCASE : ZYDIS_STRBUF_APPEND_MODE_DEFAULT
ZYDIS_LETTER_CASE_UPPER : ZYDIS_LETTER_CASE_DEFAULT
/* ---------------------------------------------------------------------------------------------- */
/* Intel style */
@ -214,34 +56,34 @@ static ZydisStatus ZydisFormatterPrintPrefixesIntel(const ZydisFormatter* format
if (instruction->attributes & ZYDIS_ATTRIB_HAS_LOCK)
{
return ZydisStringBufferAppend(buffer, bufferLen, ZYDIS_APPENDMODE, "lock ");
return ZydisPrintStr(buffer, bufferLen, "lock ", ZYDIS_LETTER_CASE);
}
if (instruction->attributes & ZYDIS_ATTRIB_HAS_REP)
{
return ZydisStringBufferAppend(buffer, bufferLen, ZYDIS_APPENDMODE, "rep ");
return ZydisPrintStr(buffer, bufferLen, "rep ", ZYDIS_LETTER_CASE);
}
if (instruction->attributes & ZYDIS_ATTRIB_HAS_REPE)
{
return ZydisStringBufferAppend(buffer, bufferLen, ZYDIS_APPENDMODE, "repe ");
return ZydisPrintStr(buffer, bufferLen, "repe ", ZYDIS_LETTER_CASE);
}
if (instruction->attributes & ZYDIS_ATTRIB_HAS_REPNE)
{
return ZydisStringBufferAppend(buffer, bufferLen, ZYDIS_APPENDMODE, "repne ");
return ZydisPrintStr(buffer, bufferLen, "repne ", ZYDIS_LETTER_CASE);
}
if (instruction->attributes & ZYDIS_ATTRIB_HAS_BOUND)
{
return ZydisStringBufferAppend(buffer, bufferLen, ZYDIS_APPENDMODE, "bnd ");
return ZydisPrintStr(buffer, bufferLen, "bnd ", ZYDIS_LETTER_CASE);
}
if (instruction->attributes & ZYDIS_ATTRIB_HAS_XACQUIRE)
{
return ZydisStringBufferAppend(buffer, bufferLen, ZYDIS_APPENDMODE, "xacquire ");
return ZydisPrintStr(buffer, bufferLen, "xacquire ", ZYDIS_LETTER_CASE);
}
if (instruction->attributes & ZYDIS_ATTRIB_HAS_XRELEASE)
{
return ZydisStringBufferAppend(buffer, bufferLen, ZYDIS_APPENDMODE, "xrelease ");
return ZydisPrintStr(buffer, bufferLen, "xrelease ", ZYDIS_LETTER_CASE);
}
return ZYDIS_STATUS_SUCCESS;
@ -260,7 +102,7 @@ static ZydisStatus ZydisFormatterPrintMnemonicIntel(const ZydisFormatter* format
{
mnemonic = "invalid";
}
return ZydisStringBufferAppend(buffer, bufferLen, ZYDIS_APPENDMODE, mnemonic);
return ZydisPrintStr(buffer, bufferLen, mnemonic, ZYDIS_LETTER_CASE);
}
/* ---------------------------------------------------------------------------------------------- */
@ -284,7 +126,7 @@ static ZydisStatus ZydisFormatterFormatOperandRegIntel(const ZydisFormatter* for
{
reg = "invalid";
}
return ZydisStringBufferAppend(buffer, bufferLen, ZYDIS_APPENDMODE, reg);
return ZydisPrintStr(buffer, bufferLen, reg, ZYDIS_LETTER_CASE);
}
static ZydisStatus ZydisFormatterFormatOperandMemIntel(const ZydisFormatter* formatter,
@ -298,8 +140,7 @@ static ZydisStatus ZydisFormatterFormatOperandMemIntel(const ZydisFormatter* for
char* bufEnd = *buffer + bufferLen;
ZYDIS_CHECK(
ZydisStringBufferAppend(buffer, bufEnd - *buffer, ZYDIS_STRBUF_APPEND_MODE_DEFAULT, "["));
ZYDIS_CHECK(ZydisPrintStr(buffer, bufEnd - *buffer, "[", ZYDIS_LETTER_CASE_DEFAULT));
if (operand->mem.disp.hasDisplacement && (
(operand->mem.base == ZYDIS_REGISTER_NONE) ||
@ -330,7 +171,7 @@ static ZydisStatus ZydisFormatterFormatOperandMemIntel(const ZydisFormatter* for
{
return ZYDIS_STATUS_INVALID_PARAMETER;
}
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer, ZYDIS_APPENDMODE, reg));
ZYDIS_CHECK(ZydisPrintStr(buffer, bufEnd - *buffer, reg, ZYDIS_LETTER_CASE));
}
if (operand->mem.index != ZYDIS_REGISTER_NONE)
{
@ -339,20 +180,29 @@ static ZydisStatus ZydisFormatterFormatOperandMemIntel(const ZydisFormatter* for
{
return ZYDIS_STATUS_INVALID_PARAMETER;
}
const char* c = (operand->mem.base != ZYDIS_REGISTER_NONE) ? "+" : "";
ZYDIS_CHECK(ZydisStringBufferAppendFormat(buffer, bufEnd - *buffer, ZYDIS_APPENDMODE,
"%s%s", c, reg));
if (operand->mem.base != ZYDIS_REGISTER_NONE)
{
ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer, "+", ZYDIS_LETTER_CASE_DEFAULT));
}
ZYDIS_CHECK(ZydisPrintStr(buffer, bufEnd - *buffer, reg, ZYDIS_LETTER_CASE));
//const char* c = (operand->mem.base != ZYDIS_REGISTER_NONE) ? "+" : "";
//ZYDIS_CHECK(ZydisPrintStrFormat(buffer, bufEnd - *buffer, ZYDIS_APPENDMODE,
// "%s%s", c, reg));
if (operand->mem.scale)
{
ZYDIS_CHECK(ZydisStringBufferAppendFormat(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, "*%d", operand->mem.scale));
ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer, "*", ZYDIS_LETTER_CASE_DEFAULT));
ZYDIS_CHECK(ZydisPrintDec32U(buffer, bufEnd - *buffer, operand->mem.scale, 0));
//ZYDIS_CHECK(ZydisPrintStrFormat(buffer, bufEnd - *buffer,
// ZYDIS_STRBUF_APPEND_MODE_DEFAULT, "*%d", operand->mem.scale));
}
}
ZYDIS_CHECK(formatter->funcPrintDisplacement(formatter, buffer, bufEnd - *buffer,
instruction, operand));
}
return ZydisStringBufferAppend(buffer, bufEnd - *buffer, ZYDIS_STRBUF_APPEND_MODE_DEFAULT, "]");
return ZydisPrintStr(buffer, bufEnd - *buffer, "]", ZYDIS_LETTER_CASE_DEFAULT);
}
static ZydisStatus ZydisFormatterFormatOperandPtrIntel(const ZydisFormatter* formatter,
@ -364,8 +214,14 @@ static ZydisStatus ZydisFormatterFormatOperandPtrIntel(const ZydisFormatter* for
return ZYDIS_STATUS_INVALID_PARAMETER;
}
return ZydisStringBufferAppendFormat(buffer, bufferLen, ZYDIS_STRBUF_APPEND_MODE_DEFAULT,
"0x%04"PRIX16":0x%08"PRIX32, operand->ptr.segment, operand->ptr.offset);
char* bufEnd = *buffer + bufferLen;
ZYDIS_CHECK(ZydisPrintHex32U(
buffer, bufEnd - *buffer, operand->ptr.segment, 4, ZYDIS_TRUE, ZYDIS_TRUE));
ZYDIS_CHECK(ZydisPrintStr(buffer, bufEnd - *buffer, ":", ZYDIS_LETTER_CASE_DEFAULT));
return ZydisPrintHex32U(
buffer, bufEnd - *buffer, operand->ptr.offset, 8, ZYDIS_TRUE, ZYDIS_TRUE);
//return ZydisPrintStrFormat(buffer, bufferLen, ZYDIS_STRBUF_APPEND_MODE_DEFAULT,
// "0x%04"PRIX16":0x%08"PRIX32, operand->ptr.segment, operand->ptr.offset);
}
static ZydisStatus ZydisFormatterFormatOperandImmIntel(const ZydisFormatter* formatter,
@ -399,13 +255,16 @@ static ZydisStatus ZydisFormatterFormatOperandImmIntel(const ZydisFormatter* for
default:
return ZYDIS_STATUS_INVALID_PARAMETER;
}
if (printSignedHEX && (operand->imm.value.s < 0))
return ZydisPrintHex32S(
buffer, bufferLen, (int32_t)operand->imm.value.s, 2, ZYDIS_TRUE, ZYDIS_TRUE);
/*if (printSignedHEX && (operand->imm.value.s < 0))
{
return ZydisStringBufferAppendFormat(buffer, bufferLen,
return ZydisPrintStrFormat(buffer, bufferLen,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, "-0x%02"PRIX32, -(int32_t)operand->imm.value.s);
}
return ZydisStringBufferAppendFormat(buffer, bufferLen, ZYDIS_STRBUF_APPEND_MODE_DEFAULT,
"0x%02"PRIX32, (int32_t)operand->imm.value.s);
return ZydisPrintStrFormat(buffer, bufferLen, ZYDIS_STRBUF_APPEND_MODE_DEFAULT,
"0x%02"PRIX32, (int32_t)operand->imm.value.s);*/
}
// The immediate operand contains an actual ordinal value
@ -428,11 +287,13 @@ static ZydisStatus ZydisFormatterPrintAddressIntel(const ZydisFormatter* formatt
{
case 16:
case 32:
return ZydisStringBufferAppendFormat(buffer, bufferLen, ZYDIS_STRBUF_APPEND_MODE_DEFAULT,
"0x%08"PRIX64, address);
return ZydisPrintHex64U(buffer, bufferLen, address, 8, ZYDIS_TRUE, ZYDIS_TRUE);
//return ZydisPrintStrFormat(buffer, bufferLen, ZYDIS_STRBUF_APPEND_MODE_DEFAULT,
// "0x%08"PRIX64, address);
case 64:
return ZydisStringBufferAppendFormat(buffer, bufferLen, ZYDIS_STRBUF_APPEND_MODE_DEFAULT,
"0x%016"PRIX64, address);
return ZydisPrintHex64U(buffer, bufferLen, address, 16, ZYDIS_TRUE, ZYDIS_TRUE);
//return ZydisPrintStrFormat(buffer, bufferLen, ZYDIS_STRBUF_APPEND_MODE_DEFAULT,
// "0x%016"PRIX64, address);
default:
return ZYDIS_STATUS_INVALID_PARAMETER;
}
@ -457,14 +318,17 @@ static ZydisStatus ZydisFormatterPrintDisplacementIntel(const ZydisFormatter* fo
(operand->mem.base != ZYDIS_REGISTER_NONE) ||
(operand->mem.index != ZYDIS_REGISTER_NONE)))
{
return ZydisStringBufferAppendFormat(buffer, bufferLen,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, "-0x%02"PRIX32, -operand->mem.disp.value);
return ZydisPrintHex64S(
buffer, bufferLen, operand->mem.disp.value, 2, ZYDIS_TRUE, ZYDIS_TRUE);
}
const char* sign =
((operand->mem.base == ZYDIS_REGISTER_NONE) &&
(operand->mem.index == ZYDIS_REGISTER_NONE)) ? "" : "+";
return ZydisStringBufferAppendFormat(buffer, bufferLen, ZYDIS_STRBUF_APPEND_MODE_DEFAULT,
"%s0x%02"PRIX32, sign, operand->mem.disp.value);
char* bufEnd = *buffer + bufferLen;
if ((operand->mem.base != ZYDIS_REGISTER_NONE) ||
(operand->mem.index != ZYDIS_REGISTER_NONE))
{
ZYDIS_CHECK(ZydisPrintStr(buffer, bufferLen, "+", ZYDIS_LETTER_CASE_DEFAULT));
}
return ZydisPrintHex64U(
buffer, bufEnd - *buffer, operand->mem.disp.value, 2, ZYDIS_TRUE, ZYDIS_TRUE);
}
return ZYDIS_STATUS_SUCCESS;
}
@ -483,22 +347,23 @@ static ZydisStatus ZydisFormatterPrintImmediateIntel(const ZydisFormatter* forma
{
printSignedHEX = operand->imm.isSigned;
}
if (printSignedHEX && (operand->imm.value.s < 0))
{
switch (operand->size)
{
case 8:
return ZydisStringBufferAppendFormat(buffer, bufferLen,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, "-0x%02"PRIX8, -(int8_t)operand->imm.value.s);
return ZydisPrintHex8S(
buffer, bufferLen, (int8_t)operand->imm.value.s, 2, ZYDIS_TRUE, ZYDIS_TRUE);
case 16:
return ZydisStringBufferAppendFormat(buffer, bufferLen,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, "-0x%02"PRIX16, -(int16_t)operand->imm.value.s);
return ZydisPrintHex16S(
buffer, bufferLen, (int16_t)operand->imm.value.s, 2, ZYDIS_TRUE, ZYDIS_TRUE);
case 32:
return ZydisStringBufferAppendFormat(buffer, bufferLen,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, "-0x%02"PRIX32, -(int32_t)operand->imm.value.s);
return ZydisPrintHex32S(
buffer, bufferLen, (int32_t)operand->imm.value.s, 2, ZYDIS_TRUE, ZYDIS_TRUE);
case 64:
return ZydisStringBufferAppendFormat(buffer, bufferLen,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, "-0x%02"PRIX64, -operand->imm.value.s);
return ZydisPrintHex64S(
buffer, bufferLen, (int64_t)operand->imm.value.s, 2, ZYDIS_TRUE, ZYDIS_TRUE);
default:
return ZYDIS_STATUS_INVALID_PARAMETER;
}
@ -506,14 +371,14 @@ static ZydisStatus ZydisFormatterPrintImmediateIntel(const ZydisFormatter* forma
switch (instruction->operandSize)
{
case 16:
return ZydisStringBufferAppendFormat(buffer, bufferLen,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, "0x%02"PRIX16, (uint16_t)operand->imm.value.u);
return ZydisPrintHex32U(
buffer, bufferLen, (uint16_t)operand->imm.value.u, 2, ZYDIS_TRUE, ZYDIS_TRUE);
case 32:
return ZydisStringBufferAppendFormat(buffer, bufferLen,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, "0x%02"PRIX32, (uint32_t)operand->imm.value.u);
return ZydisPrintHex32U(
buffer, bufferLen, (int32_t)operand->imm.value.u, 2, ZYDIS_TRUE, ZYDIS_TRUE);
case 64:
return ZydisStringBufferAppendFormat(buffer, bufferLen,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, "0x%02"PRIX64, operand->imm.value.u);
return ZydisPrintHex64U(
buffer, bufferLen, (int64_t)operand->imm.value.u, 2, ZYDIS_TRUE, ZYDIS_TRUE);
default:
return ZYDIS_STATUS_INVALID_PARAMETER;
}
@ -614,7 +479,7 @@ static ZydisStatus ZydisFormatterPrintOperandSizeIntel(const ZydisFormatter* for
default:
break;
}
return ZydisStringBufferAppend(buffer, bufferLen, ZYDIS_APPENDMODE, str);
return ZydisPrintStr(buffer, bufferLen, str, ZYDIS_LETTER_CASE);
}
return ZYDIS_STATUS_SUCCESS;
}
@ -628,28 +493,41 @@ static ZydisStatus ZydisFormatterPrintSegmentIntel(const ZydisFormatter* formatt
return ZYDIS_STATUS_INVALID_PARAMETER;
}
char* bufEnd = *buffer + bufferLen;
switch (operand->mem.segment)
{
case ZYDIS_REGISTER_ES:
case ZYDIS_REGISTER_CS:
case ZYDIS_REGISTER_FS:
case ZYDIS_REGISTER_GS:
return ZydisStringBufferAppendFormat(buffer, bufferLen, ZYDIS_APPENDMODE, "%s:",
ZydisRegisterGetString(operand->mem.segment));
ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer,
ZydisRegisterGetString(operand->mem.segment), ZYDIS_LETTER_CASE));
return ZydisPrintStr(buffer, bufEnd - *buffer, ":", ZYDIS_LETTER_CASE_DEFAULT);
//return ZydisPrintStrFormat(buffer, bufferLen, ZYDIS_APPENDMODE, "%s:",
// ZydisRegisterGetString(operand->mem.segment));
case ZYDIS_REGISTER_SS:
if ((formatter->flags & ZYDIS_FMTFLAG_FORCE_SEGMENTS) ||
(instruction->attributes & ZYDIS_ATTRIB_HAS_SEGMENT_SS))
{
return ZydisStringBufferAppendFormat(buffer, bufferLen, ZYDIS_APPENDMODE, "%s:",
ZydisRegisterGetString(operand->mem.segment));
ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer,
ZydisRegisterGetString(operand->mem.segment), ZYDIS_LETTER_CASE));
return ZydisPrintStr(buffer, bufEnd - *buffer, ":", ZYDIS_LETTER_CASE_DEFAULT);
//return ZydisPrintStrFormat(buffer, bufferLen, ZYDIS_APPENDMODE, "%s:",
// ZydisRegisterGetString(operand->mem.segment));
}
break;
case ZYDIS_REGISTER_DS:
if ((formatter->flags & ZYDIS_FMTFLAG_FORCE_SEGMENTS) ||
(instruction->attributes & ZYDIS_ATTRIB_HAS_SEGMENT_DS))
{
return ZydisStringBufferAppendFormat(buffer, bufferLen, ZYDIS_APPENDMODE, "%s:",
ZydisRegisterGetString(operand->mem.segment));
ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer,
ZydisRegisterGetString(operand->mem.segment), ZYDIS_LETTER_CASE));
return ZydisPrintStr(buffer, bufEnd - *buffer, ":", ZYDIS_LETTER_CASE_DEFAULT);
//return ZydisPrintStrFormat(buffer, bufferLen, ZYDIS_APPENDMODE, "%s:",
// ZydisRegisterGetString(operand->mem.segment));
}
break;
default:
@ -679,12 +557,13 @@ static ZydisStatus ZydisFormatterPrintDecoratorIntel(const ZydisFormatter* forma
{
return ZYDIS_STATUS_INVALID_PARAMETER;
}
ZYDIS_CHECK(ZydisStringBufferAppendFormat(
buffer, bufEnd - *buffer, ZYDIS_APPENDMODE, " {%s}", reg));
ZYDIS_CHECK(ZydisPrintStr(buffer, bufEnd - *buffer, " {", ZYDIS_LETTER_CASE_DEFAULT));
ZYDIS_CHECK(ZydisPrintStr(buffer, bufEnd - *buffer, reg, ZYDIS_LETTER_CASE));
ZYDIS_CHECK(ZydisPrintStr(buffer, bufEnd - *buffer, "}", ZYDIS_LETTER_CASE_DEFAULT));
if (instruction->avx.mask.mode == ZYDIS_MASK_MODE_ZERO)
{
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {z}"));
ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer, " {z}", ZYDIS_LETTER_CASE_DEFAULT));
}
}
break;
@ -697,28 +576,28 @@ static ZydisStatus ZydisFormatterPrintDecoratorIntel(const ZydisFormatter* forma
case ZYDIS_BROADCAST_MODE_INVALID:
break;
case ZYDIS_BROADCAST_MODE_1_TO_2:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {1to2}"));
ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer, " {1to2}", ZYDIS_LETTER_CASE_DEFAULT));
break;
case ZYDIS_BROADCAST_MODE_1_TO_4:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {1to4}"));
ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer, " {1to4}", ZYDIS_LETTER_CASE_DEFAULT));
break;
case ZYDIS_BROADCAST_MODE_1_TO_8:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {1to8}"));
ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer, " {1to8}", ZYDIS_LETTER_CASE_DEFAULT));
break;
case ZYDIS_BROADCAST_MODE_1_TO_16:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {1to16}"));
ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer, " {1to16}", ZYDIS_LETTER_CASE_DEFAULT));
break;
case ZYDIS_BROADCAST_MODE_4_TO_8:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {4to8}"));
ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer, " {4to8}", ZYDIS_LETTER_CASE_DEFAULT));
break;
case ZYDIS_BROADCAST_MODE_4_TO_16:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {4to16}"));
ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer, " {4to16}", ZYDIS_LETTER_CASE_DEFAULT));
break;
default:
return ZYDIS_STATUS_INVALID_PARAMETER;
@ -733,20 +612,20 @@ static ZydisStatus ZydisFormatterPrintDecoratorIntel(const ZydisFormatter* forma
case ZYDIS_ROUNDING_MODE_INVALID:
break;
case ZYDIS_ROUNDING_MODE_RN:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {rn-sae}"));
ZYDIS_CHECK(ZydisPrintStr(
buffer, bufEnd - *buffer, " {rn-sae}", ZYDIS_LETTER_CASE_DEFAULT));
break;
case ZYDIS_ROUNDING_MODE_RD:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {rd-sae}"));
ZYDIS_CHECK(ZydisPrintStr(
buffer, bufEnd - *buffer, " {rd-sae}", ZYDIS_LETTER_CASE_DEFAULT));
break;
case ZYDIS_ROUNDING_MODE_RU:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {ru-sae}"));
ZYDIS_CHECK(ZydisPrintStr(
buffer, bufEnd - *buffer, " {ru-sae}", ZYDIS_LETTER_CASE_DEFAULT));
break;
case ZYDIS_ROUNDING_MODE_RZ:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {rz-sae}"));
ZYDIS_CHECK(ZydisPrintStr(
buffer, bufEnd - *buffer, " {rz-sae}", ZYDIS_LETTER_CASE_DEFAULT));
break;
default:
return ZYDIS_STATUS_INVALID_PARAMETER;
@ -758,20 +637,20 @@ static ZydisStatus ZydisFormatterPrintDecoratorIntel(const ZydisFormatter* forma
case ZYDIS_ROUNDING_MODE_INVALID:
break;
case ZYDIS_ROUNDING_MODE_RN:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {rn}"));
ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer, " {rn}", ZYDIS_LETTER_CASE_DEFAULT));
break;
case ZYDIS_ROUNDING_MODE_RD:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {rd}"));
ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer, " {rd}", ZYDIS_LETTER_CASE_DEFAULT));
break;
case ZYDIS_ROUNDING_MODE_RU:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {ru}"));
ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer, " {ru}", ZYDIS_LETTER_CASE_DEFAULT));
break;
case ZYDIS_ROUNDING_MODE_RZ:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {rz}"));
ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer, " {rz}", ZYDIS_LETTER_CASE_DEFAULT));
break;
default:
return ZYDIS_STATUS_INVALID_PARAMETER;
@ -781,8 +660,8 @@ static ZydisStatus ZydisFormatterPrintDecoratorIntel(const ZydisFormatter* forma
case ZYDIS_DECORATOR_TYPE_SAE:
if (instruction->avx.hasSAE && !instruction->avx.rounding.mode)
{
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {sae}"));
ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer, " {sae}", ZYDIS_LETTER_CASE_DEFAULT));
}
break;
case ZYDIS_DECORATOR_TYPE_SWIZZLE:
@ -793,32 +672,32 @@ static ZydisStatus ZydisFormatterPrintDecoratorIntel(const ZydisFormatter* forma
// Nothing to do here
break;
case ZYDIS_SWIZZLE_MODE_CDAB:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {cdab}"));
ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer, " {cdab}", ZYDIS_LETTER_CASE_DEFAULT));
break;
case ZYDIS_SWIZZLE_MODE_BADC:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {badc}"));
ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer, " {badc}", ZYDIS_LETTER_CASE_DEFAULT));
break;
case ZYDIS_SWIZZLE_MODE_DACB:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {dacb}"));
ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer, " {dacb}", ZYDIS_LETTER_CASE_DEFAULT));
break;
case ZYDIS_SWIZZLE_MODE_AAAA:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {aaaa}"));
ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer, " {aaaa}", ZYDIS_LETTER_CASE_DEFAULT));
break;
case ZYDIS_SWIZZLE_MODE_BBBB:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {bbbb}"));
ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer, " {bbbb}", ZYDIS_LETTER_CASE_DEFAULT));
break;
case ZYDIS_SWIZZLE_MODE_CCCC:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {cccc}"));
ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer, " {cccc}", ZYDIS_LETTER_CASE_DEFAULT));
break;
case ZYDIS_SWIZZLE_MODE_DDDD:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {dddd}"));
ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer, " {dddd}", ZYDIS_LETTER_CASE_DEFAULT));
break;
default:
return ZYDIS_STATUS_INVALID_PARAMETER;
@ -830,24 +709,24 @@ static ZydisStatus ZydisFormatterPrintDecoratorIntel(const ZydisFormatter* forma
case ZYDIS_CONVERSION_MODE_INVALID:
break;
case ZYDIS_CONVERSION_MODE_FLOAT16:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {float16}"));
ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer, " {float16}", ZYDIS_LETTER_CASE_DEFAULT));
break;
case ZYDIS_CONVERSION_MODE_SINT8:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {sint8}"));
ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer, " {sint8}", ZYDIS_LETTER_CASE_DEFAULT));
break;
case ZYDIS_CONVERSION_MODE_UINT8:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {uint8}"));
ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer, " {uint8}", ZYDIS_LETTER_CASE_DEFAULT));
break;
case ZYDIS_CONVERSION_MODE_SINT16:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {sint16}"));
ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer, " {sint16}", ZYDIS_LETTER_CASE_DEFAULT));
break;
case ZYDIS_CONVERSION_MODE_UINT16:
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {uint16}"));
ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer, " {uint16}", ZYDIS_LETTER_CASE_DEFAULT));
break;
default:
return ZYDIS_STATUS_INVALID_PARAMETER;
@ -856,8 +735,8 @@ static ZydisStatus ZydisFormatterPrintDecoratorIntel(const ZydisFormatter* forma
case ZYDIS_DECORATOR_TYPE_EVICTION_HINT:
if (instruction->avx.hasEvictionHint)
{
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer,
ZYDIS_STRBUF_APPEND_MODE_DEFAULT, " {eh}"));
ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer, " {eh}", ZYDIS_LETTER_CASE_DEFAULT));
}
break;
default:
@ -889,11 +768,11 @@ static ZydisStatus ZydisFormatterFormatInstrIntel(const ZydisFormatter* formatte
if (i == 0)
{
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer, 0, " "));
ZYDIS_CHECK(ZydisPrintStr(buffer, bufEnd - *buffer, " ", ZYDIS_LETTER_CASE_DEFAULT));
} else
{
bufRestore = *buffer;
ZYDIS_CHECK(ZydisStringBufferAppend(buffer, bufEnd - *buffer, 0, ", "));
ZYDIS_CHECK(ZydisPrintStr(buffer, bufEnd - *buffer, ", ", ZYDIS_LETTER_CASE_DEFAULT));
}
const char* bufPreOperand = *buffer;