Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
stenzek
GitHub Repository: stenzek/duckstation
Path: blob/master/dep/zydis/src/FormatterATT.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 <Zydis/Internal/FormatterATT.h>
28
29
/* ============================================================================================== */
30
/* Constants */
31
/* ============================================================================================== */
32
33
#include <Generated/FormatterStrings.inc>
34
35
/* ============================================================================================== */
36
/* Formatter functions */
37
/* ============================================================================================== */
38
39
/* ---------------------------------------------------------------------------------------------- */
40
/* Instruction */
41
/* ---------------------------------------------------------------------------------------------- */
42
43
ZyanStatus ZydisFormatterATTFormatInstruction(const ZydisFormatter* formatter,
44
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
45
{
46
ZYAN_ASSERT(formatter);
47
ZYAN_ASSERT(buffer);
48
ZYAN_ASSERT(context);
49
ZYAN_ASSERT(context->instruction);
50
ZYAN_ASSERT(context->operands);
51
52
ZYAN_CHECK(formatter->func_print_prefixes(formatter, buffer, context));
53
ZYAN_CHECK(formatter->func_print_mnemonic(formatter, buffer, context));
54
55
ZyanUPointer state_mnemonic;
56
ZYDIS_BUFFER_REMEMBER(buffer, state_mnemonic);
57
58
const ZyanI8 c = (ZyanI8)context->instruction->operand_count_visible - 1;
59
for (ZyanI8 i = c; i >= 0; --i)
60
{
61
const ZydisDecodedOperand* const operand = &context->operands[i];
62
63
// Print embedded-mask registers as decorator instead of a regular operand
64
if ((i == 1) && (operand->type == ZYDIS_OPERAND_TYPE_REGISTER) &&
65
(operand->encoding == ZYDIS_OPERAND_ENCODING_MASK))
66
{
67
continue;
68
}
69
70
ZyanUPointer buffer_state;
71
ZYDIS_BUFFER_REMEMBER(buffer, buffer_state);
72
73
if (buffer_state != state_mnemonic)
74
{
75
ZYDIS_BUFFER_APPEND(buffer, DELIM_OPERAND);
76
} else
77
{
78
ZYDIS_BUFFER_APPEND(buffer, DELIM_MNEMONIC);
79
}
80
81
// Set current operand
82
context->operand = operand;
83
84
ZyanStatus status;
85
if (formatter->func_pre_operand)
86
{
87
status = formatter->func_pre_operand(formatter, buffer, context);
88
if (status == ZYDIS_STATUS_SKIP_TOKEN)
89
{
90
ZYAN_CHECK(ZydisFormatterBufferRestore(buffer, buffer_state));
91
continue;
92
}
93
if (!ZYAN_SUCCESS(status))
94
{
95
return status;
96
}
97
}
98
99
switch (operand->type)
100
{
101
case ZYDIS_OPERAND_TYPE_REGISTER:
102
status = formatter->func_format_operand_reg(formatter, buffer, context);
103
break;
104
case ZYDIS_OPERAND_TYPE_MEMORY:
105
status = formatter->func_format_operand_mem(formatter, buffer, context);
106
break;
107
case ZYDIS_OPERAND_TYPE_POINTER:
108
status = formatter->func_format_operand_ptr(formatter, buffer, context);
109
break;
110
case ZYDIS_OPERAND_TYPE_IMMEDIATE:
111
status = formatter->func_format_operand_imm(formatter, buffer, context);
112
break;
113
default:
114
return ZYAN_STATUS_INVALID_ARGUMENT;
115
}
116
if (status == ZYDIS_STATUS_SKIP_TOKEN)
117
{
118
ZYAN_CHECK(ZydisFormatterBufferRestore(buffer, buffer_state));
119
continue;
120
}
121
if (!ZYAN_SUCCESS(status))
122
{
123
return status;
124
}
125
126
if (formatter->func_post_operand)
127
{
128
status = formatter->func_post_operand(formatter, buffer, context);
129
if (status == ZYDIS_STATUS_SKIP_TOKEN)
130
{
131
ZYAN_CHECK(ZydisFormatterBufferRestore(buffer, buffer_state));
132
continue;
133
}
134
if (ZYAN_SUCCESS(status))
135
{
136
return status;
137
}
138
}
139
140
#if !defined(ZYDIS_DISABLE_AVX512) || !defined(ZYDIS_DISABLE_KNC)
141
if ((context->instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_EVEX) ||
142
(context->instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_MVEX))
143
{
144
if ((i == 0) &&
145
(context->instruction->operand_count_visible > 1) &&
146
(context->operands[1].encoding == ZYDIS_OPERAND_ENCODING_MASK))
147
{
148
ZYAN_CHECK(formatter->func_print_decorator(formatter, buffer, context,
149
ZYDIS_DECORATOR_MASK));
150
}
151
if (operand->type == ZYDIS_OPERAND_TYPE_MEMORY)
152
{
153
ZYAN_CHECK(formatter->func_print_decorator(formatter, buffer, context,
154
ZYDIS_DECORATOR_BC));
155
if (context->instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_MVEX)
156
{
157
ZYAN_CHECK(formatter->func_print_decorator(formatter, buffer, context,
158
ZYDIS_DECORATOR_CONVERSION));
159
ZYAN_CHECK(formatter->func_print_decorator(formatter, buffer, context,
160
ZYDIS_DECORATOR_EH));
161
}
162
} else
163
{
164
ZyanBool decorate_operand;
165
if (i == (context->instruction->operand_count_visible - 1))
166
{
167
decorate_operand = operand->type != ZYDIS_OPERAND_TYPE_IMMEDIATE;
168
}
169
else
170
{
171
decorate_operand =
172
(context->instruction->operand_count_visible > (i + 1)) &&
173
((context->operands[i + 1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE) ||
174
(context->operands[i + 1].visibility == ZYDIS_OPERAND_VISIBILITY_HIDDEN));
175
}
176
if (decorate_operand)
177
{
178
if (context->instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_MVEX)
179
{
180
ZYAN_CHECK(formatter->func_print_decorator(formatter, buffer, context,
181
ZYDIS_DECORATOR_SWIZZLE));
182
}
183
ZYAN_CHECK(formatter->func_print_decorator(formatter, buffer, context,
184
ZYDIS_DECORATOR_RC));
185
ZYAN_CHECK(formatter->func_print_decorator(formatter, buffer, context,
186
ZYDIS_DECORATOR_SAE));
187
}
188
}
189
}
190
#endif
191
}
192
193
return ZYAN_STATUS_SUCCESS;
194
}
195
196
/* ---------------------------------------------------------------------------------------------- */
197
/* Operands */
198
/* ---------------------------------------------------------------------------------------------- */
199
200
ZyanStatus ZydisFormatterATTFormatOperandMEM(const ZydisFormatter* formatter,
201
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
202
{
203
ZYAN_ASSERT(formatter);
204
ZYAN_ASSERT(buffer);
205
ZYAN_ASSERT(context);
206
207
ZYAN_CHECK(formatter->func_print_segment(formatter, buffer, context));
208
209
const ZyanBool absolute = !formatter->force_relative_riprel &&
210
(context->runtime_address != ZYDIS_RUNTIME_ADDRESS_NONE);
211
if (absolute && context->operand->mem.disp.has_displacement &&
212
(context->operand->mem.index == ZYDIS_REGISTER_NONE) &&
213
((context->operand->mem.base == ZYDIS_REGISTER_NONE) ||
214
(context->operand->mem.base == ZYDIS_REGISTER_EIP ) ||
215
(context->operand->mem.base == ZYDIS_REGISTER_RIP )))
216
{
217
// EIP/RIP-relative or absolute-displacement address operand
218
ZYAN_CHECK(formatter->func_print_address_abs(formatter, buffer, context));
219
} else
220
{
221
const ZyanBool should_print_reg = context->operand->mem.base != ZYDIS_REGISTER_NONE;
222
const ZyanBool should_print_idx = context->operand->mem.index != ZYDIS_REGISTER_NONE;
223
const ZyanBool neither_reg_nor_idx = !should_print_reg && !should_print_idx;
224
225
// Regular memory operand
226
if (neither_reg_nor_idx)
227
{
228
ZYAN_CHECK(formatter->func_print_address_abs(formatter, buffer, context));
229
} else if (context->operand->mem.disp.has_displacement && context->operand->mem.disp.value)
230
{
231
ZYAN_CHECK(formatter->func_print_disp(formatter, buffer, context));
232
}
233
234
if (neither_reg_nor_idx)
235
{
236
return ZYAN_STATUS_SUCCESS;
237
}
238
239
ZYDIS_BUFFER_APPEND(buffer, MEMORY_BEGIN_ATT);
240
241
if (should_print_reg)
242
{
243
ZYAN_CHECK(formatter->func_print_register(formatter, buffer, context,
244
context->operand->mem.base));
245
}
246
if (should_print_idx)
247
{
248
ZYDIS_BUFFER_APPEND(buffer, DELIM_MEMORY);
249
ZYAN_CHECK(formatter->func_print_register(formatter, buffer, context,
250
context->operand->mem.index));
251
if (context->operand->mem.scale &&
252
(context->operand->mem.type != ZYDIS_MEMOP_TYPE_MIB) &&
253
((context->operand->mem.scale > 1) || formatter->force_memory_scale))
254
{
255
ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_DELIMITER);
256
ZYDIS_BUFFER_APPEND(buffer, DELIM_MEMORY);
257
ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_IMMEDIATE);
258
ZYAN_CHECK(ZydisStringAppendDecU(&buffer->string, context->operand->mem.scale, 0,
259
ZYAN_NULL, ZYAN_NULL));
260
}
261
}
262
263
ZYDIS_BUFFER_APPEND(buffer, MEMORY_END_ATT);
264
return ZYAN_STATUS_SUCCESS;
265
}
266
267
return ZYAN_STATUS_SUCCESS;
268
}
269
270
/* ---------------------------------------------------------------------------------------------- */
271
/* Elemental tokens */
272
/* ---------------------------------------------------------------------------------------------- */
273
274
ZyanStatus ZydisFormatterATTPrintMnemonic(const ZydisFormatter* formatter,
275
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
276
{
277
ZYAN_ASSERT(formatter);
278
ZYAN_ASSERT(buffer);
279
ZYAN_ASSERT(context);
280
ZYAN_ASSERT(context->instruction);
281
ZYAN_ASSERT(context->operands);
282
283
const ZydisShortString* mnemonic = ZydisMnemonicGetStringWrapped(
284
context->instruction->mnemonic);
285
if (!mnemonic)
286
{
287
ZYDIS_BUFFER_APPEND_CASE(buffer, INVALID_MNEMONIC, formatter->case_mnemonic);
288
return ZYAN_STATUS_SUCCESS;
289
}
290
291
ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_MNEMONIC);
292
if (context->instruction->meta.branch_type == ZYDIS_BRANCH_TYPE_FAR)
293
{
294
ZYAN_CHECK(ZydisStringAppendShortCase(&buffer->string, &STR_FAR_ATT,
295
formatter->case_mnemonic));
296
}
297
ZYAN_CHECK(ZydisStringAppendShortCase(&buffer->string, mnemonic, formatter->case_mnemonic));
298
299
// Append operand-size suffix
300
ZyanU32 size = 0;
301
for (ZyanU8 i = 0; i < context->instruction->operand_count_visible; ++i)
302
{
303
const ZydisDecodedOperand* const operand = &context->operands[i];
304
if ((operand->type == ZYDIS_OPERAND_TYPE_MEMORY) &&
305
((operand->mem.type == ZYDIS_MEMOP_TYPE_MEM) ||
306
(operand->mem.type == ZYDIS_MEMOP_TYPE_VSIB)))
307
{
308
size = ZydisFormatterHelperGetExplicitSize(formatter, context, operand);
309
break;
310
}
311
}
312
313
switch (size)
314
{
315
case 8: ZydisStringAppendShort(&buffer->string, &STR_SIZE_8_ATT ); break;
316
case 16: ZydisStringAppendShort(&buffer->string, &STR_SIZE_16_ATT ); break;
317
case 32: ZydisStringAppendShort(&buffer->string, &STR_SIZE_32_ATT ); break;
318
case 64: ZydisStringAppendShort(&buffer->string, &STR_SIZE_64_ATT ); break;
319
case 128: ZydisStringAppendShort(&buffer->string, &STR_SIZE_128_ATT); break;
320
case 256: ZydisStringAppendShort(&buffer->string, &STR_SIZE_256_ATT); break;
321
case 512: ZydisStringAppendShort(&buffer->string, &STR_SIZE_512_ATT); break;
322
default:
323
break;
324
}
325
326
if (formatter->print_branch_size)
327
{
328
switch (context->instruction->meta.branch_type)
329
{
330
case ZYDIS_BRANCH_TYPE_NONE:
331
break;
332
case ZYDIS_BRANCH_TYPE_SHORT:
333
return ZydisStringAppendShortCase(&buffer->string, &STR_SHORT,
334
formatter->case_mnemonic);
335
case ZYDIS_BRANCH_TYPE_NEAR:
336
return ZydisStringAppendShortCase(&buffer->string, &STR_NEAR,
337
formatter->case_mnemonic);
338
default:
339
return ZYAN_STATUS_INVALID_ARGUMENT;
340
}
341
}
342
343
return ZYAN_STATUS_SUCCESS;
344
}
345
346
ZyanStatus ZydisFormatterATTPrintRegister(const ZydisFormatter* formatter,
347
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context, ZydisRegister reg)
348
{
349
ZYAN_UNUSED(context);
350
351
ZYAN_ASSERT(formatter);
352
ZYAN_ASSERT(buffer);
353
ZYAN_ASSERT(context);
354
355
ZYDIS_BUFFER_APPEND(buffer, REGISTER);
356
const ZydisShortString* str = ZydisRegisterGetStringWrapped(reg);
357
if (!str)
358
{
359
return ZydisStringAppendShortCase(&buffer->string, &STR_INVALID_REG,
360
formatter->case_registers);
361
}
362
return ZydisStringAppendShortCase(&buffer->string, str, formatter->case_registers);
363
}
364
365
ZyanStatus ZydisFormatterATTPrintAddressABS(const ZydisFormatter* formatter,
366
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
367
{
368
ZYAN_ASSERT(formatter);
369
ZYAN_ASSERT(buffer);
370
ZYAN_ASSERT(context);
371
372
if ((context->instruction->meta.branch_type != ZYDIS_BRANCH_TYPE_NONE) &&
373
(context->operand->type == ZYDIS_OPERAND_TYPE_MEMORY))
374
{
375
ZYDIS_BUFFER_APPEND(buffer, MUL);
376
}
377
378
return ZydisFormatterBasePrintAddressABS(formatter, buffer, context);
379
}
380
381
ZyanStatus ZydisFormatterATTPrintDISP(const ZydisFormatter* formatter,
382
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
383
{
384
ZYAN_ASSERT(formatter);
385
ZYAN_ASSERT(buffer);
386
ZYAN_ASSERT(context);
387
388
ZYDIS_BUFFER_APPEND_TOKEN(buffer, ZYDIS_TOKEN_DISPLACEMENT);
389
switch (formatter->disp_signedness)
390
{
391
case ZYDIS_SIGNEDNESS_AUTO:
392
case ZYDIS_SIGNEDNESS_SIGNED:
393
ZYDIS_STRING_APPEND_NUM_S(formatter, formatter->disp_base, &buffer->string,
394
context->operand->mem.disp.value, formatter->disp_padding,
395
formatter->hex_force_leading_number, ZYAN_FALSE);
396
break;
397
case ZYDIS_SIGNEDNESS_UNSIGNED:
398
ZYDIS_STRING_APPEND_NUM_U(formatter, formatter->disp_base, &buffer->string,
399
context->operand->mem.disp.value, formatter->disp_padding,
400
formatter->hex_force_leading_number);
401
break;
402
default:
403
return ZYAN_STATUS_INVALID_ARGUMENT;
404
}
405
406
return ZYAN_STATUS_SUCCESS;
407
}
408
409
ZyanStatus ZydisFormatterATTPrintIMM(const ZydisFormatter* formatter,
410
ZydisFormatterBuffer* buffer, ZydisFormatterContext* context)
411
{
412
ZYAN_ASSERT(formatter);
413
ZYAN_ASSERT(buffer);
414
ZYAN_ASSERT(context);
415
416
ZYDIS_BUFFER_APPEND(buffer, IMMEDIATE);
417
return ZydisFormatterBasePrintIMM(formatter, buffer, context);
418
}
419
420
/* ---------------------------------------------------------------------------------------------- */
421
422
/* ============================================================================================== */
423
424