Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve INTEL_MASM formatter style #543

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions include/Zydis/FormatterBuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,18 @@ typedef struct ZydisFormatterBuffer_
ZyanString string;
} ZydisFormatterBuffer;

/**
* Defines the `ZydisFormatterBufferState` struct.
*
* All fields in this struct should be considered as "private". Any changes may
* lead to unexpected behavior.
*/
typedef struct ZydisFormatterBufferState_
{
ZyanUPointer data;
ZyanUSize size;
} ZydisFormatterBufferState;

/* ---------------------------------------------------------------------------------------------- */

/* ============================================================================================== */
Expand Down Expand Up @@ -276,7 +288,7 @@ ZYDIS_EXPORT ZyanStatus ZydisFormatterBufferAppend(ZydisFormatterBuffer* buffer,
* as the buffer gets overwritten or destroyed.
*/
ZYDIS_EXPORT ZyanStatus ZydisFormatterBufferRemember(const ZydisFormatterBuffer* buffer,
ZyanUPointer* state);
ZydisFormatterBufferState* state);

/**
* Restores a previously saved buffer-state.
Expand All @@ -293,7 +305,7 @@ ZYDIS_EXPORT ZyanStatus ZydisFormatterBufferRemember(const ZydisFormatterBuffer*
* automatically be updated by calling this function.
*/
ZYDIS_EXPORT ZyanStatus ZydisFormatterBufferRestore(ZydisFormatterBuffer* buffer,
ZyanUPointer state);
ZydisFormatterBufferState* state);

/* ---------------------------------------------------------------------------------------------- */

Expand Down
10 changes: 4 additions & 6 deletions include/Zydis/Internal/FormatterBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,13 +138,11 @@ extern "C" {
* performance for non-tokenizing passes.
*/
#define ZYDIS_BUFFER_REMEMBER(buffer, state) \
if ((buffer)->is_token_list) \
{ \
(state) = (ZyanUPointer)(buffer)->string.vector.data; \
} else \
do \
{ \
(state) = (ZyanUPointer)(buffer)->string.vector.size; \
}
(state).data = (ZyanUPointer)(buffer)->string.vector.data; \
(state).size = (buffer)->string.vector.size; \
} while (0)

/**
* Appends a string (`STR_`-prefix) or a predefined token-list (`TOK_`-prefix).
Expand Down
15 changes: 12 additions & 3 deletions include/Zydis/Internal/FormatterIntel.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,15 @@ ZyanStatus ZydisFormatterIntelFormatInstructionMASM(const ZydisFormatter* format
ZyanStatus ZydisFormatterIntelPrintAddressMASM(const ZydisFormatter* formatter,
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);

ZyanStatus ZydisFormatterIntelFormatOperandREGMASM(const ZydisFormatter* formatter,
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);

ZyanStatus ZydisFormatterIntelPrintMnemonicMASM(const ZydisFormatter* formatter,
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context);

ZyanStatus ZydisFormatterIntelPrintRegisterMASM(const ZydisFormatter* formatter,
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context, ZydisRegister reg);

/* ---------------------------------------------------------------------------------------------- */

/* ============================================================================================== */
Expand Down Expand Up @@ -244,12 +253,12 @@ static const ZydisFormatter FORMATTER_INTEL_MASM =
/* func_format_instruction */ &ZydisFormatterIntelFormatInstructionMASM,
/* func_pre_operand */ ZYAN_NULL,
/* func_post_operand */ ZYAN_NULL,
/* func_format_operand_reg */ &ZydisFormatterBaseFormatOperandREG,
/* func_format_operand_reg */ &ZydisFormatterIntelFormatOperandREGMASM,
/* func_format_operand_mem */ &ZydisFormatterIntelFormatOperandMEM,
/* func_format_operand_ptr */ &ZydisFormatterBaseFormatOperandPTR,
/* func_format_operand_imm */ &ZydisFormatterBaseFormatOperandIMM,
/* func_print_mnemonic */ &ZydisFormatterIntelPrintMnemonic,
/* func_print_register */ &ZydisFormatterIntelPrintRegister,
/* func_print_mnemonic */ &ZydisFormatterIntelPrintMnemonicMASM,
/* func_print_register */ &ZydisFormatterIntelPrintRegisterMASM,
/* func_print_address_abs */ &ZydisFormatterIntelPrintAddressMASM,
/* func_print_address_rel */ &ZydisFormatterIntelPrintAddressMASM,
/* func_print_disp */ &ZydisFormatterIntelPrintDISP,
Expand Down
15 changes: 8 additions & 7 deletions src/FormatterATT.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ ZyanStatus ZydisFormatterATTFormatInstruction(const ZydisFormatter* formatter,
ZYAN_CHECK(formatter->func_print_prefixes(formatter, buffer, context));
ZYAN_CHECK(formatter->func_print_mnemonic(formatter, buffer, context));

ZyanUPointer state_mnemonic;
ZydisFormatterBufferState state_mnemonic;
ZYDIS_BUFFER_REMEMBER(buffer, state_mnemonic);

const ZyanI8 c = (ZyanI8)context->instruction->operand_count_visible - 1;
Expand All @@ -67,10 +67,11 @@ ZyanStatus ZydisFormatterATTFormatInstruction(const ZydisFormatter* formatter,
continue;
}

ZyanUPointer buffer_state;
ZydisFormatterBufferState buffer_state;
ZYDIS_BUFFER_REMEMBER(buffer, buffer_state);

if (buffer_state != state_mnemonic)
if ((buffer_state.data != state_mnemonic.data) ||
(buffer_state.size != state_mnemonic.size))
{
ZYDIS_BUFFER_APPEND(buffer, DELIM_OPERAND);
} else
Expand All @@ -87,7 +88,7 @@ ZyanStatus ZydisFormatterATTFormatInstruction(const ZydisFormatter* formatter,
status = formatter->func_pre_operand(formatter, buffer, context);
if (status == ZYDIS_STATUS_SKIP_TOKEN)
{
ZYAN_CHECK(ZydisFormatterBufferRestore(buffer, buffer_state));
ZYAN_CHECK(ZydisFormatterBufferRestore(buffer, &buffer_state));
continue;
}
if (!ZYAN_SUCCESS(status))
Expand Down Expand Up @@ -115,7 +116,7 @@ ZyanStatus ZydisFormatterATTFormatInstruction(const ZydisFormatter* formatter,
}
if (status == ZYDIS_STATUS_SKIP_TOKEN)
{
ZYAN_CHECK(ZydisFormatterBufferRestore(buffer, buffer_state));
ZYAN_CHECK(ZydisFormatterBufferRestore(buffer, &buffer_state));
continue;
}
if (!ZYAN_SUCCESS(status))
Expand All @@ -128,10 +129,10 @@ ZyanStatus ZydisFormatterATTFormatInstruction(const ZydisFormatter* formatter,
status = formatter->func_post_operand(formatter, buffer, context);
if (status == ZYDIS_STATUS_SKIP_TOKEN)
{
ZYAN_CHECK(ZydisFormatterBufferRestore(buffer, buffer_state));
ZYAN_CHECK(ZydisFormatterBufferRestore(buffer, &buffer_state));
continue;
}
if (ZYAN_SUCCESS(status))
if (!ZYAN_SUCCESS(status))
{
return status;
}
Expand Down
28 changes: 11 additions & 17 deletions src/FormatterBuffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -144,25 +144,22 @@ ZyanStatus ZydisFormatterBufferAppend(ZydisFormatterBuffer* buffer, ZydisTokenTy
return ZYAN_STATUS_SUCCESS;
}

ZyanStatus ZydisFormatterBufferRemember(const ZydisFormatterBuffer* buffer, ZyanUPointer* state)
ZyanStatus ZydisFormatterBufferRemember(const ZydisFormatterBuffer* buffer,
ZydisFormatterBufferState* state)
{
if (!buffer || !state)
{
return ZYAN_STATUS_INVALID_ARGUMENT;
}

if (buffer->is_token_list)
{
*state = (ZyanUPointer)buffer->string.vector.data;
} else
{
*state = (ZyanUPointer)buffer->string.vector.size;
}
state->data = (ZyanUPointer)buffer->string.vector.data;
state->size = buffer->string.vector.size;

return ZYAN_STATUS_SUCCESS;
}

ZyanStatus ZydisFormatterBufferRestore(ZydisFormatterBuffer* buffer, ZyanUPointer state)
ZyanStatus ZydisFormatterBufferRestore(ZydisFormatterBuffer* buffer,
ZydisFormatterBufferState* state)
{
if (!buffer)
{
Expand All @@ -171,18 +168,15 @@ ZyanStatus ZydisFormatterBufferRestore(ZydisFormatterBuffer* buffer, ZyanUPointe

if (buffer->is_token_list)
{
const ZyanUSize delta = (ZyanUPointer)buffer->string.vector.data - state;
const ZyanUSize delta = (ZyanUPointer)buffer->string.vector.data - state->data;
buffer->capacity += delta;
buffer->string.vector.data = (void*)state;
buffer->string.vector.size = 1; // TODO: Restore size?
buffer->string.vector.data = (void*)state->data;
buffer->string.vector.capacity = ZYAN_MIN(buffer->capacity, 255);
*(char*)buffer->string.vector.data = '\0';
} else
{
buffer->string.vector.size = (ZyanUSize)state;
ZYDIS_STRING_NULLTERMINATE(&buffer->string);
}

buffer->string.vector.size = state->size;
ZYDIS_STRING_NULLTERMINATE(&buffer->string);

return ZYAN_STATUS_SUCCESS;
}

Expand Down
87 changes: 80 additions & 7 deletions src/FormatterIntel.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ ZyanStatus ZydisFormatterIntelFormatInstruction(const ZydisFormatter* formatter,
ZYAN_CHECK(formatter->func_print_prefixes(formatter, buffer, context));
ZYAN_CHECK(formatter->func_print_mnemonic(formatter, buffer, context));

ZyanUPointer state_mnemonic;
ZydisFormatterBufferState state_mnemonic;
ZYDIS_BUFFER_REMEMBER(buffer, state_mnemonic);
for (ZyanU8 i = 0; i < context->instruction->operand_count_visible; ++i)
{
Expand All @@ -67,10 +67,11 @@ ZyanStatus ZydisFormatterIntelFormatInstruction(const ZydisFormatter* formatter,
continue;
}

ZyanUPointer buffer_state;
ZydisFormatterBufferState buffer_state;
ZYDIS_BUFFER_REMEMBER(buffer, buffer_state);

if (buffer_state != state_mnemonic)
if ((buffer_state.data != state_mnemonic.data) ||
(buffer_state.size != state_mnemonic.size))
{
ZYDIS_BUFFER_APPEND(buffer, DELIM_OPERAND);
} else
Expand All @@ -87,7 +88,7 @@ ZyanStatus ZydisFormatterIntelFormatInstruction(const ZydisFormatter* formatter,
status = formatter->func_pre_operand(formatter, buffer, context);
if (status == ZYDIS_STATUS_SKIP_TOKEN)
{
ZYAN_CHECK(ZydisFormatterBufferRestore(buffer, buffer_state));
ZYAN_CHECK(ZydisFormatterBufferRestore(buffer, &buffer_state));
continue;
}
if (!ZYAN_SUCCESS(status))
Expand Down Expand Up @@ -115,7 +116,7 @@ ZyanStatus ZydisFormatterIntelFormatInstruction(const ZydisFormatter* formatter,
}
if (status == ZYDIS_STATUS_SKIP_TOKEN)
{
ZYAN_CHECK(ZydisFormatterBufferRestore(buffer, buffer_state));
ZYAN_CHECK(ZydisFormatterBufferRestore(buffer, &buffer_state));
continue;
}
if (!ZYAN_SUCCESS(status))
Expand All @@ -128,10 +129,10 @@ ZyanStatus ZydisFormatterIntelFormatInstruction(const ZydisFormatter* formatter,
status = formatter->func_post_operand(formatter, buffer, context);
if (status == ZYDIS_STATUS_SKIP_TOKEN)
{
ZYAN_CHECK(ZydisFormatterBufferRestore(buffer, buffer_state));
ZYAN_CHECK(ZydisFormatterBufferRestore(buffer, &buffer_state));
continue;
}
if (ZYAN_SUCCESS(status))
if (!ZYAN_SUCCESS(status))
{
return status;
}
Expand Down Expand Up @@ -408,6 +409,26 @@ ZyanStatus ZydisFormatterIntelFormatInstructionMASM(const ZydisFormatter* format
// memory operands
context->runtime_address = 0;

if (context->instruction->mnemonic == ZYDIS_MNEMONIC_INT3)
{
ZydisFormatterContext context_copy = *context;
ZydisDecodedInstruction instruction;
ZydisDecodedOperand operands[1];
instruction = *context->instruction;
instruction.mnemonic = ZYDIS_MNEMONIC_INT;
instruction.operand_count = 1;
instruction.operand_count_visible = 1;
context_copy.instruction = &instruction;
operands[0].type = ZYDIS_OPERAND_TYPE_IMMEDIATE;
operands[0].visibility = ZYDIS_OPERAND_VISIBILITY_IMPLICIT;
operands[0].imm.is_relative = ZYAN_FALSE;
operands[0].imm.is_signed = ZYAN_FALSE;
operands[0].imm.value.u = 3;
operands[0].imm.size = 8;
context_copy.operands = operands;
return ZydisFormatterIntelFormatInstruction(formatter, buffer, &context_copy);
}

return ZydisFormatterIntelFormatInstruction(formatter, buffer, context);
}

Expand Down Expand Up @@ -451,6 +472,58 @@ ZyanStatus ZydisFormatterIntelPrintAddressMASM(const ZydisFormatter* formatter,
return ZYAN_STATUS_SUCCESS;
}

ZyanStatus ZydisFormatterIntelFormatOperandREGMASM(const ZydisFormatter* formatter,
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
{
ZYAN_ASSERT(formatter);
ZYAN_ASSERT(buffer);
ZYAN_ASSERT(context);

if ((context->instruction->mnemonic == ZYDIS_MNEMONIC_FUCOMP) && (context->operand->id == 0))
{
return ZYDIS_STATUS_SKIP_TOKEN;
}

return ZydisFormatterBaseFormatOperandREG(formatter, buffer, context);
}

ZyanStatus ZydisFormatterIntelPrintMnemonicMASM(const ZydisFormatter* formatter,
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
{
ZYAN_ASSERT(formatter);
ZYAN_ASSERT(buffer);
ZYAN_ASSERT(context);

if (context->instruction->mnemonic == ZYDIS_MNEMONIC_INT1)
{
ZYDIS_BUFFER_APPEND_CASE(buffer, INVALID_MNEMONIC, formatter->case_mnemonic);
return ZYAN_STATUS_SUCCESS;
}

return ZydisFormatterIntelPrintMnemonic(formatter, buffer, context);
}

ZyanStatus ZydisFormatterIntelPrintRegisterMASM(const ZydisFormatter* formatter,
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context, ZydisRegister reg)
{
ZYAN_ASSERT(formatter);
ZYAN_ASSERT(buffer);
ZYAN_ASSERT(context);

if ((reg >= ZYDIS_REGISTER_ST0) && (reg <= ZYDIS_REGISTER_ST7))
{
static const ZydisShortString STR_ST_PREFIX = ZYDIS_MAKE_SHORTSTRING("st(");
static const ZyanStringView STR_ST_SUFFIX = ZYAN_DEFINE_STRING_VIEW(")");
ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_REGISTER);
ZYAN_CHECK(ZydisStringAppendShortCase(&buffer->string, &STR_ST_PREFIX,
formatter->case_registers));
return ZydisStringAppendDecU(&buffer->string, reg - ZYDIS_REGISTER_ST0, 0, ZYAN_NULL,
&STR_ST_SUFFIX);
}

return ZydisFormatterIntelPrintRegister(formatter, buffer, context, reg);
}

/* ---------------------------------------------------------------------------------------------- */

/* ============================================================================================== */
14 changes: 9 additions & 5 deletions tests/cases/3dnow_000.out
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
== [ BASIC ] ============================================================================================
== [ BASIC ] ==========================================================================================
MNEMONIC: pfsqrt [ENC: 3DNOW, MAP: 0F0F, OPC: 0x97]
LENGTH: 4
SSZ: 64
Expand All @@ -11,7 +11,7 @@
ATTRIBUTES: HAS_MODRM ACCEPTS_SEGMENT
OPTIMIZED: 0F 0F 37 97

== [ OPERANDS ] ============================================================================================
== [ OPERANDS ] ==========================================================================================
## TYPE VISIBILITY ACTION ENCODING SIZE NELEM ELEMSZ ELEMTYPE VALUE
-- --------- ---------- ------ ------------ ---- ----- ------ -------- ---------------------------
0 REGISTER EXPLICIT RW MODRM_REG 64 1 64 INT mm6
Expand All @@ -23,15 +23,19 @@
DISP = 0x0000000000000000
-- --------- ---------- ------ ------------ ---- ----- ------ -------- ---------------------------

== [ ATT ] ============================================================================================
== [ ATT ] ==========================================================================================
ABSOLUTE: pfsqrt (%rdi), %mm6
RELATIVE: pfsqrt (%rdi), %mm6

== [ INTEL ] ============================================================================================
== [ INTEL ] ==========================================================================================
ABSOLUTE: pfsqrt mm6, qword ptr ds:[rdi]
RELATIVE: pfsqrt mm6, qword ptr ds:[rdi]

== [ SEGMENTS ] ============================================================================================
== [ INTEL_MASM ] ==========================================================================================
ABSOLUTE: pfsqrt mm6, qword ptr ds:[rdi]
RELATIVE: pfsqrt mm6, qword ptr ds:[rdi]

== [ SEGMENTS ] ==========================================================================================
0F 0F 37 97
: : :..OPCODE
: :..MODRM
Expand Down
Loading