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