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