mirror of https://github.com/x64dbg/zydis
More formatter changes
- Added `ZydisFormatterFormatOperand` and `ZydisFormatterFormatOperandEx` (this won't print AVX-512/KNC decorators) - User defined callbacks should return `ZYDIS_STATUS_SKIP_OPERAND` to omit an operand (returning `ZYDIS_STATUS_SUCCESS` without writing to the buffer is now deprecated)
This commit is contained in:
parent
4e189721b2
commit
bbb864561d
|
@ -144,8 +144,8 @@ static ZydisStatus ZydisFormatterPrintMnemonic(const ZydisFormatter* formatter,
|
||||||
// Rewrite the instruction-mnemonic for the given instructions
|
// Rewrite the instruction-mnemonic for the given instructions
|
||||||
if (instruction->operands[instruction->operandCount - 1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE)
|
if (instruction->operands[instruction->operandCount - 1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE)
|
||||||
{
|
{
|
||||||
const uint8_t conditionCode =
|
const ZydisU8 conditionCode =
|
||||||
(uint8_t)instruction->operands[instruction->operandCount - 1].imm.value.u;
|
(ZydisU8)instruction->operands[instruction->operandCount - 1].imm.value.u;
|
||||||
switch (instruction->mnemonic)
|
switch (instruction->mnemonic)
|
||||||
{
|
{
|
||||||
case ZYDIS_MNEMONIC_CMPPS:
|
case ZYDIS_MNEMONIC_CMPPS:
|
||||||
|
@ -201,9 +201,7 @@ static ZydisStatus ZydisFormatterFormatOperandImm(const ZydisFormatter* formatte
|
||||||
// operand, because it got replaced by the alias-mnemonic
|
// operand, because it got replaced by the alias-mnemonic
|
||||||
if (userData->ommitImmediate)
|
if (userData->ommitImmediate)
|
||||||
{
|
{
|
||||||
// The formatter will automatically omit the operand, if the buffer remains unchanged
|
return ZYDIS_STATUS_SKIP_OPERAND;
|
||||||
// after the callback returns
|
|
||||||
return ZYDIS_STATUS_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default immediate formatting
|
// Default immediate formatting
|
||||||
|
@ -216,7 +214,8 @@ static ZydisStatus ZydisFormatterFormatOperandImm(const ZydisFormatter* formatte
|
||||||
/* Helper functions */
|
/* Helper functions */
|
||||||
/* ============================================================================================== */
|
/* ============================================================================================== */
|
||||||
|
|
||||||
void disassembleBuffer(ZydisDecoder* decoder, uint8_t* data, size_t length, ZydisBool installHooks)
|
void disassembleBuffer(ZydisDecoder* decoder, ZydisU8* data, ZydisUSize length,
|
||||||
|
ZydisBool installHooks)
|
||||||
{
|
{
|
||||||
ZydisFormatter formatter;
|
ZydisFormatter formatter;
|
||||||
ZydisFormatterInit(&formatter, ZYDIS_FORMATTER_STYLE_INTEL);
|
ZydisFormatterInit(&formatter, ZYDIS_FORMATTER_STYLE_INTEL);
|
||||||
|
@ -233,7 +232,7 @@ void disassembleBuffer(ZydisDecoder* decoder, uint8_t* data, size_t length, Zydi
|
||||||
(const void**)&defaultFormatOperandImm);
|
(const void**)&defaultFormatOperandImm);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t instructionPointer = 0x007FFFFFFF400000;
|
ZydisU64 instructionPointer = 0x007FFFFFFF400000;
|
||||||
|
|
||||||
ZydisDecodedInstruction instruction;
|
ZydisDecodedInstruction instruction;
|
||||||
ZydisCustomUserData userData;
|
ZydisCustomUserData userData;
|
||||||
|
@ -263,7 +262,7 @@ int main()
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t data[] =
|
ZydisU8 data[] =
|
||||||
{
|
{
|
||||||
// cmpps xmm1, xmm4, 0x03
|
// cmpps xmm1, xmm4, 0x03
|
||||||
0x0F, 0xC2, 0xCC, 0x03,
|
0x0F, 0xC2, 0xCC, 0x03,
|
||||||
|
|
|
@ -456,9 +456,6 @@ typedef struct ZydisFormatter_ ZydisFormatter;
|
||||||
*
|
*
|
||||||
* Returning a status code other than `ZYDIS_STATUS_SUCCESS` will immediately cause the formatting
|
* Returning a status code other than `ZYDIS_STATUS_SUCCESS` will immediately cause the formatting
|
||||||
* process to fail.
|
* process to fail.
|
||||||
*
|
|
||||||
* Returning `ZYDIS_STATUS_SUCCESS` in `ZYDIS_FORMATTER_HOOK_PRINT_PREFIXES` without writing to
|
|
||||||
* the string is valid and signals that the corresponding element should not be printed.
|
|
||||||
*
|
*
|
||||||
* This function type is used for:
|
* This function type is used for:
|
||||||
* - `ZYDIS_FORMATTER_HOOK_PRE_INSTRUCTION`
|
* - `ZYDIS_FORMATTER_HOOK_PRE_INSTRUCTION`
|
||||||
|
@ -482,15 +479,17 @@ typedef ZydisStatus (*ZydisFormatterFunc)(const ZydisFormatter* formatter,
|
||||||
* @return A zydis status code.
|
* @return A zydis status code.
|
||||||
*
|
*
|
||||||
* Returning a status code other than `ZYDIS_STATUS_SUCCESS` will immediately cause the formatting
|
* Returning a status code other than `ZYDIS_STATUS_SUCCESS` will immediately cause the formatting
|
||||||
* process to fail.
|
* process to fail (see exceptions below).
|
||||||
*
|
*
|
||||||
* Returning `ZYDIS_STATUS_SUCCESS` in one of the `ZYDIS_FORMATTER_HOOK_FORMAT_OPERAND_X` hooks
|
* Returning `ZYDIS_STATUS_SKIP_OPERAND` is valid for `ZYDIS_FORMATTER_HOOK_PRE_OPERAND`,
|
||||||
* without writing to the string is valid and will cause the formatter to omit the current
|
* `ZYDIS_FORMATTER_HOOK_POST_OPERAND` and all of the `ZYDIS_FORMATTER_HOOK_FORMAT_OPERAND_XXX`
|
||||||
|
* callbacks. This will cause the formatter to omit the current operand.
|
||||||
|
*
|
||||||
|
* DEPRECATED:
|
||||||
|
* Returning `ZYDIS_STATUS_SUCCESS` without writing to the string is valid for
|
||||||
|
* `ZYDIS_FORMATTER_HOOK_PRE_OPERAND`, `ZYDIS_FORMATTER_HOOK_POST_OPERAND` and all of the
|
||||||
|
* `ZYDIS_FORMATTER_HOOK_FORMAT_OPERAND_XXX`. This will cause the formatter to omit the current
|
||||||
* operand.
|
* operand.
|
||||||
*
|
|
||||||
* Returning `ZYDIS_STATUS_SUCCESS` in `ZYDIS_FORMATTER_HOOK_PRINT_MEMSIZE` or
|
|
||||||
* `ZYDIS_FORMATTER_HOOK_PRINT_DECORATOR` without writing to the string is valid and signals that
|
|
||||||
* the corresponding element should not be printed for the current operand.
|
|
||||||
*
|
*
|
||||||
* This function type is used for:
|
* This function type is used for:
|
||||||
* - `ZYDIS_FORMATTER_HOOK_PRE_OPERAND`
|
* - `ZYDIS_FORMATTER_HOOK_PRE_OPERAND`
|
||||||
|
@ -559,9 +558,6 @@ typedef ZydisStatus (*ZydisFormatterAddressFunc)(const ZydisFormatter* formatter
|
||||||
*
|
*
|
||||||
* @return Returning a status code other than `ZYDIS_STATUS_SUCCESS` will immediately cause the
|
* @return Returning a status code other than `ZYDIS_STATUS_SUCCESS` will immediately cause the
|
||||||
* formatting process to fail.
|
* formatting process to fail.
|
||||||
*
|
|
||||||
* Returning `ZYDIS_STATUS_SUCCESS` without writing to the string is valid and will cause the
|
|
||||||
* formatter to omit the current decorator.
|
|
||||||
*
|
*
|
||||||
* This function type is used for:
|
* This function type is used for:
|
||||||
* - `ZYDIS_FORMATTER_HOOK_PRINT_DECORATOR`
|
* - `ZYDIS_FORMATTER_HOOK_PRINT_DECORATOR`
|
||||||
|
@ -685,6 +681,43 @@ ZYDIS_EXPORT ZydisStatus ZydisFormatterFormatInstruction(const ZydisFormatter* f
|
||||||
ZYDIS_EXPORT ZydisStatus ZydisFormatterFormatInstructionEx(const ZydisFormatter* formatter,
|
ZYDIS_EXPORT ZydisStatus ZydisFormatterFormatInstructionEx(const ZydisFormatter* formatter,
|
||||||
const ZydisDecodedInstruction* instruction, char* buffer, ZydisUSize bufferLen, void* userData);
|
const ZydisDecodedInstruction* instruction, char* buffer, ZydisUSize bufferLen, void* userData);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Formats the given operand and writes it into the output buffer.
|
||||||
|
*
|
||||||
|
* @param formatter A pointer to the `ZydisFormatter` instance.
|
||||||
|
* @param instruction A pointer to the `ZydisDecodedInstruction` struct.
|
||||||
|
* @param index The index of the operand to format.
|
||||||
|
* @param buffer A pointer to the output buffer.
|
||||||
|
* @param bufferLen The length of the output buffer.
|
||||||
|
*
|
||||||
|
* @return A zydis status code.
|
||||||
|
*
|
||||||
|
* Use `ZydisFormatterFormatInstruction` or `ZydisFormatterFormatInstructionEx` to format a
|
||||||
|
* complete instruction.
|
||||||
|
*/
|
||||||
|
ZYDIS_EXPORT ZydisStatus ZydisFormatterFormatOperand(const ZydisFormatter* formatter,
|
||||||
|
const ZydisDecodedInstruction* instruction, ZydisU8 index, char* buffer, ZydisUSize bufferLen);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Formats the given operand and writes it into the output buffer.
|
||||||
|
*
|
||||||
|
* @param formatter A pointer to the `ZydisFormatter` instance.
|
||||||
|
* @param instruction A pointer to the `ZydisDecodedInstruction` struct.
|
||||||
|
* @param index The index of the operand to format.
|
||||||
|
* @param buffer A pointer to the output buffer.
|
||||||
|
* @param bufferLen The length of the output buffer.
|
||||||
|
* @param userData A pointer to user-defined data which can be used in custom formatter
|
||||||
|
* callbacks.
|
||||||
|
*
|
||||||
|
* @return A zydis status code.
|
||||||
|
*
|
||||||
|
* Use `ZydisFormatterFormatInstruction` or `ZydisFormatterFormatInstructionEx` to format a
|
||||||
|
* complete instruction.
|
||||||
|
*/
|
||||||
|
ZYDIS_EXPORT ZydisStatus ZydisFormatterFormatOperandEx(const ZydisFormatter* formatter,
|
||||||
|
const ZydisDecodedInstruction* instruction, ZydisU8 index, char* buffer, ZydisUSize bufferLen,
|
||||||
|
void* userData);
|
||||||
|
|
||||||
/* ============================================================================================== */
|
/* ============================================================================================== */
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -126,6 +126,16 @@ enum ZydisStatusCodes
|
||||||
*/
|
*/
|
||||||
ZYDIS_STATUS_INVALID_MASK,
|
ZYDIS_STATUS_INVALID_MASK,
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------------------------ */
|
||||||
|
/* Formatter */
|
||||||
|
/* ------------------------------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returning this status code in operand-related custom formatter callbacks will cause
|
||||||
|
* the formatter to omit the operand.
|
||||||
|
*/
|
||||||
|
ZYDIS_STATUS_SKIP_OPERAND,
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------------------------------ */
|
||||||
/* Encoder */
|
/* Encoder */
|
||||||
/* ------------------------------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------------------------------ */
|
||||||
|
@ -141,8 +151,8 @@ enum ZydisStatusCodes
|
||||||
*/
|
*/
|
||||||
ZYDIS_STATUS_USER = 0x10000000
|
ZYDIS_STATUS_USER = 0x10000000
|
||||||
|
|
||||||
// Max value entry intentionally omitted since users might
|
// Max value entry intentionally omitted since users might define custom error codes for
|
||||||
// define custom error codes for formatter hooks.
|
// formatter hooks.
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ============================================================================================== */
|
/* ============================================================================================== */
|
||||||
|
|
143
src/Formatter.c
143
src/Formatter.c
|
@ -89,53 +89,80 @@ static ZydisStatus ZydisFormatInstrIntel(const ZydisFormatter* formatter, ZydisS
|
||||||
}
|
}
|
||||||
|
|
||||||
const ZydisUSize strLenPreOperand = string->length;
|
const ZydisUSize strLenPreOperand = string->length;
|
||||||
|
|
||||||
|
// Print embedded-mask registers as decorator instead of a regular operand
|
||||||
|
if ((i == 1) && (instruction->operands[i].type == ZYDIS_OPERAND_TYPE_REGISTER) &&
|
||||||
|
(instruction->operands[i].encoding == ZYDIS_OPERAND_ENCODING_MASK))
|
||||||
|
{
|
||||||
|
goto SkipOperand;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZydisStatus status;
|
||||||
if (formatter->funcPreOperand)
|
if (formatter->funcPreOperand)
|
||||||
{
|
{
|
||||||
if (!ZYDIS_SUCCESS(formatter->funcPreOperand(formatter, string, instruction,
|
status = formatter->funcPreOperand(formatter, string, instruction,
|
||||||
&instruction->operands[i], userData)))
|
&instruction->operands[i], userData);
|
||||||
|
if (status == ZYDIS_STATUS_SKIP_OPERAND)
|
||||||
{
|
{
|
||||||
goto SkipOperand;
|
goto SkipOperand;
|
||||||
}
|
}
|
||||||
|
if (status != ZYDIS_STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
return status;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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, string, instruction,
|
status = formatter->funcFormatOperandReg(formatter, string, instruction,
|
||||||
&instruction->operands[i], userData));
|
&instruction->operands[i], userData);
|
||||||
break;
|
break;
|
||||||
case ZYDIS_OPERAND_TYPE_MEMORY:
|
case ZYDIS_OPERAND_TYPE_MEMORY:
|
||||||
{
|
{
|
||||||
ZYDIS_CHECK(formatter->funcPrintMemSize(formatter, string, instruction,
|
ZYDIS_CHECK(formatter->funcPrintMemSize(formatter, string, instruction,
|
||||||
&instruction->operands[i], userData));
|
&instruction->operands[i], userData));
|
||||||
const ZydisUSize strLenTemp = string->length;
|
const ZydisUSize strLenTemp = string->length;
|
||||||
ZYDIS_CHECK(formatter->funcFormatOperandMem(formatter, string, instruction,
|
status = formatter->funcFormatOperandMem(formatter, string, instruction,
|
||||||
&instruction->operands[i], userData));
|
&instruction->operands[i], userData);
|
||||||
if (strLenTemp == string->length)
|
if ((status == ZYDIS_STATUS_SUCCESS) && (strLenTemp == string->length))
|
||||||
{
|
{
|
||||||
string->length = strLenPreOperand;
|
string->length = strLenPreOperand;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ZYDIS_OPERAND_TYPE_POINTER:
|
case ZYDIS_OPERAND_TYPE_POINTER:
|
||||||
ZYDIS_CHECK(formatter->funcFormatOperandPtr(formatter, string, instruction,
|
status = formatter->funcFormatOperandPtr(formatter, string, instruction,
|
||||||
&instruction->operands[i], userData));
|
&instruction->operands[i], userData);
|
||||||
break;
|
break;
|
||||||
case ZYDIS_OPERAND_TYPE_IMMEDIATE:
|
case ZYDIS_OPERAND_TYPE_IMMEDIATE:
|
||||||
ZYDIS_CHECK(formatter->funcFormatOperandImm(formatter, string, instruction,
|
status = formatter->funcFormatOperandImm(formatter, string, instruction,
|
||||||
&instruction->operands[i], userData));
|
&instruction->operands[i], userData);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return ZYDIS_STATUS_INVALID_PARAMETER;
|
return ZYDIS_STATUS_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
if (status == ZYDIS_STATUS_SKIP_OPERAND)
|
||||||
|
{
|
||||||
|
goto SkipOperand;
|
||||||
|
}
|
||||||
|
if (status != ZYDIS_STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
if (formatter->funcPostOperand)
|
if (formatter->funcPostOperand)
|
||||||
{
|
{
|
||||||
if (!ZYDIS_SUCCESS(formatter->funcPostOperand(formatter, string, instruction,
|
status = formatter->funcPostOperand(formatter, string, instruction,
|
||||||
&instruction->operands[i], userData)))
|
&instruction->operands[i], userData);
|
||||||
|
if (status == ZYDIS_STATUS_SKIP_OPERAND)
|
||||||
{
|
{
|
||||||
goto SkipOperand;
|
goto SkipOperand;
|
||||||
}
|
}
|
||||||
|
if (status != ZYDIS_STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
return status;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strLenPreOperand == string->length)
|
if (strLenPreOperand == string->length)
|
||||||
|
@ -203,12 +230,6 @@ static ZydisStatus ZydisFormatOperandRegIntel(const ZydisFormatter* formatter, Z
|
||||||
return ZYDIS_STATUS_INVALID_PARAMETER;
|
return ZYDIS_STATUS_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We want to print embedded-mask registers as decorator instead of a regular operand
|
|
||||||
if ((operand->id == 1) && (operand->encoding == ZYDIS_OPERAND_ENCODING_MASK))
|
|
||||||
{
|
|
||||||
return ZYDIS_STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
return formatter->funcPrintRegister(formatter, string, instruction, operand,
|
return formatter->funcPrintRegister(formatter, string, instruction, operand,
|
||||||
operand->reg.value, userData);
|
operand->reg.value, userData);
|
||||||
}
|
}
|
||||||
|
@ -1176,7 +1197,91 @@ ZydisStatus ZydisFormatterFormatInstructionEx(const ZydisFormatter* formatter,
|
||||||
const ZydisStatus status = ZydisFormatInstruction(formatter, instruction, &string, userData);
|
const ZydisStatus status = ZydisFormatInstruction(formatter, instruction, &string, userData);
|
||||||
|
|
||||||
buffer[string.length] = 0;
|
buffer[string.length] = 0;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZydisStatus ZydisFormatterFormatOperand(const ZydisFormatter* formatter,
|
||||||
|
const ZydisDecodedInstruction* instruction, ZydisU8 index, char* buffer, ZydisUSize bufferLen)
|
||||||
|
{
|
||||||
|
return ZydisFormatterFormatOperandEx(
|
||||||
|
formatter, instruction, index, buffer, bufferLen, ZYDIS_NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
ZydisStatus ZydisFormatterFormatOperandEx(const ZydisFormatter* formatter,
|
||||||
|
const ZydisDecodedInstruction* instruction, ZydisU8 index, char* buffer, ZydisUSize bufferLen,
|
||||||
|
void* userData)
|
||||||
|
{
|
||||||
|
if (!formatter || !instruction || index >= instruction->operandCount || !buffer ||
|
||||||
|
(bufferLen == 0))
|
||||||
|
{
|
||||||
|
return ZYDIS_STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZydisString string;
|
||||||
|
string.buffer = buffer;
|
||||||
|
string.length = 0;
|
||||||
|
string.capacity = bufferLen - 1;
|
||||||
|
|
||||||
|
ZydisStatus status;
|
||||||
|
const ZydisDecodedOperand* operand = &instruction->operands[index];
|
||||||
|
|
||||||
|
if (formatter->funcPreOperand)
|
||||||
|
{
|
||||||
|
status = formatter->funcPreOperand(formatter, &string, instruction, operand, userData);
|
||||||
|
// We ignore `ZYDIS_STATUS_SKIP_OPERAND` as it does not make any sense to skip the only
|
||||||
|
// operand printed by this function
|
||||||
|
if ((status != ZYDIS_STATUS_SUCCESS) && (status != ZYDIS_STATUS_SKIP_OPERAND))
|
||||||
|
{
|
||||||
|
goto FinalizeString;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (operand->type)
|
||||||
|
{
|
||||||
|
case ZYDIS_OPERAND_TYPE_REGISTER:
|
||||||
|
status = formatter->funcFormatOperandReg(formatter, &string, instruction, operand,
|
||||||
|
userData);
|
||||||
|
break;
|
||||||
|
case ZYDIS_OPERAND_TYPE_MEMORY:
|
||||||
|
status = formatter->funcPrintMemSize(formatter, &string, instruction, operand, userData);
|
||||||
|
if (!ZYDIS_SUCCESS(status))
|
||||||
|
{
|
||||||
|
goto FinalizeString;
|
||||||
|
}
|
||||||
|
status = formatter->funcFormatOperandMem(formatter, &string, instruction, operand,
|
||||||
|
userData);
|
||||||
|
break;
|
||||||
|
case ZYDIS_OPERAND_TYPE_IMMEDIATE:
|
||||||
|
status = formatter->funcFormatOperandImm(formatter, &string, instruction, operand,
|
||||||
|
userData);
|
||||||
|
break;
|
||||||
|
case ZYDIS_OPERAND_TYPE_POINTER:
|
||||||
|
status = formatter->funcFormatOperandPtr(formatter, &string, instruction, operand,
|
||||||
|
userData);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
status = ZYDIS_STATUS_INVALID_PARAMETER;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!ZYDIS_SUCCESS(status))
|
||||||
|
{
|
||||||
|
goto FinalizeString;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Print AVX512/KNC decorator
|
||||||
|
|
||||||
|
if (formatter->funcPostOperand)
|
||||||
|
{
|
||||||
|
status = formatter->funcPostOperand(formatter, &string, instruction, operand, userData);
|
||||||
|
// Ignore `ZYDIS_STATUS_SKIP_OPERAND`
|
||||||
|
if (status == ZYDIS_STATUS_SKIP_OPERAND)
|
||||||
|
{
|
||||||
|
status = ZYDIS_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FinalizeString:
|
||||||
|
buffer[string.length] = 0;
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue