1 /***************************************************************************************************
3 Zyan Disassembler Library (Zydis)
5 Original Author : Florian Bernd, Joel Hoener
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included in all
15 * copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 ***************************************************************************************************/
27 #include <Zydis/Internal/FormatterIntel.h>
28 #include <Zydis/Utils.h>
29 #include <Zycore/Format.h>
31 /* ============================================================================================== */
33 /* ============================================================================================== */
35 #include <Generated/FormatterStrings.inc>
37 /* ============================================================================================== */
38 /* Formatter functions */
39 /* ============================================================================================== */
41 /* ---------------------------------------------------------------------------------------------- */
43 /* ---------------------------------------------------------------------------------------------- */
45 ZyanStatus
ZydisFormatterIntelFormatInstruction(const ZydisFormatter
* formatter
,
46 ZydisFormatterBuffer
* buffer
, ZydisFormatterContext
* context
)
48 ZYAN_ASSERT(formatter
);
51 ZYAN_ASSERT(context
->instruction
);
52 ZYAN_ASSERT(context
->operands
);
54 ZYAN_CHECK(formatter
->func_print_prefixes(formatter
, buffer
, context
));
55 ZYAN_CHECK(formatter
->func_print_mnemonic(formatter
, buffer
, context
));
57 ZyanUPointer state_mnemonic
;
58 ZYDIS_BUFFER_REMEMBER(buffer
, state_mnemonic
);
59 for (ZyanU8 i
= 0; i
< context
->instruction
->operand_count_visible
; ++i
)
61 const ZydisDecodedOperand
* const operand
= &context
->operands
[i
];
63 // Print embedded-mask registers as decorator instead of a regular operand
64 if ((i
== 1) && (operand
->type
== ZYDIS_OPERAND_TYPE_REGISTER
) &&
65 (operand
->encoding
== ZYDIS_OPERAND_ENCODING_MASK
))
70 ZyanUPointer buffer_state
;
71 ZYDIS_BUFFER_REMEMBER(buffer
, buffer_state
);
73 if (buffer_state
!= state_mnemonic
)
75 ZYDIS_BUFFER_APPEND(buffer
, DELIM_OPERAND
);
78 ZYDIS_BUFFER_APPEND(buffer
, DELIM_MNEMONIC
);
81 // Set current operand
82 context
->operand
= operand
;
85 if (formatter
->func_pre_operand
)
87 status
= formatter
->func_pre_operand(formatter
, buffer
, context
);
88 if (status
== ZYDIS_STATUS_SKIP_TOKEN
)
90 ZYAN_CHECK(ZydisFormatterBufferRestore(buffer
, buffer_state
));
93 if (!ZYAN_SUCCESS(status
))
99 switch (operand
->type
)
101 case ZYDIS_OPERAND_TYPE_REGISTER
:
102 status
= formatter
->func_format_operand_reg(formatter
, buffer
, context
);
104 case ZYDIS_OPERAND_TYPE_MEMORY
:
105 status
= formatter
->func_format_operand_mem(formatter
, buffer
, context
);
107 case ZYDIS_OPERAND_TYPE_POINTER
:
108 status
= formatter
->func_format_operand_ptr(formatter
, buffer
, context
);
110 case ZYDIS_OPERAND_TYPE_IMMEDIATE
:
111 status
= formatter
->func_format_operand_imm(formatter
, buffer
, context
);
114 return ZYAN_STATUS_INVALID_ARGUMENT
;
116 if (status
== ZYDIS_STATUS_SKIP_TOKEN
)
118 ZYAN_CHECK(ZydisFormatterBufferRestore(buffer
, buffer_state
));
121 if (!ZYAN_SUCCESS(status
))
126 if (formatter
->func_post_operand
)
128 status
= formatter
->func_post_operand(formatter
, buffer
, context
);
129 if (status
== ZYDIS_STATUS_SKIP_TOKEN
)
131 ZYAN_CHECK(ZydisFormatterBufferRestore(buffer
, buffer_state
));
134 if (ZYAN_SUCCESS(status
))
140 #if !defined(ZYDIS_DISABLE_AVX512) || !defined(ZYDIS_DISABLE_KNC)
141 if ((context
->instruction
->encoding
== ZYDIS_INSTRUCTION_ENCODING_EVEX
) ||
142 (context
->instruction
->encoding
== ZYDIS_INSTRUCTION_ENCODING_MVEX
))
145 (context
->instruction
->operand_count_visible
> 1) &&
146 (context
->operands
[i
+ 1].encoding
== ZYDIS_OPERAND_ENCODING_MASK
))
148 ZYAN_CHECK(formatter
->func_print_decorator(formatter
, buffer
, context
,
149 ZYDIS_DECORATOR_MASK
));
151 if (operand
->type
== ZYDIS_OPERAND_TYPE_MEMORY
)
153 ZYAN_CHECK(formatter
->func_print_decorator(formatter
, buffer
, context
,
154 ZYDIS_DECORATOR_BC
));
155 if (context
->instruction
->encoding
== ZYDIS_INSTRUCTION_ENCODING_MVEX
)
157 ZYAN_CHECK(formatter
->func_print_decorator(formatter
, buffer
, context
,
158 ZYDIS_DECORATOR_CONVERSION
));
159 ZYAN_CHECK(formatter
->func_print_decorator(formatter
, buffer
, context
,
160 ZYDIS_DECORATOR_EH
));
164 ZyanBool decorate_operand
;
165 if (i
== (context
->instruction
->operand_count_visible
- 1))
167 decorate_operand
= operand
->type
!= ZYDIS_OPERAND_TYPE_IMMEDIATE
;
172 (context
->instruction
->operand_count_visible
> (i
+ 1)) &&
173 ((context
->operands
[i
+ 1].type
== ZYDIS_OPERAND_TYPE_IMMEDIATE
) ||
174 (context
->operands
[i
+ 1].visibility
== ZYDIS_OPERAND_VISIBILITY_HIDDEN
));
176 if (decorate_operand
)
178 if (context
->instruction
->encoding
== ZYDIS_INSTRUCTION_ENCODING_MVEX
)
180 ZYAN_CHECK(formatter
->func_print_decorator(formatter
, buffer
, context
,
181 ZYDIS_DECORATOR_SWIZZLE
));
183 ZYAN_CHECK(formatter
->func_print_decorator(formatter
, buffer
, context
,
184 ZYDIS_DECORATOR_RC
));
185 ZYAN_CHECK(formatter
->func_print_decorator(formatter
, buffer
, context
,
186 ZYDIS_DECORATOR_SAE
));
193 return ZYAN_STATUS_SUCCESS
;
196 ZyanStatus
ZydisFormatterIntelFormatOperandMEM(const ZydisFormatter
* formatter
,
197 ZydisFormatterBuffer
* buffer
, ZydisFormatterContext
* context
)
199 ZYAN_ASSERT(formatter
);
201 ZYAN_ASSERT(context
);
203 if ((context
->operand
->mem
.type
== ZYDIS_MEMOP_TYPE_MEM
) ||
204 (context
->operand
->mem
.type
== ZYDIS_MEMOP_TYPE_VSIB
))
206 ZYAN_CHECK(formatter
->func_print_typecast(formatter
, buffer
, context
));
208 ZYAN_CHECK(formatter
->func_print_segment(formatter
, buffer
, context
));
210 ZYDIS_BUFFER_APPEND(buffer
, MEMORY_BEGIN_INTEL
);
212 const ZyanBool absolute
= !formatter
->force_relative_riprel
&&
213 (context
->runtime_address
!= ZYDIS_RUNTIME_ADDRESS_NONE
);
214 if (absolute
&& context
->operand
->mem
.disp
.has_displacement
&&
215 (context
->operand
->mem
.index
== ZYDIS_REGISTER_NONE
) &&
216 ((context
->operand
->mem
.base
== ZYDIS_REGISTER_NONE
) ||
217 (context
->operand
->mem
.base
== ZYDIS_REGISTER_EIP
) ||
218 (context
->operand
->mem
.base
== ZYDIS_REGISTER_RIP
)))
220 // EIP/RIP-relative or absolute-displacement address operand
221 ZYAN_CHECK(formatter
->func_print_address_abs(formatter
, buffer
, context
));
224 const ZyanBool should_print_reg
= context
->operand
->mem
.base
!= ZYDIS_REGISTER_NONE
;
225 const ZyanBool should_print_idx
= context
->operand
->mem
.index
!= ZYDIS_REGISTER_NONE
;
226 const ZyanBool neither_reg_nor_idx
= !should_print_reg
&& !should_print_idx
;
228 // Regular memory operand
229 if (should_print_reg
)
231 ZYAN_CHECK(formatter
->func_print_register(formatter
, buffer
, context
,
232 context
->operand
->mem
.base
));
234 if (should_print_idx
)
236 if (context
->operand
->mem
.base
!= ZYDIS_REGISTER_NONE
)
238 ZYDIS_BUFFER_APPEND(buffer
, ADD
);
240 ZYAN_CHECK(formatter
->func_print_register(formatter
, buffer
, context
,
241 context
->operand
->mem
.index
));
242 if (context
->operand
->mem
.scale
&&
243 (context
->operand
->mem
.type
!= ZYDIS_MEMOP_TYPE_MIB
) &&
244 ((context
->operand
->mem
.scale
> 1) || formatter
->force_memory_scale
))
246 ZYDIS_BUFFER_APPEND(buffer
, MUL
);
247 ZYDIS_BUFFER_APPEND_TOKEN(buffer
, ZYDIS_TOKEN_IMMEDIATE
);
248 ZYAN_CHECK(ZydisStringAppendDecU(&buffer
->string
, context
->operand
->mem
.scale
, 0,
249 ZYAN_NULL
, ZYAN_NULL
));
252 if (neither_reg_nor_idx
)
254 ZYAN_CHECK(formatter
->func_print_address_abs(formatter
, buffer
, context
));
255 } else if (context
->operand
->mem
.disp
.has_displacement
&& context
->operand
->mem
.disp
.value
)
257 ZYAN_CHECK(formatter
->func_print_disp(formatter
, buffer
, context
));
261 ZYDIS_BUFFER_APPEND(buffer
, MEMORY_END_INTEL
);
262 return ZYAN_STATUS_SUCCESS
;
265 ZyanStatus
ZydisFormatterIntelPrintMnemonic(const ZydisFormatter
* formatter
,
266 ZydisFormatterBuffer
* buffer
, ZydisFormatterContext
* context
)
268 ZYAN_ASSERT(formatter
);
270 ZYAN_ASSERT(context
);
272 const ZydisShortString
* mnemonic
= ZydisMnemonicGetStringWrapped(
273 context
->instruction
->mnemonic
);
276 ZYDIS_BUFFER_APPEND_CASE(buffer
, INVALID_MNEMONIC
, formatter
->case_mnemonic
);
277 return ZYAN_STATUS_SUCCESS
;
280 ZYDIS_BUFFER_APPEND_TOKEN(buffer
, ZYDIS_TOKEN_MNEMONIC
);
281 ZYAN_CHECK(ZydisStringAppendShortCase(&buffer
->string
, mnemonic
, formatter
->case_mnemonic
));
282 if (context
->instruction
->meta
.branch_type
== ZYDIS_BRANCH_TYPE_FAR
)
284 return ZydisStringAppendShortCase(&buffer
->string
, &STR_FAR
, formatter
->case_mnemonic
);
286 if (formatter
->print_branch_size
)
288 switch (context
->instruction
->meta
.branch_type
)
290 case ZYDIS_BRANCH_TYPE_NONE
:
292 case ZYDIS_BRANCH_TYPE_SHORT
:
293 return ZydisStringAppendShortCase(&buffer
->string
, &STR_SHORT
,
294 formatter
->case_mnemonic
);
295 case ZYDIS_BRANCH_TYPE_NEAR
:
296 return ZydisStringAppendShortCase(&buffer
->string
, &STR_NEAR
,
297 formatter
->case_mnemonic
);
299 return ZYAN_STATUS_INVALID_ARGUMENT
;
303 return ZYAN_STATUS_SUCCESS
;
306 ZyanStatus
ZydisFormatterIntelPrintRegister(const ZydisFormatter
* formatter
,
307 ZydisFormatterBuffer
* buffer
, ZydisFormatterContext
* context
, ZydisRegister reg
)
309 ZYAN_UNUSED(context
);
311 ZYAN_ASSERT(formatter
);
313 ZYAN_ASSERT(context
);
315 const ZydisShortString
* str
= ZydisRegisterGetStringWrapped(reg
);
318 ZYDIS_BUFFER_APPEND_CASE(buffer
, INVALID_REG
, formatter
->case_registers
);
319 return ZYAN_STATUS_SUCCESS
;
322 ZYDIS_BUFFER_APPEND_TOKEN(buffer
, ZYDIS_TOKEN_REGISTER
);
323 return ZydisStringAppendShortCase(&buffer
->string
, str
, formatter
->case_registers
);
326 ZyanStatus
ZydisFormatterIntelPrintDISP(const ZydisFormatter
* formatter
,
327 ZydisFormatterBuffer
* buffer
, ZydisFormatterContext
* context
)
329 ZYAN_ASSERT(formatter
);
331 ZYAN_ASSERT(context
);
333 switch (formatter
->disp_signedness
)
335 case ZYDIS_SIGNEDNESS_AUTO
:
336 case ZYDIS_SIGNEDNESS_SIGNED
:
337 if (context
->operand
->mem
.disp
.value
< 0)
339 if ((context
->operand
->mem
.base
!= ZYDIS_REGISTER_NONE
) ||
340 (context
->operand
->mem
.index
!= ZYDIS_REGISTER_NONE
))
342 ZYDIS_BUFFER_APPEND(buffer
, SUB
);
344 ZYDIS_BUFFER_APPEND_TOKEN(buffer
, ZYDIS_TOKEN_DISPLACEMENT
);
345 ZYDIS_STRING_APPEND_NUM_U(formatter
, formatter
->disp_base
, &buffer
->string
,
346 ZyanAbsI64(context
->operand
->mem
.disp
.value
), formatter
->disp_padding
,
347 formatter
->hex_force_leading_number
);
351 case ZYDIS_SIGNEDNESS_UNSIGNED
:
352 if ((context
->operand
->mem
.base
!= ZYDIS_REGISTER_NONE
) ||
353 (context
->operand
->mem
.index
!= ZYDIS_REGISTER_NONE
))
355 ZYDIS_BUFFER_APPEND(buffer
, ADD
);
357 ZYDIS_BUFFER_APPEND_TOKEN(buffer
, ZYDIS_TOKEN_DISPLACEMENT
);
358 ZYDIS_STRING_APPEND_NUM_U(formatter
, formatter
->disp_base
, &buffer
->string
,
359 context
->operand
->mem
.disp
.value
, formatter
->disp_padding
,
360 formatter
->hex_force_leading_number
);
363 return ZYAN_STATUS_INVALID_ARGUMENT
;
366 return ZYAN_STATUS_SUCCESS
;
369 ZyanStatus
ZydisFormatterIntelPrintTypecast(const ZydisFormatter
* formatter
,
370 ZydisFormatterBuffer
* buffer
, ZydisFormatterContext
* context
)
372 ZYAN_ASSERT(formatter
);
374 ZYAN_ASSERT(context
);
376 switch (ZydisFormatterHelperGetExplicitSize(formatter
, context
, context
->operand
))
378 case 8: ZYDIS_BUFFER_APPEND(buffer
, SIZE_8_INTEL
); break;
379 case 16: ZYDIS_BUFFER_APPEND(buffer
, SIZE_16_INTEL
); break;
380 case 32: ZYDIS_BUFFER_APPEND(buffer
, SIZE_32_INTEL
); break;
381 case 48: ZYDIS_BUFFER_APPEND(buffer
, SIZE_48
); break;
382 case 64: ZYDIS_BUFFER_APPEND(buffer
, SIZE_64_INTEL
); break;
383 case 80: ZYDIS_BUFFER_APPEND(buffer
, SIZE_80
); break;
384 case 128: ZYDIS_BUFFER_APPEND(buffer
, SIZE_128_INTEL
); break;
385 case 256: ZYDIS_BUFFER_APPEND(buffer
, SIZE_256_INTEL
); break;
386 case 512: ZYDIS_BUFFER_APPEND(buffer
, SIZE_512_INTEL
); break;
391 return ZYAN_STATUS_SUCCESS
;
394 /* ---------------------------------------------------------------------------------------------- */
396 /* ---------------------------------------------------------------------------------------------- */
398 ZyanStatus
ZydisFormatterIntelFormatInstructionMASM(const ZydisFormatter
* formatter
,
399 ZydisFormatterBuffer
* buffer
, ZydisFormatterContext
* context
)
401 ZYAN_ASSERT(formatter
);
403 ZYAN_ASSERT(context
);
405 // Force the formatter to always call our MASM `ZYDIS_FORMATTER_PRINT_ADDRESS_ABS` function.
406 // This implicitly omits printing of the `RIP`/`EIP` registers for `RIP`/`EIP`-relative
408 context
->runtime_address
= 0;
410 return ZydisFormatterIntelFormatInstruction(formatter
, buffer
, context
);
413 ZyanStatus
ZydisFormatterIntelPrintAddressMASM(const ZydisFormatter
* formatter
,
414 ZydisFormatterBuffer
* buffer
, ZydisFormatterContext
* context
)
416 ZYAN_ASSERT(formatter
);
418 ZYAN_ASSERT(context
);
421 ZYAN_CHECK(ZydisCalcAbsoluteAddress(context
->instruction
, context
->operand
, 0, &address
));
423 ZyanU8 padding
= (formatter
->addr_padding_relative
==
424 ZYDIS_PADDING_AUTO
) ? 0 : (ZyanU8
)formatter
->addr_padding_relative
;
425 if ((formatter
->addr_padding_relative
== ZYDIS_PADDING_AUTO
) &&
426 (formatter
->addr_base
== ZYDIS_NUMERIC_BASE_HEX
))
428 switch (context
->instruction
->stack_width
)
432 address
= (ZyanU16
)address
;
436 address
= (ZyanU32
)address
;
442 return ZYAN_STATUS_INVALID_ARGUMENT
;
446 ZYDIS_BUFFER_APPEND(buffer
, ADDR_RELATIVE
);
447 ZYDIS_STRING_APPEND_NUM_S(formatter
, formatter
->addr_base
, &buffer
->string
, address
, padding
,
448 formatter
->hex_force_leading_number
, ZYAN_TRUE
);
450 return ZYAN_STATUS_SUCCESS
;
453 /* ---------------------------------------------------------------------------------------------- */
455 /* ============================================================================================== */