1 /***************************************************************************************************
2
3 Zyan Disassembler Library (Zydis)
4
5 Original Author : Florian Bernd, Joel Hoener
6
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:
13 *
14 * The above copyright notice and this permission notice shall be included in all
15 * copies or substantial portions of the Software.
16 *
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
23 * SOFTWARE.
24
25 ***************************************************************************************************/
26
27 #include <Zydis/Internal/FormatterIntel.h>
28 #include <Zydis/Utils.h>
29 #include <Zycore/Format.h>
30
31 /* ============================================================================================== */
32 /* Constants */
33 /* ============================================================================================== */
34
35 #include <Generated/FormatterStrings.inc>
36
37 /* ============================================================================================== */
38 /* Formatter functions */
39 /* ============================================================================================== */
40
41 /* ---------------------------------------------------------------------------------------------- */
42 /* Intel */
43 /* ---------------------------------------------------------------------------------------------- */
44
ZydisFormatterIntelFormatInstruction(const ZydisFormatter * formatter,ZydisFormatterBuffer * buffer,ZydisFormatterContext * context)45 ZyanStatus ZydisFormatterIntelFormatInstruction(const ZydisFormatter* formatter,
46 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
47 {
48 ZYAN_ASSERT(formatter);
49 ZYAN_ASSERT(buffer);
50 ZYAN_ASSERT(context);
51 ZYAN_ASSERT(context->instruction);
52 ZYAN_ASSERT(context->operands);
53
54 ZYAN_CHECK(formatter->func_print_prefixes(formatter, buffer, context));
55 ZYAN_CHECK(formatter->func_print_mnemonic(formatter, buffer, context));
56
57 ZyanUPointer state_mnemonic;
58 ZYDIS_BUFFER_REMEMBER(buffer, state_mnemonic);
59 for (ZyanU8 i = 0; i < context->instruction->operand_count_visible; ++i)
60 {
61 const ZydisDecodedOperand* const operand = &context->operands[i];
62
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))
66 {
67 continue;
68 }
69
70 ZyanUPointer buffer_state;
71 ZYDIS_BUFFER_REMEMBER(buffer, buffer_state);
72
73 if (buffer_state != state_mnemonic)
74 {
75 ZYDIS_BUFFER_APPEND(buffer, DELIM_OPERAND);
76 } else
77 {
78 ZYDIS_BUFFER_APPEND(buffer, DELIM_MNEMONIC);
79 }
80
81 // Set current operand
82 context->operand = operand;
83
84 ZyanStatus status;
85 if (formatter->func_pre_operand)
86 {
87 status = formatter->func_pre_operand(formatter, buffer, context);
88 if (status == ZYDIS_STATUS_SKIP_TOKEN)
89 {
90 ZYAN_CHECK(ZydisFormatterBufferRestore(buffer, buffer_state));
91 continue;
92 }
93 if (!ZYAN_SUCCESS(status))
94 {
95 return status;
96 }
97 }
98
99 switch (operand->type)
100 {
101 case ZYDIS_OPERAND_TYPE_REGISTER:
102 status = formatter->func_format_operand_reg(formatter, buffer, context);
103 break;
104 case ZYDIS_OPERAND_TYPE_MEMORY:
105 status = formatter->func_format_operand_mem(formatter, buffer, context);
106 break;
107 case ZYDIS_OPERAND_TYPE_POINTER:
108 status = formatter->func_format_operand_ptr(formatter, buffer, context);
109 break;
110 case ZYDIS_OPERAND_TYPE_IMMEDIATE:
111 status = formatter->func_format_operand_imm(formatter, buffer, context);
112 break;
113 default:
114 return ZYAN_STATUS_INVALID_ARGUMENT;
115 }
116 if (status == ZYDIS_STATUS_SKIP_TOKEN)
117 {
118 ZYAN_CHECK(ZydisFormatterBufferRestore(buffer, buffer_state));
119 continue;
120 }
121 if (!ZYAN_SUCCESS(status))
122 {
123 return status;
124 }
125
126 if (formatter->func_post_operand)
127 {
128 status = formatter->func_post_operand(formatter, buffer, context);
129 if (status == ZYDIS_STATUS_SKIP_TOKEN)
130 {
131 ZYAN_CHECK(ZydisFormatterBufferRestore(buffer, buffer_state));
132 continue;
133 }
134 if (ZYAN_SUCCESS(status))
135 {
136 return status;
137 }
138 }
139
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))
143 {
144 if ((i == 0) &&
145 (context->instruction->operand_count_visible > 1) &&
146 (context->operands[i + 1].encoding == ZYDIS_OPERAND_ENCODING_MASK))
147 {
148 ZYAN_CHECK(formatter->func_print_decorator(formatter, buffer, context,
149 ZYDIS_DECORATOR_MASK));
150 }
151 if (operand->type == ZYDIS_OPERAND_TYPE_MEMORY)
152 {
153 ZYAN_CHECK(formatter->func_print_decorator(formatter, buffer, context,
154 ZYDIS_DECORATOR_BC));
155 if (context->instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_MVEX)
156 {
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));
161 }
162 } else
163 {
164 ZyanBool decorate_operand;
165 if (i == (context->instruction->operand_count_visible - 1))
166 {
167 decorate_operand = operand->type != ZYDIS_OPERAND_TYPE_IMMEDIATE;
168 }
169 else
170 {
171 decorate_operand =
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));
175 }
176 if (decorate_operand)
177 {
178 if (context->instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_MVEX)
179 {
180 ZYAN_CHECK(formatter->func_print_decorator(formatter, buffer, context,
181 ZYDIS_DECORATOR_SWIZZLE));
182 }
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));
187 }
188 }
189 }
190 #endif
191 }
192
193 return ZYAN_STATUS_SUCCESS;
194 }
195
ZydisFormatterIntelFormatOperandMEM(const ZydisFormatter * formatter,ZydisFormatterBuffer * buffer,ZydisFormatterContext * context)196 ZyanStatus ZydisFormatterIntelFormatOperandMEM(const ZydisFormatter* formatter,
197 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
198 {
199 ZYAN_ASSERT(formatter);
200 ZYAN_ASSERT(buffer);
201 ZYAN_ASSERT(context);
202
203 if ((context->operand->mem.type == ZYDIS_MEMOP_TYPE_MEM) ||
204 (context->operand->mem.type == ZYDIS_MEMOP_TYPE_AGEN) ||
205 (context->operand->mem.type == ZYDIS_MEMOP_TYPE_VSIB))
206 {
207 ZYAN_CHECK(formatter->func_print_typecast(formatter, buffer, context));
208 }
209 ZYAN_CHECK(formatter->func_print_segment(formatter, buffer, context));
210
211 ZYDIS_BUFFER_APPEND(buffer, MEMORY_BEGIN_INTEL);
212
213 const ZyanBool absolute = !formatter->force_relative_riprel &&
214 (context->runtime_address != ZYDIS_RUNTIME_ADDRESS_NONE);
215 if (absolute && context->operand->mem.disp.has_displacement &&
216 (context->operand->mem.index == ZYDIS_REGISTER_NONE) &&
217 ((context->operand->mem.base == ZYDIS_REGISTER_NONE) ||
218 (context->operand->mem.base == ZYDIS_REGISTER_EIP ) ||
219 (context->operand->mem.base == ZYDIS_REGISTER_RIP )))
220 {
221 // EIP/RIP-relative or absolute-displacement address operand
222 ZYAN_CHECK(formatter->func_print_address_abs(formatter, buffer, context));
223 } else
224 {
225 const ZyanBool should_print_reg = context->operand->mem.base != ZYDIS_REGISTER_NONE;
226 const ZyanBool should_print_idx = context->operand->mem.index != ZYDIS_REGISTER_NONE;
227 const ZyanBool neither_reg_nor_idx = !should_print_reg && !should_print_idx;
228
229 // Regular memory operand
230 if (should_print_reg)
231 {
232 ZYAN_CHECK(formatter->func_print_register(formatter, buffer, context,
233 context->operand->mem.base));
234 }
235 if (should_print_idx)
236 {
237 if (context->operand->mem.base != ZYDIS_REGISTER_NONE)
238 {
239 ZYDIS_BUFFER_APPEND(buffer, ADD);
240 }
241 ZYAN_CHECK(formatter->func_print_register(formatter, buffer, context,
242 context->operand->mem.index));
243 if (context->operand->mem.scale &&
244 (context->operand->mem.type != ZYDIS_MEMOP_TYPE_MIB) &&
245 ((context->operand->mem.scale > 1) || formatter->force_memory_scale))
246 {
247 ZYDIS_BUFFER_APPEND(buffer, MUL);
248 ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_IMMEDIATE);
249 ZYAN_CHECK(ZydisStringAppendDecU(&buffer->string, context->operand->mem.scale, 0,
250 ZYAN_NULL, ZYAN_NULL));
251 }
252 }
253 if (neither_reg_nor_idx)
254 {
255 ZYAN_CHECK(formatter->func_print_address_abs(formatter, buffer, context));
256 } else if (context->operand->mem.disp.has_displacement && context->operand->mem.disp.value)
257 {
258 ZYAN_CHECK(formatter->func_print_disp(formatter, buffer, context));
259 }
260 }
261
262 ZYDIS_BUFFER_APPEND(buffer, MEMORY_END_INTEL);
263 return ZYAN_STATUS_SUCCESS;
264 }
265
ZydisFormatterIntelPrintMnemonic(const ZydisFormatter * formatter,ZydisFormatterBuffer * buffer,ZydisFormatterContext * context)266 ZyanStatus ZydisFormatterIntelPrintMnemonic(const ZydisFormatter* formatter,
267 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
268 {
269 ZYAN_ASSERT(formatter);
270 ZYAN_ASSERT(buffer);
271 ZYAN_ASSERT(context);
272
273 const ZydisShortString* mnemonic = ZydisMnemonicGetStringWrapped(
274 context->instruction->mnemonic);
275 if (!mnemonic)
276 {
277 ZYDIS_BUFFER_APPEND_CASE(buffer, INVALID_MNEMONIC, formatter->case_mnemonic);
278 return ZYAN_STATUS_SUCCESS;
279 }
280
281 ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_MNEMONIC);
282 ZYAN_CHECK(ZydisStringAppendShortCase(&buffer->string, mnemonic, formatter->case_mnemonic));
283 if (context->instruction->meta.branch_type == ZYDIS_BRANCH_TYPE_FAR)
284 {
285 return ZydisStringAppendShortCase(&buffer->string, &STR_FAR, formatter->case_mnemonic);
286 }
287 if (formatter->print_branch_size)
288 {
289 switch (context->instruction->meta.branch_type)
290 {
291 case ZYDIS_BRANCH_TYPE_NONE:
292 break;
293 case ZYDIS_BRANCH_TYPE_SHORT:
294 return ZydisStringAppendShortCase(&buffer->string, &STR_SHORT,
295 formatter->case_mnemonic);
296 case ZYDIS_BRANCH_TYPE_NEAR:
297 return ZydisStringAppendShortCase(&buffer->string, &STR_NEAR,
298 formatter->case_mnemonic);
299 default:
300 return ZYAN_STATUS_INVALID_ARGUMENT;
301 }
302 }
303
304 return ZYAN_STATUS_SUCCESS;
305 }
306
ZydisFormatterIntelPrintRegister(const ZydisFormatter * formatter,ZydisFormatterBuffer * buffer,ZydisFormatterContext * context,ZydisRegister reg)307 ZyanStatus ZydisFormatterIntelPrintRegister(const ZydisFormatter* formatter,
308 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context, ZydisRegister reg)
309 {
310 ZYAN_UNUSED(context);
311
312 ZYAN_ASSERT(formatter);
313 ZYAN_ASSERT(buffer);
314 ZYAN_ASSERT(context);
315
316 const ZydisShortString* str = ZydisRegisterGetStringWrapped(reg);
317 if (!str)
318 {
319 ZYDIS_BUFFER_APPEND_CASE(buffer, INVALID_REG, formatter->case_registers);
320 return ZYAN_STATUS_SUCCESS;
321 }
322
323 ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_REGISTER);
324 return ZydisStringAppendShortCase(&buffer->string, str, formatter->case_registers);
325 }
326
ZydisFormatterIntelPrintDISP(const ZydisFormatter * formatter,ZydisFormatterBuffer * buffer,ZydisFormatterContext * context)327 ZyanStatus ZydisFormatterIntelPrintDISP(const ZydisFormatter* formatter,
328 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
329 {
330 ZYAN_ASSERT(formatter);
331 ZYAN_ASSERT(buffer);
332 ZYAN_ASSERT(context);
333
334 switch (formatter->disp_signedness)
335 {
336 case ZYDIS_SIGNEDNESS_AUTO:
337 case ZYDIS_SIGNEDNESS_SIGNED:
338 if (context->operand->mem.disp.value < 0)
339 {
340 if ((context->operand->mem.base != ZYDIS_REGISTER_NONE) ||
341 (context->operand->mem.index != ZYDIS_REGISTER_NONE))
342 {
343 ZYDIS_BUFFER_APPEND(buffer, SUB);
344 }
345 ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_DISPLACEMENT);
346 ZYDIS_STRING_APPEND_NUM_U(formatter, formatter->disp_base, &buffer->string,
347 ZyanAbsI64(context->operand->mem.disp.value), formatter->disp_padding,
348 formatter->hex_force_leading_number);
349 break;
350 }
351 ZYAN_FALLTHROUGH;
352 case ZYDIS_SIGNEDNESS_UNSIGNED:
353 if ((context->operand->mem.base != ZYDIS_REGISTER_NONE) ||
354 (context->operand->mem.index != ZYDIS_REGISTER_NONE))
355 {
356 ZYDIS_BUFFER_APPEND(buffer, ADD);
357 }
358 ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_DISPLACEMENT);
359 ZYDIS_STRING_APPEND_NUM_U(formatter, formatter->disp_base, &buffer->string,
360 context->operand->mem.disp.value, formatter->disp_padding,
361 formatter->hex_force_leading_number);
362 break;
363 default:
364 return ZYAN_STATUS_INVALID_ARGUMENT;
365 }
366
367 return ZYAN_STATUS_SUCCESS;
368 }
369
ZydisFormatterIntelPrintTypecast(const ZydisFormatter * formatter,ZydisFormatterBuffer * buffer,ZydisFormatterContext * context)370 ZyanStatus ZydisFormatterIntelPrintTypecast(const ZydisFormatter* formatter,
371 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
372 {
373 ZYAN_ASSERT(formatter);
374 ZYAN_ASSERT(buffer);
375 ZYAN_ASSERT(context);
376
377 switch (ZydisFormatterHelperGetExplicitSize(formatter, context, context->operand))
378 {
379 case 8: ZYDIS_BUFFER_APPEND(buffer, SIZE_8_INTEL ); break;
380 case 16: ZYDIS_BUFFER_APPEND(buffer, SIZE_16_INTEL ); break;
381 case 32: ZYDIS_BUFFER_APPEND(buffer, SIZE_32_INTEL ); break;
382 case 48: ZYDIS_BUFFER_APPEND(buffer, SIZE_48 ); break;
383 case 64: ZYDIS_BUFFER_APPEND(buffer, SIZE_64_INTEL ); break;
384 case 80: ZYDIS_BUFFER_APPEND(buffer, SIZE_80 ); break;
385 case 128: ZYDIS_BUFFER_APPEND(buffer, SIZE_128_INTEL); break;
386 case 256: ZYDIS_BUFFER_APPEND(buffer, SIZE_256_INTEL); break;
387 case 512: ZYDIS_BUFFER_APPEND(buffer, SIZE_512_INTEL); break;
388 default:
389 break;
390 }
391
392 return ZYAN_STATUS_SUCCESS;
393 }
394
395 /* ---------------------------------------------------------------------------------------------- */
396 /* MASM */
397 /* ---------------------------------------------------------------------------------------------- */
398
ZydisFormatterIntelFormatInstructionMASM(const ZydisFormatter * formatter,ZydisFormatterBuffer * buffer,ZydisFormatterContext * context)399 ZyanStatus ZydisFormatterIntelFormatInstructionMASM(const ZydisFormatter* formatter,
400 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
401 {
402 ZYAN_ASSERT(formatter);
403 ZYAN_ASSERT(buffer);
404 ZYAN_ASSERT(context);
405
406 // Force the formatter to always call our MASM `ZYDIS_FORMATTER_PRINT_ADDRESS_ABS` function.
407 // This implicitly omits printing of the `RIP`/`EIP` registers for `RIP`/`EIP`-relative
408 // memory operands
409 context->runtime_address = 0;
410
411 return ZydisFormatterIntelFormatInstruction(formatter, buffer, context);
412 }
413
ZydisFormatterIntelPrintAddressMASM(const ZydisFormatter * formatter,ZydisFormatterBuffer * buffer,ZydisFormatterContext * context)414 ZyanStatus ZydisFormatterIntelPrintAddressMASM(const ZydisFormatter* formatter,
415 ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
416 {
417 ZYAN_ASSERT(formatter);
418 ZYAN_ASSERT(buffer);
419 ZYAN_ASSERT(context);
420
421 ZyanU64 address;
422 ZYAN_CHECK(ZydisCalcAbsoluteAddress(context->instruction, context->operand, 0, &address));
423
424 ZyanU8 padding = (formatter->addr_padding_relative ==
425 ZYDIS_PADDING_AUTO) ? 0 : (ZyanU8)formatter->addr_padding_relative;
426 if ((formatter->addr_padding_relative == ZYDIS_PADDING_AUTO) &&
427 (formatter->addr_base == ZYDIS_NUMERIC_BASE_HEX))
428 {
429 switch (context->instruction->address_width)
430 {
431 case 16:
432 padding = 4;
433 address = (ZyanU16)address;
434 break;
435 case 32:
436 padding = 8;
437 address = (ZyanU32)address;
438 break;
439 case 64:
440 padding = 16;
441 break;
442 default:
443 return ZYAN_STATUS_INVALID_ARGUMENT;
444 }
445 }
446
447 ZYDIS_BUFFER_APPEND(buffer, ADDR_RELATIVE);
448 ZYDIS_STRING_APPEND_NUM_S(formatter, formatter->addr_base, &buffer->string, address, padding,
449 formatter->hex_force_leading_number, ZYAN_TRUE);
450
451 return ZYAN_STATUS_SUCCESS;
452 }
453
454 /* ---------------------------------------------------------------------------------------------- */
455
456 /* ============================================================================================== */
457