Coverage Report

Created: 2025-07-11 06:19

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