xref: /haiku/src/libs/zydis/Zydis/FormatterATT.c (revision caed67a8cba83913b9c21ac2b06ebc6bd1cb3111)
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/FormatterATT.h>
28 
29 /* ============================================================================================== */
30 /* Constants                                                                                      */
31 /* ============================================================================================== */
32 
33 #include <Generated/FormatterStrings.inc>
34 
35 /* ============================================================================================== */
36 /* Formatter functions                                                                            */
37 /* ============================================================================================== */
38 
39 /* ---------------------------------------------------------------------------------------------- */
40 /* Instruction                                                                                    */
41 /* ---------------------------------------------------------------------------------------------- */
42 
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     ZYAN_ASSERT(context->instruction);
50     ZYAN_ASSERT(context->operands);
51 
52     ZYAN_CHECK(formatter->func_print_prefixes(formatter, buffer, context));
53     ZYAN_CHECK(formatter->func_print_mnemonic(formatter, buffer, context));
54 
55     ZyanUPointer state_mnemonic;
56     ZYDIS_BUFFER_REMEMBER(buffer, state_mnemonic);
57 
58     const ZyanI8 c = (ZyanI8)context->instruction->operand_count_visible - 1;
59     for (ZyanI8 i = c; i >= 0; --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[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 
196 /* ---------------------------------------------------------------------------------------------- */
197 /* Operands                                                                                       */
198 /* ---------------------------------------------------------------------------------------------- */
199 
200 ZyanStatus ZydisFormatterATTFormatOperandMEM(const ZydisFormatter* formatter,
201     ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
202 {
203     ZYAN_ASSERT(formatter);
204     ZYAN_ASSERT(buffer);
205     ZYAN_ASSERT(context);
206 
207     ZYAN_CHECK(formatter->func_print_segment(formatter, buffer, context));
208 
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 )))
216     {
217         // EIP/RIP-relative or absolute-displacement address operand
218         ZYAN_CHECK(formatter->func_print_address_abs(formatter, buffer, context));
219     } else
220     {
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;
224 
225         // Regular memory operand
226         if (neither_reg_nor_idx)
227         {
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)
230         {
231             ZYAN_CHECK(formatter->func_print_disp(formatter, buffer, context));
232         }
233 
234         if (neither_reg_nor_idx)
235         {
236             return ZYAN_STATUS_SUCCESS;
237         }
238 
239         ZYDIS_BUFFER_APPEND(buffer, MEMORY_BEGIN_ATT);
240 
241         if (should_print_reg)
242         {
243             ZYAN_CHECK(formatter->func_print_register(formatter, buffer, context,
244                 context->operand->mem.base));
245         }
246         if (should_print_idx)
247         {
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))
254             {
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));
260             }
261         }
262 
263         ZYDIS_BUFFER_APPEND(buffer, MEMORY_END_ATT);
264         return ZYAN_STATUS_SUCCESS;
265     }
266 
267     return ZYAN_STATUS_SUCCESS;
268 }
269 
270 /* ---------------------------------------------------------------------------------------------- */
271 /* Elemental tokens                                                                               */
272 /* ---------------------------------------------------------------------------------------------- */
273 
274 ZyanStatus ZydisFormatterATTPrintMnemonic(const ZydisFormatter* formatter,
275     ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
276 {
277     ZYAN_ASSERT(formatter);
278     ZYAN_ASSERT(buffer);
279     ZYAN_ASSERT(context);
280     ZYAN_ASSERT(context->instruction);
281     ZYAN_ASSERT(context->operands);
282 
283     const ZydisShortString* mnemonic = ZydisMnemonicGetStringWrapped(
284         context->instruction->mnemonic);
285     if (!mnemonic)
286     {
287         ZYDIS_BUFFER_APPEND_CASE(buffer, INVALID_MNEMONIC, formatter->case_mnemonic);
288         return ZYAN_STATUS_SUCCESS;
289     }
290 
291     ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_MNEMONIC);
292     if (context->instruction->meta.branch_type == ZYDIS_BRANCH_TYPE_FAR)
293     {
294         ZYAN_CHECK(ZydisStringAppendShortCase(&buffer->string, &STR_FAR_ATT,
295             formatter->case_mnemonic));
296     }
297     ZYAN_CHECK(ZydisStringAppendShortCase(&buffer->string, mnemonic, formatter->case_mnemonic));
298 
299     // Append operand-size suffix
300     ZyanU32 size = 0;
301     for (ZyanU8 i = 0; i < context->instruction->operand_count_visible; ++i)
302     {
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)))
307         {
308             size = ZydisFormatterHelperGetExplicitSize(formatter, context, operand);
309             break;
310         }
311     }
312 
313     switch (size)
314     {
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;
322     default:
323         break;
324     }
325 
326     if (formatter->print_branch_size)
327     {
328         switch (context->instruction->meta.branch_type)
329         {
330         case ZYDIS_BRANCH_TYPE_NONE:
331             break;
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);
338         default:
339             return ZYAN_STATUS_INVALID_ARGUMENT;
340         }
341     }
342 
343     return ZYAN_STATUS_SUCCESS;
344 }
345 
346 ZyanStatus ZydisFormatterATTPrintRegister(const ZydisFormatter* formatter,
347     ZydisFormatterBuffer* buffer, ZydisFormatterContext* context, ZydisRegister reg)
348 {
349     ZYAN_UNUSED(context);
350 
351     ZYAN_ASSERT(formatter);
352     ZYAN_ASSERT(buffer);
353     ZYAN_ASSERT(context);
354 
355     ZYDIS_BUFFER_APPEND(buffer, REGISTER);
356     const ZydisShortString* str = ZydisRegisterGetStringWrapped(reg);
357     if (!str)
358     {
359         return ZydisStringAppendShortCase(&buffer->string, &STR_INVALID_REG,
360             formatter->case_registers);
361     }
362     return ZydisStringAppendShortCase(&buffer->string, str, formatter->case_registers);
363 }
364 
365 ZyanStatus ZydisFormatterATTPrintAddressABS(const ZydisFormatter* formatter,
366     ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
367 {
368     ZYAN_ASSERT(formatter);
369     ZYAN_ASSERT(buffer);
370     ZYAN_ASSERT(context);
371 
372     if ((context->instruction->meta.branch_type != ZYDIS_BRANCH_TYPE_NONE) &&
373         (context->operand->type == ZYDIS_OPERAND_TYPE_MEMORY))
374     {
375         ZYDIS_BUFFER_APPEND(buffer, MUL);
376     }
377 
378     return ZydisFormatterBasePrintAddressABS(formatter, buffer, context);
379 }
380 
381 ZyanStatus ZydisFormatterATTPrintDISP(const ZydisFormatter* formatter,
382     ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
383 {
384     ZYAN_ASSERT(formatter);
385     ZYAN_ASSERT(buffer);
386     ZYAN_ASSERT(context);
387 
388     ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_DISPLACEMENT);
389     switch (formatter->disp_signedness)
390     {
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);
396         break;
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);
401         break;
402     default:
403         return ZYAN_STATUS_INVALID_ARGUMENT;
404     }
405 
406     return ZYAN_STATUS_SUCCESS;
407 }
408 
409 ZyanStatus ZydisFormatterATTPrintIMM(const ZydisFormatter* formatter,
410     ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
411 {
412     ZYAN_ASSERT(formatter);
413     ZYAN_ASSERT(buffer);
414     ZYAN_ASSERT(context);
415 
416     ZYDIS_BUFFER_APPEND(buffer, IMMEDIATE);
417     return ZydisFormatterBasePrintIMM(formatter, buffer, context);
418 }
419 
420 /* ---------------------------------------------------------------------------------------------- */
421 
422 /* ============================================================================================== */
423