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
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 /* ============================================================================================== */
35 /* ============================================================================================== */
37 /* ---------------------------------------------------------------------------------------------- */
38 /* Formatter presets */
39 /* ---------------------------------------------------------------------------------------------- */
41 static const ZydisFormatter
* const FORMATTER_PRESETS
[ZYDIS_FORMATTER_STYLE_MAX_VALUE
+ 1] =
48 /* ---------------------------------------------------------------------------------------------- */
50 /* ============================================================================================== */
51 /* Internal functions */
52 /* ============================================================================================== */
54 /* ---------------------------------------------------------------------------------------------- */
55 /* Helper functions */
56 /* ---------------------------------------------------------------------------------------------- */
58 void ZydisFormatterBufferInit(ZydisFormatterBuffer
* buffer
, char* user_buffer
,
62 ZYAN_ASSERT(user_buffer
);
65 buffer
->is_token_list
= ZYAN_FALSE
;
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
;
80 void ZydisFormatterBufferInitTokenized(ZydisFormatterBuffer
* buffer
,
81 ZydisFormatterToken
** first_token
, void* user_buffer
, ZyanUSize length
)
84 ZYAN_ASSERT(first_token
);
85 ZYAN_ASSERT(user_buffer
);
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 /* ---------------------------------------------------------------------------------------------- */
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 /* ---------------------------------------------------------------------------------------------- */
134 /* ---------------------------------------------------------------------------------------------- */
136 ZyanStatus
ZydisFormatterSetProperty(ZydisFormatter
* formatter
, ZydisFormatterProperty property
,
141 return ZYAN_STATUS_INVALID_ARGUMENT
;
144 ZydisNumericBase base
= (ZydisNumericBase
)(-1);
149 case ZYDIS_FORMATTER_PROP_FORCE_SIZE
:
151 formatter
->force_memory_size
= (value
) ? ZYAN_TRUE
: ZYAN_FALSE
;
154 case ZYDIS_FORMATTER_PROP_FORCE_SEGMENT
:
156 formatter
->force_memory_segment
= (value
) ? ZYAN_TRUE
: ZYAN_FALSE
;
159 case ZYDIS_FORMATTER_PROP_FORCE_SCALE_ONE
:
161 formatter
->force_memory_scale
= (value
) ? ZYAN_TRUE
: ZYAN_FALSE
;
164 case ZYDIS_FORMATTER_PROP_FORCE_RELATIVE_BRANCHES
:
166 formatter
->force_relative_branches
= (value
) ? ZYAN_TRUE
: ZYAN_FALSE
;
169 case ZYDIS_FORMATTER_PROP_FORCE_RELATIVE_RIPREL
:
171 formatter
->force_relative_riprel
= (value
) ? ZYAN_TRUE
: ZYAN_FALSE
;
174 case ZYDIS_FORMATTER_PROP_PRINT_BRANCH_SIZE
:
176 formatter
->print_branch_size
= (value
) ? ZYAN_TRUE
: ZYAN_FALSE
;
179 case ZYDIS_FORMATTER_PROP_DETAILED_PREFIXES
:
181 formatter
->detailed_prefixes
= (value
) ? ZYAN_TRUE
: ZYAN_FALSE
;
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
;
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
;
202 case ZYDIS_FORMATTER_PROP_ADDR_PADDING_ABSOLUTE
:
204 if (((ZydisPadding
)value
!= ZYDIS_PADDING_AUTO
) &&
207 return ZYAN_STATUS_INVALID_ARGUMENT
;
209 formatter
->addr_padding_absolute
= (ZydisPadding
)value
;
212 case ZYDIS_FORMATTER_PROP_ADDR_PADDING_RELATIVE
:
214 if (((ZydisPadding
)value
!= ZYDIS_PADDING_AUTO
) &&
217 return ZYAN_STATUS_INVALID_ARGUMENT
;
219 formatter
->addr_padding_relative
= (ZydisPadding
)value
;
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
;
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
;
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
;
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
;
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
;
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
;
292 case ZYDIS_FORMATTER_PROP_UPPERCASE_PREFIXES
:
294 formatter
->case_prefixes
= (value
) ? ZYDIS_LETTER_CASE_UPPER
: ZYDIS_LETTER_CASE_DEFAULT
;
297 case ZYDIS_FORMATTER_PROP_UPPERCASE_MNEMONIC
:
299 formatter
->case_mnemonic
= (value
) ? ZYDIS_LETTER_CASE_UPPER
: ZYDIS_LETTER_CASE_DEFAULT
;
302 case ZYDIS_FORMATTER_PROP_UPPERCASE_REGISTERS
:
304 formatter
->case_registers
= (value
) ? ZYDIS_LETTER_CASE_UPPER
: ZYDIS_LETTER_CASE_DEFAULT
;
307 case ZYDIS_FORMATTER_PROP_UPPERCASE_TYPECASTS
:
309 formatter
->case_typecasts
= (value
) ? ZYDIS_LETTER_CASE_UPPER
: ZYDIS_LETTER_CASE_DEFAULT
;
312 case ZYDIS_FORMATTER_PROP_UPPERCASE_DECORATORS
:
314 formatter
->case_decorators
= (value
) ? ZYDIS_LETTER_CASE_UPPER
: ZYDIS_LETTER_CASE_DEFAULT
;
317 case ZYDIS_FORMATTER_PROP_DEC_PREFIX
:
319 base
= ZYDIS_NUMERIC_BASE_DEC
;
323 case ZYDIS_FORMATTER_PROP_DEC_SUFFIX
:
325 base
= ZYDIS_NUMERIC_BASE_DEC
;
329 case ZYDIS_FORMATTER_PROP_HEX_UPPERCASE
:
331 formatter
->hex_uppercase
= (value
) ? ZYAN_TRUE
: ZYAN_FALSE
;
334 case ZYDIS_FORMATTER_PROP_HEX_PREFIX
:
336 base
= ZYDIS_NUMERIC_BASE_HEX
;
340 case ZYDIS_FORMATTER_PROP_HEX_SUFFIX
:
342 base
= ZYDIS_NUMERIC_BASE_HEX
;
347 return ZYAN_STATUS_INVALID_ARGUMENT
;
350 // Set prefix or suffix
351 if (base
!= (ZydisNumericBase
)(-1))
355 const ZyanUSize len
= ZYAN_STRLEN((char*)value
);
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
;
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
390 const ZyanUPointer
* test
= (ZyanUPointer
*)(&formatter
->func_pre_instruction
+ 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;
436 *callback
= *(const void**)(&formatter
->func_pre_instruction
+ type
);
439 return ZYAN_STATUS_SUCCESS
;
441 ZYAN_MEMCPY(&formatter
->func_pre_instruction
+ type
, &temp
, sizeof(ZyanUPointer
));
443 return ZYAN_STATUS_SUCCESS
;
446 /* ---------------------------------------------------------------------------------------------- */
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
));
518 case ZYDIS_OPERAND_TYPE_MEMORY
:
519 ZYAN_CHECK(formatter
->func_format_operand_mem(formatter
, &formatter_buffer
, &context
));
521 case ZYDIS_OPERAND_TYPE_IMMEDIATE
:
522 ZYAN_CHECK(formatter
->func_format_operand_imm(formatter
, &formatter_buffer
, &context
));
524 case ZYDIS_OPERAND_TYPE_POINTER
:
525 ZYAN_CHECK(formatter
->func_format_operand_ptr(formatter
, &formatter_buffer
, &context
));
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 /* ---------------------------------------------------------------------------------------------- */
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
) +
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
,
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
));
625 case ZYDIS_OPERAND_TYPE_MEMORY
:
626 ZYAN_CHECK(formatter
->func_format_operand_mem(formatter
, &formatter_buffer
, &context
));
628 case ZYDIS_OPERAND_TYPE_IMMEDIATE
:
629 ZYAN_CHECK(formatter
->func_format_operand_imm(formatter
, &formatter_buffer
, &context
));
631 case ZYDIS_OPERAND_TYPE_POINTER
:
632 ZYAN_CHECK(formatter
->func_format_operand_ptr(formatter
, &formatter_buffer
, &context
));
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
) +
647 return ZYAN_STATUS_SUCCESS
;
650 *token
= first_token
;
651 return ZYAN_STATUS_SUCCESS
;
654 /* ============================================================================================== */
656 /* ============================================================================================== */