Switch to length aware string

This commit is contained in:
Joel Höner 2017-12-01 20:40:56 +01:00
parent 1cd788f751
commit fa12ccb64b
6 changed files with 363 additions and 416 deletions

View File

@ -35,6 +35,7 @@
#include <Zydis/DecoderTypes.h> #include <Zydis/DecoderTypes.h>
#include <Zydis/Defines.h> #include <Zydis/Defines.h>
#include <Zydis/Status.h> #include <Zydis/Status.h>
#include <Zydis/String.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -413,14 +414,13 @@ typedef struct ZydisFormatter_ ZydisFormatter;
* @c ZYDIS_FORMATTER_HOOK_POST hook-types. * @c ZYDIS_FORMATTER_HOOK_POST hook-types.
*/ */
typedef ZydisStatus (*ZydisFormatterNotifyFunc)(const ZydisFormatter* formatter, typedef ZydisStatus (*ZydisFormatterNotifyFunc)(const ZydisFormatter* formatter,
const ZydisDecodedInstruction* instruction, void* userData); ZydisString* buffer, const ZydisDecodedInstruction* instruction, void* userData);
/** /**
* @brief Defines the @c ZydisFormatterFormatFunc function pointer. * @brief Defines the @c ZydisFormatterFormatFunc function pointer.
* *
* @param formatter A pointer to the @c ZydisFormatter instance. * @param formatter A pointer to the @c ZydisFormatter instance.
* @param buffer A pointer to the string-buffer. * @param str A pointer to the string buffer.
* @param bufferLen The length of the string-buffer.
* @param instruction A pointer to the @c ZydisDecodedInstruction struct. * @param instruction A pointer to the @c ZydisDecodedInstruction struct.
* @param userData A pointer to user-defined data. * @param userData A pointer to user-defined data.
* *
@ -434,14 +434,13 @@ typedef ZydisStatus (*ZydisFormatterNotifyFunc)(const ZydisFormatter* formatter,
* @c ZYDIS_FORMATTER_HOOK_PRINT_PREFIXES and @c ZYDIS_FORMATTER_HOOK_PRINT_MNEMONIC hook-types. * @c ZYDIS_FORMATTER_HOOK_PRINT_PREFIXES and @c ZYDIS_FORMATTER_HOOK_PRINT_MNEMONIC hook-types.
*/ */
typedef ZydisStatus (*ZydisFormatterFormatFunc)(const ZydisFormatter* formatter, typedef ZydisStatus (*ZydisFormatterFormatFunc)(const ZydisFormatter* formatter,
char** buffer, ZydisUSize bufferLen, const ZydisDecodedInstruction* instruction, void* userData); ZydisString* buffer, const ZydisDecodedInstruction* instruction, void* userData);
/** /**
* @brief Defines the @c ZydisFormatterFormatOperandFunc function pointer. * @brief Defines the @c ZydisFormatterFormatOperandFunc function pointer.
* *
* @param formatter A pointer to the @c ZydisFormatter instance. * @param formatter A pointer to the @c ZydisFormatter instance.
* @param buffer A pointer to the string-buffer. * @param str A pointer to the string buffer.
* @param bufferLen The length of the string-buffer.
* @param instruction A pointer to the @c ZydisDecodedInstruction struct. * @param instruction A pointer to the @c ZydisDecodedInstruction struct.
* @param operand A pointer to the @c ZydisDecodedOperand struct. * @param operand A pointer to the @c ZydisDecodedOperand struct.
* @param userData A pointer to user-defined data. * @param userData A pointer to user-defined data.
@ -471,15 +470,14 @@ typedef ZydisStatus (*ZydisFormatterFormatFunc)(const ZydisFormatter* formatter,
* hook-types. * hook-types.
*/ */
typedef ZydisStatus (*ZydisFormatterFormatOperandFunc)(const ZydisFormatter* formatter, typedef ZydisStatus (*ZydisFormatterFormatOperandFunc)(const ZydisFormatter* formatter,
char** buffer, ZydisUSize bufferLen, const ZydisDecodedInstruction* instruction, ZydisString* buffer, const ZydisDecodedInstruction* instruction,
const ZydisDecodedOperand* operand, void* userData); const ZydisDecodedOperand* operand, void* userData);
/** /**
* @brief Defines the @c ZydisFormatterFormatAddressFunc function pointer. * @brief Defines the @c ZydisFormatterFormatAddressFunc function pointer.
* *
* @param formatter A pointer to the @c ZydisFormatter instance. * @param formatter A pointer to the @c ZydisFormatter instance.
* @param buffer A pointer to the string-buffer. * @param str A pointer to the string buffer.
* @param bufferLen The length of the string-buffer.
* @param instruction A pointer to the @c ZydisDecodedInstruction struct. * @param instruction A pointer to the @c ZydisDecodedInstruction struct.
* @param operand A pointer to the @c ZydisDecodedOperand struct. * @param operand A pointer to the @c ZydisDecodedOperand struct.
* @param userData A pointer to user-defined data. * @param userData A pointer to user-defined data.
@ -494,15 +492,14 @@ typedef ZydisStatus (*ZydisFormatterFormatOperandFunc)(const ZydisFormatter* for
* This function type is used for the @c ZYDIS_FORMATTER_HOOK_PRINT_ADDRESS hook-type. * This function type is used for the @c ZYDIS_FORMATTER_HOOK_PRINT_ADDRESS hook-type.
*/ */
typedef ZydisStatus (*ZydisFormatterFormatAddressFunc)(const ZydisFormatter* formatter, typedef ZydisStatus (*ZydisFormatterFormatAddressFunc)(const ZydisFormatter* formatter,
char** buffer, ZydisUSize bufferLen, const ZydisDecodedInstruction* instruction, ZydisString* buffer, const ZydisDecodedInstruction* instruction,
const ZydisDecodedOperand* operand, ZydisU64 address, void* userData); const ZydisDecodedOperand* operand, ZydisU64 address, void* userData);
/** /**
* @brief Defines the @c ZydisFormatterFormatDecoratorFunc function pointer. * @brief Defines the @c ZydisFormatterFormatDecoratorFunc function pointer.
* *
* @param formatter A pointer to the @c ZydisFormatter instance. * @param formatter A pointer to the @c ZydisFormatter instance.
* @param buffer A pointer to the string-buffer. * @param str A pointer to the string buffer.
* @param bufferLen The length of the string-buffer.
* @param instruction A pointer to the @c ZydisDecodedInstruction struct. * @param instruction A pointer to the @c ZydisDecodedInstruction struct.
* @param operand A pointer to the @c ZydisDecodedOperand struct. * @param operand A pointer to the @c ZydisDecodedOperand struct.
* @param type The decorator type. * @param type The decorator type.
@ -520,7 +517,7 @@ typedef ZydisStatus (*ZydisFormatterFormatAddressFunc)(const ZydisFormatter* for
* This function type is used for the @c ZYDIS_FORMATTER_HOOK_PRINT_DECORATOR hook-type. * This function type is used for the @c ZYDIS_FORMATTER_HOOK_PRINT_DECORATOR hook-type.
*/ */
typedef ZydisStatus (*ZydisFormatterFormatDecoratorFunc)(const ZydisFormatter* formatter, typedef ZydisStatus (*ZydisFormatterFormatDecoratorFunc)(const ZydisFormatter* formatter,
char** buffer, ZydisUSize bufferLen, const ZydisDecodedInstruction* instruction, ZydisString* buffer, const ZydisDecodedInstruction* instruction,
const ZydisDecodedOperand* operand, ZydisDecoratorType type, void* userData); const ZydisDecodedOperand* operand, ZydisDecoratorType type, void* userData);
/* ---------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------- */

View File

@ -164,10 +164,10 @@ enum ZydisStatusCodes
#define ZYDIS_CHECK(status) \ #define ZYDIS_CHECK(status) \
do \ do \
{ \ { \
ZydisStatus s = status; \ ZydisStatus status_w4587ntvmEgDG = status; \
if (!ZYDIS_SUCCESS(s)) \ if (!ZYDIS_SUCCESS(status_w4587ntvmEgDG)) \
{ \ { \
return s; \ return status_w4587ntvmEgDG; \
} \ } \
} while (0) } while (0)

45
include/Zydis/String.h Normal file
View File

@ -0,0 +1,45 @@
/***************************************************************************************************
Zyan Disassembler Library (Zydis)
Original Author : Joel Höner
* 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_STRING_H
#define ZYDIS_STRING_H
#include <Zydis/CommonTypes.h>
/* ============================================================================================== */
/* String struct */
/* ============================================================================================== */
typedef struct ZydisString_
{
char *s; // NOT always 0-terminated!
ZydisUSize length;
ZydisUSize capacity; // always -1 for 0 byte
} ZydisString;
/* ============================================================================================== */
#endif // ZYDIS_STRING_H

View File

@ -25,7 +25,6 @@
***************************************************************************************************/ ***************************************************************************************************/
#include <FormatHelper.h> #include <FormatHelper.h>
#include <LibC.h>
/* ============================================================================================== */ /* ============================================================================================== */
/* Constants */ /* Constants */
@ -98,127 +97,16 @@ void ZydisToUpperCase(char* buffer, ZydisUSize bufferLen)
} }
} }
#if defined(ZYDIS_X86) || defined(ZYDIS_ARM) ZydisStatus ZydisPrintDecU64(ZydisString* s, ZydisU64 value, ZydisU8 paddingLength)
ZydisStatus ZydisPrintDecU32(char** buffer, ZydisUSize bufferLen, ZydisU32 value, ZydisU8 paddingLength)
{ {
ZYDIS_ASSERT(buffer); ZYDIS_ASSERT(s);
ZYDIS_ASSERT(bufferLen > 0);
char temp[ZYDIS_MAXCHARS_DEC_32 + 1];
char *p = &temp[ZYDIS_MAXCHARS_DEC_32];
*p = '\0';
while (value >= 100)
{
ZydisU32 const old = value;
p -= 2;
value /= 100;
ZydisMemoryCopy(p, &decimalLookup[(old - (value * 100)) * 2], sizeof(ZydisU16));
}
p -= 2;
ZydisMemoryCopy(p, &decimalLookup[value * 2], sizeof(ZydisU16));
const ZydisUSize n = &temp[ZYDIS_MAXCHARS_DEC_32] - p;
if ((bufferLen < (ZydisUSize)(n + 1)) || (bufferLen < (ZydisUSize)(paddingLength + 1)))
{
return ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE;
}
ZydisUSize offset = 0;
if (n <= paddingLength)
{
offset = paddingLength - n + 1;
ZydisMemorySet(*buffer, '0', offset);
}
ZydisMemoryCopy(&(*buffer)[offset], &p[value < 10], n + 1);
*buffer += n + offset - (ZydisU8)(value < 10);
return ZYDIS_STATUS_SUCCESS;
}
ZydisStatus ZydisPrintHexU32(char** buffer, ZydisUSize bufferLen, ZydisU32 value, ZydisU8 paddingLength,
ZydisBool uppercase, const char* prefix, const char* suffix)
{
ZYDIS_ASSERT(buffer);
ZYDIS_ASSERT(bufferLen);
if (prefix)
{
const char* bufEnd = *buffer + bufferLen;
ZYDIS_CHECK(ZydisPrintStr(buffer, bufferLen, prefix, ZYDIS_LETTER_CASE_DEFAULT));
bufferLen = bufEnd - *buffer;
}
if (bufferLen < (ZydisUSize)(paddingLength + 1))
{
return ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE;
}
if (!value)
{
const ZydisU8 n = (paddingLength ? paddingLength : 1);
if (bufferLen < (ZydisUSize)(n + 1))
{
return ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE;
}
ZydisMemorySet(*buffer, '0', n);
(*buffer)[n] = '\0';
*buffer += n;
return ZYDIS_STATUS_SUCCESS;
}
ZydisU8 n = 0;
for (ZydisI8 i = ZYDIS_MAXCHARS_HEX_32 - 1; i >= 0; --i)
{
const ZydisU8 v = (value >> i * 4) & 0x0F;
if (!n)
{
if (!v)
{
continue;
}
if (bufferLen <= (ZydisU8)(i + 1))
{
return ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE;
}
if (paddingLength > i)
{
n = paddingLength - i - 1;
ZydisMemorySet(*buffer, '0', n);
}
}
if (uppercase)
{
(*buffer)[n++] = "0123456789ABCDEF"[v];
} else
{
(*buffer)[n++] = "0123456789abcdef"[v];
}
}
(*buffer)[n] = '\0';
*buffer += n;
if (suffix)
{
ZYDIS_CHECK(ZydisPrintStr(buffer, bufferLen - n, suffix, ZYDIS_LETTER_CASE_DEFAULT));
}
return ZYDIS_STATUS_SUCCESS;
}
#endif
ZydisStatus ZydisPrintDecU64(char** buffer, ZydisUSize bufferLen, ZydisU64 value, ZydisU8 paddingLength)
{
ZYDIS_ASSERT(buffer);
ZYDIS_ASSERT(bufferLen > 0);
char temp[ZYDIS_MAXCHARS_DEC_64 + 1]; char temp[ZYDIS_MAXCHARS_DEC_64 + 1];
char *p = &temp[ZYDIS_MAXCHARS_DEC_64]; char *p = &temp[ZYDIS_MAXCHARS_DEC_64];
*p = '\0';
while (value >= 100) while (value >= 100)
{ {
ZydisU64 const old = value; const ZydisU64 old = value;
p -= 2; p -= 2;
value /= 100; value /= 100;
ZydisMemoryCopy(p, &decimalLookup[(old - (value * 100)) * 2], 2); ZydisMemoryCopy(p, &decimalLookup[(old - (value * 100)) * 2], 2);
@ -227,7 +115,8 @@ ZydisStatus ZydisPrintDecU64(char** buffer, ZydisUSize bufferLen, ZydisU64 value
ZydisMemoryCopy(p, &decimalLookup[value * 2], 2); ZydisMemoryCopy(p, &decimalLookup[value * 2], 2);
const ZydisUSize n = &temp[ZYDIS_MAXCHARS_DEC_64] - p; const ZydisUSize n = &temp[ZYDIS_MAXCHARS_DEC_64] - p;
if ((bufferLen < (ZydisUSize)(n + 1)) || (bufferLen < (ZydisUSize)(paddingLength + 1))) if ((s->capacity - s->length < (ZydisUSize)(n + 1)) ||
(s->capacity - s->length < (ZydisUSize)(paddingLength + 1)))
{ {
return ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE; return ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE;
} }
@ -236,179 +125,176 @@ ZydisStatus ZydisPrintDecU64(char** buffer, ZydisUSize bufferLen, ZydisU64 value
if (n <= paddingLength) if (n <= paddingLength)
{ {
offset = paddingLength - n + 1; offset = paddingLength - n + 1;
ZydisMemorySet(*buffer, '0', offset); ZydisMemorySet(s->s + s->length, '0', offset);
} }
ZydisMemoryCopy(&(*buffer)[offset], &p[value < 10], n + 1); ZydisMemoryCopy(s->s + s->length + offset, &p[value < 10], n + 1);
*buffer += n + offset - (ZydisU8)(value < 10); s->length += n + offset - (ZydisU8)(value < 10);
return ZYDIS_STATUS_SUCCESS; return ZYDIS_STATUS_SUCCESS;
} }
ZydisStatus ZydisPrintHexU64(char** buffer, ZydisUSize bufferLen, ZydisU64 value, ZydisU8 paddingLength, ZydisStatus ZydisPrintHexU64(ZydisString* s, ZydisU64 value, ZydisU8 paddingLength,
ZydisBool uppercase, const char* prefix, const char* suffix) ZydisBool uppercase, const char* prefix, const char* suffix)
{ {
ZYDIS_ASSERT(buffer); ZYDIS_ASSERT(s);
ZYDIS_ASSERT(bufferLen);
if (prefix)
if (prefix) {
{ ZYDIS_CHECK(ZydisStringAppendC(s, prefix, ZYDIS_LETTER_CASE_DEFAULT));
const char* bufEnd = *buffer + bufferLen; }
ZYDIS_CHECK(ZydisPrintStr(buffer, bufferLen, prefix, ZYDIS_LETTER_CASE_DEFAULT));
bufferLen = bufEnd - *buffer; char* buffer = s->s + s->length;
} ZydisUSize numRemainingBytes = s->capacity - s->length;
if (bufferLen < (ZydisUSize)(paddingLength + 1))
{ if (numRemainingBytes < (ZydisUSize)paddingLength)
return ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE; {
} return ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE;
}
if (!value)
{ if (!value)
const ZydisU8 n = (paddingLength ? paddingLength : 1); {
const ZydisU8 n = (paddingLength ? paddingLength : 1);
if (bufferLen < (ZydisUSize)(n + 1))
{ if (numRemainingBytes < (ZydisUSize)n)
return ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE; {
} return ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE;
}
ZydisMemorySet(*buffer, '0', n);
(*buffer)[n] = '\0'; ZydisMemorySet(buffer, '0', n);
*buffer += n; s->length += n;
return ZYDIS_STATUS_SUCCESS; return ZYDIS_STATUS_SUCCESS;
} }
ZydisU8 n = 0; ZydisU8 n = 0;
const ZydisU8 c = ((value & 0xFFFFFFFF00000000) ? ZYDIS_MAXCHARS_HEX_64 : ZYDIS_MAXCHARS_HEX_32); const ZydisU8 c = ((value & 0xFFFFFFFF00000000) ? ZYDIS_MAXCHARS_HEX_64 : ZYDIS_MAXCHARS_HEX_32);
for (ZydisI8 i = c - 1; i >= 0; --i) for (ZydisI8 i = c - 1; i >= 0; --i)
{ {
const ZydisU8 v = (value >> i * 4) & 0x0F; const ZydisU8 v = (value >> i * 4) & 0x0F;
if (!n) if (!n)
{ {
if (!v) if (!v)
{ {
continue; continue;
} }
if (bufferLen <= (ZydisU8)(i + 1)) if (numRemainingBytes <= (ZydisU8)(i + 1))
{ {
return ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE; return ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE;
} }
if (paddingLength > i) if (paddingLength > i)
{ {
n = paddingLength - i - 1; n = paddingLength - i - 1;
ZydisMemorySet(*buffer, '0', n); ZydisMemorySet(buffer, '0', n);
} }
} }
if (uppercase) if (uppercase)
{ {
(*buffer)[n++] = "0123456789ABCDEF"[v]; buffer[n++] = "0123456789ABCDEF"[v];
} else } else
{ {
(*buffer)[n++] = "0123456789abcdef"[v]; buffer[n++] = "0123456789abcdef"[v];
} }
} }
(*buffer)[n] = '\0'; s->length += n;
*buffer += n;
if (suffix)
if (suffix) {
{ ZYDIS_CHECK(ZydisStringAppendC(s, suffix, ZYDIS_LETTER_CASE_DEFAULT));
ZYDIS_CHECK(ZydisPrintStr(buffer, bufferLen - n, suffix, ZYDIS_LETTER_CASE_DEFAULT)); }
}
return ZYDIS_STATUS_SUCCESS;
return ZYDIS_STATUS_SUCCESS;
} }
/* ---------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------- */
/* Public Functions */ /* Public Functions */
/* ---------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------- */
ZydisStatus ZydisPrintStr(char** buffer, ZydisUSize bufferLen, const char* text, ZydisStatus ZydisStringAppend(ZydisString* s, const ZydisString* text, ZydisLetterCase letterCase)
ZydisLetterCase letterCase)
{ {
ZYDIS_ASSERT(buffer); ZYDIS_ASSERT(s);
ZYDIS_ASSERT(bufferLen > 0); ZYDIS_ASSERT(s->capacity >= s->length);
ZYDIS_ASSERT(text); ZYDIS_ASSERT(text);
ZYDIS_ASSERT(text->capacity >= s->length);
const ZydisUSize strLen = ZydisStrLen(text); if (s->length + text->length >= s->capacity)
if (strLen >= bufferLen)
{ {
return ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE; return ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE;
} }
ZydisMemoryCopy(*buffer, text, strLen + 1); ZydisMemoryCopy(s->s + s->length, text->s, text->length);
switch (letterCase) switch (letterCase)
{ {
case ZYDIS_LETTER_CASE_DEFAULT: case ZYDIS_LETTER_CASE_DEFAULT:
break; break;
case ZYDIS_LETTER_CASE_LOWER: case ZYDIS_LETTER_CASE_LOWER:
ZydisToLowerCase(*buffer, strLen); ZydisToLowerCase(s->s + s->length, text->length);
break; break;
case ZYDIS_LETTER_CASE_UPPER: case ZYDIS_LETTER_CASE_UPPER:
ZydisToUpperCase(*buffer, strLen); ZydisToUpperCase(s->s + s->length, text->length);
break; break;
default: default:
ZYDIS_UNREACHABLE; ZYDIS_UNREACHABLE;
} }
*buffer += strLen;
s->length += text->length;
return ZYDIS_STATUS_SUCCESS; return ZYDIS_STATUS_SUCCESS;
} }
ZydisStatus ZydisPrintDecU(char** buffer, ZydisUSize bufferLen, ZydisU64 value, ZydisU8 paddingLength) ZydisStatus ZydisPrintDecU(ZydisString *s, ZydisU64 value, ZydisU8 paddingLength)
{ {
#if defined(ZYDIS_X64) || defined(ZYDIS_AARCH64) #if defined(ZYDIS_X64) || defined(ZYDIS_AARCH64)
return ZydisPrintDecU64(buffer, bufferLen, value, paddingLength); return ZydisPrintDecU64(s, value, paddingLength);
#else #else
if (value & 0xFFFFFFFF00000000) if (value & 0xFFFFFFFF00000000)
{ {
return ZydisPrintDecU64(buffer, bufferLen, value, paddingLength); return ZydisPrintDecU64(s, value, paddingLength);
} else } else
{ {
return ZydisPrintDecU32(buffer, bufferLen, (ZydisU32)value, paddingLength); return ZydisPrintDecU32(s, (ZydisU32)value, paddingLength);
} }
#endif #endif
} }
ZydisStatus ZydisPrintDecS(char** buffer, ZydisUSize bufferLen, ZydisI64 value, ZydisU8 paddingLength) ZydisStatus ZydisPrintDecS(ZydisString *s, ZydisI64 value, ZydisU8 paddingLength)
{ {
if (value < 0) if (value < 0)
{ {
ZYDIS_CHECK(ZydisPrintStr(buffer, bufferLen, "-", ZYDIS_LETTER_CASE_DEFAULT)); ZYDIS_CHECK(ZydisStringAppendC(s, "-", ZYDIS_LETTER_CASE_DEFAULT));
return ZydisPrintDecU(buffer, bufferLen - 1, -value, paddingLength); return ZydisPrintDecU(s, -value, paddingLength);
} }
return ZydisPrintDecU(buffer, bufferLen, value, paddingLength); return ZydisPrintDecU(s, value, paddingLength);
} }
ZydisStatus ZydisPrintHexU(char** buffer, ZydisUSize bufferLen, ZydisU64 value, ZydisU8 paddingLength, ZydisStatus ZydisPrintHexU(ZydisString *s, ZydisU64 value, ZydisU8 paddingLength,
ZydisBool uppercase, const char* prefix, const char* suffix) ZydisBool uppercase, const char* prefix, const char* suffix)
{ {
#if defined(ZYDIS_X64) || defined(ZYDIS_AARCH64) #if defined(ZYDIS_X64) || defined(ZYDIS_AARCH64)
return ZydisPrintHexU64(buffer, bufferLen, value, paddingLength, uppercase, prefix, suffix); return ZydisPrintHexU64(s, value, paddingLength, uppercase, prefix, suffix);
#else #else
if (value & 0xFFFFFFFF00000000) if (value & 0xFFFFFFFF00000000)
{ {
return ZydisPrintHexU64(buffer, bufferLen, value, paddingLength, uppercase, prefix, suffix); return ZydisPrintHexU64(s, value, paddingLength, uppercase, prefix, suffix);
} else } else
{ {
return ZydisPrintHexU32(buffer, bufferLen, (ZydisU32)value, paddingLength, uppercase, return ZydisPrintHexU32(s, (ZydisU32)value, paddingLength, uppercase, prefix, suffix);
prefix, suffix);
} }
#endif #endif
} }
ZydisStatus ZydisPrintHexS(char** buffer, ZydisUSize bufferLen, ZydisI64 value, ZydisU8 paddingLength, ZydisStatus ZydisPrintHexS(ZydisString *s, ZydisI64 value, ZydisU8 paddingLength,
ZydisBool uppercase, const char* prefix, const char* suffix) ZydisBool uppercase, const char* prefix, const char* suffix)
{ {
if (value < 0) if (value < 0)
{ {
const char* bufEnd = *buffer + bufferLen; ZYDIS_CHECK(ZydisStringAppendC(s, "-", ZYDIS_LETTER_CASE_DEFAULT));
ZYDIS_CHECK(ZydisPrintStr(buffer, bufferLen, "-", ZYDIS_LETTER_CASE_DEFAULT));
if (prefix) if (prefix)
{ {
ZYDIS_CHECK(ZydisPrintStr(buffer, bufEnd - *buffer, prefix, ZYDIS_LETTER_CASE_DEFAULT)); ZYDIS_CHECK(ZydisStringAppendC(s, prefix, ZYDIS_LETTER_CASE_DEFAULT));
} }
return ZydisPrintHexU(buffer, bufEnd - *buffer, -value, paddingLength, uppercase, return ZydisPrintHexU(s, -value, paddingLength, uppercase, ZYDIS_NULL, suffix);
ZYDIS_NULL, suffix);
} }
return ZydisPrintHexU(buffer, bufferLen, value, paddingLength, uppercase, prefix, suffix); return ZydisPrintHexU(s, value, paddingLength, uppercase, prefix, suffix);
} }
/* ---------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------- */

View File

@ -29,6 +29,8 @@
#include <Zydis/Defines.h> #include <Zydis/Defines.h>
#include <Zydis/Status.h> #include <Zydis/Status.h>
#include <Zydis/String.h>
#include <LibC.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -77,22 +79,44 @@ enum ZydisLetterCases
/* ---------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------- */
/** /**
* @brief Appends the given @c text to the @c buffer. * @brief Appends the @c ZydisString to another @c ZydisString.
* *
* @param buffer A pointer to the string-buffer. * @param buffer The string to append to.
* @param bufferLen The length of the string-buffer. * @param text The string 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.
*/
ZYDIS_NO_EXPORT ZydisStatus ZydisStringAppend(
ZydisString* s, const ZydisString* text, ZydisLetterCase letterCase);
/**
* @brief Appends the given C string to the @c ZydisString.
*
* @param s The string to append to.
* @param text The text to append. * @param text The text to append.
* @param letterCase The desired letter-case. * @param letterCase The desired letter-case.
* *
* @return @c ZYDIS_STATUS_SUCCESS, if the function succeeded, or * @return @c ZYDIS_STATUS_SUCCESS, if the function succeeded, or
* @c ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE, if the size of the buffer was not * @c ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE, if the size of the buffer was not
* sufficient to append the given @c text. * 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, ZydisUSize bufferLen, const char* text, ZYDIS_INLINE ZydisStatus ZydisStringAppendC(
ZydisLetterCase letterCase); ZydisString* s, const char* text, ZydisLetterCase letterCase)
{
ZYDIS_ASSERT(text);
ZydisUSize len = ZydisStrLen(text);
ZydisString zyStr = {
.s = (char*)text,
.length = len,
.capacity = len
};
return ZydisStringAppend(s, &zyStr, letterCase);
}
/* ---------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------- */
/* Decimal values */ /* Decimal values */
@ -100,10 +124,9 @@ ZYDIS_NO_EXPORT ZydisStatus ZydisPrintStr(char** buffer, ZydisUSize bufferLen, c
/** /**
* @brief Formats the given unsigned ordinal @c value to its decimal text-representation and * @brief Formats the given unsigned ordinal @c value to its decimal text-representation and
* appends it to the @c buffer. * appends it to @c s.
* *
* @param buffer A pointer to the string-buffer. * @param s A pointer to the string.
* @param bufferLen The length of the string-buffer.
* @param value The value. * @param value The value.
* @param paddingLength Padds the converted value with leading zeros, if the number of chars is * @param paddingLength Padds the converted value with leading zeros, if the number of chars is
* less than the @c paddingLength. * less than the @c paddingLength.
@ -115,15 +138,13 @@ ZYDIS_NO_EXPORT ZydisStatus ZydisPrintStr(char** buffer, ZydisUSize bufferLen, c
* The string-buffer pointer is increased by the number of chars written, if the call was * The string-buffer pointer is increased by the number of chars written, if the call was
* successfull. * successfull.
*/ */
ZYDIS_NO_EXPORT ZydisStatus ZydisPrintDecU(char** buffer, ZydisUSize bufferLen, ZydisU64 value, ZYDIS_NO_EXPORT ZydisStatus ZydisPrintDecU(ZydisString* s, ZydisU64 value, ZydisU8 paddingLength);
ZydisU8 paddingLength);
/** /**
* @brief Formats the given signed ordinal @c value to its decimal text-representation and * @brief Formats the given signed ordinal @c value to its decimal text-representation and
* appends it to the @c buffer. * appends it to @c s.
* *
* @param buffer A pointer to the string-buffer. * @param s A pointer to the string.
* @param bufferLen The length of the string-buffer.
* @param value The value. * @param value The value.
* @param paddingLength Padds the converted value with leading zeros, if the number of chars is * @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). * less than the @c paddingLength (the sign char is ignored).
@ -135,7 +156,7 @@ ZYDIS_NO_EXPORT ZydisStatus ZydisPrintDecU(char** buffer, ZydisUSize bufferLen,
* The string-buffer pointer is increased by the number of chars written, if the call was * The string-buffer pointer is increased by the number of chars written, if the call was
* successfull. * successfull.
*/ */
ZYDIS_NO_EXPORT ZydisStatus ZydisPrintDecS(char** buffer, ZydisUSize bufferLen, ZydisI64 value, ZYDIS_NO_EXPORT ZydisStatus ZydisPrintDecS(ZydisString* s, ZydisI64 value,
ZydisU8 paddingLength); ZydisU8 paddingLength);
/* ---------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------- */
@ -146,8 +167,7 @@ ZYDIS_NO_EXPORT ZydisStatus ZydisPrintDecS(char** buffer, ZydisUSize bufferLen,
* @brief Formats the given unsigned ordinal @c value to its hexadecimal text-representation and * @brief Formats the given unsigned ordinal @c value to its hexadecimal text-representation and
* appends it to the @c buffer. * appends it to the @c buffer.
* *
* @param buffer A pointer to the string-buffer. * @param s A pointer to the string.
* @param bufferLen The length of the string-buffer.
* @param value The value. * @param value The value.
* @param paddingLength Padds the converted value with leading zeros, if the number of chars is * @param paddingLength Padds the converted value with leading zeros, if the number of chars is
* less than the @c paddingLength. * less than the @c paddingLength.
@ -163,15 +183,14 @@ ZYDIS_NO_EXPORT ZydisStatus ZydisPrintDecS(char** buffer, ZydisUSize bufferLen,
* The string-buffer pointer is increased by the number of chars written, if the call was * The string-buffer pointer is increased by the number of chars written, if the call was
* successfull. * successfull.
*/ */
ZYDIS_NO_EXPORT ZydisStatus ZydisPrintHexU(char** buffer, ZydisUSize bufferLen, ZydisU64 value, ZYDIS_NO_EXPORT ZydisStatus ZydisPrintHexU(ZydisString* s, ZydisU64 value,
ZydisU8 paddingLength, ZydisBool uppercase, const char* prefix, const char* suffix); ZydisU8 paddingLength, ZydisBool uppercase, const char* prefix, const char* suffix);
/** /**
* @brief Formats the given signed ordinal @c value to its hexadecimal text-representation and * @brief Formats the given signed ordinal @c value to its hexadecimal text-representation and
* appends it to the @c buffer. * appends it to the @c buffer.
* *
* @param buffer A pointer to the string-buffer. * @param s A pointer to the string.
* @param bufferLen The length of the string-buffer.
* @param value The value. * @param value The value.
* @param paddingLength Padds the converted value with leading zeros, if the number of chars is * @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). * less than the @c paddingLength (the sign char is ignored).
@ -187,7 +206,7 @@ ZYDIS_NO_EXPORT ZydisStatus ZydisPrintHexU(char** buffer, ZydisUSize bufferLen,
* The string-buffer pointer is increased by the number of chars written, if the call was * The string-buffer pointer is increased by the number of chars written, if the call was
* successfull. * successfull.
*/ */
ZYDIS_NO_EXPORT ZydisStatus ZydisPrintHexS(char** buffer, ZydisUSize bufferLen, ZydisI64 value, ZYDIS_NO_EXPORT ZydisStatus ZydisPrintHexS(ZydisString* s, ZydisI64 value,
ZydisU8 paddingLength, ZydisBool uppercase, const char* prefix, const char* suffix); ZydisU8 paddingLength, ZydisBool uppercase, const char* prefix, const char* suffix);
/* ---------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------- */

View File

@ -39,72 +39,70 @@
/* ---------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------- */
static ZydisStatus ZydisFormatterPrintPrefixesIntel(const ZydisFormatter* formatter, static ZydisStatus ZydisFormatterPrintPrefixesIntel(const ZydisFormatter* formatter,
char** buffer, ZydisUSize bufferLen, const ZydisDecodedInstruction* instruction, void* userData) ZydisString* buffer, const ZydisDecodedInstruction* instruction, void* userData)
{ {
(void)userData; (void)userData;
if (!formatter || !buffer || !*buffer || (bufferLen <= 0) || !instruction) if (!formatter || !buffer || !instruction)
{ {
return ZYDIS_STATUS_INVALID_PARAMETER; return ZYDIS_STATUS_INVALID_PARAMETER;
} }
if (instruction->attributes & ZYDIS_ATTRIB_HAS_LOCK) if (instruction->attributes & ZYDIS_ATTRIB_HAS_LOCK)
{ {
return ZydisPrintStr(buffer, bufferLen, "lock ", formatter->letterCase); return ZydisStringAppendC(buffer, "lock ", formatter->letterCase);
} }
if (instruction->attributes & ZYDIS_ATTRIB_HAS_REP) if (instruction->attributes & ZYDIS_ATTRIB_HAS_REP)
{ {
return ZydisPrintStr(buffer, bufferLen, "rep ", formatter->letterCase); return ZydisStringAppendC(buffer, "rep ", formatter->letterCase);
} }
if (instruction->attributes & ZYDIS_ATTRIB_HAS_REPE) if (instruction->attributes & ZYDIS_ATTRIB_HAS_REPE)
{ {
return ZydisPrintStr(buffer, bufferLen, "repe ", formatter->letterCase); return ZydisStringAppendC(buffer, "repe ", formatter->letterCase);
} }
if (instruction->attributes & ZYDIS_ATTRIB_HAS_REPNE) if (instruction->attributes & ZYDIS_ATTRIB_HAS_REPNE)
{ {
return ZydisPrintStr(buffer, bufferLen, "repne ", formatter->letterCase); return ZydisStringAppendC(buffer, "repne ", formatter->letterCase);
} }
if (instruction->attributes & ZYDIS_ATTRIB_HAS_BOUND) if (instruction->attributes & ZYDIS_ATTRIB_HAS_BOUND)
{ {
return ZydisPrintStr(buffer, bufferLen, "bnd ", formatter->letterCase); return ZydisStringAppendC(buffer, "bnd ", formatter->letterCase);
} }
if (instruction->attributes & ZYDIS_ATTRIB_HAS_XACQUIRE) if (instruction->attributes & ZYDIS_ATTRIB_HAS_XACQUIRE)
{ {
return ZydisPrintStr(buffer, bufferLen, "xacquire ", formatter->letterCase); return ZydisStringAppendC(buffer, "xacquire ", formatter->letterCase);
} }
if (instruction->attributes & ZYDIS_ATTRIB_HAS_XRELEASE) if (instruction->attributes & ZYDIS_ATTRIB_HAS_XRELEASE)
{ {
return ZydisPrintStr(buffer, bufferLen, "xrelease ", formatter->letterCase); return ZydisStringAppendC(buffer, "xrelease ", formatter->letterCase);
} }
return ZYDIS_STATUS_SUCCESS; return ZYDIS_STATUS_SUCCESS;
} }
static ZydisStatus ZydisFormatterPrintMnemonicIntel(const ZydisFormatter* formatter, static ZydisStatus ZydisFormatterPrintMnemonicIntel(const ZydisFormatter* formatter,
char** buffer, ZydisUSize bufferLen, const ZydisDecodedInstruction* instruction, void* userData) ZydisString* buffer, const ZydisDecodedInstruction* instruction, void* userData)
{ {
(void)userData; (void)userData;
if (!formatter || !buffer || !*buffer || (bufferLen <= 0) || !instruction) if (!formatter || !buffer || !instruction)
{ {
return ZYDIS_STATUS_INVALID_PARAMETER; return ZYDIS_STATUS_INVALID_PARAMETER;
} }
const char* bufEnd = *buffer + bufferLen;
const char* mnemonic = ZydisMnemonicGetString(instruction->mnemonic); const char* mnemonic = ZydisMnemonicGetString(instruction->mnemonic);
if (!mnemonic) if (!mnemonic)
{ {
mnemonic = "invalid"; mnemonic = "invalid";
} }
ZYDIS_CHECK(ZydisPrintStr(buffer, bufferLen, mnemonic, formatter->letterCase)); ZYDIS_CHECK(ZydisStringAppendC(buffer, mnemonic, formatter->letterCase));
if (instruction->attributes & ZYDIS_ATTRIB_IS_FAR_BRANCH) if (instruction->attributes & ZYDIS_ATTRIB_IS_FAR_BRANCH)
{ {
return ZydisPrintStr(buffer, bufEnd - *buffer, " far", formatter->letterCase); return ZydisStringAppendC(buffer, " far", formatter->letterCase);
} }
return ZYDIS_STATUS_SUCCESS; return ZYDIS_STATUS_SUCCESS;
@ -113,12 +111,12 @@ static ZydisStatus ZydisFormatterPrintMnemonicIntel(const ZydisFormatter* format
/* ---------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------- */
static ZydisStatus ZydisFormatterFormatOperandRegIntel(const ZydisFormatter* formatter, static ZydisStatus ZydisFormatterFormatOperandRegIntel(const ZydisFormatter* formatter,
char** buffer, ZydisUSize bufferLen, const ZydisDecodedInstruction* instruction, ZydisString* buffer, const ZydisDecodedInstruction* instruction,
const ZydisDecodedOperand* operand, void* userData) const ZydisDecodedOperand* operand, void* userData)
{ {
(void)userData; (void)userData;
if (!formatter || !buffer || !*buffer || (bufferLen <= 0) || !instruction || !operand) if (!formatter || !buffer || !instruction || !operand)
{ {
return ZYDIS_STATUS_INVALID_PARAMETER; return ZYDIS_STATUS_INVALID_PARAMETER;
} }
@ -133,21 +131,20 @@ static ZydisStatus ZydisFormatterFormatOperandRegIntel(const ZydisFormatter* for
{ {
reg = "invalid"; reg = "invalid";
} }
return ZydisPrintStr(buffer, bufferLen, reg, formatter->letterCase);
return ZydisStringAppendC(buffer, reg, formatter->letterCase);
} }
static ZydisStatus ZydisFormatterFormatOperandMemIntel(const ZydisFormatter* formatter, static ZydisStatus ZydisFormatterFormatOperandMemIntel(const ZydisFormatter* formatter,
char** buffer, ZydisUSize bufferLen, const ZydisDecodedInstruction* instruction, ZydisString* buffer, const ZydisDecodedInstruction* instruction,
const ZydisDecodedOperand* operand, void* userData) const ZydisDecodedOperand* operand, void* userData)
{ {
if (!formatter || !buffer || !*buffer || (bufferLen <= 0) || !instruction || !operand) if (!formatter || !buffer || !instruction || !operand)
{ {
return ZYDIS_STATUS_INVALID_PARAMETER; return ZYDIS_STATUS_INVALID_PARAMETER;
} }
const char* bufEnd = *buffer + bufferLen; ZYDIS_CHECK(ZydisStringAppendC(buffer, "[", ZYDIS_LETTER_CASE_DEFAULT));
ZYDIS_CHECK(ZydisPrintStr(buffer, bufEnd - *buffer, "[", ZYDIS_LETTER_CASE_DEFAULT));
if (operand->mem.disp.hasDisplacement && ( if (operand->mem.disp.hasDisplacement && (
(operand->mem.base == ZYDIS_REGISTER_NONE) || (operand->mem.base == ZYDIS_REGISTER_NONE) ||
@ -161,14 +158,14 @@ static ZydisStatus ZydisFormatterFormatOperandMemIntel(const ZydisFormatter* for
{ {
ZydisU64 address; ZydisU64 address;
ZYDIS_CHECK(ZydisCalcAbsoluteAddress(instruction, operand, &address)); ZYDIS_CHECK(ZydisCalcAbsoluteAddress(instruction, operand, &address));
ZYDIS_CHECK(formatter->funcPrintAddress(formatter, buffer, bufEnd - *buffer, ZYDIS_CHECK(formatter->funcPrintAddress(formatter, buffer, instruction, operand,
instruction, operand, address, userData)); address, userData));
} else } else
{ {
ZYDIS_CHECK(ZydisPrintStr(buffer, bufEnd - *buffer, ZYDIS_CHECK(ZydisStringAppendC(buffer, ZydisRegisterGetString(operand->mem.base),
ZydisRegisterGetString(operand->mem.base), formatter->letterCase)); formatter->letterCase));
ZYDIS_CHECK(formatter->funcPrintDisplacement(formatter, buffer, bufEnd - *buffer, ZYDIS_CHECK(formatter->funcPrintDisplacement(formatter, buffer, instruction, operand,
instruction, operand, userData)); userData));
} }
} else } else
{ {
@ -180,7 +177,7 @@ static ZydisStatus ZydisFormatterFormatOperandMemIntel(const ZydisFormatter* for
{ {
return ZYDIS_STATUS_INVALID_PARAMETER; return ZYDIS_STATUS_INVALID_PARAMETER;
} }
ZYDIS_CHECK(ZydisPrintStr(buffer, bufEnd - *buffer, reg, formatter->letterCase)); ZYDIS_CHECK(ZydisStringAppendC(buffer, reg, formatter->letterCase));
} }
if ((operand->mem.index != ZYDIS_REGISTER_NONE) && if ((operand->mem.index != ZYDIS_REGISTER_NONE) &&
(operand->mem.type != ZYDIS_MEMOP_TYPE_MIB)) (operand->mem.type != ZYDIS_MEMOP_TYPE_MIB))
@ -193,47 +190,46 @@ static ZydisStatus ZydisFormatterFormatOperandMemIntel(const ZydisFormatter* for
if (operand->mem.base != ZYDIS_REGISTER_NONE) if (operand->mem.base != ZYDIS_REGISTER_NONE)
{ {
ZYDIS_CHECK( ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer, "+", ZYDIS_LETTER_CASE_DEFAULT)); ZydisStringAppendC(buffer, "+", ZYDIS_LETTER_CASE_DEFAULT));
} }
ZYDIS_CHECK(ZydisPrintStr(buffer, bufEnd - *buffer, reg, formatter->letterCase)); ZYDIS_CHECK(ZydisStringAppendC(buffer, reg, formatter->letterCase));
if (operand->mem.scale) if (operand->mem.scale)
{ {
ZYDIS_CHECK( ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer, "*", ZYDIS_LETTER_CASE_DEFAULT)); ZydisStringAppendC(buffer, "*", ZYDIS_LETTER_CASE_DEFAULT));
ZYDIS_CHECK(ZydisPrintDecU(buffer, bufEnd - *buffer, operand->mem.scale, 0)); ZYDIS_CHECK(ZydisPrintDecU(buffer, operand->mem.scale, 0));
} }
} }
ZYDIS_CHECK(formatter->funcPrintDisplacement(formatter, buffer, bufEnd - *buffer, ZYDIS_CHECK(formatter->funcPrintDisplacement(formatter, buffer,
instruction, operand, userData)); instruction, operand, userData));
} }
return ZydisPrintStr(buffer, bufEnd - *buffer, "]", ZYDIS_LETTER_CASE_DEFAULT); return ZydisStringAppendC(buffer, "]", ZYDIS_LETTER_CASE_DEFAULT);
} }
static ZydisStatus ZydisFormatterFormatOperandPtrIntel(const ZydisFormatter* formatter, static ZydisStatus ZydisFormatterFormatOperandPtrIntel(const ZydisFormatter* formatter,
char** buffer, ZydisUSize bufferLen, const ZydisDecodedInstruction* instruction, ZydisString* buffer, const ZydisDecodedInstruction* instruction,
const ZydisDecodedOperand* operand, void* userData) const ZydisDecodedOperand* operand, void* userData)
{ {
(void)userData; (void)userData;
if (!formatter || !buffer || !*buffer || (bufferLen <= 0) || !instruction || !operand) if (!formatter || !buffer || !instruction || !operand)
{ {
return ZYDIS_STATUS_INVALID_PARAMETER; return ZYDIS_STATUS_INVALID_PARAMETER;
} }
const char* bufEnd = *buffer + bufferLen; ZYDIS_CHECK(ZydisPrintHexU(buffer, operand->ptr.segment, 4,
ZYDIS_CHECK(ZydisPrintHexU(buffer, bufEnd - *buffer, operand->ptr.segment, 4,
formatter->hexUppercase, formatter->hexPrefix, formatter->hexSuffix)); formatter->hexUppercase, formatter->hexPrefix, formatter->hexSuffix));
ZYDIS_CHECK(ZydisPrintStr(buffer, bufEnd - *buffer, ":", ZYDIS_LETTER_CASE_DEFAULT)); ZYDIS_CHECK(ZydisStringAppendC(buffer, ":", ZYDIS_LETTER_CASE_DEFAULT));
return ZydisPrintHexU(buffer, bufEnd - *buffer, operand->ptr.offset, 8, return ZydisPrintHexU(buffer, operand->ptr.offset, 8,
formatter->hexUppercase, formatter->hexPrefix, formatter->hexSuffix); formatter->hexUppercase, formatter->hexPrefix, formatter->hexSuffix);
} }
static ZydisStatus ZydisFormatterFormatOperandImmIntel(const ZydisFormatter* formatter, static ZydisStatus ZydisFormatterFormatOperandImmIntel(const ZydisFormatter* formatter,
char** buffer, ZydisUSize bufferLen, const ZydisDecodedInstruction* instruction, ZydisString* buffer, const ZydisDecodedInstruction* instruction,
const ZydisDecodedOperand* operand, void* userData) const ZydisDecodedOperand* operand, void* userData)
{ {
if (!formatter || !buffer || !*buffer || (bufferLen <= 0) || !instruction || !operand) if (!formatter || !buffer || !instruction || !operand)
{ {
return ZYDIS_STATUS_INVALID_PARAMETER; return ZYDIS_STATUS_INVALID_PARAMETER;
} }
@ -248,7 +244,7 @@ static ZydisStatus ZydisFormatterFormatOperandImmIntel(const ZydisFormatter* for
{ {
ZydisU64 address; ZydisU64 address;
ZYDIS_CHECK(ZydisCalcAbsoluteAddress(instruction, operand, &address)); ZYDIS_CHECK(ZydisCalcAbsoluteAddress(instruction, operand, &address));
return formatter->funcPrintAddress(formatter, buffer, bufferLen, instruction, operand, return formatter->funcPrintAddress(formatter, buffer, instruction, operand,
address, userData); address, userData);
} }
case ZYDIS_ADDR_FORMAT_RELATIVE_SIGNED: case ZYDIS_ADDR_FORMAT_RELATIVE_SIGNED:
@ -262,29 +258,29 @@ static ZydisStatus ZydisFormatterFormatOperandImmIntel(const ZydisFormatter* for
if (printSignedHEX) if (printSignedHEX)
{ {
return ZydisPrintHexS(buffer, bufferLen, (ZydisI32)operand->imm.value.s, return ZydisPrintHexS(buffer, (ZydisI32)operand->imm.value.s,
formatter->hexPaddingAddress, formatter->hexUppercase, formatter->hexPrefix, formatter->hexPaddingAddress, formatter->hexUppercase, formatter->hexPrefix,
formatter->hexSuffix); formatter->hexSuffix);
} }
return ZydisPrintHexU(buffer, bufferLen, operand->imm.value.u, return ZydisPrintHexU(buffer, operand->imm.value.u,
formatter->hexPaddingAddress, formatter->hexUppercase, formatter->hexPrefix, formatter->hexPaddingAddress, formatter->hexUppercase, formatter->hexPrefix,
formatter->hexSuffix); formatter->hexSuffix);
} }
// The immediate operand contains an actual ordinal value // The immediate operand contains an actual ordinal value
return formatter->funcPrintImmediate( return formatter->funcPrintImmediate(
formatter, buffer, bufferLen, instruction, operand, userData); formatter, buffer, instruction, operand, userData);
} }
/* ---------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------- */
static ZydisStatus ZydisFormatterPrintAddressIntel(const ZydisFormatter* formatter, static ZydisStatus ZydisFormatterPrintAddressIntel(const ZydisFormatter* formatter,
char** buffer, ZydisUSize bufferLen, const ZydisDecodedInstruction* instruction, ZydisString* buffer, const ZydisDecodedInstruction* instruction,
const ZydisDecodedOperand* operand, ZydisU64 address, void* userData) const ZydisDecodedOperand* operand, ZydisU64 address, void* userData)
{ {
(void)userData; (void)userData;
if (!formatter || !buffer || !*buffer || (bufferLen <= 0) || !instruction || !operand) if (!formatter || !buffer || !instruction || !operand)
{ {
return ZYDIS_STATUS_INVALID_PARAMETER; return ZYDIS_STATUS_INVALID_PARAMETER;
} }
@ -292,13 +288,13 @@ static ZydisStatus ZydisFormatterPrintAddressIntel(const ZydisFormatter* formatt
switch (instruction->stackWidth) switch (instruction->stackWidth)
{ {
case 16: case 16:
return ZydisPrintHexU(buffer, bufferLen, (ZydisU16)address, 4, return ZydisPrintHexU(buffer, (ZydisU16)address, 4,
formatter->hexUppercase, formatter->hexPrefix, formatter->hexSuffix); formatter->hexUppercase, formatter->hexPrefix, formatter->hexSuffix);
case 32: case 32:
return ZydisPrintHexU(buffer, bufferLen, (ZydisU32)address, 8, return ZydisPrintHexU(buffer, (ZydisU32)address, 8,
formatter->hexUppercase, formatter->hexPrefix, formatter->hexSuffix); formatter->hexUppercase, formatter->hexPrefix, formatter->hexSuffix);
case 64: case 64:
return ZydisPrintHexU(buffer, bufferLen, address, 16, return ZydisPrintHexU(buffer, address, 16,
formatter->hexUppercase, formatter->hexPrefix, formatter->hexSuffix); formatter->hexUppercase, formatter->hexPrefix, formatter->hexSuffix);
default: default:
return ZYDIS_STATUS_INVALID_PARAMETER; return ZYDIS_STATUS_INVALID_PARAMETER;
@ -306,12 +302,12 @@ static ZydisStatus ZydisFormatterPrintAddressIntel(const ZydisFormatter* formatt
} }
static ZydisStatus ZydisFormatterPrintDisplacementIntel(const ZydisFormatter* formatter, static ZydisStatus ZydisFormatterPrintDisplacementIntel(const ZydisFormatter* formatter,
char** buffer, ZydisUSize bufferLen, const ZydisDecodedInstruction* instruction, ZydisString* buffer, const ZydisDecodedInstruction* instruction,
const ZydisDecodedOperand* operand, void* userData) const ZydisDecodedOperand* operand, void* userData)
{ {
(void)userData; (void)userData;
if (!formatter || !buffer || !*buffer || (bufferLen <= 0) || !instruction || !operand) if (!formatter || !buffer || !instruction || !operand)
{ {
return ZYDIS_STATUS_INVALID_PARAMETER; return ZYDIS_STATUS_INVALID_PARAMETER;
} }
@ -326,17 +322,16 @@ static ZydisStatus ZydisFormatterPrintDisplacementIntel(const ZydisFormatter* fo
(operand->mem.base != ZYDIS_REGISTER_NONE) || (operand->mem.base != ZYDIS_REGISTER_NONE) ||
(operand->mem.index != ZYDIS_REGISTER_NONE))) (operand->mem.index != ZYDIS_REGISTER_NONE)))
{ {
return ZydisPrintHexS(buffer, bufferLen, operand->mem.disp.value, return ZydisPrintHexS(buffer, operand->mem.disp.value,
formatter->hexPaddingDisplacement, formatter->hexUppercase, formatter->hexPrefix, formatter->hexPaddingDisplacement, formatter->hexUppercase, formatter->hexPrefix,
formatter->hexSuffix); formatter->hexSuffix);
} }
const char* bufEnd = *buffer + bufferLen;
if ((operand->mem.base != ZYDIS_REGISTER_NONE) || if ((operand->mem.base != ZYDIS_REGISTER_NONE) ||
(operand->mem.index != ZYDIS_REGISTER_NONE)) (operand->mem.index != ZYDIS_REGISTER_NONE))
{ {
ZYDIS_CHECK(ZydisPrintStr(buffer, bufferLen, "+", ZYDIS_LETTER_CASE_DEFAULT)); ZYDIS_CHECK(ZydisStringAppendC(buffer, "+", ZYDIS_LETTER_CASE_DEFAULT));
} }
return ZydisPrintHexU(buffer, bufEnd - *buffer, (ZydisU64)operand->mem.disp.value, return ZydisPrintHexU(buffer, (ZydisU64)operand->mem.disp.value,
formatter->hexPaddingDisplacement, formatter->hexUppercase, formatter->hexPrefix, formatter->hexPaddingDisplacement, formatter->hexUppercase, formatter->hexPrefix,
formatter->hexSuffix); formatter->hexSuffix);
} }
@ -344,12 +339,12 @@ static ZydisStatus ZydisFormatterPrintDisplacementIntel(const ZydisFormatter* fo
} }
static ZydisStatus ZydisFormatterPrintImmediateIntel(const ZydisFormatter* formatter, static ZydisStatus ZydisFormatterPrintImmediateIntel(const ZydisFormatter* formatter,
char** buffer, ZydisUSize bufferLen, const ZydisDecodedInstruction* instruction, ZydisString* buffer, const ZydisDecodedInstruction* instruction,
const ZydisDecodedOperand* operand, void* userData) const ZydisDecodedOperand* operand, void* userData)
{ {
(void)userData; (void)userData;
if (!formatter || !buffer || !*buffer || (bufferLen <= 0) || !instruction || !operand) if (!formatter || !buffer || !instruction || !operand)
{ {
return ZYDIS_STATUS_INVALID_PARAMETER; return ZYDIS_STATUS_INVALID_PARAMETER;
} }
@ -365,19 +360,19 @@ static ZydisStatus ZydisFormatterPrintImmediateIntel(const ZydisFormatter* forma
switch (operand->size) switch (operand->size)
{ {
case 8: case 8:
return ZydisPrintHexS(buffer, bufferLen, (ZydisI8)operand->imm.value.s, return ZydisPrintHexS(buffer, (ZydisI8)operand->imm.value.s,
formatter->hexPaddingImmediate, formatter->hexUppercase, formatter->hexPrefix, formatter->hexPaddingImmediate, formatter->hexUppercase, formatter->hexPrefix,
formatter->hexSuffix); formatter->hexSuffix);
case 16: case 16:
return ZydisPrintHexS(buffer, bufferLen, (ZydisI16)operand->imm.value.s, return ZydisPrintHexS(buffer, (ZydisI16)operand->imm.value.s,
formatter->hexPaddingImmediate, formatter->hexUppercase, formatter->hexPrefix, formatter->hexPaddingImmediate, formatter->hexUppercase, formatter->hexPrefix,
formatter->hexSuffix); formatter->hexSuffix);
case 32: case 32:
return ZydisPrintHexS(buffer, bufferLen, (ZydisI32)operand->imm.value.s, return ZydisPrintHexS(buffer, (ZydisI32)operand->imm.value.s,
formatter->hexPaddingImmediate, formatter->hexUppercase, formatter->hexPrefix, formatter->hexPaddingImmediate, formatter->hexUppercase, formatter->hexPrefix,
formatter->hexSuffix); formatter->hexSuffix);
case 64: case 64:
return ZydisPrintHexS(buffer, bufferLen, operand->imm.value.s, return ZydisPrintHexS(buffer, operand->imm.value.s,
formatter->hexPaddingImmediate, formatter->hexUppercase, formatter->hexPrefix, formatter->hexPaddingImmediate, formatter->hexUppercase, formatter->hexPrefix,
formatter->hexSuffix); formatter->hexSuffix);
default: default:
@ -387,19 +382,19 @@ static ZydisStatus ZydisFormatterPrintImmediateIntel(const ZydisFormatter* forma
switch (instruction->operandWidth) switch (instruction->operandWidth)
{ {
case 8: case 8:
return ZydisPrintHexU(buffer, bufferLen, (ZydisU8)operand->imm.value.u, return ZydisPrintHexU(buffer, (ZydisU8)operand->imm.value.u,
formatter->hexPaddingImmediate, formatter->hexUppercase, formatter->hexPrefix, formatter->hexPaddingImmediate, formatter->hexUppercase, formatter->hexPrefix,
formatter->hexSuffix); formatter->hexSuffix);
case 16: case 16:
return ZydisPrintHexU(buffer, bufferLen, (ZydisU16)operand->imm.value.u, return ZydisPrintHexU(buffer, (ZydisU16)operand->imm.value.u,
formatter->hexPaddingImmediate, formatter->hexUppercase, formatter->hexPrefix, formatter->hexPaddingImmediate, formatter->hexUppercase, formatter->hexPrefix,
formatter->hexSuffix); formatter->hexSuffix);
case 32: case 32:
return ZydisPrintHexU(buffer, bufferLen, (ZydisU32)operand->imm.value.u, return ZydisPrintHexU(buffer, (ZydisU32)operand->imm.value.u,
formatter->hexPaddingImmediate, formatter->hexUppercase, formatter->hexPrefix, formatter->hexPaddingImmediate, formatter->hexUppercase, formatter->hexPrefix,
formatter->hexSuffix); formatter->hexSuffix);
case 64: case 64:
return ZydisPrintHexU(buffer, bufferLen, operand->imm.value.u, return ZydisPrintHexU(buffer, operand->imm.value.u,
formatter->hexPaddingImmediate, formatter->hexUppercase, formatter->hexPrefix, formatter->hexPaddingImmediate, formatter->hexUppercase, formatter->hexPrefix,
formatter->hexSuffix); formatter->hexSuffix);
default: default:
@ -410,12 +405,12 @@ static ZydisStatus ZydisFormatterPrintImmediateIntel(const ZydisFormatter* forma
/* ---------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------- */
static ZydisStatus ZydisFormatterPrintOperandSizeIntel(const ZydisFormatter* formatter, static ZydisStatus ZydisFormatterPrintOperandSizeIntel(const ZydisFormatter* formatter,
char** buffer, ZydisUSize bufferLen, const ZydisDecodedInstruction* instruction, ZydisString* buffer, const ZydisDecodedInstruction* instruction,
const ZydisDecodedOperand* operand, void* userData) const ZydisDecodedOperand* operand, void* userData)
{ {
(void)userData; (void)userData;
if (!formatter || !buffer || !*buffer || (bufferLen <= 0) || !instruction || !operand) if (!formatter || !buffer || !instruction || !operand)
{ {
return ZYDIS_STATUS_INVALID_PARAMETER; return ZYDIS_STATUS_INVALID_PARAMETER;
} }
@ -510,24 +505,23 @@ static ZydisStatus ZydisFormatterPrintOperandSizeIntel(const ZydisFormatter* for
if (str) if (str)
{ {
return ZydisPrintStr(buffer, bufferLen, str, formatter->letterCase); return ZydisStringAppendC(buffer, str, formatter->letterCase);
} }
} }
return ZYDIS_STATUS_SUCCESS; return ZYDIS_STATUS_SUCCESS;
} }
static ZydisStatus ZydisFormatterPrintSegmentIntel(const ZydisFormatter* formatter, static ZydisStatus ZydisFormatterPrintSegmentIntel(const ZydisFormatter* formatter,
char** buffer, ZydisUSize bufferLen, const ZydisDecodedInstruction* instruction, ZydisString* buffer, const ZydisDecodedInstruction* instruction,
const ZydisDecodedOperand* operand, void* userData) const ZydisDecodedOperand* operand, void* userData)
{ {
(void)userData; (void)userData;
if (!formatter || !buffer || !*buffer || (bufferLen <= 0) || !instruction || !operand) if (!formatter || !buffer || !instruction || !operand)
{ {
return ZYDIS_STATUS_INVALID_PARAMETER; return ZYDIS_STATUS_INVALID_PARAMETER;
} }
const char* bufEnd = *buffer + bufferLen;
switch (operand->mem.segment) switch (operand->mem.segment)
{ {
case ZYDIS_REGISTER_ES: case ZYDIS_REGISTER_ES:
@ -535,17 +529,17 @@ static ZydisStatus ZydisFormatterPrintSegmentIntel(const ZydisFormatter* formatt
case ZYDIS_REGISTER_FS: case ZYDIS_REGISTER_FS:
case ZYDIS_REGISTER_GS: case ZYDIS_REGISTER_GS:
ZYDIS_CHECK( ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer, ZydisStringAppendC(buffer, ZydisRegisterGetString(operand->mem.segment),
ZydisRegisterGetString(operand->mem.segment), formatter->letterCase)); formatter->letterCase));
return ZydisPrintStr(buffer, bufEnd - *buffer, ":", ZYDIS_LETTER_CASE_DEFAULT); return ZydisStringAppendC(buffer, ":", ZYDIS_LETTER_CASE_DEFAULT);
case ZYDIS_REGISTER_SS: case ZYDIS_REGISTER_SS:
if ((formatter->forceSegments) || if ((formatter->forceSegments) ||
(instruction->attributes & ZYDIS_ATTRIB_HAS_SEGMENT_SS)) (instruction->attributes & ZYDIS_ATTRIB_HAS_SEGMENT_SS))
{ {
ZYDIS_CHECK( ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer, ZydisStringAppendC(buffer, ZydisRegisterGetString(operand->mem.segment),
ZydisRegisterGetString(operand->mem.segment), formatter->letterCase)); formatter->letterCase));
return ZydisPrintStr(buffer, bufEnd - *buffer, ":", ZYDIS_LETTER_CASE_DEFAULT); return ZydisStringAppendC(buffer, ":", ZYDIS_LETTER_CASE_DEFAULT);
} }
break; break;
case ZYDIS_REGISTER_DS: case ZYDIS_REGISTER_DS:
@ -553,9 +547,9 @@ static ZydisStatus ZydisFormatterPrintSegmentIntel(const ZydisFormatter* formatt
(instruction->attributes & ZYDIS_ATTRIB_HAS_SEGMENT_DS)) (instruction->attributes & ZYDIS_ATTRIB_HAS_SEGMENT_DS))
{ {
ZYDIS_CHECK( ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer, ZydisStringAppendC(buffer, ZydisRegisterGetString(operand->mem.segment),
ZydisRegisterGetString(operand->mem.segment), formatter->letterCase)); formatter->letterCase));
return ZydisPrintStr(buffer, bufEnd - *buffer, ":", ZYDIS_LETTER_CASE_DEFAULT); return ZydisStringAppendC(buffer, ":", ZYDIS_LETTER_CASE_DEFAULT);
} }
break; break;
default: default:
@ -565,17 +559,16 @@ static ZydisStatus ZydisFormatterPrintSegmentIntel(const ZydisFormatter* formatt
} }
static ZydisStatus ZydisFormatterPrintDecoratorIntel(const ZydisFormatter* formatter, static ZydisStatus ZydisFormatterPrintDecoratorIntel(const ZydisFormatter* formatter,
char** buffer, ZydisUSize bufferLen, const ZydisDecodedInstruction* instruction, ZydisString* buffer, const ZydisDecodedInstruction* instruction,
const ZydisDecodedOperand* operand, ZydisDecoratorType type, void* userData) const ZydisDecodedOperand* operand, ZydisDecoratorType type, void* userData)
{ {
(void)userData; (void)userData;
if (!formatter || !buffer || !*buffer || (bufferLen <= 0) || !instruction || !operand) if (!formatter || !buffer || !instruction || !operand)
{ {
return ZYDIS_STATUS_INVALID_PARAMETER; return ZYDIS_STATUS_INVALID_PARAMETER;
} }
const char* bufEnd = *buffer + bufferLen;
switch (type) switch (type)
{ {
case ZYDIS_DECORATOR_TYPE_MASK: case ZYDIS_DECORATOR_TYPE_MASK:
@ -587,13 +580,13 @@ static ZydisStatus ZydisFormatterPrintDecoratorIntel(const ZydisFormatter* forma
{ {
return ZYDIS_STATUS_INVALID_PARAMETER; return ZYDIS_STATUS_INVALID_PARAMETER;
} }
ZYDIS_CHECK(ZydisPrintStr(buffer, bufEnd - *buffer, " {", ZYDIS_LETTER_CASE_DEFAULT)); ZYDIS_CHECK(ZydisStringAppendC(buffer, " {", ZYDIS_LETTER_CASE_DEFAULT));
ZYDIS_CHECK(ZydisPrintStr(buffer, bufEnd - *buffer, reg, formatter->letterCase)); ZYDIS_CHECK(ZydisStringAppendC(buffer, reg, formatter->letterCase));
ZYDIS_CHECK(ZydisPrintStr(buffer, bufEnd - *buffer, "}", ZYDIS_LETTER_CASE_DEFAULT)); ZYDIS_CHECK(ZydisStringAppendC(buffer, "}", ZYDIS_LETTER_CASE_DEFAULT));
if (instruction->avx.mask.mode == ZYDIS_MASK_MODE_ZERO) if (instruction->avx.mask.mode == ZYDIS_MASK_MODE_ZERO)
{ {
ZYDIS_CHECK( ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer, " {z}", ZYDIS_LETTER_CASE_DEFAULT)); ZydisStringAppendC(buffer, " {z}", ZYDIS_LETTER_CASE_DEFAULT));
} }
} }
break; break;
@ -607,27 +600,27 @@ static ZydisStatus ZydisFormatterPrintDecoratorIntel(const ZydisFormatter* forma
break; break;
case ZYDIS_BROADCAST_MODE_1_TO_2: case ZYDIS_BROADCAST_MODE_1_TO_2:
ZYDIS_CHECK( ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer, " {1to2}", ZYDIS_LETTER_CASE_DEFAULT)); ZydisStringAppendC(buffer, " {1to2}", ZYDIS_LETTER_CASE_DEFAULT));
break; break;
case ZYDIS_BROADCAST_MODE_1_TO_4: case ZYDIS_BROADCAST_MODE_1_TO_4:
ZYDIS_CHECK( ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer, " {1to4}", ZYDIS_LETTER_CASE_DEFAULT)); ZydisStringAppendC(buffer, " {1to4}", ZYDIS_LETTER_CASE_DEFAULT));
break; break;
case ZYDIS_BROADCAST_MODE_1_TO_8: case ZYDIS_BROADCAST_MODE_1_TO_8:
ZYDIS_CHECK( ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer, " {1to8}", ZYDIS_LETTER_CASE_DEFAULT)); ZydisStringAppendC(buffer, " {1to8}", ZYDIS_LETTER_CASE_DEFAULT));
break; break;
case ZYDIS_BROADCAST_MODE_1_TO_16: case ZYDIS_BROADCAST_MODE_1_TO_16:
ZYDIS_CHECK( ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer, " {1to16}", ZYDIS_LETTER_CASE_DEFAULT)); ZydisStringAppendC(buffer, " {1to16}", ZYDIS_LETTER_CASE_DEFAULT));
break; break;
case ZYDIS_BROADCAST_MODE_4_TO_8: case ZYDIS_BROADCAST_MODE_4_TO_8:
ZYDIS_CHECK( ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer, " {4to8}", ZYDIS_LETTER_CASE_DEFAULT)); ZydisStringAppendC(buffer, " {4to8}", ZYDIS_LETTER_CASE_DEFAULT));
break; break;
case ZYDIS_BROADCAST_MODE_4_TO_16: case ZYDIS_BROADCAST_MODE_4_TO_16:
ZYDIS_CHECK( ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer, " {4to16}", ZYDIS_LETTER_CASE_DEFAULT)); ZydisStringAppendC(buffer, " {4to16}", ZYDIS_LETTER_CASE_DEFAULT));
break; break;
default: default:
return ZYDIS_STATUS_INVALID_PARAMETER; return ZYDIS_STATUS_INVALID_PARAMETER;
@ -642,20 +635,20 @@ static ZydisStatus ZydisFormatterPrintDecoratorIntel(const ZydisFormatter* forma
case ZYDIS_ROUNDING_MODE_INVALID: case ZYDIS_ROUNDING_MODE_INVALID:
break; break;
case ZYDIS_ROUNDING_MODE_RN: case ZYDIS_ROUNDING_MODE_RN:
ZYDIS_CHECK(ZydisPrintStr( ZYDIS_CHECK(ZydisStringAppendC(
buffer, bufEnd - *buffer, " {rn-sae}", ZYDIS_LETTER_CASE_DEFAULT)); buffer, " {rn-sae}", ZYDIS_LETTER_CASE_DEFAULT));
break; break;
case ZYDIS_ROUNDING_MODE_RD: case ZYDIS_ROUNDING_MODE_RD:
ZYDIS_CHECK(ZydisPrintStr( ZYDIS_CHECK(ZydisStringAppendC(
buffer, bufEnd - *buffer, " {rd-sae}", ZYDIS_LETTER_CASE_DEFAULT)); buffer, " {rd-sae}", ZYDIS_LETTER_CASE_DEFAULT));
break; break;
case ZYDIS_ROUNDING_MODE_RU: case ZYDIS_ROUNDING_MODE_RU:
ZYDIS_CHECK(ZydisPrintStr( ZYDIS_CHECK(ZydisStringAppendC(
buffer, bufEnd - *buffer, " {ru-sae}", ZYDIS_LETTER_CASE_DEFAULT)); buffer, " {ru-sae}", ZYDIS_LETTER_CASE_DEFAULT));
break; break;
case ZYDIS_ROUNDING_MODE_RZ: case ZYDIS_ROUNDING_MODE_RZ:
ZYDIS_CHECK(ZydisPrintStr( ZYDIS_CHECK(ZydisStringAppendC(
buffer, bufEnd - *buffer, " {rz-sae}", ZYDIS_LETTER_CASE_DEFAULT)); buffer, " {rz-sae}", ZYDIS_LETTER_CASE_DEFAULT));
break; break;
default: default:
return ZYDIS_STATUS_INVALID_PARAMETER; return ZYDIS_STATUS_INVALID_PARAMETER;
@ -668,19 +661,19 @@ static ZydisStatus ZydisFormatterPrintDecoratorIntel(const ZydisFormatter* forma
break; break;
case ZYDIS_ROUNDING_MODE_RN: case ZYDIS_ROUNDING_MODE_RN:
ZYDIS_CHECK( ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer, " {rn}", ZYDIS_LETTER_CASE_DEFAULT)); ZydisStringAppendC(buffer, " {rn}", ZYDIS_LETTER_CASE_DEFAULT));
break; break;
case ZYDIS_ROUNDING_MODE_RD: case ZYDIS_ROUNDING_MODE_RD:
ZYDIS_CHECK( ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer, " {rd}", ZYDIS_LETTER_CASE_DEFAULT)); ZydisStringAppendC(buffer, " {rd}", ZYDIS_LETTER_CASE_DEFAULT));
break; break;
case ZYDIS_ROUNDING_MODE_RU: case ZYDIS_ROUNDING_MODE_RU:
ZYDIS_CHECK( ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer, " {ru}", ZYDIS_LETTER_CASE_DEFAULT)); ZydisStringAppendC(buffer, " {ru}", ZYDIS_LETTER_CASE_DEFAULT));
break; break;
case ZYDIS_ROUNDING_MODE_RZ: case ZYDIS_ROUNDING_MODE_RZ:
ZYDIS_CHECK( ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer, " {rz}", ZYDIS_LETTER_CASE_DEFAULT)); ZydisStringAppendC(buffer, " {rz}", ZYDIS_LETTER_CASE_DEFAULT));
break; break;
default: default:
return ZYDIS_STATUS_INVALID_PARAMETER; return ZYDIS_STATUS_INVALID_PARAMETER;
@ -691,7 +684,7 @@ static ZydisStatus ZydisFormatterPrintDecoratorIntel(const ZydisFormatter* forma
if (instruction->avx.hasSAE && !instruction->avx.rounding.mode) if (instruction->avx.hasSAE && !instruction->avx.rounding.mode)
{ {
ZYDIS_CHECK( ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer, " {sae}", ZYDIS_LETTER_CASE_DEFAULT)); ZydisStringAppendC(buffer, " {sae}", ZYDIS_LETTER_CASE_DEFAULT));
} }
break; break;
case ZYDIS_DECORATOR_TYPE_SWIZZLE: case ZYDIS_DECORATOR_TYPE_SWIZZLE:
@ -703,31 +696,31 @@ static ZydisStatus ZydisFormatterPrintDecoratorIntel(const ZydisFormatter* forma
break; break;
case ZYDIS_SWIZZLE_MODE_CDAB: case ZYDIS_SWIZZLE_MODE_CDAB:
ZYDIS_CHECK( ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer, " {cdab}", ZYDIS_LETTER_CASE_DEFAULT)); ZydisStringAppendC(buffer, " {cdab}", ZYDIS_LETTER_CASE_DEFAULT));
break; break;
case ZYDIS_SWIZZLE_MODE_BADC: case ZYDIS_SWIZZLE_MODE_BADC:
ZYDIS_CHECK( ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer, " {badc}", ZYDIS_LETTER_CASE_DEFAULT)); ZydisStringAppendC(buffer, " {badc}", ZYDIS_LETTER_CASE_DEFAULT));
break; break;
case ZYDIS_SWIZZLE_MODE_DACB: case ZYDIS_SWIZZLE_MODE_DACB:
ZYDIS_CHECK( ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer, " {dacb}", ZYDIS_LETTER_CASE_DEFAULT)); ZydisStringAppendC(buffer, " {dacb}", ZYDIS_LETTER_CASE_DEFAULT));
break; break;
case ZYDIS_SWIZZLE_MODE_AAAA: case ZYDIS_SWIZZLE_MODE_AAAA:
ZYDIS_CHECK( ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer, " {aaaa}", ZYDIS_LETTER_CASE_DEFAULT)); ZydisStringAppendC(buffer, " {aaaa}", ZYDIS_LETTER_CASE_DEFAULT));
break; break;
case ZYDIS_SWIZZLE_MODE_BBBB: case ZYDIS_SWIZZLE_MODE_BBBB:
ZYDIS_CHECK( ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer, " {bbbb}", ZYDIS_LETTER_CASE_DEFAULT)); ZydisStringAppendC(buffer, " {bbbb}", ZYDIS_LETTER_CASE_DEFAULT));
break; break;
case ZYDIS_SWIZZLE_MODE_CCCC: case ZYDIS_SWIZZLE_MODE_CCCC:
ZYDIS_CHECK( ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer, " {cccc}", ZYDIS_LETTER_CASE_DEFAULT)); ZydisStringAppendC(buffer, " {cccc}", ZYDIS_LETTER_CASE_DEFAULT));
break; break;
case ZYDIS_SWIZZLE_MODE_DDDD: case ZYDIS_SWIZZLE_MODE_DDDD:
ZYDIS_CHECK( ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer, " {dddd}", ZYDIS_LETTER_CASE_DEFAULT)); ZydisStringAppendC(buffer, " {dddd}", ZYDIS_LETTER_CASE_DEFAULT));
break; break;
default: default:
return ZYDIS_STATUS_INVALID_PARAMETER; return ZYDIS_STATUS_INVALID_PARAMETER;
@ -740,23 +733,23 @@ static ZydisStatus ZydisFormatterPrintDecoratorIntel(const ZydisFormatter* forma
break; break;
case ZYDIS_CONVERSION_MODE_FLOAT16: case ZYDIS_CONVERSION_MODE_FLOAT16:
ZYDIS_CHECK( ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer, " {float16}", ZYDIS_LETTER_CASE_DEFAULT)); ZydisStringAppendC(buffer, " {float16}", ZYDIS_LETTER_CASE_DEFAULT));
break; break;
case ZYDIS_CONVERSION_MODE_SINT8: case ZYDIS_CONVERSION_MODE_SINT8:
ZYDIS_CHECK( ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer, " {sint8}", ZYDIS_LETTER_CASE_DEFAULT)); ZydisStringAppendC(buffer, " {sint8}", ZYDIS_LETTER_CASE_DEFAULT));
break; break;
case ZYDIS_CONVERSION_MODE_UINT8: case ZYDIS_CONVERSION_MODE_UINT8:
ZYDIS_CHECK( ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer, " {uint8}", ZYDIS_LETTER_CASE_DEFAULT)); ZydisStringAppendC(buffer, " {uint8}", ZYDIS_LETTER_CASE_DEFAULT));
break; break;
case ZYDIS_CONVERSION_MODE_SINT16: case ZYDIS_CONVERSION_MODE_SINT16:
ZYDIS_CHECK( ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer, " {sint16}", ZYDIS_LETTER_CASE_DEFAULT)); ZydisStringAppendC(buffer, " {sint16}", ZYDIS_LETTER_CASE_DEFAULT));
break; break;
case ZYDIS_CONVERSION_MODE_UINT16: case ZYDIS_CONVERSION_MODE_UINT16:
ZYDIS_CHECK( ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer, " {uint16}", ZYDIS_LETTER_CASE_DEFAULT)); ZydisStringAppendC(buffer, " {uint16}", ZYDIS_LETTER_CASE_DEFAULT));
break; break;
default: default:
return ZYDIS_STATUS_INVALID_PARAMETER; return ZYDIS_STATUS_INVALID_PARAMETER;
@ -766,7 +759,7 @@ static ZydisStatus ZydisFormatterPrintDecoratorIntel(const ZydisFormatter* forma
if (instruction->avx.hasEvictionHint) if (instruction->avx.hasEvictionHint)
{ {
ZYDIS_CHECK( ZYDIS_CHECK(
ZydisPrintStr(buffer, bufEnd - *buffer, " {eh}", ZYDIS_LETTER_CASE_DEFAULT)); ZydisStringAppendC(buffer, " {eh}", ZYDIS_LETTER_CASE_DEFAULT));
} }
break; break;
default: default:
@ -777,20 +770,19 @@ static ZydisStatus ZydisFormatterPrintDecoratorIntel(const ZydisFormatter* forma
} }
static ZydisStatus ZydisFormatterFormatInstrIntel(const ZydisFormatter* formatter, static ZydisStatus ZydisFormatterFormatInstrIntel(const ZydisFormatter* formatter,
char** buffer, ZydisUSize bufferLen, const ZydisDecodedInstruction* instruction, void* userData) ZydisString* buffer, const ZydisDecodedInstruction* instruction, void* userData)
{ {
if (!formatter || !buffer || !*buffer || (bufferLen <= 0) || !instruction) if (!formatter || !buffer || !instruction)
{ {
return ZYDIS_STATUS_INVALID_PARAMETER; return ZYDIS_STATUS_INVALID_PARAMETER;
} }
const char* bufEnd = *buffer + bufferLen;
ZYDIS_CHECK( ZYDIS_CHECK(
formatter->funcPrintPrefixes(formatter, buffer, bufEnd - *buffer, instruction, userData)); formatter->funcPrintPrefixes(formatter, buffer, instruction, userData));
ZYDIS_CHECK( ZYDIS_CHECK(
formatter->funcPrintMnemonic(formatter, buffer, bufEnd - *buffer, instruction, userData)); formatter->funcPrintMnemonic(formatter, buffer, instruction, userData));
char* bufRestore = *buffer; ZydisUSize lenRestore = buffer->length;
for (ZydisU8 i = 0; i < instruction->operandCount; ++i) for (ZydisU8 i = 0; i < instruction->operandCount; ++i)
{ {
if (instruction->operands[i].visibility == ZYDIS_OPERAND_VISIBILITY_HIDDEN) if (instruction->operands[i].visibility == ZYDIS_OPERAND_VISIBILITY_HIDDEN)
@ -800,52 +792,51 @@ static ZydisStatus ZydisFormatterFormatInstrIntel(const ZydisFormatter* formatte
if (i == 0) if (i == 0)
{ {
ZYDIS_CHECK(ZydisPrintStr(buffer, bufEnd - *buffer, " ", ZYDIS_LETTER_CASE_DEFAULT)); ZYDIS_CHECK(ZydisStringAppendC(buffer, " ", ZYDIS_LETTER_CASE_DEFAULT));
} else } else
{ {
bufRestore = *buffer; lenRestore = buffer->length;
ZYDIS_CHECK(ZydisPrintStr(buffer, bufEnd - *buffer, ", ", ZYDIS_LETTER_CASE_DEFAULT)); ZYDIS_CHECK(ZydisStringAppendC(buffer, ", ", ZYDIS_LETTER_CASE_DEFAULT));
} }
const char* bufPreOperand = *buffer; ZydisUSize bufPreOperandLen = buffer->length;
switch (instruction->operands[i].type) switch (instruction->operands[i].type)
{ {
case ZYDIS_OPERAND_TYPE_REGISTER: case ZYDIS_OPERAND_TYPE_REGISTER:
ZYDIS_CHECK(formatter->funcFormatOperandReg(formatter, buffer, bufEnd - *buffer, ZYDIS_CHECK(formatter->funcFormatOperandReg(formatter, buffer,
instruction, &instruction->operands[i], userData)); instruction, &instruction->operands[i], userData));
break; break;
case ZYDIS_OPERAND_TYPE_MEMORY: case ZYDIS_OPERAND_TYPE_MEMORY:
{ {
ZYDIS_CHECK(formatter->funcPrintOperandSize(formatter, buffer, bufEnd - *buffer, ZYDIS_CHECK(formatter->funcPrintOperandSize(formatter, buffer,
instruction, &instruction->operands[i], userData)); instruction, &instruction->operands[i], userData));
ZYDIS_CHECK(formatter->funcPrintSegment(formatter, buffer, bufEnd - *buffer, ZYDIS_CHECK(formatter->funcPrintSegment(formatter, buffer,
instruction, &instruction->operands[i], userData)); instruction, &instruction->operands[i], userData));
const char* bufTemp = *buffer; ZydisUSize lenTemp = buffer->length;
ZYDIS_CHECK(formatter->funcFormatOperandMem(formatter, buffer, bufEnd - *buffer, ZYDIS_CHECK(formatter->funcFormatOperandMem(formatter, buffer,
instruction, &instruction->operands[i], userData)); instruction, &instruction->operands[i], userData));
if (bufTemp == *buffer) if (lenTemp == buffer->length)
{ {
*buffer = (char*)bufPreOperand; buffer->length = bufPreOperandLen;
} }
break; break;
} }
case ZYDIS_OPERAND_TYPE_POINTER: case ZYDIS_OPERAND_TYPE_POINTER:
ZYDIS_CHECK(formatter->funcFormatOperandPtr(formatter, buffer, bufEnd - *buffer, ZYDIS_CHECK(formatter->funcFormatOperandPtr(formatter, buffer,
instruction, &instruction->operands[i], userData)); instruction, &instruction->operands[i], userData));
break; break;
case ZYDIS_OPERAND_TYPE_IMMEDIATE: case ZYDIS_OPERAND_TYPE_IMMEDIATE:
ZYDIS_CHECK(formatter->funcFormatOperandImm(formatter, buffer, bufEnd - *buffer, ZYDIS_CHECK(formatter->funcFormatOperandImm(formatter, buffer,
instruction, &instruction->operands[i], userData)); instruction, &instruction->operands[i], userData));
break; break;
default: default:
return ZYDIS_STATUS_INVALID_PARAMETER; return ZYDIS_STATUS_INVALID_PARAMETER;
} }
if (bufPreOperand == *buffer) if (lenRestore == buffer->length)
{ {
// Omit whole operand, if the buffer did not change during the formatting-callback // Omit whole operand, if the buffer did not change during the formatting-callback
*buffer = bufRestore; buffer->length = lenRestore;
*buffer[0] = 0;
} else } else
{ {
if ((instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_EVEX) || if ((instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_EVEX) ||
@ -855,21 +846,21 @@ static ZydisStatus ZydisFormatterFormatInstrIntel(const ZydisFormatter* formatte
(instruction->operands[i + 1].encoding == ZYDIS_OPERAND_ENCODING_MASK)) (instruction->operands[i + 1].encoding == ZYDIS_OPERAND_ENCODING_MASK))
{ {
ZYDIS_CHECK(formatter->funcPrintDecorator(formatter, buffer, ZYDIS_CHECK(formatter->funcPrintDecorator(formatter, buffer,
bufEnd - *buffer, instruction, &instruction->operands[i], instruction, &instruction->operands[i],
ZYDIS_DECORATOR_TYPE_MASK, userData)); ZYDIS_DECORATOR_TYPE_MASK, userData));
} }
if (instruction->operands[i].type == ZYDIS_OPERAND_TYPE_MEMORY) if (instruction->operands[i].type == ZYDIS_OPERAND_TYPE_MEMORY)
{ {
ZYDIS_CHECK(formatter->funcPrintDecorator(formatter, buffer, ZYDIS_CHECK(formatter->funcPrintDecorator(formatter, buffer,
bufEnd - *buffer, instruction, &instruction->operands[i], instruction, &instruction->operands[i],
ZYDIS_DECORATOR_TYPE_BROADCAST, userData)); ZYDIS_DECORATOR_TYPE_BROADCAST, userData));
if (instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_MVEX) if (instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_MVEX)
{ {
ZYDIS_CHECK(formatter->funcPrintDecorator(formatter, buffer, ZYDIS_CHECK(formatter->funcPrintDecorator(formatter, buffer,
bufEnd - *buffer, instruction, &instruction->operands[i], instruction, &instruction->operands[i],
ZYDIS_DECORATOR_TYPE_CONVERSION, userData)); ZYDIS_DECORATOR_TYPE_CONVERSION, userData));
ZYDIS_CHECK(formatter->funcPrintDecorator(formatter, buffer, ZYDIS_CHECK(formatter->funcPrintDecorator(formatter, buffer,
bufEnd - *buffer, instruction, &instruction->operands[i], instruction, &instruction->operands[i],
ZYDIS_DECORATOR_TYPE_EVICTION_HINT, userData)); ZYDIS_DECORATOR_TYPE_EVICTION_HINT, userData));
} }
} else } else
@ -880,14 +871,14 @@ static ZydisStatus ZydisFormatterFormatInstrIntel(const ZydisFormatter* formatte
if (instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_MVEX) if (instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_MVEX)
{ {
ZYDIS_CHECK(formatter->funcPrintDecorator(formatter, buffer, ZYDIS_CHECK(formatter->funcPrintDecorator(formatter, buffer,
bufEnd - *buffer, instruction, &instruction->operands[i], instruction, &instruction->operands[i],
ZYDIS_DECORATOR_TYPE_SWIZZLE, userData)); ZYDIS_DECORATOR_TYPE_SWIZZLE, userData));
} }
ZYDIS_CHECK(formatter->funcPrintDecorator(formatter, buffer, ZYDIS_CHECK(formatter->funcPrintDecorator(formatter, buffer,
bufEnd - *buffer, instruction, &instruction->operands[i], instruction, &instruction->operands[i],
ZYDIS_DECORATOR_TYPE_ROUNDING_CONTROL, userData)); ZYDIS_DECORATOR_TYPE_ROUNDING_CONTROL, userData));
ZYDIS_CHECK(formatter->funcPrintDecorator(formatter, buffer, ZYDIS_CHECK(formatter->funcPrintDecorator(formatter, buffer,
bufEnd - *buffer, instruction, &instruction->operands[i], instruction, &instruction->operands[i],
ZYDIS_DECORATOR_TYPE_SAE, userData)); ZYDIS_DECORATOR_TYPE_SAE, userData));
} }
} }
@ -1156,21 +1147,30 @@ ZydisStatus ZydisFormatterFormatInstruction(const ZydisFormatter* formatter,
ZydisStatus ZydisFormatterFormatInstructionEx(const ZydisFormatter* formatter, ZydisStatus ZydisFormatterFormatInstructionEx(const ZydisFormatter* formatter,
const ZydisDecodedInstruction* instruction, char* buffer, ZydisUSize bufferLen, void* userData) const ZydisDecodedInstruction* instruction, char* buffer, ZydisUSize bufferLen, void* userData)
{ {
if (!formatter || !instruction || !buffer || (bufferLen == 0)) if (!formatter || !instruction || !buffer || !bufferLen)
{ {
return ZYDIS_STATUS_INVALID_PARAMETER; return ZYDIS_STATUS_INVALID_PARAMETER;
} }
ZydisString str = {
.s = buffer,
.length = 0,
.capacity = bufferLen - 1
};
if (formatter->funcPre) if (formatter->funcPre)
{ {
ZYDIS_CHECK(formatter->funcPre(formatter, instruction, userData)); ZYDIS_CHECK(formatter->funcPre(formatter, &str, instruction, userData));
} }
ZYDIS_CHECK(
formatter->funcFormatInstruction(formatter, &buffer, bufferLen, instruction, userData)); ZYDIS_CHECK(formatter->funcFormatInstruction(formatter, &str, instruction, userData));
if (formatter->funcPost) if (formatter->funcPost)
{ {
return formatter->funcPost(formatter, instruction, userData); ZYDIS_CHECK(formatter->funcPost(formatter, &str, instruction, userData));
} }
str.s[str.length] = 0;
return ZYDIS_STATUS_SUCCESS; return ZYDIS_STATUS_SUCCESS;
} }