diff --git a/CMakeLists.txt b/CMakeLists.txt index 89b3b2a..f2529fc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) diff --git a/examples/ZydisPerfTest.c b/examples/ZydisPerfTest.c index 271bab7..811ed72 100644 --- a/examples/ZydisPerfTest.c +++ b/examples/ZydisPerfTest.c @@ -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); diff --git a/src/FormatHelper.c b/src/FormatHelper.c new file mode 100644 index 0000000..5e90d7c --- /dev/null +++ b/src/FormatHelper.c @@ -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 +#include +#include + +/* ============================================================================================== */ +/* 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); +} + +/* ---------------------------------------------------------------------------------------------- */ + +/* ============================================================================================== */ diff --git a/src/FormatHelper.h b/src/FormatHelper.h new file mode 100644 index 0000000..6af7fb9 --- /dev/null +++ b/src/FormatHelper.h @@ -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 +#include + +#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 */ diff --git a/src/Formatter.c b/src/Formatter.c index fbdee5e..4c0e5e9 100644 --- a/src/Formatter.c +++ b/src/Formatter.c @@ -24,169 +24,11 @@ ***************************************************************************************************/ -#include -#include #include -#include +#include #include #include -#include - -#if defined(ZYDIS_WINKERNEL) -# include -# include -#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 /* ============================================================================================== */ /* 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;