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