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