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/FormatterATT.h>
29 /* ============================================================================================== */
31 /* ============================================================================================== */
33 #include <Generated/FormatterStrings.inc>
35 /* ============================================================================================== */
36 /* Formatter functions */
37 /* ============================================================================================== */
39 /* ---------------------------------------------------------------------------------------------- */
41 /* ---------------------------------------------------------------------------------------------- */
43 ZyanStatus
ZydisFormatterATTFormatInstruction(const ZydisFormatter
* formatter
,
44 ZydisFormatterBuffer
* buffer
, ZydisFormatterContext
* context
)
46 ZYAN_ASSERT(formatter
);
49 ZYAN_ASSERT(context
->instruction
);
50 ZYAN_ASSERT(context
->operands
);
52 ZYAN_CHECK(formatter
->func_print_prefixes(formatter
, buffer
, context
));
53 ZYAN_CHECK(formatter
->func_print_mnemonic(formatter
, buffer
, context
));
55 ZyanUPointer state_mnemonic
;
56 ZYDIS_BUFFER_REMEMBER(buffer
, state_mnemonic
);
58 const ZyanI8 c
= (ZyanI8
)context
->instruction
->operand_count_visible
- 1;
59 for (ZyanI8 i
= c
; i
>= 0; --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
[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 /* ---------------------------------------------------------------------------------------------- */
198 /* ---------------------------------------------------------------------------------------------- */
200 ZyanStatus
ZydisFormatterATTFormatOperandMEM(const ZydisFormatter
* formatter
,
201 ZydisFormatterBuffer
* buffer
, ZydisFormatterContext
* context
)
203 ZYAN_ASSERT(formatter
);
205 ZYAN_ASSERT(context
);
207 ZYAN_CHECK(formatter
->func_print_segment(formatter
, buffer
, context
));
209 const ZyanBool absolute
= !formatter
->force_relative_riprel
&&
210 (context
->runtime_address
!= ZYDIS_RUNTIME_ADDRESS_NONE
);
211 if (absolute
&& context
->operand
->mem
.disp
.has_displacement
&&
212 (context
->operand
->mem
.index
== ZYDIS_REGISTER_NONE
) &&
213 ((context
->operand
->mem
.base
== ZYDIS_REGISTER_NONE
) ||
214 (context
->operand
->mem
.base
== ZYDIS_REGISTER_EIP
) ||
215 (context
->operand
->mem
.base
== ZYDIS_REGISTER_RIP
)))
217 // EIP/RIP-relative or absolute-displacement address operand
218 ZYAN_CHECK(formatter
->func_print_address_abs(formatter
, buffer
, context
));
221 const ZyanBool should_print_reg
= context
->operand
->mem
.base
!= ZYDIS_REGISTER_NONE
;
222 const ZyanBool should_print_idx
= context
->operand
->mem
.index
!= ZYDIS_REGISTER_NONE
;
223 const ZyanBool neither_reg_nor_idx
= !should_print_reg
&& !should_print_idx
;
225 // Regular memory operand
226 if (neither_reg_nor_idx
)
228 ZYAN_CHECK(formatter
->func_print_address_abs(formatter
, buffer
, context
));
229 } else if (context
->operand
->mem
.disp
.has_displacement
&& context
->operand
->mem
.disp
.value
)
231 ZYAN_CHECK(formatter
->func_print_disp(formatter
, buffer
, context
));
234 if (neither_reg_nor_idx
)
236 return ZYAN_STATUS_SUCCESS
;
239 ZYDIS_BUFFER_APPEND(buffer
, MEMORY_BEGIN_ATT
);
241 if (should_print_reg
)
243 ZYAN_CHECK(formatter
->func_print_register(formatter
, buffer
, context
,
244 context
->operand
->mem
.base
));
246 if (should_print_idx
)
248 ZYDIS_BUFFER_APPEND(buffer
, DELIM_MEMORY
);
249 ZYAN_CHECK(formatter
->func_print_register(formatter
, buffer
, context
,
250 context
->operand
->mem
.index
));
251 if (context
->operand
->mem
.scale
&&
252 (context
->operand
->mem
.type
!= ZYDIS_MEMOP_TYPE_MIB
) &&
253 ((context
->operand
->mem
.scale
> 1) || formatter
->force_memory_scale
))
255 ZYDIS_BUFFER_APPEND_TOKEN(buffer
, ZYDIS_TOKEN_DELIMITER
);
256 ZYDIS_BUFFER_APPEND(buffer
, DELIM_MEMORY
);
257 ZYDIS_BUFFER_APPEND_TOKEN(buffer
, ZYDIS_TOKEN_IMMEDIATE
);
258 ZYAN_CHECK(ZydisStringAppendDecU(&buffer
->string
, context
->operand
->mem
.scale
, 0,
259 ZYAN_NULL
, ZYAN_NULL
));
263 ZYDIS_BUFFER_APPEND(buffer
, MEMORY_END_ATT
);
264 return ZYAN_STATUS_SUCCESS
;
267 return ZYAN_STATUS_SUCCESS
;
270 /* ---------------------------------------------------------------------------------------------- */
271 /* Elemental tokens */
272 /* ---------------------------------------------------------------------------------------------- */
274 ZyanStatus
ZydisFormatterATTPrintMnemonic(const ZydisFormatter
* formatter
,
275 ZydisFormatterBuffer
* buffer
, ZydisFormatterContext
* context
)
277 ZYAN_ASSERT(formatter
);
279 ZYAN_ASSERT(context
);
280 ZYAN_ASSERT(context
->instruction
);
281 ZYAN_ASSERT(context
->operands
);
283 const ZydisShortString
* mnemonic
= ZydisMnemonicGetStringWrapped(
284 context
->instruction
->mnemonic
);
287 ZYDIS_BUFFER_APPEND_CASE(buffer
, INVALID_MNEMONIC
, formatter
->case_mnemonic
);
288 return ZYAN_STATUS_SUCCESS
;
291 ZYDIS_BUFFER_APPEND_TOKEN(buffer
, ZYDIS_TOKEN_MNEMONIC
);
292 if (context
->instruction
->meta
.branch_type
== ZYDIS_BRANCH_TYPE_FAR
)
294 ZYAN_CHECK(ZydisStringAppendShortCase(&buffer
->string
, &STR_FAR_ATT
,
295 formatter
->case_mnemonic
));
297 ZYAN_CHECK(ZydisStringAppendShortCase(&buffer
->string
, mnemonic
, formatter
->case_mnemonic
));
299 // Append operand-size suffix
301 for (ZyanU8 i
= 0; i
< context
->instruction
->operand_count_visible
; ++i
)
303 const ZydisDecodedOperand
* const operand
= &context
->operands
[i
];
304 if ((operand
->type
== ZYDIS_OPERAND_TYPE_MEMORY
) &&
305 ((operand
->mem
.type
== ZYDIS_MEMOP_TYPE_MEM
) ||
306 (operand
->mem
.type
== ZYDIS_MEMOP_TYPE_VSIB
)))
308 size
= ZydisFormatterHelperGetExplicitSize(formatter
, context
, operand
);
315 case 8: ZydisStringAppendShort(&buffer
->string
, &STR_SIZE_8_ATT
); break;
316 case 16: ZydisStringAppendShort(&buffer
->string
, &STR_SIZE_16_ATT
); break;
317 case 32: ZydisStringAppendShort(&buffer
->string
, &STR_SIZE_32_ATT
); break;
318 case 64: ZydisStringAppendShort(&buffer
->string
, &STR_SIZE_64_ATT
); break;
319 case 128: ZydisStringAppendShort(&buffer
->string
, &STR_SIZE_128_ATT
); break;
320 case 256: ZydisStringAppendShort(&buffer
->string
, &STR_SIZE_256_ATT
); break;
321 case 512: ZydisStringAppendShort(&buffer
->string
, &STR_SIZE_512_ATT
); break;
326 if (formatter
->print_branch_size
)
328 switch (context
->instruction
->meta
.branch_type
)
330 case ZYDIS_BRANCH_TYPE_NONE
:
332 case ZYDIS_BRANCH_TYPE_SHORT
:
333 return ZydisStringAppendShortCase(&buffer
->string
, &STR_SHORT
,
334 formatter
->case_mnemonic
);
335 case ZYDIS_BRANCH_TYPE_NEAR
:
336 return ZydisStringAppendShortCase(&buffer
->string
, &STR_NEAR
,
337 formatter
->case_mnemonic
);
339 return ZYAN_STATUS_INVALID_ARGUMENT
;
343 return ZYAN_STATUS_SUCCESS
;
346 ZyanStatus
ZydisFormatterATTPrintRegister(const ZydisFormatter
* formatter
,
347 ZydisFormatterBuffer
* buffer
, ZydisFormatterContext
* context
, ZydisRegister reg
)
349 ZYAN_UNUSED(context
);
351 ZYAN_ASSERT(formatter
);
353 ZYAN_ASSERT(context
);
355 ZYDIS_BUFFER_APPEND(buffer
, REGISTER
);
356 const ZydisShortString
* str
= ZydisRegisterGetStringWrapped(reg
);
359 return ZydisStringAppendShortCase(&buffer
->string
, &STR_INVALID_REG
,
360 formatter
->case_registers
);
362 return ZydisStringAppendShortCase(&buffer
->string
, str
, formatter
->case_registers
);
365 ZyanStatus
ZydisFormatterATTPrintAddressABS(const ZydisFormatter
* formatter
,
366 ZydisFormatterBuffer
* buffer
, ZydisFormatterContext
* context
)
368 ZYAN_ASSERT(formatter
);
370 ZYAN_ASSERT(context
);
372 if ((context
->instruction
->meta
.branch_type
!= ZYDIS_BRANCH_TYPE_NONE
) &&
373 (context
->operand
->type
== ZYDIS_OPERAND_TYPE_MEMORY
))
375 ZYDIS_BUFFER_APPEND(buffer
, MUL
);
378 return ZydisFormatterBasePrintAddressABS(formatter
, buffer
, context
);
381 ZyanStatus
ZydisFormatterATTPrintDISP(const ZydisFormatter
* formatter
,
382 ZydisFormatterBuffer
* buffer
, ZydisFormatterContext
* context
)
384 ZYAN_ASSERT(formatter
);
386 ZYAN_ASSERT(context
);
388 ZYDIS_BUFFER_APPEND_TOKEN(buffer
, ZYDIS_TOKEN_DISPLACEMENT
);
389 switch (formatter
->disp_signedness
)
391 case ZYDIS_SIGNEDNESS_AUTO
:
392 case ZYDIS_SIGNEDNESS_SIGNED
:
393 ZYDIS_STRING_APPEND_NUM_S(formatter
, formatter
->disp_base
, &buffer
->string
,
394 context
->operand
->mem
.disp
.value
, formatter
->disp_padding
,
395 formatter
->hex_force_leading_number
, ZYAN_FALSE
);
397 case ZYDIS_SIGNEDNESS_UNSIGNED
:
398 ZYDIS_STRING_APPEND_NUM_U(formatter
, formatter
->disp_base
, &buffer
->string
,
399 context
->operand
->mem
.disp
.value
, formatter
->disp_padding
,
400 formatter
->hex_force_leading_number
);
403 return ZYAN_STATUS_INVALID_ARGUMENT
;
406 return ZYAN_STATUS_SUCCESS
;
409 ZyanStatus
ZydisFormatterATTPrintIMM(const ZydisFormatter
* formatter
,
410 ZydisFormatterBuffer
* buffer
, ZydisFormatterContext
* context
)
412 ZYAN_ASSERT(formatter
);
414 ZYAN_ASSERT(context
);
416 ZYDIS_BUFFER_APPEND(buffer
, IMMEDIATE
);
417 return ZydisFormatterBasePrintIMM(formatter
, buffer
, context
);
420 /* ---------------------------------------------------------------------------------------------- */
422 /* ============================================================================================== */