d3d8/tests: Test the presentation parameters after creating an additional swap chain.
[wine.git] / libs / zydis / src / Formatter.c
blobd9f15c790faab763724a9563339532e88f65c6cd
1 /***************************************************************************************************
3 Zyan Disassembler Library (Zydis)
5 Original Author : Florian Bernd, Joel Hoener
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:
14 * The above copyright notice and this permission notice shall be included in all
15 * copies or substantial portions of the Software.
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.
25 ***************************************************************************************************/
27 #include <Zycore/LibC.h>
28 #include <Zydis/Formatter.h>
29 #include <Zydis/Internal/FormatterATT.h>
30 #include <Zydis/Internal/FormatterIntel.h>
31 #include <Zydis/Internal/String.h>
33 /* ============================================================================================== */
34 /* Constants */
35 /* ============================================================================================== */
37 /* ---------------------------------------------------------------------------------------------- */
38 /* Formatter presets */
39 /* ---------------------------------------------------------------------------------------------- */
41 static const ZydisFormatter* const FORMATTER_PRESETS[ZYDIS_FORMATTER_STYLE_MAX_VALUE + 1] =
43 &FORMATTER_ATT,
44 &FORMATTER_INTEL,
45 &FORMATTER_INTEL_MASM
48 /* ---------------------------------------------------------------------------------------------- */
50 /* ============================================================================================== */
51 /* Internal functions */
52 /* ============================================================================================== */
54 /* ---------------------------------------------------------------------------------------------- */
55 /* Helper functions */
56 /* ---------------------------------------------------------------------------------------------- */
58 void ZydisFormatterBufferInit(ZydisFormatterBuffer* buffer, char* user_buffer,
59 ZyanUSize length)
61 ZYAN_ASSERT(buffer);
62 ZYAN_ASSERT(user_buffer);
63 ZYAN_ASSERT(length);
65 buffer->is_token_list = ZYAN_FALSE;
66 buffer->capacity = 0;
67 buffer->string.flags = ZYAN_STRING_HAS_FIXED_CAPACITY;
68 buffer->string.vector.allocator = ZYAN_NULL;
69 buffer->string.vector.growth_factor = 1;
70 buffer->string.vector.shrink_threshold = 0;
71 buffer->string.vector.destructor = ZYAN_NULL;
72 buffer->string.vector.element_size = sizeof(char);
73 buffer->string.vector.size = 1;
74 buffer->string.vector.capacity = length;
75 buffer->string.vector.data = user_buffer;
77 *user_buffer = '\0';
80 void ZydisFormatterBufferInitTokenized(ZydisFormatterBuffer* buffer,
81 ZydisFormatterToken** first_token, void* user_buffer, ZyanUSize length)
83 ZYAN_ASSERT(buffer);
84 ZYAN_ASSERT(first_token);
85 ZYAN_ASSERT(user_buffer);
86 ZYAN_ASSERT(length);
88 *first_token = user_buffer;
89 (*first_token)->type = ZYDIS_TOKEN_INVALID;
90 (*first_token)->next = 0;
92 user_buffer = (ZyanU8*)user_buffer + sizeof(ZydisFormatterToken);
93 length -= sizeof(ZydisFormatterToken);
95 buffer->is_token_list = ZYAN_TRUE;
96 buffer->capacity = length;
97 buffer->string.flags = ZYAN_STRING_HAS_FIXED_CAPACITY;
98 buffer->string.vector.allocator = ZYAN_NULL;
99 buffer->string.vector.growth_factor = 1;
100 buffer->string.vector.shrink_threshold = 0;
101 buffer->string.vector.destructor = ZYAN_NULL;
102 buffer->string.vector.element_size = sizeof(char);
103 buffer->string.vector.size = 1;
104 buffer->string.vector.capacity = length;
105 buffer->string.vector.data = user_buffer;
107 *(char*)user_buffer = '\0';
110 /* ---------------------------------------------------------------------------------------------- */
112 /* ============================================================================================== */
113 /* Exported functions */
114 /* ============================================================================================== */
116 /* ---------------------------------------------------------------------------------------------- */
117 /* Initialization */
118 /* ---------------------------------------------------------------------------------------------- */
120 ZyanStatus ZydisFormatterInit(ZydisFormatter* formatter, ZydisFormatterStyle style)
122 if (!formatter || ((ZyanUSize)style > ZYDIS_FORMATTER_STYLE_MAX_VALUE))
124 return ZYAN_STATUS_INVALID_ARGUMENT;
127 ZYAN_MEMCPY(formatter, FORMATTER_PRESETS[style], sizeof(*formatter));
129 return ZYAN_STATUS_SUCCESS;
132 /* ---------------------------------------------------------------------------------------------- */
133 /* Setter */
134 /* ---------------------------------------------------------------------------------------------- */
136 ZyanStatus ZydisFormatterSetProperty(ZydisFormatter* formatter, ZydisFormatterProperty property,
137 ZyanUPointer value)
139 if (!formatter)
141 return ZYAN_STATUS_INVALID_ARGUMENT;
144 ZydisNumericBase base = (ZydisNumericBase)(-1);
145 ZyanU8 index = 0xFF;
147 switch (property)
149 case ZYDIS_FORMATTER_PROP_FORCE_SIZE:
151 formatter->force_memory_size = (value) ? ZYAN_TRUE : ZYAN_FALSE;
152 break;
154 case ZYDIS_FORMATTER_PROP_FORCE_SEGMENT:
156 formatter->force_memory_segment = (value) ? ZYAN_TRUE : ZYAN_FALSE;
157 break;
159 case ZYDIS_FORMATTER_PROP_FORCE_SCALE_ONE:
161 formatter->force_memory_scale = (value) ? ZYAN_TRUE : ZYAN_FALSE;
162 break;
164 case ZYDIS_FORMATTER_PROP_FORCE_RELATIVE_BRANCHES:
166 formatter->force_relative_branches = (value) ? ZYAN_TRUE : ZYAN_FALSE;
167 break;
169 case ZYDIS_FORMATTER_PROP_FORCE_RELATIVE_RIPREL:
171 formatter->force_relative_riprel = (value) ? ZYAN_TRUE : ZYAN_FALSE;
172 break;
174 case ZYDIS_FORMATTER_PROP_PRINT_BRANCH_SIZE:
176 formatter->print_branch_size = (value) ? ZYAN_TRUE : ZYAN_FALSE;
177 break;
179 case ZYDIS_FORMATTER_PROP_DETAILED_PREFIXES:
181 formatter->detailed_prefixes = (value) ? ZYAN_TRUE : ZYAN_FALSE;
182 break;
184 case ZYDIS_FORMATTER_PROP_ADDR_BASE:
186 if (value > ZYDIS_NUMERIC_BASE_MAX_VALUE)
188 return ZYAN_STATUS_INVALID_ARGUMENT;
190 formatter->addr_base = (ZydisNumericBase)value;
191 break;
193 case ZYDIS_FORMATTER_PROP_ADDR_SIGNEDNESS:
195 if (value > ZYDIS_SIGNEDNESS_MAX_VALUE)
197 return ZYAN_STATUS_INVALID_ARGUMENT;
199 formatter->addr_signedness = (ZydisSignedness)value;
200 break;
202 case ZYDIS_FORMATTER_PROP_ADDR_PADDING_ABSOLUTE:
204 if (((ZydisPadding)value != ZYDIS_PADDING_AUTO) &&
205 (value > 0xFF))
207 return ZYAN_STATUS_INVALID_ARGUMENT;
209 formatter->addr_padding_absolute = (ZydisPadding)value;
210 break;
212 case ZYDIS_FORMATTER_PROP_ADDR_PADDING_RELATIVE:
214 if (((ZydisPadding)value != ZYDIS_PADDING_AUTO) &&
215 (value > 0xFF))
217 return ZYAN_STATUS_INVALID_ARGUMENT;
219 formatter->addr_padding_relative = (ZydisPadding)value;
220 break;
222 case ZYDIS_FORMATTER_PROP_DISP_BASE:
224 if (value > ZYDIS_NUMERIC_BASE_MAX_VALUE)
226 return ZYAN_STATUS_INVALID_ARGUMENT;
228 formatter->disp_base = (ZydisNumericBase)value;
229 break;
231 case ZYDIS_FORMATTER_PROP_DISP_SIGNEDNESS:
233 if (value > ZYDIS_SIGNEDNESS_MAX_VALUE)
235 return ZYAN_STATUS_INVALID_ARGUMENT;
237 formatter->disp_signedness = (ZydisSignedness)value;
238 break;
240 case ZYDIS_FORMATTER_PROP_DISP_PADDING:
242 if ((ZydisPadding)value == ZYDIS_PADDING_AUTO)
244 if ((ZyanUSize)formatter->style > ZYDIS_FORMATTER_STYLE_MAX_VALUE)
246 return ZYAN_STATUS_INVALID_ARGUMENT;
248 formatter->disp_padding = FORMATTER_PRESETS[formatter->style]->disp_padding;
250 else if (value > 0xFF)
252 return ZYAN_STATUS_INVALID_ARGUMENT;
254 formatter->disp_padding = (ZydisPadding)value;
255 break;
257 case ZYDIS_FORMATTER_PROP_IMM_BASE:
259 if (value > ZYDIS_NUMERIC_BASE_MAX_VALUE)
261 return ZYAN_STATUS_INVALID_ARGUMENT;
263 formatter->imm_base = (ZydisNumericBase)value;
264 break;
266 case ZYDIS_FORMATTER_PROP_IMM_SIGNEDNESS:
268 if (value > ZYDIS_SIGNEDNESS_MAX_VALUE)
270 return ZYAN_STATUS_INVALID_ARGUMENT;
272 formatter->imm_signedness = (ZydisSignedness)value;
273 break;
275 case ZYDIS_FORMATTER_PROP_IMM_PADDING:
277 if ((ZydisPadding)value == ZYDIS_PADDING_AUTO)
279 if ((ZyanUSize)formatter->style > ZYDIS_FORMATTER_STYLE_MAX_VALUE)
281 return ZYAN_STATUS_INVALID_ARGUMENT;
283 formatter->imm_padding = FORMATTER_PRESETS[formatter->style]->imm_padding;
285 else if (value > 0xFF)
287 return ZYAN_STATUS_INVALID_ARGUMENT;
289 formatter->imm_padding = (ZydisPadding)value;
290 break;
292 case ZYDIS_FORMATTER_PROP_UPPERCASE_PREFIXES:
294 formatter->case_prefixes = (value) ? ZYDIS_LETTER_CASE_UPPER : ZYDIS_LETTER_CASE_DEFAULT;
295 break;
297 case ZYDIS_FORMATTER_PROP_UPPERCASE_MNEMONIC:
299 formatter->case_mnemonic = (value) ? ZYDIS_LETTER_CASE_UPPER : ZYDIS_LETTER_CASE_DEFAULT;
300 break;
302 case ZYDIS_FORMATTER_PROP_UPPERCASE_REGISTERS:
304 formatter->case_registers = (value) ? ZYDIS_LETTER_CASE_UPPER : ZYDIS_LETTER_CASE_DEFAULT;
305 break;
307 case ZYDIS_FORMATTER_PROP_UPPERCASE_TYPECASTS:
309 formatter->case_typecasts = (value) ? ZYDIS_LETTER_CASE_UPPER : ZYDIS_LETTER_CASE_DEFAULT;
310 break;
312 case ZYDIS_FORMATTER_PROP_UPPERCASE_DECORATORS:
314 formatter->case_decorators = (value) ? ZYDIS_LETTER_CASE_UPPER : ZYDIS_LETTER_CASE_DEFAULT;
315 break;
317 case ZYDIS_FORMATTER_PROP_DEC_PREFIX:
319 base = ZYDIS_NUMERIC_BASE_DEC;
320 index = 0;
321 break;
323 case ZYDIS_FORMATTER_PROP_DEC_SUFFIX:
325 base = ZYDIS_NUMERIC_BASE_DEC;
326 index = 1;
327 break;
329 case ZYDIS_FORMATTER_PROP_HEX_UPPERCASE:
331 formatter->hex_uppercase = (value) ? ZYAN_TRUE : ZYAN_FALSE;
332 break;
334 case ZYDIS_FORMATTER_PROP_HEX_PREFIX:
336 base = ZYDIS_NUMERIC_BASE_HEX;
337 index = 0;
338 break;
340 case ZYDIS_FORMATTER_PROP_HEX_SUFFIX:
342 base = ZYDIS_NUMERIC_BASE_HEX;
343 index = 1;
344 break;
346 default:
347 return ZYAN_STATUS_INVALID_ARGUMENT;
350 // Set prefix or suffix
351 if (base != (ZydisNumericBase)(-1))
353 if (value)
355 const ZyanUSize len = ZYAN_STRLEN((char*)value);
356 if (len > 10)
358 return ZYAN_STATUS_INVALID_ARGUMENT;
360 ZYAN_MEMCPY(formatter->number_format[base][index].buffer, (void*)value, len);
361 formatter->number_format[base][index].buffer[len] = '\0';
362 formatter->number_format[base][index].string_data.string.vector.data =
363 formatter->number_format[base][index].buffer;
364 formatter->number_format[base][index].string_data.string.vector.size = len + 1;
365 formatter->number_format[base][index].string =
366 &formatter->number_format[base][index].string_data;
367 } else
369 formatter->number_format[base][index].string = ZYAN_NULL;
373 return ZYAN_STATUS_SUCCESS;
376 ZyanStatus ZydisFormatterSetHook(ZydisFormatter* formatter, ZydisFormatterFunction type,
377 const void** callback)
379 if (!formatter || !callback || ((ZyanUSize)type > ZYDIS_FORMATTER_FUNC_MAX_VALUE))
381 return ZYAN_STATUS_INVALID_ARGUMENT;
384 const void* const temp = *callback;
386 // The following code relies on the order of the enum values and the function fields inside
387 // the `ZydisFormatter` struct
389 #ifdef ZYAN_DEBUG
390 const ZyanUPointer* test = (ZyanUPointer*)(&formatter->func_pre_instruction + type);
391 switch (type)
393 case ZYDIS_FORMATTER_FUNC_PRE_INSTRUCTION:
394 ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_pre_instruction ); break;
395 case ZYDIS_FORMATTER_FUNC_POST_INSTRUCTION:
396 ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_post_instruction ); break;
397 case ZYDIS_FORMATTER_FUNC_FORMAT_INSTRUCTION:
398 ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_format_instruction); break;
399 case ZYDIS_FORMATTER_FUNC_PRE_OPERAND:
400 ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_pre_operand ); break;
401 case ZYDIS_FORMATTER_FUNC_POST_OPERAND:
402 ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_post_operand ); break;
403 case ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_REG:
404 ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_format_operand_reg); break;
405 case ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_MEM:
406 ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_format_operand_mem); break;
407 case ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_PTR:
408 ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_format_operand_ptr); break;
409 case ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_IMM:
410 ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_format_operand_imm); break;
411 case ZYDIS_FORMATTER_FUNC_PRINT_MNEMONIC:
412 ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_print_mnemonic ); break;
413 case ZYDIS_FORMATTER_FUNC_PRINT_REGISTER:
414 ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_print_register ); break;
415 case ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_ABS:
416 ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_print_address_abs ); break;
417 case ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_REL:
418 ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_print_address_rel ); break;
419 case ZYDIS_FORMATTER_FUNC_PRINT_DISP:
420 ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_print_disp ); break;
421 case ZYDIS_FORMATTER_FUNC_PRINT_IMM:
422 ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_print_imm ); break;
423 case ZYDIS_FORMATTER_FUNC_PRINT_TYPECAST:
424 ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_print_typecast ); break;
425 case ZYDIS_FORMATTER_FUNC_PRINT_SEGMENT:
426 ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_print_segment ); break;
427 case ZYDIS_FORMATTER_FUNC_PRINT_PREFIXES:
428 ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_print_prefixes ); break;
429 case ZYDIS_FORMATTER_FUNC_PRINT_DECORATOR:
430 ZYAN_ASSERT(test == (ZyanUPointer*)&formatter->func_print_decorator ); break;
431 default:
432 ZYAN_UNREACHABLE;
434 #endif
436 *callback = *(const void**)(&formatter->func_pre_instruction + type);
437 if (!temp)
439 return ZYAN_STATUS_SUCCESS;
441 ZYAN_MEMCPY(&formatter->func_pre_instruction + type, &temp, sizeof(ZyanUPointer));
443 return ZYAN_STATUS_SUCCESS;
446 /* ---------------------------------------------------------------------------------------------- */
447 /* Formatting */
448 /* ---------------------------------------------------------------------------------------------- */
450 ZyanStatus ZydisFormatterFormatInstruction(const ZydisFormatter* formatter,
451 const ZydisDecodedInstruction* instruction, const ZydisDecodedOperand* operands,
452 ZyanU8 operand_count, char* buffer, ZyanUSize length, ZyanU64 runtime_address, void* user_data)
454 if (!formatter || !instruction || (operand_count && !operands) ||
455 (operand_count > ZYDIS_MAX_OPERAND_COUNT) ||
456 (operand_count < instruction->operand_count_visible) || !buffer || (length == 0))
458 return ZYAN_STATUS_INVALID_ARGUMENT;
461 ZydisFormatterBuffer formatter_buffer;
462 ZydisFormatterBufferInit(&formatter_buffer, buffer, length);
464 ZydisFormatterContext context;
465 context.instruction = instruction;
466 context.operands = operands;
467 context.runtime_address = runtime_address;
468 context.operand = ZYAN_NULL;
469 context.user_data = user_data;
471 if (formatter->func_pre_instruction)
473 ZYAN_CHECK(formatter->func_pre_instruction(formatter, &formatter_buffer, &context));
476 ZYAN_CHECK(formatter->func_format_instruction(formatter, &formatter_buffer, &context));
478 if (formatter->func_post_instruction)
480 ZYAN_CHECK(formatter->func_post_instruction(formatter, &formatter_buffer, &context));
483 return ZYAN_STATUS_SUCCESS;
486 ZyanStatus ZydisFormatterFormatOperand(const ZydisFormatter* formatter,
487 const ZydisDecodedInstruction* instruction, const ZydisDecodedOperand* operand,
488 char* buffer, ZyanUSize length, ZyanU64 runtime_address, void* user_data)
490 if (!formatter || !instruction || !operand || !buffer || (length == 0))
492 return ZYAN_STATUS_INVALID_ARGUMENT;
495 ZydisFormatterBuffer formatter_buffer;
496 ZydisFormatterBufferInit(&formatter_buffer, buffer, length);
498 ZydisFormatterContext context;
499 context.instruction = instruction;
500 context.operands = ZYAN_NULL;
501 context.runtime_address = runtime_address;
502 context.operand = operand;
503 context.user_data = user_data;
505 // We ignore `ZYDIS_STATUS_SKIP_TOKEN` for all operand-functions as it does not make any sense
506 // to skip the only operand printed by this function
508 if (formatter->func_pre_operand)
510 ZYAN_CHECK(formatter->func_pre_operand(formatter, &formatter_buffer, &context));
513 switch (context.operand->type)
515 case ZYDIS_OPERAND_TYPE_REGISTER:
516 ZYAN_CHECK(formatter->func_format_operand_reg(formatter, &formatter_buffer, &context));
517 break;
518 case ZYDIS_OPERAND_TYPE_MEMORY:
519 ZYAN_CHECK(formatter->func_format_operand_mem(formatter, &formatter_buffer, &context));
520 break;
521 case ZYDIS_OPERAND_TYPE_IMMEDIATE:
522 ZYAN_CHECK(formatter->func_format_operand_imm(formatter, &formatter_buffer, &context));
523 break;
524 case ZYDIS_OPERAND_TYPE_POINTER:
525 ZYAN_CHECK(formatter->func_format_operand_ptr(formatter, &formatter_buffer, &context));
526 break;
527 default:
528 return ZYAN_STATUS_INVALID_ARGUMENT;
531 if (formatter->func_post_operand)
533 ZYAN_CHECK(formatter->func_post_operand(formatter, &formatter_buffer, &context));
536 return ZYAN_STATUS_SUCCESS;
539 /* ---------------------------------------------------------------------------------------------- */
540 /* Tokenizing */
541 /* ---------------------------------------------------------------------------------------------- */
543 ZyanStatus ZydisFormatterTokenizeInstruction(const ZydisFormatter* formatter,
544 const ZydisDecodedInstruction* instruction, const ZydisDecodedOperand* operands,
545 ZyanU8 operand_count, void* buffer, ZyanUSize length, ZyanU64 runtime_address,
546 ZydisFormatterTokenConst** token, void* user_data)
548 if (!formatter || !instruction || (operand_count && !operands) ||
549 (operand_count > ZYDIS_MAX_OPERAND_COUNT) ||
550 (operand_count < instruction->operand_count_visible) || !buffer ||
551 (length <= sizeof(ZydisFormatterToken)) || !token)
553 return ZYAN_STATUS_INVALID_ARGUMENT;
556 ZydisFormatterBuffer formatter_buffer;
557 ZydisFormatterToken* first_token;
558 ZydisFormatterBufferInitTokenized(&formatter_buffer, &first_token, buffer, length);
560 ZydisFormatterContext context;
561 context.instruction = instruction;
562 context.operands = operands;
563 context.runtime_address = runtime_address;
564 context.operand = ZYAN_NULL;
565 context.user_data = user_data;
567 if (formatter->func_pre_instruction)
569 ZYAN_CHECK(formatter->func_pre_instruction(formatter, &formatter_buffer, &context));
572 ZYAN_CHECK(formatter->func_format_instruction(formatter, &formatter_buffer, &context));
574 if (formatter->func_post_instruction)
576 ZYAN_CHECK(formatter->func_post_instruction(formatter, &formatter_buffer, &context));
579 if (first_token->next)
581 *token = (ZydisFormatterTokenConst*)((ZyanU8*)first_token + sizeof(ZydisFormatterToken) +
582 first_token->next);
583 return ZYAN_STATUS_SUCCESS;
586 *token = first_token;
587 return ZYAN_STATUS_SUCCESS;
590 ZyanStatus ZydisFormatterTokenizeOperand(const ZydisFormatter* formatter,
591 const ZydisDecodedInstruction* instruction, const ZydisDecodedOperand* operand,
592 void* buffer, ZyanUSize length, ZyanU64 runtime_address, ZydisFormatterTokenConst** token,
593 void* user_data)
595 if (!formatter || !instruction || !operand || !buffer ||
596 (length <= sizeof(ZydisFormatterToken)) || !token)
598 return ZYAN_STATUS_INVALID_ARGUMENT;
601 ZydisFormatterToken* first_token;
602 ZydisFormatterBuffer formatter_buffer;
603 ZydisFormatterBufferInitTokenized(&formatter_buffer, &first_token, buffer, length);
605 ZydisFormatterContext context;
606 context.instruction = instruction;
607 context.operands = ZYAN_NULL;
608 context.runtime_address = runtime_address;
609 context.operand = operand;
610 context.user_data = user_data;
612 // We ignore `ZYDIS_STATUS_SKIP_TOKEN` for all operand-functions as it does not make any sense
613 // to skip the only operand printed by this function
615 if (formatter->func_pre_operand)
617 ZYAN_CHECK(formatter->func_pre_operand(formatter, &formatter_buffer, &context));
620 switch (context.operand->type)
622 case ZYDIS_OPERAND_TYPE_REGISTER:
623 ZYAN_CHECK(formatter->func_format_operand_reg(formatter, &formatter_buffer, &context));
624 break;
625 case ZYDIS_OPERAND_TYPE_MEMORY:
626 ZYAN_CHECK(formatter->func_format_operand_mem(formatter, &formatter_buffer, &context));
627 break;
628 case ZYDIS_OPERAND_TYPE_IMMEDIATE:
629 ZYAN_CHECK(formatter->func_format_operand_imm(formatter, &formatter_buffer, &context));
630 break;
631 case ZYDIS_OPERAND_TYPE_POINTER:
632 ZYAN_CHECK(formatter->func_format_operand_ptr(formatter, &formatter_buffer, &context));
633 break;
634 default:
635 return ZYAN_STATUS_INVALID_ARGUMENT;
638 if (formatter->func_post_operand)
640 ZYAN_CHECK(formatter->func_post_operand(formatter, &formatter_buffer, &context));
643 if (first_token->next)
645 *token = (ZydisFormatterTokenConst*)((ZyanU8*)first_token + sizeof(ZydisFormatterToken) +
646 first_token->next);
647 return ZYAN_STATUS_SUCCESS;
650 *token = first_token;
651 return ZYAN_STATUS_SUCCESS;
654 /* ============================================================================================== */
656 /* ============================================================================================== */