Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
stenzek
GitHub Repository: stenzek/duckstation
Path: blob/master/dep/zydis/src/Formatter.c
4212 views
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
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->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
80
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
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
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_PREFIX:
335
{
336
base = ZYDIS_NUMERIC_BASE_HEX;
337
index = 0;
338
break;
339
}
340
case ZYDIS_FORMATTER_PROP_HEX_SUFFIX:
341
{
342
base = ZYDIS_NUMERIC_BASE_HEX;
343
index = 1;
344
break;
345
}
346
default:
347
return ZYAN_STATUS_INVALID_ARGUMENT;
348
}
349
350
// Set prefix or suffix
351
if (base != (ZydisNumericBase)(-1))
352
{
353
if (value)
354
{
355
const ZyanUSize len = ZYAN_STRLEN((char*)value);
356
if (len > 10)
357
{
358
return ZYAN_STATUS_INVALID_ARGUMENT;
359
}
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
368
{
369
formatter->number_format[base][index].string = ZYAN_NULL;
370
}
371
}
372
373
return ZYAN_STATUS_SUCCESS;
374
}
375
376
ZyanStatus ZydisFormatterSetHook(ZydisFormatter* formatter, ZydisFormatterFunction type,
377
const void** callback)
378
{
379
if (!formatter || !callback || ((ZyanUSize)type > ZYDIS_FORMATTER_FUNC_MAX_VALUE))
380
{
381
return ZYAN_STATUS_INVALID_ARGUMENT;
382
}
383
384
const void* const temp = *callback;
385
386
// The following code relies on the order of the enum values and the function fields inside
387
// the `ZydisFormatter` struct
388
389
#ifdef ZYAN_DEBUG
390
const ZyanUPointer* test = (ZyanUPointer*)(&formatter->func_pre_instruction + type);
391
switch (type)
392
{
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;
433
}
434
#endif
435
436
*callback = *(const void**)(&formatter->func_pre_instruction + type);
437
if (!temp)
438
{
439
return ZYAN_STATUS_SUCCESS;
440
}
441
ZYAN_MEMCPY(&formatter->func_pre_instruction + type, &temp, sizeof(ZyanUPointer));
442
443
return ZYAN_STATUS_SUCCESS;
444
}
445
446
/* ---------------------------------------------------------------------------------------------- */
447
/* Formatting */
448
/* ---------------------------------------------------------------------------------------------- */
449
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)
453
{
454
if (!formatter || !instruction || (operand_count && !operands) ||
455
(operand_count > ZYDIS_MAX_OPERAND_COUNT) ||
456
(operand_count < instruction->operand_count_visible) || !buffer || (length == 0))
457
{
458
return ZYAN_STATUS_INVALID_ARGUMENT;
459
}
460
461
ZydisFormatterBuffer formatter_buffer;
462
ZydisFormatterBufferInit(&formatter_buffer, buffer, length);
463
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;
470
471
if (formatter->func_pre_instruction)
472
{
473
ZYAN_CHECK(formatter->func_pre_instruction(formatter, &formatter_buffer, &context));
474
}
475
476
ZYAN_CHECK(formatter->func_format_instruction(formatter, &formatter_buffer, &context));
477
478
if (formatter->func_post_instruction)
479
{
480
ZYAN_CHECK(formatter->func_post_instruction(formatter, &formatter_buffer, &context));
481
}
482
483
return ZYAN_STATUS_SUCCESS;
484
}
485
486
ZyanStatus ZydisFormatterFormatOperand(const ZydisFormatter* formatter,
487
const ZydisDecodedInstruction* instruction, const ZydisDecodedOperand* operand,
488
char* buffer, ZyanUSize length, ZyanU64 runtime_address, void* user_data)
489
{
490
if (!formatter || !instruction || !operand || !buffer || (length == 0))
491
{
492
return ZYAN_STATUS_INVALID_ARGUMENT;
493
}
494
495
ZydisFormatterBuffer formatter_buffer;
496
ZydisFormatterBufferInit(&formatter_buffer, buffer, length);
497
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;
504
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
507
508
if (formatter->func_pre_operand)
509
{
510
ZYAN_CHECK(formatter->func_pre_operand(formatter, &formatter_buffer, &context));
511
}
512
513
switch (context.operand->type)
514
{
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;
529
}
530
531
if (formatter->func_post_operand)
532
{
533
ZYAN_CHECK(formatter->func_post_operand(formatter, &formatter_buffer, &context));
534
}
535
536
return ZYAN_STATUS_SUCCESS;
537
}
538
539
/* ---------------------------------------------------------------------------------------------- */
540
/* Tokenizing */
541
/* ---------------------------------------------------------------------------------------------- */
542
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)
547
{
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)
552
{
553
return ZYAN_STATUS_INVALID_ARGUMENT;
554
}
555
556
ZydisFormatterBuffer formatter_buffer;
557
ZydisFormatterToken* first_token;
558
ZydisFormatterBufferInitTokenized(&formatter_buffer, &first_token, buffer, length);
559
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;
566
567
if (formatter->func_pre_instruction)
568
{
569
ZYAN_CHECK(formatter->func_pre_instruction(formatter, &formatter_buffer, &context));
570
}
571
572
ZYAN_CHECK(formatter->func_format_instruction(formatter, &formatter_buffer, &context));
573
574
if (formatter->func_post_instruction)
575
{
576
ZYAN_CHECK(formatter->func_post_instruction(formatter, &formatter_buffer, &context));
577
}
578
579
if (first_token->next)
580
{
581
*token = (ZydisFormatterTokenConst*)((ZyanU8*)first_token + sizeof(ZydisFormatterToken) +
582
first_token->next);
583
return ZYAN_STATUS_SUCCESS;
584
}
585
586
*token = first_token;
587
return ZYAN_STATUS_SUCCESS;
588
}
589
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)
594
{
595
if (!formatter || !instruction || !operand || !buffer ||
596
(length <= sizeof(ZydisFormatterToken)) || !token)
597
{
598
return ZYAN_STATUS_INVALID_ARGUMENT;
599
}
600
601
ZydisFormatterToken* first_token;
602
ZydisFormatterBuffer formatter_buffer;
603
ZydisFormatterBufferInitTokenized(&formatter_buffer, &first_token, buffer, length);
604
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;
611
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
614
615
if (formatter->func_pre_operand)
616
{
617
ZYAN_CHECK(formatter->func_pre_operand(formatter, &formatter_buffer, &context));
618
}
619
620
switch (context.operand->type)
621
{
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;
636
}
637
638
if (formatter->func_post_operand)
639
{
640
ZYAN_CHECK(formatter->func_post_operand(formatter, &formatter_buffer, &context));
641
}
642
643
if (first_token->next)
644
{
645
*token = (ZydisFormatterTokenConst*)((ZyanU8*)first_token + sizeof(ZydisFormatterToken) +
646
first_token->next);
647
return ZYAN_STATUS_SUCCESS;
648
}
649
650
*token = first_token;
651
return ZYAN_STATUS_SUCCESS;
652
}
653
654
/* ============================================================================================== */
655
656
/* ============================================================================================== */
657
658