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