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/Zycore/LibC.h"
28 #include "zydis/Zydis/Formatter.h"
29 #include "zydis/Zydis/Internal/FormatterATT.h"
30 #include "zydis/Zydis/Internal/FormatterIntel.h"
31 #include "zydis/Zydis/Internal/String.h"
32 
33 /* ============================================================================================== */
34 /* Constants                                                                                      */
35 /* ============================================================================================== */
36 
37 /* ---------------------------------------------------------------------------------------------- */
38 /* Formatter presets                                                                              */
39 /* ---------------------------------------------------------------------------------------------- */
40 
41 static const ZydisFormatter* const FORMATTER_PRESETS[ZYDIS_FORMATTER_STYLE_MAX_VALUE + 1] =
42 {
43     &FORMATTER_ATT,
44     &FORMATTER_INTEL,
45     &FORMATTER_INTEL_MASM
46 };
47 
48 /* ---------------------------------------------------------------------------------------------- */
49 
50 /* ============================================================================================== */
51 /* Internal functions                                                                             */
52 /* ============================================================================================== */
53 
54 /* ---------------------------------------------------------------------------------------------- */
55 /* Helper functions                                                                               */
56 /* ---------------------------------------------------------------------------------------------- */
57 
ZydisFormatterBufferInit(ZydisFormatterBuffer * buffer,char * user_buffer,ZyanUSize length)58 void ZydisFormatterBufferInit(ZydisFormatterBuffer* buffer, char* user_buffer,
59     ZyanUSize length)
60 {
61     ZYAN_ASSERT(buffer);
62     ZYAN_ASSERT(user_buffer);
63     ZYAN_ASSERT(length);
64 
65     buffer->is_token_list              = ZYAN_FALSE;
66     buffer->string.flags               = ZYAN_STRING_HAS_FIXED_CAPACITY;
67     buffer->string.vector.allocator    = ZYAN_NULL;
68     buffer->string.vector.element_size = sizeof(char);
69     buffer->string.vector.size         = 1;
70     buffer->string.vector.capacity     = length;
71     buffer->string.vector.data         = user_buffer;
72     *user_buffer = '\0';
73 }
74 
ZydisFormatterBufferInitTokenized(ZydisFormatterBuffer * buffer,ZydisFormatterToken ** first_token,void * user_buffer,ZyanUSize length)75 void ZydisFormatterBufferInitTokenized(ZydisFormatterBuffer* buffer,
76     ZydisFormatterToken** first_token, void* user_buffer, ZyanUSize length)
77 {
78     ZYAN_ASSERT(buffer);
79     ZYAN_ASSERT(first_token);
80     ZYAN_ASSERT(user_buffer);
81     ZYAN_ASSERT(length);
82 
83     *first_token = user_buffer;
84     (*first_token)->type = ZYDIS_TOKEN_INVALID;
85     (*first_token)->next = 0;
86 
87     user_buffer = (ZyanU8*)user_buffer + sizeof(ZydisFormatterToken);
88     length -= sizeof(ZydisFormatterToken);
89 
90     buffer->is_token_list              = ZYAN_TRUE;
91     buffer->capacity                   = length;
92     buffer->string.flags               = ZYAN_STRING_HAS_FIXED_CAPACITY;
93     buffer->string.vector.allocator    = ZYAN_NULL;
94     buffer->string.vector.element_size = sizeof(char);
95     buffer->string.vector.size         = 1;
96     buffer->string.vector.capacity     = length;
97     buffer->string.vector.data         = user_buffer;
98     *(char*)user_buffer = '\0';
99 }
100 
101 /* ---------------------------------------------------------------------------------------------- */
102 
103 /* ============================================================================================== */
104 /* Exported functions                                                                             */
105 /* ============================================================================================== */
106 
107 /* ---------------------------------------------------------------------------------------------- */
108 /* Initialization                                                                                 */
109 /* ---------------------------------------------------------------------------------------------- */
110 
ZydisFormatterInit(ZydisFormatter * formatter,ZydisFormatterStyle style)111 ZyanStatus ZydisFormatterInit(ZydisFormatter* formatter, ZydisFormatterStyle style)
112 {
113     if (!formatter || (style > ZYDIS_FORMATTER_STYLE_MAX_VALUE))
114     {
115         return ZYAN_STATUS_INVALID_ARGUMENT;
116     }
117 
118     ZYAN_MEMCPY(formatter, FORMATTER_PRESETS[style], sizeof(*formatter));
119 
120     return ZYAN_STATUS_SUCCESS;
121 }
122 
123 /* ---------------------------------------------------------------------------------------------- */
124 /* Setter                                                                                         */
125 /* ---------------------------------------------------------------------------------------------- */
126 
ZydisFormatterSetProperty(ZydisFormatter * formatter,ZydisFormatterProperty property,ZyanUPointer value)127 ZyanStatus ZydisFormatterSetProperty(ZydisFormatter* formatter, ZydisFormatterProperty property,
128     ZyanUPointer value)
129 {
130     if (!formatter)
131     {
132         return ZYAN_STATUS_INVALID_ARGUMENT;
133     }
134 
135     ZydisNumericBase base = (ZydisNumericBase)(-1);
136     ZyanU8 index = 0xFF;
137 
138     switch (property)
139     {
140     case ZYDIS_FORMATTER_PROP_FORCE_SIZE:
141     {
142         formatter->force_memory_size = (value) ? ZYAN_TRUE : ZYAN_FALSE;
143         break;
144     }
145     case ZYDIS_FORMATTER_PROP_FORCE_SEGMENT:
146     {
147         formatter->force_memory_segment = (value) ? ZYAN_TRUE : ZYAN_FALSE;
148         break;
149     }
150     case ZYDIS_FORMATTER_PROP_FORCE_RELATIVE_BRANCHES:
151     {
152         formatter->force_relative_branches = (value) ? ZYAN_TRUE : ZYAN_FALSE;
153         break;
154     }
155     case ZYDIS_FORMATTER_PROP_FORCE_RELATIVE_RIPREL:
156     {
157         formatter->force_relative_riprel = (value) ? ZYAN_TRUE : ZYAN_FALSE;
158         break;
159     }
160     case ZYDIS_FORMATTER_PROP_PRINT_BRANCH_SIZE:
161     {
162         formatter->print_branch_size = (value) ? ZYAN_TRUE : ZYAN_FALSE;
163         break;
164     }
165     case ZYDIS_FORMATTER_PROP_DETAILED_PREFIXES:
166     {
167         formatter->detailed_prefixes = (value) ? ZYAN_TRUE : ZYAN_FALSE;
168         break;
169     }
170     case ZYDIS_FORMATTER_PROP_ADDR_BASE:
171     {
172         if ((ZydisNumericBase)value > ZYDIS_NUMERIC_BASE_MAX_VALUE)
173         {
174             return ZYAN_STATUS_INVALID_ARGUMENT;
175         }
176         formatter->addr_base = (ZydisNumericBase)value;
177         break;
178     }
179     case ZYDIS_FORMATTER_PROP_ADDR_SIGNEDNESS:
180     {
181         if ((ZydisSignedness)value > ZYDIS_SIGNEDNESS_MAX_VALUE)
182         {
183             return ZYAN_STATUS_INVALID_ARGUMENT;
184         }
185         formatter->addr_signedness = (ZydisSignedness)value;
186         break;
187     }
188     case ZYDIS_FORMATTER_PROP_ADDR_PADDING_ABSOLUTE:
189     {
190         formatter->addr_padding_absolute = (ZydisPadding)value;
191         break;
192     }
193     case ZYDIS_FORMATTER_PROP_ADDR_PADDING_RELATIVE:
194     {
195         formatter->addr_padding_relative = (ZydisPadding)value;
196         break;
197     }
198     case ZYDIS_FORMATTER_PROP_DISP_BASE:
199     {
200         if ((ZydisNumericBase)value > ZYDIS_NUMERIC_BASE_MAX_VALUE)
201         {
202             return ZYAN_STATUS_INVALID_ARGUMENT;
203         }
204         formatter->disp_base = (ZydisNumericBase)value;
205         break;
206     }
207     case ZYDIS_FORMATTER_PROP_DISP_SIGNEDNESS:
208     {
209         if ((ZydisSignedness)value > ZYDIS_SIGNEDNESS_MAX_VALUE)
210         {
211             return ZYAN_STATUS_INVALID_ARGUMENT;
212         }
213         formatter->disp_signedness = (ZydisSignedness)value;
214         break;
215     }
216     case ZYDIS_FORMATTER_PROP_DISP_PADDING:
217     {
218         if ((ZydisPadding)value == ZYDIS_PADDING_AUTO)
219         {
220             if (formatter->style > ZYDIS_FORMATTER_STYLE_MAX_VALUE)
221             {
222                 return ZYAN_STATUS_INVALID_ARGUMENT;
223             }
224             formatter->disp_padding = FORMATTER_PRESETS[formatter->style]->disp_padding;
225         }
226         formatter->disp_padding = (ZydisPadding)value;
227         break;
228     }
229     case ZYDIS_FORMATTER_PROP_IMM_BASE:
230     {
231         if ((ZydisNumericBase)value > ZYDIS_NUMERIC_BASE_MAX_VALUE)
232         {
233             return ZYAN_STATUS_INVALID_ARGUMENT;
234         }
235         formatter->imm_base = (ZydisNumericBase)value;
236         break;
237     }
238     case ZYDIS_FORMATTER_PROP_IMM_SIGNEDNESS:
239     {
240         if ((ZydisSignedness)value  > ZYDIS_SIGNEDNESS_MAX_VALUE)
241         {
242             return ZYAN_STATUS_INVALID_ARGUMENT;
243         }
244         formatter->imm_signedness  = (ZydisSignedness)value;
245         break;
246     }
247     case ZYDIS_FORMATTER_PROP_IMM_PADDING:
248     {
249         if ((ZydisPadding)value == ZYDIS_PADDING_AUTO)
250         {
251             if (formatter->style > ZYDIS_FORMATTER_STYLE_MAX_VALUE)
252             {
253                 return ZYAN_STATUS_INVALID_ARGUMENT;
254             }
255             formatter->imm_padding = FORMATTER_PRESETS[formatter->style]->imm_padding;
256         }
257         formatter->imm_padding = (ZydisPadding)value;
258         break;
259     }
260     case ZYDIS_FORMATTER_PROP_UPPERCASE_PREFIXES:
261     {
262         formatter->case_prefixes = (value) ? ZYDIS_LETTER_CASE_UPPER : ZYDIS_LETTER_CASE_DEFAULT;
263         break;
264     }
265     case ZYDIS_FORMATTER_PROP_UPPERCASE_MNEMONIC:
266     {
267         formatter->case_mnemonic = (value) ? ZYDIS_LETTER_CASE_UPPER : ZYDIS_LETTER_CASE_DEFAULT;
268         break;
269     }
270     case ZYDIS_FORMATTER_PROP_UPPERCASE_REGISTERS:
271     {
272         formatter->case_registers = (value) ? ZYDIS_LETTER_CASE_UPPER : ZYDIS_LETTER_CASE_DEFAULT;
273         break;
274     }
275     case ZYDIS_FORMATTER_PROP_UPPERCASE_TYPECASTS:
276     {
277         formatter->case_typecasts = (value) ? ZYDIS_LETTER_CASE_UPPER : ZYDIS_LETTER_CASE_DEFAULT;
278         break;
279     }
280     case ZYDIS_FORMATTER_PROP_UPPERCASE_DECORATORS:
281     {
282         formatter->case_decorators = (value) ? ZYDIS_LETTER_CASE_UPPER : ZYDIS_LETTER_CASE_DEFAULT;
283         break;
284     }
285     case ZYDIS_FORMATTER_PROP_DEC_PREFIX:
286     {
287         base  = ZYDIS_NUMERIC_BASE_DEC;
288         index = 0;
289         break;
290     }
291     case ZYDIS_FORMATTER_PROP_DEC_SUFFIX:
292     {
293         base  = ZYDIS_NUMERIC_BASE_DEC;
294         index = 1;
295         break;
296     }
297     case ZYDIS_FORMATTER_PROP_HEX_UPPERCASE:
298     {
299         formatter->hex_uppercase = (value) ? ZYAN_TRUE : ZYAN_FALSE;
300         break;
301     }
302     case ZYDIS_FORMATTER_PROP_HEX_PREFIX:
303     {
304         base  = ZYDIS_NUMERIC_BASE_HEX;
305         index = 0;
306         break;
307     }
308     case ZYDIS_FORMATTER_PROP_HEX_SUFFIX:
309     {
310         base  = ZYDIS_NUMERIC_BASE_HEX;
311         index = 1;
312         break;
313     }
314     default:
315         return ZYAN_STATUS_INVALID_ARGUMENT;
316     }
317 
318     // Set prefix or suffix
319     if (base != (ZydisNumericBase)(-1))
320     {
321         if (value)
322         {
323             const ZyanUSize len = ZYAN_STRLEN((char*)value);
324             if (len > 10)
325             {
326                 return ZYAN_STATUS_INVALID_ARGUMENT;
327             }
328             ZYAN_MEMCPY(formatter->number_format[base][index].buffer, (void*)value, len);
329             formatter->number_format[base][index].buffer[len] = '\0';
330             formatter->number_format[base][index].string_data.string.vector.data =
331                 formatter->number_format[base][index].buffer;
332             formatter->number_format[base][index].string_data.string.vector.size = len + 1;
333             formatter->number_format[base][index].string =
334                 &formatter->number_format[base][index].string_data;
335         } else
336         {
337             formatter->number_format[base][index].string = ZYAN_NULL;
338         }
339     }
340 
341     return ZYAN_STATUS_SUCCESS;
342 }
343 
ZydisFormatterSetHook(ZydisFormatter * formatter,ZydisFormatterFunction type,const void ** callback)344 ZyanStatus ZydisFormatterSetHook(ZydisFormatter* formatter, ZydisFormatterFunction type,
345     const void** callback)
346 {
347     if (!formatter || !callback || (type > ZYDIS_FORMATTER_FUNC_MAX_VALUE))
348     {
349         return ZYAN_STATUS_INVALID_ARGUMENT;
350     }
351 
352     const void* const temp = *callback;
353 
354     // The following code relies on the order of the enum values and the function fields inside
355     // the `ZydisFormatter` struct
356 
357 #ifdef ZYAN_DEBUG
358     const ZyanUPointer* test = (ZyanUPointer*)(&formatter->func_pre_instruction + type);
359     switch (type)
360     {
361     case ZYDIS_FORMATTER_FUNC_PRE_INSTRUCTION:
362         ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_pre_instruction   ); break;
363     case ZYDIS_FORMATTER_FUNC_POST_INSTRUCTION:
364         ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_post_instruction  ); break;
365     case ZYDIS_FORMATTER_FUNC_FORMAT_INSTRUCTION:
366         ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_format_instruction); break;
367     case ZYDIS_FORMATTER_FUNC_PRE_OPERAND:
368         ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_pre_operand       ); break;
369     case ZYDIS_FORMATTER_FUNC_POST_OPERAND:
370         ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_post_operand      ); break;
371     case ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_REG:
372         ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_format_operand_reg); break;
373     case ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_MEM:
374         ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_format_operand_mem); break;
375     case ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_PTR:
376         ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_format_operand_ptr); break;
377     case ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_IMM:
378         ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_format_operand_imm); break;
379     case ZYDIS_FORMATTER_FUNC_PRINT_MNEMONIC:
380         ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_print_mnemonic    ); break;
381     case ZYDIS_FORMATTER_FUNC_PRINT_REGISTER:
382         ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_print_register    ); break;
383     case ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_ABS:
384         ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_print_address_abs ); break;
385     case ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_REL:
386         ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_print_address_rel ); break;
387     case ZYDIS_FORMATTER_FUNC_PRINT_DISP:
388         ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_print_disp        ); break;
389     case ZYDIS_FORMATTER_FUNC_PRINT_IMM:
390         ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_print_imm         ); break;
391     case ZYDIS_FORMATTER_FUNC_PRINT_TYPECAST:
392         ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_print_typecast    ); break;
393     case ZYDIS_FORMATTER_FUNC_PRINT_SEGMENT:
394         ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_print_segment     ); break;
395     case ZYDIS_FORMATTER_FUNC_PRINT_PREFIXES:
396         ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_print_prefixes    ); break;
397     case ZYDIS_FORMATTER_FUNC_PRINT_DECORATOR:
398         ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_print_decorator   ); break;
399     default:
400         ZYAN_UNREACHABLE;
401     }
402 #endif
403 
404     *callback = *(const void**)(&formatter->func_pre_instruction + type);
405     if (!temp)
406     {
407         return ZYAN_STATUS_SUCCESS;
408     }
409     ZYAN_MEMCPY(&formatter->func_pre_instruction + type, &temp, sizeof(ZyanUPointer));
410 
411     return ZYAN_STATUS_SUCCESS;
412 }
413 
414 /* ---------------------------------------------------------------------------------------------- */
415 /* Formatting                                                                                     */
416 /* ---------------------------------------------------------------------------------------------- */
417 
ZydisFormatterFormatInstruction(const ZydisFormatter * formatter,const ZydisDecodedInstruction * instruction,char * buffer,ZyanUSize length,ZyanU64 runtime_address)418 ZyanStatus ZydisFormatterFormatInstruction(const ZydisFormatter* formatter,
419     const ZydisDecodedInstruction* instruction, char* buffer, ZyanUSize length,
420     ZyanU64 runtime_address)
421 {
422      return ZydisFormatterFormatInstructionEx(formatter, instruction, buffer, length,
423          runtime_address, ZYAN_NULL);
424 }
425 
ZydisFormatterFormatInstructionEx(const ZydisFormatter * formatter,const ZydisDecodedInstruction * instruction,char * buffer,ZyanUSize length,ZyanU64 runtime_address,void * user_data)426 ZyanStatus ZydisFormatterFormatInstructionEx(const ZydisFormatter* formatter,
427     const ZydisDecodedInstruction* instruction, char* buffer, ZyanUSize length,
428     ZyanU64 runtime_address, void* user_data)
429 {
430     if (!formatter || !instruction || !buffer || (length == 0))
431     {
432         return ZYAN_STATUS_INVALID_ARGUMENT;
433     }
434 
435     ZydisFormatterBuffer formatter_buffer;
436     ZydisFormatterBufferInit(&formatter_buffer, buffer, length);
437 
438     ZydisFormatterContext context;
439     context.instruction     = instruction;
440     context.runtime_address = runtime_address;
441     context.operand         = ZYAN_NULL;
442     context.user_data       = user_data;
443 
444     if (formatter->func_pre_instruction)
445     {
446         ZYAN_CHECK(formatter->func_pre_instruction(formatter, &formatter_buffer, &context));
447     }
448 
449     ZYAN_CHECK(formatter->func_format_instruction(formatter, &formatter_buffer, &context));
450 
451     if (formatter->func_post_instruction)
452     {
453         ZYAN_CHECK(formatter->func_post_instruction(formatter, &formatter_buffer, &context));
454     }
455 
456     return ZYAN_STATUS_SUCCESS;
457 }
458 
ZydisFormatterFormatOperand(const ZydisFormatter * formatter,const ZydisDecodedInstruction * instruction,ZyanU8 index,char * buffer,ZyanUSize length,ZyanU64 runtime_address)459 ZyanStatus ZydisFormatterFormatOperand(const ZydisFormatter* formatter,
460     const ZydisDecodedInstruction* instruction, ZyanU8 index, char* buffer, ZyanUSize length,
461     ZyanU64 runtime_address)
462 {
463     return ZydisFormatterFormatOperandEx(formatter, instruction, index, buffer, length,
464         runtime_address, ZYAN_NULL);
465 }
466 
ZydisFormatterFormatOperandEx(const ZydisFormatter * formatter,const ZydisDecodedInstruction * instruction,ZyanU8 index,char * buffer,ZyanUSize length,ZyanU64 runtime_address,void * user_data)467 ZyanStatus ZydisFormatterFormatOperandEx(const ZydisFormatter* formatter,
468     const ZydisDecodedInstruction* instruction, ZyanU8 index, char* buffer, ZyanUSize length,
469     ZyanU64 runtime_address, void* user_data)
470 {
471     if (!formatter || !instruction || index >= instruction->operand_count || !buffer ||
472         (length == 0))
473     {
474         return ZYAN_STATUS_INVALID_ARGUMENT;
475     }
476 
477     ZydisFormatterBuffer formatter_buffer;
478     ZydisFormatterBufferInit(&formatter_buffer, buffer, length);
479 
480     ZydisFormatterContext context;
481     context.instruction     = instruction;
482     context.runtime_address = runtime_address;
483     context.operand         = &instruction->operands[index];
484     context.user_data       = user_data;
485 
486     // We ignore `ZYDIS_STATUS_SKIP_TOKEN` for all operand-functions as it does not make any sense
487     // to skip the only operand printed by this function
488 
489     if (formatter->func_pre_operand)
490     {
491         ZYAN_CHECK(formatter->func_pre_operand(formatter, &formatter_buffer, &context));
492     }
493 
494     switch (context.operand->type)
495     {
496     case ZYDIS_OPERAND_TYPE_REGISTER:
497         ZYAN_CHECK(formatter->func_format_operand_reg(formatter, &formatter_buffer, &context));
498         break;
499     case ZYDIS_OPERAND_TYPE_MEMORY:
500         ZYAN_CHECK(formatter->func_format_operand_mem(formatter, &formatter_buffer, &context));
501         break;
502     case ZYDIS_OPERAND_TYPE_IMMEDIATE:
503         ZYAN_CHECK(formatter->func_format_operand_imm(formatter, &formatter_buffer, &context));
504         break;
505     case ZYDIS_OPERAND_TYPE_POINTER:
506         ZYAN_CHECK(formatter->func_format_operand_ptr(formatter, &formatter_buffer, &context));
507         break;
508     default:
509         return ZYAN_STATUS_INVALID_ARGUMENT;
510     }
511 
512     if (formatter->func_post_operand)
513     {
514         ZYAN_CHECK(formatter->func_post_operand(formatter, &formatter_buffer, &context));
515     }
516 
517     return ZYAN_STATUS_SUCCESS;
518 }
519 
520 /* ---------------------------------------------------------------------------------------------- */
521 /* Tokenizing                                                                                     */
522 /* ---------------------------------------------------------------------------------------------- */
523 
ZydisFormatterTokenizeInstruction(const ZydisFormatter * formatter,const ZydisDecodedInstruction * instruction,void * buffer,ZyanUSize length,ZyanU64 runtime_address,ZydisFormatterTokenConst ** token)524 ZyanStatus ZydisFormatterTokenizeInstruction(const ZydisFormatter* formatter,
525     const ZydisDecodedInstruction* instruction, void* buffer, ZyanUSize length,
526     ZyanU64 runtime_address, ZydisFormatterTokenConst** token)
527 {
528     return ZydisFormatterTokenizeInstructionEx(formatter, instruction, buffer, length,
529         runtime_address, token, ZYAN_NULL);
530 }
531 
ZydisFormatterTokenizeInstructionEx(const ZydisFormatter * formatter,const ZydisDecodedInstruction * instruction,void * buffer,ZyanUSize length,ZyanU64 runtime_address,ZydisFormatterTokenConst ** token,void * user_data)532 ZyanStatus ZydisFormatterTokenizeInstructionEx(const ZydisFormatter* formatter,
533     const ZydisDecodedInstruction* instruction, void* buffer, ZyanUSize length,
534     ZyanU64 runtime_address, ZydisFormatterTokenConst** token, void* user_data)
535 {
536     if (!formatter || !instruction || !buffer || (length <= sizeof(ZydisFormatterToken)) || !token)
537     {
538         return ZYAN_STATUS_INVALID_ARGUMENT;
539     }
540 
541     ZydisFormatterBuffer formatter_buffer;
542     ZydisFormatterToken* first_token;
543     ZydisFormatterBufferInitTokenized(&formatter_buffer, &first_token, buffer, length);
544 
545     ZydisFormatterContext context;
546     context.instruction     = instruction;
547     context.runtime_address = runtime_address;
548     context.operand         = ZYAN_NULL;
549     context.user_data       = user_data;
550 
551     if (formatter->func_pre_instruction)
552     {
553         ZYAN_CHECK(formatter->func_pre_instruction(formatter, &formatter_buffer, &context));
554     }
555 
556     ZYAN_CHECK(formatter->func_format_instruction(formatter, &formatter_buffer, &context));
557 
558     if (formatter->func_post_instruction)
559     {
560         ZYAN_CHECK(formatter->func_post_instruction(formatter, &formatter_buffer, &context));
561     }
562 
563     if (first_token->next)
564     {
565         *token = (ZydisFormatterTokenConst*)((ZyanU8*)first_token + sizeof(ZydisFormatterToken) +
566             first_token->next);
567         return ZYAN_STATUS_SUCCESS;
568     }
569 
570     *token = first_token;
571     return ZYAN_STATUS_SUCCESS;
572 }
573 
ZydisFormatterTokenizeOperand(const ZydisFormatter * formatter,const ZydisDecodedInstruction * instruction,ZyanU8 index,void * buffer,ZyanUSize length,ZyanU64 runtime_address,ZydisFormatterTokenConst ** token)574 ZyanStatus ZydisFormatterTokenizeOperand(const ZydisFormatter* formatter,
575     const ZydisDecodedInstruction* instruction, ZyanU8 index, void* buffer, ZyanUSize length,
576     ZyanU64 runtime_address, ZydisFormatterTokenConst** token)
577 {
578     return ZydisFormatterTokenizeOperandEx(formatter, instruction, index, buffer, length,
579         runtime_address, token, ZYAN_NULL);
580 }
581 
ZydisFormatterTokenizeOperandEx(const ZydisFormatter * formatter,const ZydisDecodedInstruction * instruction,ZyanU8 index,void * buffer,ZyanUSize length,ZyanU64 runtime_address,ZydisFormatterTokenConst ** token,void * user_data)582 ZyanStatus ZydisFormatterTokenizeOperandEx(const ZydisFormatter* formatter,
583     const ZydisDecodedInstruction* instruction, ZyanU8 index, void* buffer, ZyanUSize length,
584     ZyanU64 runtime_address, ZydisFormatterTokenConst** token, void* user_data)
585 {
586     if (!formatter || !instruction || (index >= instruction->operand_count) || !buffer ||
587         (length <= sizeof(ZydisFormatterToken)) || !token)
588     {
589         return ZYAN_STATUS_INVALID_ARGUMENT;
590     }
591 
592     ZydisFormatterToken* first_token;
593     ZydisFormatterBuffer formatter_buffer;
594     ZydisFormatterBufferInitTokenized(&formatter_buffer, &first_token, buffer, length);
595 
596     ZydisFormatterContext context;
597     context.instruction     = instruction;
598     context.runtime_address = runtime_address;
599     context.operand         = &instruction->operands[index];
600     context.user_data       = user_data;
601 
602     // We ignore `ZYDIS_STATUS_SKIP_TOKEN` for all operand-functions as it does not make any sense
603     // to skip the only operand printed by this function
604 
605     if (formatter->func_pre_operand)
606     {
607         ZYAN_CHECK(formatter->func_pre_operand(formatter, &formatter_buffer, &context));
608     }
609 
610     switch (context.operand->type)
611     {
612     case ZYDIS_OPERAND_TYPE_REGISTER:
613         ZYAN_CHECK(formatter->func_format_operand_reg(formatter, &formatter_buffer, &context));
614         break;
615     case ZYDIS_OPERAND_TYPE_MEMORY:
616         ZYAN_CHECK(formatter->func_format_operand_mem(formatter, &formatter_buffer, &context));
617         break;
618     case ZYDIS_OPERAND_TYPE_IMMEDIATE:
619         ZYAN_CHECK(formatter->func_format_operand_imm(formatter, &formatter_buffer, &context));
620         break;
621     case ZYDIS_OPERAND_TYPE_POINTER:
622         ZYAN_CHECK(formatter->func_format_operand_ptr(formatter, &formatter_buffer, &context));
623         break;
624     default:
625         return ZYAN_STATUS_INVALID_ARGUMENT;
626     }
627 
628     if (formatter->func_post_operand)
629     {
630         ZYAN_CHECK(formatter->func_post_operand(formatter, &formatter_buffer, &context));
631     }
632 
633     if (first_token->next)
634     {
635         *token = (ZydisFormatterTokenConst*)((ZyanU8*)first_token + sizeof(ZydisFormatterToken) +
636             first_token->next);
637         return ZYAN_STATUS_SUCCESS;
638     }
639 
640     *token = first_token;
641     return ZYAN_STATUS_SUCCESS;
642 }
643 
644 /* ============================================================================================== */
645 
646 /* ============================================================================================== */
647