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