1 /***************************************************************************************************
2
3 Zyan Disassembler Library (Zydis)
4
5 Original Author : Florian Bernd
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 // ReSharper disable CppClangTidyClangDiagnosticImplicitFallthrough
28 // ReSharper disable CppClangTidyClangDiagnosticSwitchEnum
29 // ReSharper disable CppClangTidyClangDiagnosticCoveredSwitchDefault
30
31 // Temporarily disabled due to a LLVM issue:
32 // ReSharper disable CppClangTidyBugproneNarrowingConversions
33
34 #include <Zycore/LibC.h>
35 #include <Zydis/Decoder.h>
36 #include <Zydis/Status.h>
37 #include <Zydis/Internal/DecoderData.h>
38 #include <Zydis/Internal/SharedData.h>
39
40 /* ============================================================================================== */
41 /* Internal enums and types */
42 /* ============================================================================================== */
43
44 /* ---------------------------------------------------------------------------------------------- */
45 /* Decoder context */
46 /* ---------------------------------------------------------------------------------------------- */
47
48 /**
49 * Defines the `ZydisDecoderState` struct.
50 */
51 typedef struct ZydisDecoderState_
52 {
53 /**
54 * A pointer to the `ZydisDecoder` instance.
55 */
56 const ZydisDecoder* decoder;
57 /**
58 * A pointer to the `ZydisDecoderContext` struct.
59 */
60 ZydisDecoderContext* context;
61 /**
62 * The input buffer.
63 */
64 const ZyanU8* buffer;
65 /**
66 * The input buffer length.
67 */
68 ZyanUSize buffer_len;
69 /**
70 * Prefix information.
71 */
72 struct
73 {
74 /**
75 * Signals, if the instruction has a `LOCK` prefix (`F0`).
76 *
77 * This prefix originally belongs to group 1, but separating it from the other ones makes
78 * parsing easier for us later.
79 */
80 ZyanBool has_lock;
81 /**
82 * The effective prefix of group 1 (either `F2` or `F3`).
83 */
84 ZyanU8 group1;
85 /**
86 * The effective prefix of group 2 (`2E`, `36`, `3E`, `26`, `64` or `65`).
87 */
88 ZyanU8 group2;
89 /**
90 * The effective segment prefix.
91 */
92 ZyanU8 effective_segment;
93 /**
94 * The prefix that should be treated as the mandatory-prefix, if the
95 * current instruction needs one.
96 *
97 * The last `F3`/`F2` prefix has precedence over previous ones and
98 * `F3`/`F2` in general have precedence over `66`.
99 */
100 ZyanU8 mandatory_candidate;
101 /**
102 * The offset of the effective `LOCK` prefix.
103 */
104 ZyanU8 offset_lock;
105 /**
106 * The offset of the effective prefix in group 1.
107 */
108 ZyanU8 offset_group1;
109 /**
110 * The offset of the effective prefix in group 2.
111 */
112 ZyanU8 offset_group2;
113 /**
114 * The offset of the operand-size override prefix (`66`).
115 *
116 * This is the only prefix in group 3.
117 */
118 ZyanU8 offset_osz_override;
119 /**
120 * The offset of the address-size override prefix (`67`).
121 *
122 * This is the only prefix in group 4.
123 */
124 ZyanU8 offset_asz_override;
125 /**
126 * The offset of the effective segment prefix.
127 */
128 ZyanU8 offset_segment;
129 /**
130 * The offset of the mandatory-candidate prefix.
131 */
132 ZyanU8 offset_mandatory;
133 /**
134 * The offset of a possible `CET` `no-lock` prefix.
135 */
136 ZyanI8 offset_notrack;
137 } prefixes;
138 } ZydisDecoderState;
139
140 /* ---------------------------------------------------------------------------------------------- */
141 /* Register encoding */
142 /* ---------------------------------------------------------------------------------------------- */
143
144 /**
145 * Defines the `ZydisRegisterEncoding` enum.
146 */
147 typedef enum ZydisRegisterEncoding_
148 {
149 ZYDIS_REG_ENCODING_INVALID,
150 /**
151 * The register-id is encoded as part of the opcode (bits [3..0]).
152 *
153 * Possible extension by:
154 * - `REX.B`
155 */
156 ZYDIS_REG_ENCODING_OPCODE,
157 /**
158 * The register-id is encoded in `modrm.reg`.
159 *
160 * Possible extension by:
161 * - `.R`
162 * - `.R'` (vector only, EVEX/MVEX)
163 */
164 ZYDIS_REG_ENCODING_REG,
165 /**
166 * The register-id is encoded in `.vvvv`.
167 *
168 * Possible extension by:
169 * - `.v'` (vector only, EVEX/MVEX).
170 */
171 ZYDIS_REG_ENCODING_NDSNDD,
172 /**
173 * The register-id is encoded in `modrm.rm`.
174 *
175 * Possible extension by:
176 * - `.B`
177 * - `.X` (vector only, EVEX/MVEX)`
178 */
179 ZYDIS_REG_ENCODING_RM,
180 /**
181 * The register-id is encoded in `modrm.rm` or `sib.base` (if `SIB` is present).
182 *
183 * Possible extension by:
184 * - `.B`
185 */
186 ZYDIS_REG_ENCODING_BASE,
187 /**
188 * The register-id is encoded in `sib.index`.
189 *
190 * Possible extension by:
191 * - `.X`
192 */
193 ZYDIS_REG_ENCODING_INDEX,
194 /**
195 * The register-id is encoded in `sib.index`.
196 *
197 * Possible extension by:
198 * - `.X`
199 * - `.V'` (vector only, EVEX/MVEX)
200 */
201 ZYDIS_REG_ENCODING_VIDX,
202 /**
203 * The register-id is encoded in an additional 8-bit immediate value.
204 *
205 * Bits [7:4] in 64-bit mode with possible extension by bit [3] (vector only), bits [7:5] for
206 * all other modes.
207 */
208 ZYDIS_REG_ENCODING_IS4,
209 /**
210 * The register-id is encoded in `EVEX.aaa/MVEX.kkk`.
211 */
212 ZYDIS_REG_ENCODING_MASK,
213
214 /**
215 * Maximum value of this enum.
216 */
217 ZYDIS_REG_ENCODING_MAX_VALUE = ZYDIS_REG_ENCODING_MASK,
218 /**
219 * The minimum number of bits required to represent all values of this enum.
220 */
221 ZYDIS_REG_ENCODING_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_REG_ENCODING_MAX_VALUE)
222 } ZydisRegisterEncoding;
223
224 /* ---------------------------------------------------------------------------------------------- */
225
226 /* ============================================================================================== */
227 /* Internal functions */
228 /* ============================================================================================== */
229
230 /* ---------------------------------------------------------------------------------------------- */
231 /* Input helper functions */
232 /* ---------------------------------------------------------------------------------------------- */
233
234 /**
235 * Reads one byte from the current read-position of the input data-source.
236 *
237 * @param state A pointer to the `ZydisDecoderState` struct.
238 * @param instruction A pointer to the `ZydisDecodedInstruction` struct.
239 * @param value A pointer to the memory that receives the byte from the input data-source.
240 *
241 * @return A zyan status code.
242 *
243 * This function may fail, if the `ZYDIS_MAX_INSTRUCTION_LENGTH` limit got exceeded, or no more
244 * data is available.
245 */
ZydisInputPeek(ZydisDecoderState * state,ZydisDecodedInstruction * instruction,ZyanU8 * value)246 static ZyanStatus ZydisInputPeek(ZydisDecoderState* state,
247 ZydisDecodedInstruction* instruction, ZyanU8* value)
248 {
249 ZYAN_ASSERT(state);
250 ZYAN_ASSERT(instruction);
251 ZYAN_ASSERT(value);
252
253 if (instruction->length >= ZYDIS_MAX_INSTRUCTION_LENGTH)
254 {
255 return ZYDIS_STATUS_INSTRUCTION_TOO_LONG;
256 }
257
258 if (state->buffer_len > 0)
259 {
260 *value = state->buffer[0];
261 return ZYAN_STATUS_SUCCESS;
262 }
263
264 return ZYDIS_STATUS_NO_MORE_DATA;
265 }
266
267 /**
268 * Increases the read-position of the input data-source by one byte.
269 *
270 * @param state A pointer to the `ZydisDecoderState` instance
271 * @param instruction A pointer to the `ZydisDecodedInstruction` struct.
272 *
273 * This function is supposed to get called ONLY after a successful call of `ZydisInputPeek`.
274 *
275 * This function increases the `length` field of the `ZydisDecodedInstruction` struct by one.
276 */
ZydisInputSkip(ZydisDecoderState * state,ZydisDecodedInstruction * instruction)277 static void ZydisInputSkip(ZydisDecoderState* state, ZydisDecodedInstruction* instruction)
278 {
279 ZYAN_ASSERT(state);
280 ZYAN_ASSERT(instruction);
281 ZYAN_ASSERT(instruction->length < ZYDIS_MAX_INSTRUCTION_LENGTH);
282
283 ++instruction->length;
284 ++state->buffer;
285 --state->buffer_len;
286 }
287
288 /**
289 * Reads one byte from the current read-position of the input data-source and increases
290 * the read-position by one byte afterwards.
291 *
292 * @param state A pointer to the `ZydisDecoderState` struct.
293 * @param instruction A pointer to the `ZydisDecodedInstruction` struct.
294 * @param value A pointer to the memory that receives the byte from the input data-source.
295 *
296 * @return A zyan status code.
297 *
298 * This function acts like a subsequent call of `ZydisInputPeek` and `ZydisInputSkip`.
299 */
ZydisInputNext(ZydisDecoderState * state,ZydisDecodedInstruction * instruction,ZyanU8 * value)300 static ZyanStatus ZydisInputNext(ZydisDecoderState* state,
301 ZydisDecodedInstruction* instruction, ZyanU8* value)
302 {
303 ZYAN_ASSERT(state);
304 ZYAN_ASSERT(instruction);
305 ZYAN_ASSERT(value);
306
307 if (instruction->length >= ZYDIS_MAX_INSTRUCTION_LENGTH)
308 {
309 return ZYDIS_STATUS_INSTRUCTION_TOO_LONG;
310 }
311
312 if (state->buffer_len > 0)
313 {
314 *value = state->buffer++[0];
315 ++instruction->length;
316 --state->buffer_len;
317 return ZYAN_STATUS_SUCCESS;
318 }
319
320 return ZYDIS_STATUS_NO_MORE_DATA;
321 }
322
323 /**
324 * Reads a variable amount of bytes from the current read-position of the input
325 * data-source and increases the read-position by specified amount of bytes afterwards.
326 *
327 * @param state A pointer to the `ZydisDecoderState` struct.
328 * @param instruction A pointer to the `ZydisDecodedInstruction` struct.
329 * @param value A pointer to the memory that receives the byte from the input
330 * data-source.
331 * @param number_of_bytes The number of bytes to read from the input data-source.
332 *
333 * @return A zyan status code.
334 *
335 * This function acts like a subsequent call of `ZydisInputPeek` and `ZydisInputSkip`.
336 */
ZydisInputNextBytes(ZydisDecoderState * state,ZydisDecodedInstruction * instruction,ZyanU8 * value,ZyanU8 number_of_bytes)337 static ZyanStatus ZydisInputNextBytes(ZydisDecoderState* state,
338 ZydisDecodedInstruction* instruction, ZyanU8* value, ZyanU8 number_of_bytes)
339 {
340 ZYAN_ASSERT(state);
341 ZYAN_ASSERT(instruction);
342 ZYAN_ASSERT(value);
343
344 if (instruction->length + number_of_bytes > ZYDIS_MAX_INSTRUCTION_LENGTH)
345 {
346 return ZYDIS_STATUS_INSTRUCTION_TOO_LONG;
347 }
348
349 if (state->buffer_len >= number_of_bytes)
350 {
351 instruction->length += number_of_bytes;
352
353 ZYAN_MEMCPY(value, state->buffer, number_of_bytes);
354 state->buffer += number_of_bytes;
355 state->buffer_len -= number_of_bytes;
356
357 return ZYAN_STATUS_SUCCESS;
358 }
359
360 return ZYDIS_STATUS_NO_MORE_DATA;
361 }
362
363 /* ---------------------------------------------------------------------------------------------- */
364 /* Decode functions */
365 /* ---------------------------------------------------------------------------------------------- */
366
367 /**
368 * Decodes the `REX`-prefix.
369 *
370 * @param context A pointer to the `ZydisDecoderContext` struct.
371 * @param instruction A pointer to the `ZydisDecodedInstruction` struct.
372 * @param data The `REX` byte.
373 */
ZydisDecodeREX(ZydisDecoderContext * context,ZydisDecodedInstruction * instruction,ZyanU8 data)374 static void ZydisDecodeREX(ZydisDecoderContext* context, ZydisDecodedInstruction* instruction,
375 ZyanU8 data)
376 {
377 ZYAN_ASSERT(instruction);
378 ZYAN_ASSERT((data & 0xF0) == 0x40);
379
380 instruction->attributes |= ZYDIS_ATTRIB_HAS_REX;
381 instruction->raw.rex.W = (data >> 3) & 0x01;
382 instruction->raw.rex.R = (data >> 2) & 0x01;
383 instruction->raw.rex.X = (data >> 1) & 0x01;
384 instruction->raw.rex.B = (data >> 0) & 0x01;
385
386 // Update internal fields
387 context->vector_unified.W = instruction->raw.rex.W;
388 context->vector_unified.R = instruction->raw.rex.R;
389 context->vector_unified.X = instruction->raw.rex.X;
390 context->vector_unified.B = instruction->raw.rex.B;
391 }
392
393 /**
394 * Decodes the `XOP`-prefix.
395 *
396 * @param context A pointer to the `ZydisDecoderContext` struct.
397 * @param instruction A pointer to the `ZydisDecodedInstruction` struct.
398 * @param data The `XOP` bytes.
399 *
400 * @return A zyan status code.
401 */
ZydisDecodeXOP(ZydisDecoderContext * context,ZydisDecodedInstruction * instruction,const ZyanU8 data[3])402 static ZyanStatus ZydisDecodeXOP(ZydisDecoderContext* context,
403 ZydisDecodedInstruction* instruction, const ZyanU8 data[3])
404 {
405 ZYAN_ASSERT(instruction);
406 ZYAN_ASSERT(data[0] == 0x8F);
407 ZYAN_ASSERT(((data[1] >> 0) & 0x1F) >= 8);
408 ZYAN_ASSERT(instruction->raw.xop.offset == instruction->length - 3);
409
410 if (instruction->machine_mode == ZYDIS_MACHINE_MODE_REAL_16)
411 {
412 // XOP is invalid in 16-bit real mode
413 return ZYDIS_STATUS_DECODING_ERROR;
414 }
415
416 instruction->attributes |= ZYDIS_ATTRIB_HAS_XOP;
417 instruction->raw.xop.R = (data[1] >> 7) & 0x01;
418 instruction->raw.xop.X = (data[1] >> 6) & 0x01;
419 instruction->raw.xop.B = (data[1] >> 5) & 0x01;
420 instruction->raw.xop.m_mmmm = (data[1] >> 0) & 0x1F;
421
422 if ((instruction->raw.xop.m_mmmm < 0x08) || (instruction->raw.xop.m_mmmm > 0x0A))
423 {
424 // Invalid according to the AMD documentation
425 return ZYDIS_STATUS_INVALID_MAP;
426 }
427
428 instruction->raw.xop.W = (data[2] >> 7) & 0x01;
429 instruction->raw.xop.vvvv = (data[2] >> 3) & 0x0F;
430 instruction->raw.xop.L = (data[2] >> 2) & 0x01;
431 instruction->raw.xop.pp = (data[2] >> 0) & 0x03;
432
433 // Update internal fields
434 context->vector_unified.W = instruction->raw.xop.W;
435 context->vector_unified.R = 0x01 & ~instruction->raw.xop.R;
436 context->vector_unified.X = 0x01 & ~instruction->raw.xop.X;
437 context->vector_unified.B = 0x01 & ~instruction->raw.xop.B;
438 context->vector_unified.L = instruction->raw.xop.L;
439 context->vector_unified.LL = instruction->raw.xop.L;
440 context->vector_unified.vvvv = (0x0F & ~instruction->raw.xop.vvvv);
441
442 return ZYAN_STATUS_SUCCESS;
443 }
444
445 /**
446 * Decodes the `VEX`-prefix.
447 *
448 * @param context A pointer to the `ZydisDecoderContext` struct.
449 * @param instruction A pointer to the `ZydisDecodedInstruction` struct.
450 * @param data The `VEX` bytes.
451 *
452 * @return A zyan status code.
453 */
ZydisDecodeVEX(ZydisDecoderContext * context,ZydisDecodedInstruction * instruction,const ZyanU8 data[3])454 static ZyanStatus ZydisDecodeVEX(ZydisDecoderContext* context,
455 ZydisDecodedInstruction* instruction, const ZyanU8 data[3])
456 {
457 ZYAN_ASSERT(instruction);
458 ZYAN_ASSERT((data[0] == 0xC4) || (data[0] == 0xC5));
459
460 if (instruction->machine_mode == ZYDIS_MACHINE_MODE_REAL_16)
461 {
462 // VEX is invalid in 16-bit real mode
463 return ZYDIS_STATUS_DECODING_ERROR;
464 }
465
466 instruction->attributes |= ZYDIS_ATTRIB_HAS_VEX;
467 switch (data[0])
468 {
469 case 0xC4:
470 ZYAN_ASSERT(instruction->raw.vex.offset == instruction->length - 3);
471 instruction->raw.vex.size = 3;
472 instruction->raw.vex.R = (data[1] >> 7) & 0x01;
473 instruction->raw.vex.X = (data[1] >> 6) & 0x01;
474 instruction->raw.vex.B = (data[1] >> 5) & 0x01;
475 instruction->raw.vex.m_mmmm = (data[1] >> 0) & 0x1F;
476 instruction->raw.vex.W = (data[2] >> 7) & 0x01;
477 instruction->raw.vex.vvvv = (data[2] >> 3) & 0x0F;
478 instruction->raw.vex.L = (data[2] >> 2) & 0x01;
479 instruction->raw.vex.pp = (data[2] >> 0) & 0x03;
480 break;
481 case 0xC5:
482 ZYAN_ASSERT(instruction->raw.vex.offset == instruction->length - 2);
483 instruction->raw.vex.size = 2;
484 instruction->raw.vex.R = (data[1] >> 7) & 0x01;
485 instruction->raw.vex.X = 1;
486 instruction->raw.vex.B = 1;
487 instruction->raw.vex.m_mmmm = 1;
488 instruction->raw.vex.W = 0;
489 instruction->raw.vex.vvvv = (data[1] >> 3) & 0x0F;
490 instruction->raw.vex.L = (data[1] >> 2) & 0x01;
491 instruction->raw.vex.pp = (data[1] >> 0) & 0x03;
492 break;
493 default:
494 ZYAN_UNREACHABLE;
495 }
496
497 // Map 0 is only valid for some KNC instructions
498 #ifdef ZYDIS_DISABLE_KNC
499 if ((instruction->raw.vex.m_mmmm == 0) || (instruction->raw.vex.m_mmmm > 0x03))
500 #else
501 if (instruction->raw.vex.m_mmmm > 0x03)
502 #endif
503 {
504 // Invalid according to the intel documentation
505 return ZYDIS_STATUS_INVALID_MAP;
506 }
507
508 // Update internal fields
509 context->vector_unified.W = instruction->raw.vex.W;
510 context->vector_unified.R = 0x01 & ~instruction->raw.vex.R;
511 context->vector_unified.X = 0x01 & ~instruction->raw.vex.X;
512 context->vector_unified.B = 0x01 & ~instruction->raw.vex.B;
513 context->vector_unified.L = instruction->raw.vex.L;
514 context->vector_unified.LL = instruction->raw.vex.L;
515 context->vector_unified.vvvv = (0x0F & ~instruction->raw.vex.vvvv);
516
517 return ZYAN_STATUS_SUCCESS;
518 }
519
520 #ifndef ZYDIS_DISABLE_AVX512
521 /**
522 * Decodes the `EVEX`-prefix.
523 *
524 * @param context A pointer to the `ZydisDecoderContext` struct.
525 * @param instruction A pointer to the `ZydisDecodedInstruction` struct.
526 * @param data The `EVEX` bytes.
527 *
528 * @return A zyan status code.
529 */
ZydisDecodeEVEX(ZydisDecoderContext * context,ZydisDecodedInstruction * instruction,const ZyanU8 data[4])530 static ZyanStatus ZydisDecodeEVEX(ZydisDecoderContext* context,
531 ZydisDecodedInstruction* instruction, const ZyanU8 data[4])
532 {
533 ZYAN_ASSERT(instruction);
534 ZYAN_ASSERT(data[0] == 0x62);
535 ZYAN_ASSERT(instruction->raw.evex.offset == instruction->length - 4);
536
537 if (instruction->machine_mode == ZYDIS_MACHINE_MODE_REAL_16)
538 {
539 // EVEX is invalid in 16-bit real mode
540 return ZYDIS_STATUS_DECODING_ERROR;
541 }
542
543 instruction->attributes |= ZYDIS_ATTRIB_HAS_EVEX;
544 instruction->raw.evex.R = (data[1] >> 7) & 0x01;
545 instruction->raw.evex.X = (data[1] >> 6) & 0x01;
546 instruction->raw.evex.B = (data[1] >> 5) & 0x01;
547 instruction->raw.evex.R2 = (data[1] >> 4) & 0x01;
548
549 if (data[1] & 0x08)
550 {
551 // Invalid according to the intel documentation
552 return ZYDIS_STATUS_MALFORMED_EVEX;
553 }
554
555 instruction->raw.evex.mmm = (data[1] >> 0) & 0x07;
556
557 if ((instruction->raw.evex.mmm == 0x00) ||
558 (instruction->raw.evex.mmm == 0x04) ||
559 (instruction->raw.evex.mmm == 0x07))
560 {
561 // Invalid according to the intel documentation
562 return ZYDIS_STATUS_INVALID_MAP;
563 }
564
565 instruction->raw.evex.W = (data[2] >> 7) & 0x01;
566 instruction->raw.evex.vvvv = (data[2] >> 3) & 0x0F;
567
568 ZYAN_ASSERT(((data[2] >> 2) & 0x01) == 0x01);
569
570 instruction->raw.evex.pp = (data[2] >> 0) & 0x03;
571 instruction->raw.evex.z = (data[3] >> 7) & 0x01;
572 instruction->raw.evex.L2 = (data[3] >> 6) & 0x01;
573 instruction->raw.evex.L = (data[3] >> 5) & 0x01;
574 instruction->raw.evex.b = (data[3] >> 4) & 0x01;
575 instruction->raw.evex.V2 = (data[3] >> 3) & 0x01;
576
577 if (!instruction->raw.evex.V2 &&
578 (instruction->machine_mode != ZYDIS_MACHINE_MODE_LONG_64))
579 {
580 return ZYDIS_STATUS_MALFORMED_EVEX;
581 }
582
583 instruction->raw.evex.aaa = (data[3] >> 0) & 0x07;
584
585 if (instruction->raw.evex.z && !instruction->raw.evex.aaa)
586 {
587 return ZYDIS_STATUS_INVALID_MASK; // TODO: Dedicated status code
588 }
589
590 // Update internal fields
591 context->vector_unified.W = instruction->raw.evex.W;
592 context->vector_unified.R = 0x01 & ~instruction->raw.evex.R;
593 context->vector_unified.X = 0x01 & ~instruction->raw.evex.X;
594 context->vector_unified.B = 0x01 & ~instruction->raw.evex.B;
595 context->vector_unified.LL = (data[3] >> 5) & 0x03;
596 context->vector_unified.R2 = 0x01 & ~instruction->raw.evex.R2;
597 context->vector_unified.V2 = 0x01 & ~instruction->raw.evex.V2;
598 context->vector_unified.vvvv = 0x0F & ~instruction->raw.evex.vvvv;
599 context->vector_unified.mask = instruction->raw.evex.aaa;
600
601 if (!instruction->raw.evex.V2 && (instruction->machine_mode != ZYDIS_MACHINE_MODE_LONG_64))
602 {
603 return ZYDIS_STATUS_MALFORMED_EVEX;
604 }
605 if (!instruction->raw.evex.b && (context->vector_unified.LL == 3))
606 {
607 // LL = 3 is only valid for instructions with embedded rounding control
608 return ZYDIS_STATUS_MALFORMED_EVEX;
609 }
610
611 return ZYAN_STATUS_SUCCESS;
612 }
613 #endif
614
615 #ifndef ZYDIS_DISABLE_KNC
616 /**
617 * Decodes the `MVEX`-prefix.
618 *
619 * @param context A pointer to the `ZydisDecoderContext` struct.
620 * @param instruction A pointer to the `ZydisDecodedInstruction` struct.
621 * @param data The `MVEX` bytes.
622 *
623 * @return A zyan status code.
624 */
ZydisDecodeMVEX(ZydisDecoderContext * context,ZydisDecodedInstruction * instruction,const ZyanU8 data[4])625 static ZyanStatus ZydisDecodeMVEX(ZydisDecoderContext* context,
626 ZydisDecodedInstruction* instruction, const ZyanU8 data[4])
627 {
628 ZYAN_ASSERT(instruction);
629 ZYAN_ASSERT(data[0] == 0x62);
630 ZYAN_ASSERT(instruction->raw.mvex.offset == instruction->length - 4);
631
632 if (instruction->machine_mode != ZYDIS_MACHINE_MODE_LONG_64)
633 {
634 // MVEX is only valid in 64-bit mode
635 return ZYDIS_STATUS_DECODING_ERROR;
636 }
637
638 instruction->attributes |= ZYDIS_ATTRIB_HAS_MVEX;
639 instruction->raw.mvex.R = (data[1] >> 7) & 0x01;
640 instruction->raw.mvex.X = (data[1] >> 6) & 0x01;
641 instruction->raw.mvex.B = (data[1] >> 5) & 0x01;
642 instruction->raw.mvex.R2 = (data[1] >> 4) & 0x01;
643 instruction->raw.mvex.mmmm = (data[1] >> 0) & 0x0F;
644
645 if (instruction->raw.mvex.mmmm > 0x03)
646 {
647 // Invalid according to the intel documentation
648 return ZYDIS_STATUS_INVALID_MAP;
649 }
650
651 instruction->raw.mvex.W = (data[2] >> 7) & 0x01;
652 instruction->raw.mvex.vvvv = (data[2] >> 3) & 0x0F;
653
654 ZYAN_ASSERT(((data[2] >> 2) & 0x01) == 0x00);
655
656 instruction->raw.mvex.pp = (data[2] >> 0) & 0x03;
657 instruction->raw.mvex.E = (data[3] >> 7) & 0x01;
658 instruction->raw.mvex.SSS = (data[3] >> 4) & 0x07;
659 instruction->raw.mvex.V2 = (data[3] >> 3) & 0x01;
660 instruction->raw.mvex.kkk = (data[3] >> 0) & 0x07;
661
662 // Update internal fields
663 context->vector_unified.W = instruction->raw.mvex.W;
664 context->vector_unified.R = 0x01 & ~instruction->raw.mvex.R;
665 context->vector_unified.X = 0x01 & ~instruction->raw.mvex.X;
666 context->vector_unified.B = 0x01 & ~instruction->raw.mvex.B;
667 context->vector_unified.R2 = 0x01 & ~instruction->raw.mvex.R2;
668 context->vector_unified.V2 = 0x01 & ~instruction->raw.mvex.V2;
669 context->vector_unified.LL = 2;
670 context->vector_unified.vvvv = 0x0F & ~instruction->raw.mvex.vvvv;
671 context->vector_unified.mask = instruction->raw.mvex.kkk;
672
673 return ZYAN_STATUS_SUCCESS;
674 }
675 #endif
676
677 /**
678 * Decodes the `ModRM`-byte.
679 *
680 * @param instruction A pointer to the `ZydisDecodedInstruction` struct.
681 * @param data The `ModRM` byte.
682 */
ZydisDecodeModRM(ZydisDecodedInstruction * instruction,ZyanU8 data)683 static void ZydisDecodeModRM(ZydisDecodedInstruction* instruction, ZyanU8 data)
684 {
685 ZYAN_ASSERT(instruction);
686 ZYAN_ASSERT(!(instruction->attributes & ZYDIS_ATTRIB_HAS_MODRM));
687 ZYAN_ASSERT(instruction->raw.modrm.offset == instruction->length - 1);
688
689 instruction->attributes |= ZYDIS_ATTRIB_HAS_MODRM;
690 instruction->raw.modrm.mod = (data >> 6) & 0x03;
691 instruction->raw.modrm.reg = (data >> 3) & 0x07;
692 instruction->raw.modrm.rm = (data >> 0) & 0x07;
693 }
694
695 /**
696 * Decodes the `SIB`-byte.
697 *
698 * @param instruction A pointer to the `ZydisDecodedInstruction` struct
699 * @param data The `SIB` byte.
700 */
ZydisDecodeSIB(ZydisDecodedInstruction * instruction,ZyanU8 data)701 static void ZydisDecodeSIB(ZydisDecodedInstruction* instruction, ZyanU8 data)
702 {
703 ZYAN_ASSERT(instruction);
704 ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_MODRM);
705 ZYAN_ASSERT(instruction->raw.modrm.rm == 4);
706 ZYAN_ASSERT(!(instruction->attributes & ZYDIS_ATTRIB_HAS_SIB));
707 ZYAN_ASSERT(instruction->raw.sib.offset == instruction->length - 1);
708
709 instruction->attributes |= ZYDIS_ATTRIB_HAS_SIB;
710 instruction->raw.sib.scale = (data >> 6) & 0x03;
711 instruction->raw.sib.index = (data >> 3) & 0x07;
712 instruction->raw.sib.base = (data >> 0) & 0x07;
713 }
714
715 /* ---------------------------------------------------------------------------------------------- */
716
717 /**
718 * Reads a displacement value.
719 *
720 * @param state A pointer to the `ZydisDecoderState` struct.
721 * @param instruction A pointer to the `ZydisDecodedInstruction` struct.
722 * @param size The physical size of the displacement value.
723 *
724 * @return A zyan status code.
725 */
ZydisReadDisplacement(ZydisDecoderState * state,ZydisDecodedInstruction * instruction,ZyanU8 size)726 static ZyanStatus ZydisReadDisplacement(ZydisDecoderState* state,
727 ZydisDecodedInstruction* instruction, ZyanU8 size)
728 {
729 ZYAN_ASSERT(state);
730 ZYAN_ASSERT(instruction);
731 ZYAN_ASSERT(instruction->raw.disp.size == 0);
732
733 instruction->raw.disp.size = size;
734 instruction->raw.disp.offset = instruction->length;
735
736 switch (size)
737 {
738 case 8:
739 {
740 ZyanU8 value;
741 ZYAN_CHECK(ZydisInputNext(state, instruction, &value));
742 instruction->raw.disp.value = *(ZyanI8*)&value;
743 break;
744 }
745 case 16:
746 {
747 ZyanU16 value;
748 ZYAN_CHECK(ZydisInputNextBytes(state, instruction, (ZyanU8*)&value, 2));
749 instruction->raw.disp.value = *(ZyanI16*)&value;
750 break;
751 }
752 case 32:
753 {
754 ZyanU32 value;
755 ZYAN_CHECK(ZydisInputNextBytes(state, instruction, (ZyanU8*)&value, 4));
756 instruction->raw.disp.value = *(ZyanI32*)&value;
757 break;
758 }
759 case 64:
760 {
761 ZyanU64 value;
762 ZYAN_CHECK(ZydisInputNextBytes(state, instruction, (ZyanU8*)&value, 8));
763 instruction->raw.disp.value = *(ZyanI64*)&value;
764 break;
765 }
766 default:
767 ZYAN_UNREACHABLE;
768 }
769
770 // TODO: Fix endianess on big-endian systems
771
772 return ZYAN_STATUS_SUCCESS;
773 }
774
775 /**
776 * Reads an immediate value.
777 *
778 * @param state A pointer to the `ZydisDecoderState` struct.
779 * @param instruction A pointer to the `ZydisDecodedInstruction` struct.
780 * @param id The immediate id (either `0` or `1`).
781 * @param size The physical size of the immediate value.
782 * @param is_signed Signals, if the immediate value is signed.
783 * @param is_relative Signals, if the immediate value is a relative offset.
784 *
785 * @return A zyan status code.
786 */
ZydisReadImmediate(ZydisDecoderState * state,ZydisDecodedInstruction * instruction,ZyanU8 id,ZyanU8 size,ZyanBool is_signed,ZyanBool is_relative)787 static ZyanStatus ZydisReadImmediate(ZydisDecoderState* state,
788 ZydisDecodedInstruction* instruction, ZyanU8 id, ZyanU8 size, ZyanBool is_signed,
789 ZyanBool is_relative)
790 {
791 ZYAN_ASSERT(state);
792 ZYAN_ASSERT(instruction);
793 ZYAN_ASSERT((id == 0) || (id == 1));
794 ZYAN_ASSERT(is_signed || !is_relative);
795 ZYAN_ASSERT(instruction->raw.imm[id].size == 0);
796
797 instruction->raw.imm[id].size = size;
798 instruction->raw.imm[id].offset = instruction->length;
799 instruction->raw.imm[id].is_signed = is_signed;
800 instruction->raw.imm[id].is_relative = is_relative;
801 switch (size)
802 {
803 case 8:
804 {
805 ZyanU8 value;
806 ZYAN_CHECK(ZydisInputNext(state, instruction, &value));
807 if (is_signed)
808 {
809 instruction->raw.imm[id].value.s = (ZyanI8)value;
810 } else
811 {
812 instruction->raw.imm[id].value.u = value;
813 }
814 break;
815 }
816 case 16:
817 {
818 ZyanU16 value;
819 ZYAN_CHECK(ZydisInputNextBytes(state, instruction, (ZyanU8*)&value, 2));
820 if (is_signed)
821 {
822 instruction->raw.imm[id].value.s = (ZyanI16)value;
823 } else
824 {
825 instruction->raw.imm[id].value.u = value;
826 }
827 break;
828 }
829 case 32:
830 {
831 ZyanU32 value;
832 ZYAN_CHECK(ZydisInputNextBytes(state, instruction, (ZyanU8*)&value, 4));
833 if (is_signed)
834 {
835 instruction->raw.imm[id].value.s = (ZyanI32)value;
836 } else
837 {
838 instruction->raw.imm[id].value.u = value;
839 }
840 break;
841 }
842 case 64:
843 {
844 ZyanU64 value;
845 ZYAN_CHECK(ZydisInputNextBytes(state, instruction, (ZyanU8*)&value, 8));
846 if (is_signed)
847 {
848 instruction->raw.imm[id].value.s = (ZyanI64)value;
849 } else
850 {
851 instruction->raw.imm[id].value.u = value;
852 }
853 break;
854 }
855 default:
856 ZYAN_UNREACHABLE;
857 }
858
859 // TODO: Fix endianess on big-endian systems
860
861 return ZYAN_STATUS_SUCCESS;
862 }
863
864 /* ---------------------------------------------------------------------------------------------- */
865 /* Semantic instruction decoding */
866 /* ---------------------------------------------------------------------------------------------- */
867
868 #ifndef ZYDIS_MINIMAL_MODE
869 /**
870 * Calculates the register-id for a specific register-encoding and register-class.
871 *
872 * @param context A pointer to the `ZydisDecoderContext` struct.
873 * @param instruction A pointer to the ` ZydisDecodedInstruction` struct.
874 * @param encoding The register-encoding.
875 * @param register_class The register-class.
876 *
877 * @return A zyan status code.
878 *
879 * This function calculates the register-id by combining different fields and flags of previously
880 * decoded structs.
881 */
ZydisCalcRegisterId(const ZydisDecoderContext * context,const ZydisDecodedInstruction * instruction,ZydisRegisterEncoding encoding,ZydisRegisterClass register_class)882 static ZyanU8 ZydisCalcRegisterId(const ZydisDecoderContext* context,
883 const ZydisDecodedInstruction* instruction, ZydisRegisterEncoding encoding,
884 ZydisRegisterClass register_class)
885 {
886 ZYAN_ASSERT(context);
887 ZYAN_ASSERT(instruction);
888
889 // TODO: Combine OPCODE and IS4 in `ZydisPopulateRegisterIds` and get rid of this
890 // TODO: function entirely
891
892 switch (encoding)
893 {
894 case ZYDIS_REG_ENCODING_REG:
895 return context->reg_info.id_reg;
896 case ZYDIS_REG_ENCODING_NDSNDD:
897 return context->reg_info.id_ndsndd;
898 case ZYDIS_REG_ENCODING_RM:
899 return context->reg_info.id_rm;
900 case ZYDIS_REG_ENCODING_BASE:
901 return context->reg_info.id_base;
902 case ZYDIS_REG_ENCODING_INDEX:
903 case ZYDIS_REG_ENCODING_VIDX:
904 return context->reg_info.id_index;
905 case ZYDIS_REG_ENCODING_OPCODE:
906 {
907 ZYAN_ASSERT((register_class == ZYDIS_REGCLASS_GPR8) ||
908 (register_class == ZYDIS_REGCLASS_GPR16) ||
909 (register_class == ZYDIS_REGCLASS_GPR32) ||
910 (register_class == ZYDIS_REGCLASS_GPR64));
911 ZyanU8 value = (instruction->opcode & 0x0F);
912 if (value > 7)
913 {
914 value = value - 8;
915 }
916 if (instruction->machine_mode != ZYDIS_MACHINE_MODE_LONG_64)
917 {
918 return value;
919 }
920 return value | (context->vector_unified.B << 3);
921 }
922 case ZYDIS_REG_ENCODING_IS4:
923 {
924 if (instruction->machine_mode != ZYDIS_MACHINE_MODE_LONG_64)
925 {
926 return (instruction->raw.imm[0].value.u >> 4) & 0x07;
927 }
928 ZyanU8 value = (instruction->raw.imm[0].value.u >> 4) & 0x0F;
929 // We have to check the instruction-encoding, because the extension by bit [3] is only
930 // valid for EVEX and MVEX instructions
931 if ((instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_EVEX) ||
932 (instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_MVEX))
933 {
934 switch (register_class)
935 {
936 case ZYDIS_REGCLASS_XMM:
937 case ZYDIS_REGCLASS_YMM:
938 case ZYDIS_REGCLASS_ZMM:
939 value |= ((instruction->raw.imm[0].value.u & 0x08) << 1);
940 default:
941 break;
942 }
943 }
944 return value;
945 }
946 case ZYDIS_REG_ENCODING_MASK:
947 return context->vector_unified.mask;
948 default:
949 ZYAN_UNREACHABLE;
950 }
951 }
952 #endif
953
954 #ifndef ZYDIS_MINIMAL_MODE
955 /**
956 * Sets the operand-size and element-specific information for the given operand.
957 *
958 * @param context A pointer to the `ZydisDecoderContext` struct.
959 * @param instruction A pointer to the `ZydisDecodedInstruction` struct.
960 * @param operand A pointer to the `ZydisDecodedOperand` struct.
961 * @param definition A pointer to the `ZydisOperandDefinition` struct.
962 */
ZydisSetOperandSizeAndElementInfo(const ZydisDecoderContext * context,const ZydisDecodedInstruction * instruction,ZydisDecodedOperand * operand,const ZydisOperandDefinition * definition)963 static void ZydisSetOperandSizeAndElementInfo(const ZydisDecoderContext* context,
964 const ZydisDecodedInstruction* instruction, ZydisDecodedOperand* operand,
965 const ZydisOperandDefinition* definition)
966 {
967 ZYAN_ASSERT(context);
968 ZYAN_ASSERT(instruction);
969 ZYAN_ASSERT(operand);
970 ZYAN_ASSERT(definition);
971
972 // Operand size
973 switch (operand->type)
974 {
975 case ZYDIS_OPERAND_TYPE_REGISTER:
976 {
977 if (definition->size[context->eosz_index])
978 {
979 operand->size = definition->size[context->eosz_index] * 8;
980 } else
981 {
982 operand->size = ZydisRegisterGetWidth(instruction->machine_mode,
983 operand->reg.value);
984 }
985 operand->element_type = ZYDIS_ELEMENT_TYPE_INT;
986 operand->element_size = operand->size;
987 break;
988 }
989 case ZYDIS_OPERAND_TYPE_MEMORY:
990 switch (instruction->encoding)
991 {
992 case ZYDIS_INSTRUCTION_ENCODING_LEGACY:
993 case ZYDIS_INSTRUCTION_ENCODING_3DNOW:
994 case ZYDIS_INSTRUCTION_ENCODING_XOP:
995 case ZYDIS_INSTRUCTION_ENCODING_VEX:
996 if (operand->mem.type == ZYDIS_MEMOP_TYPE_AGEN)
997 {
998 ZYAN_ASSERT(definition->size[context->eosz_index] == 0);
999 operand->size = instruction->address_width;
1000 operand->element_type = ZYDIS_ELEMENT_TYPE_INT;
1001 } else
1002 {
1003 ZYAN_ASSERT(definition->size[context->eosz_index] ||
1004 (instruction->meta.category == ZYDIS_CATEGORY_AMX_TILE));
1005 operand->size = definition->size[context->eosz_index] * 8;
1006 }
1007 break;
1008 case ZYDIS_INSTRUCTION_ENCODING_EVEX:
1009 #ifndef ZYDIS_DISABLE_AVX512
1010 if (definition->size[context->eosz_index])
1011 {
1012 // Operand size is hardcoded
1013 operand->size = definition->size[context->eosz_index] * 8;
1014 } else
1015 {
1016 // Operand size depends on the tuple-type, the element-size and the number of
1017 // elements
1018 ZYAN_ASSERT(instruction->avx.vector_length);
1019 ZYAN_ASSERT(context->evex.element_size);
1020 switch (context->evex.tuple_type)
1021 {
1022 case ZYDIS_TUPLETYPE_FV:
1023 if (instruction->avx.broadcast.mode)
1024 {
1025 operand->size = context->evex.element_size;
1026 } else
1027 {
1028 operand->size = instruction->avx.vector_length;
1029 }
1030 break;
1031 case ZYDIS_TUPLETYPE_HV:
1032 if (instruction->avx.broadcast.mode)
1033 {
1034 operand->size = context->evex.element_size;
1035 } else
1036 {
1037 operand->size = (ZyanU16)instruction->avx.vector_length / 2;
1038 }
1039 break;
1040 case ZYDIS_TUPLETYPE_QUARTER:
1041 if (instruction->avx.broadcast.mode)
1042 {
1043 operand->size = context->evex.element_size;
1044 }
1045 else
1046 {
1047 operand->size = (ZyanU16)instruction->avx.vector_length / 4;
1048 }
1049 break;
1050 default:
1051 ZYAN_UNREACHABLE;
1052 }
1053 }
1054 ZYAN_ASSERT(operand->size);
1055 #else
1056 ZYAN_UNREACHABLE;
1057 #endif
1058 break;
1059 case ZYDIS_INSTRUCTION_ENCODING_MVEX:
1060 #ifndef ZYDIS_DISABLE_KNC
1061 if (definition->size[context->eosz_index])
1062 {
1063 // Operand size is hardcoded
1064 operand->size = definition->size[context->eosz_index] * 8;
1065 } else
1066 {
1067 ZYAN_ASSERT(definition->element_type == ZYDIS_IELEMENT_TYPE_VARIABLE);
1068 ZYAN_ASSERT(instruction->avx.vector_length == 512);
1069
1070 switch (instruction->avx.conversion.mode)
1071 {
1072 case ZYDIS_CONVERSION_MODE_INVALID:
1073 operand->size = 512;
1074 switch (context->mvex.functionality)
1075 {
1076 case ZYDIS_MVEX_FUNC_SF_32:
1077 case ZYDIS_MVEX_FUNC_SF_32_BCST_4TO16:
1078 case ZYDIS_MVEX_FUNC_UF_32:
1079 case ZYDIS_MVEX_FUNC_DF_32:
1080 operand->element_type = ZYDIS_ELEMENT_TYPE_FLOAT32;
1081 operand->element_size = 32;
1082 break;
1083 case ZYDIS_MVEX_FUNC_SF_32_BCST:
1084 operand->size = 256;
1085 operand->element_type = ZYDIS_ELEMENT_TYPE_FLOAT32;
1086 operand->element_size = 32;
1087 break;
1088 case ZYDIS_MVEX_FUNC_SI_32:
1089 case ZYDIS_MVEX_FUNC_SI_32_BCST_4TO16:
1090 case ZYDIS_MVEX_FUNC_UI_32:
1091 case ZYDIS_MVEX_FUNC_DI_32:
1092 operand->element_type = ZYDIS_ELEMENT_TYPE_INT;
1093 operand->element_size = 32;
1094 break;
1095 case ZYDIS_MVEX_FUNC_SI_32_BCST:
1096 operand->size = 256;
1097 operand->element_type = ZYDIS_ELEMENT_TYPE_INT;
1098 operand->element_size = 32;
1099 break;
1100 case ZYDIS_MVEX_FUNC_SF_64:
1101 case ZYDIS_MVEX_FUNC_UF_64:
1102 case ZYDIS_MVEX_FUNC_DF_64:
1103 operand->element_type = ZYDIS_ELEMENT_TYPE_FLOAT64;
1104 operand->element_size = 64;
1105 break;
1106 case ZYDIS_MVEX_FUNC_SI_64:
1107 case ZYDIS_MVEX_FUNC_UI_64:
1108 case ZYDIS_MVEX_FUNC_DI_64:
1109 operand->element_type = ZYDIS_ELEMENT_TYPE_INT;
1110 operand->element_size = 64;
1111 break;
1112 default:
1113 ZYAN_UNREACHABLE;
1114 }
1115 break;
1116 case ZYDIS_CONVERSION_MODE_FLOAT16:
1117 operand->size = 256;
1118 operand->element_type = ZYDIS_ELEMENT_TYPE_FLOAT16;
1119 operand->element_size = 16;
1120 break;
1121 case ZYDIS_CONVERSION_MODE_SINT16:
1122 operand->size = 256;
1123 operand->element_type = ZYDIS_ELEMENT_TYPE_INT;
1124 operand->element_size = 16;
1125 break;
1126 case ZYDIS_CONVERSION_MODE_UINT16:
1127 operand->size = 256;
1128 operand->element_type = ZYDIS_ELEMENT_TYPE_UINT;
1129 operand->element_size = 16;
1130 break;
1131 case ZYDIS_CONVERSION_MODE_SINT8:
1132 operand->size = 128;
1133 operand->element_type = ZYDIS_ELEMENT_TYPE_INT;
1134 operand->element_size = 8;
1135 break;
1136 case ZYDIS_CONVERSION_MODE_UINT8:
1137 operand->size = 128;
1138 operand->element_type = ZYDIS_ELEMENT_TYPE_UINT;
1139 operand->element_size = 8;
1140 break;
1141 default:
1142 ZYAN_UNREACHABLE;
1143 }
1144
1145 switch (instruction->avx.broadcast.mode)
1146 {
1147 case ZYDIS_BROADCAST_MODE_INVALID:
1148 // Nothing to do here
1149 break;
1150 case ZYDIS_BROADCAST_MODE_1_TO_8:
1151 case ZYDIS_BROADCAST_MODE_1_TO_16:
1152 operand->size = operand->element_size;
1153 break;
1154 case ZYDIS_BROADCAST_MODE_4_TO_8:
1155 case ZYDIS_BROADCAST_MODE_4_TO_16:
1156 operand->size = operand->element_size * 4;
1157 break;
1158 default:
1159 ZYAN_UNREACHABLE;
1160 }
1161 }
1162 #else
1163 ZYAN_UNREACHABLE;
1164 #endif
1165 break;
1166 default:
1167 ZYAN_UNREACHABLE;
1168 }
1169 break;
1170 case ZYDIS_OPERAND_TYPE_POINTER:
1171 ZYAN_ASSERT((instruction->raw.imm[0].size == 16) ||
1172 (instruction->raw.imm[0].size == 32));
1173 ZYAN_ASSERT( instruction->raw.imm[1].size == 16);
1174 operand->size = instruction->raw.imm[0].size + instruction->raw.imm[1].size;
1175 break;
1176 case ZYDIS_OPERAND_TYPE_IMMEDIATE:
1177 operand->size = definition->size[context->eosz_index] * 8;
1178 break;
1179 default:
1180 ZYAN_UNREACHABLE;
1181 }
1182
1183 // Element-type and -size
1184 if (definition->element_type && (definition->element_type != ZYDIS_IELEMENT_TYPE_VARIABLE))
1185 {
1186 ZydisGetElementInfo(definition->element_type, &operand->element_type,
1187 &operand->element_size);
1188 if (!operand->element_size)
1189 {
1190 // The element size is the same as the operand size. This is used for single element
1191 // scaling operands
1192 operand->element_size = operand->size;
1193 }
1194 }
1195
1196 // Element count
1197 if (operand->element_size && operand->size && (operand->element_type != ZYDIS_ELEMENT_TYPE_CC))
1198 {
1199 operand->element_count = operand->size / operand->element_size;
1200 } else
1201 {
1202 operand->element_count = 1;
1203 }
1204 }
1205 #endif
1206
1207 #ifndef ZYDIS_MINIMAL_MODE
1208 /**
1209 * Decodes an register-operand.
1210 *
1211 * @param instruction A pointer to the `ZydisDecodedInstruction` struct.
1212 * @param operand A pointer to the `ZydisDecodedOperand` struct.
1213 * @param register_class The register class.
1214 * @param register_id The register id.
1215 *
1216 * @return A zyan status code.
1217 */
ZydisDecodeOperandRegister(const ZydisDecodedInstruction * instruction,ZydisDecodedOperand * operand,ZydisRegisterClass register_class,ZyanU8 register_id)1218 static ZyanStatus ZydisDecodeOperandRegister(const ZydisDecodedInstruction* instruction,
1219 ZydisDecodedOperand* operand, ZydisRegisterClass register_class, ZyanU8 register_id)
1220 {
1221 ZYAN_ASSERT(instruction);
1222 ZYAN_ASSERT(operand);
1223
1224 operand->type = ZYDIS_OPERAND_TYPE_REGISTER;
1225
1226 if (register_class == ZYDIS_REGCLASS_GPR8)
1227 {
1228 if ((instruction->attributes & ZYDIS_ATTRIB_HAS_REX) && (register_id >= 4))
1229 {
1230 operand->reg.value = ZYDIS_REGISTER_SPL + (register_id - 4);
1231 } else
1232 {
1233 operand->reg.value = ZYDIS_REGISTER_AL + register_id;
1234 }
1235 } else
1236 {
1237 operand->reg.value = ZydisRegisterEncode(register_class, register_id);
1238 ZYAN_ASSERT(operand->reg.value);
1239 /*if (!operand->reg.value)
1240 {
1241 return ZYAN_STATUS_BAD_REGISTER;
1242 }*/
1243 }
1244
1245 return ZYAN_STATUS_SUCCESS;
1246 }
1247 #endif
1248
1249 #ifndef ZYDIS_MINIMAL_MODE
1250 /**
1251 * Decodes a memory operand.
1252 *
1253 * @param context A pointer to the `ZydisDecoderContext` struct.
1254 * @param instruction A pointer to the `ZydisDecodedInstruction` struct.
1255 * @param operand A pointer to the `ZydisDecodedOperand` struct.
1256 * @param vidx_register_class The register-class to use as the index register-class for
1257 * instructions with `VSIB` addressing.
1258 *
1259 * @return A zyan status code.
1260 */
ZydisDecodeOperandMemory(const ZydisDecoderContext * context,const ZydisDecodedInstruction * instruction,ZydisDecodedOperand * operand,ZydisRegisterClass vidx_register_class)1261 static ZyanStatus ZydisDecodeOperandMemory(const ZydisDecoderContext* context,
1262 const ZydisDecodedInstruction* instruction, ZydisDecodedOperand* operand,
1263 ZydisRegisterClass vidx_register_class)
1264 {
1265 ZYAN_ASSERT(context);
1266 ZYAN_ASSERT(instruction);
1267 ZYAN_ASSERT(operand);
1268 ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_MODRM);
1269 ZYAN_ASSERT(instruction->raw.modrm.mod != 3);
1270 ZYAN_ASSERT(!vidx_register_class || ((instruction->raw.modrm.rm == 4) &&
1271 ((instruction->address_width == 32) || (instruction->address_width == 64))));
1272
1273 operand->type = ZYDIS_OPERAND_TYPE_MEMORY;
1274 operand->mem.type = ZYDIS_MEMOP_TYPE_MEM;
1275
1276 const ZyanU8 modrm_rm = instruction->raw.modrm.rm;
1277 ZyanU8 displacement_size = 0;
1278 switch (instruction->address_width)
1279 {
1280 case 16:
1281 {
1282 static const ZydisRegister bases[] =
1283 {
1284 ZYDIS_REGISTER_BX, ZYDIS_REGISTER_BX, ZYDIS_REGISTER_BP, ZYDIS_REGISTER_BP,
1285 ZYDIS_REGISTER_SI, ZYDIS_REGISTER_DI, ZYDIS_REGISTER_BP, ZYDIS_REGISTER_BX
1286 };
1287 static const ZydisRegister indices[] =
1288 {
1289 ZYDIS_REGISTER_SI, ZYDIS_REGISTER_DI, ZYDIS_REGISTER_SI, ZYDIS_REGISTER_DI,
1290 ZYDIS_REGISTER_NONE, ZYDIS_REGISTER_NONE, ZYDIS_REGISTER_NONE, ZYDIS_REGISTER_NONE
1291 };
1292 operand->mem.base = bases[modrm_rm];
1293 operand->mem.index = indices[modrm_rm];
1294 operand->mem.scale = (operand->mem.index == ZYDIS_REGISTER_NONE) ? 0 : 1;
1295 switch (instruction->raw.modrm.mod)
1296 {
1297 case 0:
1298 if (modrm_rm == 6)
1299 {
1300 displacement_size = 16;
1301 operand->mem.base = ZYDIS_REGISTER_NONE;
1302 }
1303 break;
1304 case 1:
1305 displacement_size = 8;
1306 break;
1307 case 2:
1308 displacement_size = 16;
1309 break;
1310 default:
1311 ZYAN_UNREACHABLE;
1312 }
1313 break;
1314 }
1315 case 32:
1316 {
1317 operand->mem.base = ZYDIS_REGISTER_EAX + ZydisCalcRegisterId(context, instruction,
1318 ZYDIS_REG_ENCODING_BASE, ZYDIS_REGCLASS_GPR32);
1319 switch (instruction->raw.modrm.mod)
1320 {
1321 case 0:
1322 if (modrm_rm == 5)
1323 {
1324 if (instruction->machine_mode == ZYDIS_MACHINE_MODE_LONG_64)
1325 {
1326 operand->mem.base = ZYDIS_REGISTER_EIP;
1327 } else
1328 {
1329 operand->mem.base = ZYDIS_REGISTER_NONE;
1330 }
1331 displacement_size = 32;
1332 }
1333 break;
1334 case 1:
1335 displacement_size = 8;
1336 break;
1337 case 2:
1338 displacement_size = 32;
1339 break;
1340 default:
1341 ZYAN_UNREACHABLE;
1342 }
1343 if (modrm_rm == 4)
1344 {
1345 ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_SIB);
1346 operand->mem.index =
1347 ZydisRegisterEncode(vidx_register_class ? vidx_register_class : ZYDIS_REGCLASS_GPR32,
1348 ZydisCalcRegisterId(context, instruction,
1349 vidx_register_class ? ZYDIS_REG_ENCODING_VIDX : ZYDIS_REG_ENCODING_INDEX,
1350 vidx_register_class ? vidx_register_class : ZYDIS_REGCLASS_GPR32));
1351 operand->mem.scale = (1 << instruction->raw.sib.scale);
1352 if (operand->mem.index == ZYDIS_REGISTER_ESP)
1353 {
1354 operand->mem.index = ZYDIS_REGISTER_NONE;
1355 operand->mem.scale = 0;
1356 }
1357 if (operand->mem.base == ZYDIS_REGISTER_EBP)
1358 {
1359 if (instruction->raw.modrm.mod == 0)
1360 {
1361 operand->mem.base = ZYDIS_REGISTER_NONE;
1362 }
1363 displacement_size = (instruction->raw.modrm.mod == 1) ? 8 : 32;
1364 }
1365 } else
1366 {
1367 operand->mem.index = ZYDIS_REGISTER_NONE;
1368 operand->mem.scale = 0;
1369 }
1370 break;
1371 }
1372 case 64:
1373 {
1374 operand->mem.base = ZYDIS_REGISTER_RAX + ZydisCalcRegisterId(context, instruction,
1375 ZYDIS_REG_ENCODING_BASE, ZYDIS_REGCLASS_GPR64);
1376 switch (instruction->raw.modrm.mod)
1377 {
1378 case 0:
1379 if (modrm_rm == 5)
1380 {
1381 if (instruction->machine_mode == ZYDIS_MACHINE_MODE_LONG_64)
1382 {
1383 operand->mem.base = ZYDIS_REGISTER_RIP;
1384 } else
1385 {
1386 operand->mem.base = ZYDIS_REGISTER_NONE;
1387 }
1388 displacement_size = 32;
1389 }
1390 break;
1391 case 1:
1392 displacement_size = 8;
1393 break;
1394 case 2:
1395 displacement_size = 32;
1396 break;
1397 default:
1398 ZYAN_UNREACHABLE;
1399 }
1400 if ((modrm_rm & 0x07) == 4)
1401 {
1402 ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_SIB);
1403 operand->mem.index =
1404 ZydisRegisterEncode(vidx_register_class ? vidx_register_class : ZYDIS_REGCLASS_GPR64,
1405 ZydisCalcRegisterId(context, instruction,
1406 vidx_register_class ? ZYDIS_REG_ENCODING_VIDX : ZYDIS_REG_ENCODING_INDEX,
1407 vidx_register_class ? vidx_register_class : ZYDIS_REGCLASS_GPR64));
1408 operand->mem.scale = (1 << instruction->raw.sib.scale);
1409 if (operand->mem.index == ZYDIS_REGISTER_RSP)
1410 {
1411 operand->mem.index = ZYDIS_REGISTER_NONE;
1412 operand->mem.scale = 0;
1413 }
1414 if ((operand->mem.base == ZYDIS_REGISTER_RBP) ||
1415 (operand->mem.base == ZYDIS_REGISTER_R13))
1416 {
1417 if (instruction->raw.modrm.mod == 0)
1418 {
1419 operand->mem.base = ZYDIS_REGISTER_NONE;
1420 }
1421 displacement_size = (instruction->raw.modrm.mod == 1) ? 8 : 32;
1422 }
1423 } else
1424 {
1425 operand->mem.index = ZYDIS_REGISTER_NONE;
1426 operand->mem.scale = 0;
1427 }
1428 break;
1429 }
1430 default:
1431 ZYAN_UNREACHABLE;
1432 }
1433 if (displacement_size)
1434 {
1435 ZYAN_ASSERT(instruction->raw.disp.size == displacement_size);
1436 operand->mem.disp.has_displacement = ZYAN_TRUE;
1437 operand->mem.disp.value = instruction->raw.disp.value;
1438 }
1439 return ZYAN_STATUS_SUCCESS;
1440 }
1441 #endif
1442
1443 #ifndef ZYDIS_MINIMAL_MODE
1444 /**
1445 * Decodes an implicit register operand.
1446 *
1447 * @param decoder A pointer to the `ZydisDecoder` instance.
1448 * @param context A pointer to the `ZydisDecoderContext` struct.
1449 * @param instruction A pointer to the `ZydisDecodedInstruction` struct.
1450 * @param operand A pointer to the `ZydisDecodedOperand` struct.
1451 * @param definition A pointer to the `ZydisOperandDefinition` struct.
1452 */
ZydisDecodeOperandImplicitRegister(const ZydisDecoder * decoder,const ZydisDecoderContext * context,const ZydisDecodedInstruction * instruction,ZydisDecodedOperand * operand,const ZydisOperandDefinition * definition)1453 static void ZydisDecodeOperandImplicitRegister(const ZydisDecoder* decoder,
1454 const ZydisDecoderContext* context, const ZydisDecodedInstruction* instruction,
1455 ZydisDecodedOperand* operand, const ZydisOperandDefinition* definition)
1456 {
1457 ZYAN_ASSERT(context);
1458 ZYAN_ASSERT(instruction);
1459 ZYAN_ASSERT(operand);
1460 ZYAN_ASSERT(definition);
1461
1462 operand->type = ZYDIS_OPERAND_TYPE_REGISTER;
1463
1464 switch (definition->op.reg.type)
1465 {
1466 case ZYDIS_IMPLREG_TYPE_STATIC:
1467 operand->reg.value = definition->op.reg.reg.reg;
1468 break;
1469 case ZYDIS_IMPLREG_TYPE_GPR_OSZ:
1470 {
1471 static const ZydisRegisterClass lookup[3] =
1472 {
1473 ZYDIS_REGCLASS_GPR16,
1474 ZYDIS_REGCLASS_GPR32,
1475 ZYDIS_REGCLASS_GPR64
1476 };
1477 operand->reg.value =
1478 ZydisRegisterEncode(lookup[context->eosz_index], definition->op.reg.reg.id);
1479 break;
1480 }
1481 case ZYDIS_IMPLREG_TYPE_GPR_ASZ:
1482 operand->reg.value = ZydisRegisterEncode(
1483 (instruction->address_width == 16) ? ZYDIS_REGCLASS_GPR16 :
1484 (instruction->address_width == 32) ? ZYDIS_REGCLASS_GPR32 : ZYDIS_REGCLASS_GPR64,
1485 definition->op.reg.reg.id);
1486 break;
1487 case ZYDIS_IMPLREG_TYPE_IP_ASZ:
1488 operand->reg.value =
1489 (instruction->address_width == 16) ? ZYDIS_REGISTER_IP :
1490 (instruction->address_width == 32) ? ZYDIS_REGISTER_EIP : ZYDIS_REGISTER_RIP;
1491 break;
1492 case ZYDIS_IMPLREG_TYPE_GPR_SSZ:
1493 operand->reg.value = ZydisRegisterEncode(
1494 (decoder->stack_width == ZYDIS_STACK_WIDTH_16) ? ZYDIS_REGCLASS_GPR16 :
1495 (decoder->stack_width == ZYDIS_STACK_WIDTH_32) ? ZYDIS_REGCLASS_GPR32 :
1496 ZYDIS_REGCLASS_GPR64,
1497 definition->op.reg.reg.id);
1498 break;
1499 case ZYDIS_IMPLREG_TYPE_IP_SSZ:
1500 operand->reg.value =
1501 (decoder->stack_width == ZYDIS_STACK_WIDTH_16) ? ZYDIS_REGISTER_EIP :
1502 (decoder->stack_width == ZYDIS_STACK_WIDTH_32) ? ZYDIS_REGISTER_EIP :
1503 ZYDIS_REGISTER_RIP;
1504 break;
1505 case ZYDIS_IMPLREG_TYPE_FLAGS_SSZ:
1506 operand->reg.value =
1507 (decoder->stack_width == ZYDIS_STACK_WIDTH_16) ? ZYDIS_REGISTER_FLAGS :
1508 (decoder->stack_width == ZYDIS_STACK_WIDTH_32) ? ZYDIS_REGISTER_EFLAGS :
1509 ZYDIS_REGISTER_RFLAGS;
1510 break;
1511 default:
1512 ZYAN_UNREACHABLE;
1513 }
1514 }
1515 #endif
1516
1517 #ifndef ZYDIS_MINIMAL_MODE
1518 /**
1519 * Decodes an implicit memory operand.
1520 *
1521 * @param decoder A pointer to the `ZydisDecoder` instance.
1522 * @param context A pointer to the `ZydisDecoderContext` struct.
1523 * @param instruction A pointer to the `ZydisDecodedInstruction` struct.
1524 * @param operand A pointer to the `ZydisDecodedOperand` struct.
1525 * @param definition A pointer to the `ZydisOperandDefinition` struct.
1526 */
ZydisDecodeOperandImplicitMemory(const ZydisDecoder * decoder,const ZydisDecoderContext * context,const ZydisDecodedInstruction * instruction,ZydisDecodedOperand * operand,const ZydisOperandDefinition * definition)1527 static void ZydisDecodeOperandImplicitMemory(const ZydisDecoder* decoder,
1528 const ZydisDecoderContext* context, const ZydisDecodedInstruction* instruction,
1529 ZydisDecodedOperand* operand, const ZydisOperandDefinition* definition)
1530 {
1531 ZYAN_ASSERT(context);
1532 ZYAN_ASSERT(operand);
1533 ZYAN_ASSERT(definition);
1534
1535 static const ZydisRegisterClass lookup[3] =
1536 {
1537 ZYDIS_REGCLASS_GPR16,
1538 ZYDIS_REGCLASS_GPR32,
1539 ZYDIS_REGCLASS_GPR64
1540 };
1541
1542 operand->type = ZYDIS_OPERAND_TYPE_MEMORY;
1543 operand->mem.type = ZYDIS_MEMOP_TYPE_MEM;
1544
1545 switch (definition->op.mem.base)
1546 {
1547 case ZYDIS_IMPLMEM_BASE_AGPR_REG:
1548 operand->mem.base = ZydisRegisterEncode(lookup[context->easz_index],
1549 ZydisCalcRegisterId(context, instruction, ZYDIS_REG_ENCODING_REG,
1550 lookup[context->easz_index]));
1551 break;
1552 case ZYDIS_IMPLMEM_BASE_AGPR_RM:
1553 operand->mem.base = ZydisRegisterEncode(lookup[context->easz_index],
1554 ZydisCalcRegisterId(context, instruction, ZYDIS_REG_ENCODING_RM,
1555 lookup[context->easz_index]));
1556 break;
1557 case ZYDIS_IMPLMEM_BASE_AAX:
1558 operand->mem.base = ZydisRegisterEncode(lookup[context->easz_index], 0);
1559 break;
1560 case ZYDIS_IMPLMEM_BASE_ADX:
1561 operand->mem.base = ZydisRegisterEncode(lookup[context->easz_index], 2);
1562 break;
1563 case ZYDIS_IMPLMEM_BASE_ABX:
1564 operand->mem.base = ZydisRegisterEncode(lookup[context->easz_index], 3);
1565 break;
1566 case ZYDIS_IMPLMEM_BASE_ASI:
1567 operand->mem.base = ZydisRegisterEncode(lookup[context->easz_index], 6);
1568 break;
1569 case ZYDIS_IMPLMEM_BASE_ADI:
1570 operand->mem.base = ZydisRegisterEncode(lookup[context->easz_index], 7);
1571 break;
1572 case ZYDIS_IMPLMEM_BASE_SSP:
1573 operand->mem.base = ZydisRegisterEncode(lookup[decoder->stack_width], 4);
1574 break;
1575 case ZYDIS_IMPLMEM_BASE_SBP:
1576 operand->mem.base = ZydisRegisterEncode(lookup[decoder->stack_width], 5);
1577 break;
1578 default:
1579 ZYAN_UNREACHABLE;
1580 }
1581
1582 if (definition->op.mem.seg)
1583 {
1584 operand->mem.segment =
1585 ZydisRegisterEncode(ZYDIS_REGCLASS_SEGMENT, definition->op.mem.seg - 1);
1586 ZYAN_ASSERT(operand->mem.segment);
1587 }
1588 }
1589 #endif
1590
1591 #ifndef ZYDIS_MINIMAL_MODE
ZydisDecodeOperands(const ZydisDecoder * decoder,const ZydisDecoderContext * context,const ZydisDecodedInstruction * instruction,ZydisDecodedOperand * operands,ZyanU8 operand_count)1592 static ZyanStatus ZydisDecodeOperands(const ZydisDecoder* decoder, const ZydisDecoderContext* context,
1593 const ZydisDecodedInstruction* instruction, ZydisDecodedOperand* operands, ZyanU8 operand_count)
1594 {
1595 ZYAN_ASSERT(decoder);
1596 ZYAN_ASSERT(context);
1597 ZYAN_ASSERT(context->definition);
1598 ZYAN_ASSERT(instruction);
1599 ZYAN_ASSERT(operands);
1600 ZYAN_ASSERT(operand_count);
1601 ZYAN_ASSERT(operand_count <= instruction->operand_count);
1602
1603 const ZydisInstructionDefinition* definition = context->definition;
1604 const ZydisOperandDefinition* operand = ZydisGetOperandDefinitions(definition);
1605
1606 ZYAN_MEMSET(operands, 0, sizeof(ZydisDecodedOperand) * operand_count);
1607
1608 ZyanU8 imm_id = 0;
1609 for (ZyanU8 i = 0; i < operand_count; ++i)
1610 {
1611 ZydisRegisterClass register_class = ZYDIS_REGCLASS_INVALID;
1612
1613 operands[i].id = i;
1614 operands[i].visibility = operand->visibility;
1615 operands[i].actions = operand->actions;
1616 ZYAN_ASSERT(!(operand->actions &
1617 ZYDIS_OPERAND_ACTION_READ & ZYDIS_OPERAND_ACTION_CONDREAD) ||
1618 (operand->actions & ZYDIS_OPERAND_ACTION_READ) ^
1619 (operand->actions & ZYDIS_OPERAND_ACTION_CONDREAD));
1620 ZYAN_ASSERT(!(operand->actions &
1621 ZYDIS_OPERAND_ACTION_WRITE & ZYDIS_OPERAND_ACTION_CONDWRITE) ||
1622 (operand->actions & ZYDIS_OPERAND_ACTION_WRITE) ^
1623 (operand->actions & ZYDIS_OPERAND_ACTION_CONDWRITE));
1624
1625 // Implicit operands
1626 switch (operand->type)
1627 {
1628 case ZYDIS_SEMANTIC_OPTYPE_IMPLICIT_REG:
1629 ZydisDecodeOperandImplicitRegister(decoder, context, instruction, &operands[i], operand);
1630 break;
1631 case ZYDIS_SEMANTIC_OPTYPE_IMPLICIT_MEM:
1632 ZydisDecodeOperandImplicitMemory(decoder, context, instruction, &operands[i], operand);
1633 break;
1634 case ZYDIS_SEMANTIC_OPTYPE_IMPLICIT_IMM1:
1635 operands[i].type = ZYDIS_OPERAND_TYPE_IMMEDIATE;
1636 operands[i].size = 8;
1637 operands[i].imm.value.u = 1;
1638 operands[i].imm.is_signed = ZYAN_FALSE;
1639 operands[i].imm.is_relative = ZYAN_FALSE;
1640 break;
1641 default:
1642 break;
1643 }
1644 if (operands[i].type)
1645 {
1646 goto FinalizeOperand;
1647 }
1648
1649 operands[i].encoding = operand->op.encoding;
1650
1651 // Register operands
1652 switch (operand->type)
1653 {
1654 case ZYDIS_SEMANTIC_OPTYPE_GPR8:
1655 register_class = ZYDIS_REGCLASS_GPR8;
1656 break;
1657 case ZYDIS_SEMANTIC_OPTYPE_GPR16:
1658 register_class = ZYDIS_REGCLASS_GPR16;
1659 break;
1660 case ZYDIS_SEMANTIC_OPTYPE_GPR32:
1661 register_class = ZYDIS_REGCLASS_GPR32;
1662 break;
1663 case ZYDIS_SEMANTIC_OPTYPE_GPR64:
1664 register_class = ZYDIS_REGCLASS_GPR64;
1665 break;
1666 case ZYDIS_SEMANTIC_OPTYPE_GPR16_32_64:
1667 ZYAN_ASSERT((instruction->operand_width == 16) || (instruction->operand_width == 32) ||
1668 (instruction->operand_width == 64));
1669 register_class =
1670 (instruction->operand_width == 16) ? ZYDIS_REGCLASS_GPR16 : (
1671 (instruction->operand_width == 32) ? ZYDIS_REGCLASS_GPR32 : ZYDIS_REGCLASS_GPR64);
1672 break;
1673 case ZYDIS_SEMANTIC_OPTYPE_GPR32_32_64:
1674 ZYAN_ASSERT((instruction->operand_width == 16) || (instruction->operand_width == 32) ||
1675 (instruction->operand_width == 64));
1676 register_class =
1677 (instruction->operand_width == 16) ? ZYDIS_REGCLASS_GPR32 : (
1678 (instruction->operand_width == 32) ? ZYDIS_REGCLASS_GPR32 : ZYDIS_REGCLASS_GPR64);
1679 break;
1680 case ZYDIS_SEMANTIC_OPTYPE_GPR16_32_32:
1681 ZYAN_ASSERT((instruction->operand_width == 16) || (instruction->operand_width == 32) ||
1682 (instruction->operand_width == 64));
1683 register_class =
1684 (instruction->operand_width == 16) ? ZYDIS_REGCLASS_GPR16 : ZYDIS_REGCLASS_GPR32;
1685 break;
1686 case ZYDIS_SEMANTIC_OPTYPE_GPR_ASZ:
1687 ZYAN_ASSERT((instruction->address_width == 16) || (instruction->address_width == 32) ||
1688 (instruction->address_width == 64));
1689 register_class =
1690 (instruction->address_width == 16) ? ZYDIS_REGCLASS_GPR16 : (
1691 (instruction->address_width == 32) ? ZYDIS_REGCLASS_GPR32 : ZYDIS_REGCLASS_GPR64);
1692 break;
1693 case ZYDIS_SEMANTIC_OPTYPE_FPR:
1694 register_class = ZYDIS_REGCLASS_X87;
1695 break;
1696 case ZYDIS_SEMANTIC_OPTYPE_MMX:
1697 register_class = ZYDIS_REGCLASS_MMX;
1698 break;
1699 case ZYDIS_SEMANTIC_OPTYPE_XMM:
1700 register_class = ZYDIS_REGCLASS_XMM;
1701 break;
1702 case ZYDIS_SEMANTIC_OPTYPE_YMM:
1703 register_class = ZYDIS_REGCLASS_YMM;
1704 break;
1705 case ZYDIS_SEMANTIC_OPTYPE_ZMM:
1706 register_class = ZYDIS_REGCLASS_ZMM;
1707 break;
1708 case ZYDIS_SEMANTIC_OPTYPE_TMM:
1709 register_class = ZYDIS_REGCLASS_TMM;
1710 break;
1711 case ZYDIS_SEMANTIC_OPTYPE_BND:
1712 register_class = ZYDIS_REGCLASS_BOUND;
1713 break;
1714 case ZYDIS_SEMANTIC_OPTYPE_SREG:
1715 register_class = ZYDIS_REGCLASS_SEGMENT;
1716 break;
1717 case ZYDIS_SEMANTIC_OPTYPE_CR:
1718 register_class = ZYDIS_REGCLASS_CONTROL;
1719 break;
1720 case ZYDIS_SEMANTIC_OPTYPE_DR:
1721 register_class = ZYDIS_REGCLASS_DEBUG;
1722 break;
1723 case ZYDIS_SEMANTIC_OPTYPE_MASK:
1724 register_class = ZYDIS_REGCLASS_MASK;
1725 break;
1726 default:
1727 break;
1728 }
1729 if (register_class)
1730 {
1731 switch (operand->op.encoding)
1732 {
1733 case ZYDIS_OPERAND_ENCODING_MODRM_REG:
1734 ZYAN_CHECK(
1735 ZydisDecodeOperandRegister(
1736 instruction, &operands[i], register_class,
1737 ZydisCalcRegisterId(
1738 context, instruction, ZYDIS_REG_ENCODING_REG, register_class)));
1739 break;
1740 case ZYDIS_OPERAND_ENCODING_MODRM_RM:
1741 ZYAN_CHECK(
1742 ZydisDecodeOperandRegister(
1743 instruction, &operands[i], register_class,
1744 ZydisCalcRegisterId(
1745 context, instruction, ZYDIS_REG_ENCODING_RM, register_class)));
1746 break;
1747 case ZYDIS_OPERAND_ENCODING_OPCODE:
1748 ZYAN_CHECK(
1749 ZydisDecodeOperandRegister(
1750 instruction, &operands[i], register_class,
1751 ZydisCalcRegisterId(
1752 context, instruction, ZYDIS_REG_ENCODING_OPCODE, register_class)));
1753 break;
1754 case ZYDIS_OPERAND_ENCODING_NDSNDD:
1755 ZYAN_CHECK(
1756 ZydisDecodeOperandRegister(
1757 instruction, &operands[i], register_class,
1758 ZydisCalcRegisterId(
1759 context, instruction, ZYDIS_REG_ENCODING_NDSNDD, register_class)));
1760 break;
1761 case ZYDIS_OPERAND_ENCODING_MASK:
1762 ZYAN_CHECK(
1763 ZydisDecodeOperandRegister(
1764 instruction, &operands[i], register_class,
1765 ZydisCalcRegisterId(
1766 context, instruction, ZYDIS_REG_ENCODING_MASK, register_class)));
1767 break;
1768 case ZYDIS_OPERAND_ENCODING_IS4:
1769 ZYAN_CHECK(
1770 ZydisDecodeOperandRegister(
1771 instruction, &operands[i], register_class,
1772 ZydisCalcRegisterId(
1773 context, instruction, ZYDIS_REG_ENCODING_IS4, register_class)));
1774 break;
1775 default:
1776 ZYAN_UNREACHABLE;
1777 }
1778
1779 if (operand->is_multisource4)
1780 {
1781 operands[i].attributes |= ZYDIS_OATTRIB_IS_MULTISOURCE4;
1782 }
1783
1784 goto FinalizeOperand;
1785 }
1786
1787 // Memory operands
1788 switch (operand->type)
1789 {
1790 case ZYDIS_SEMANTIC_OPTYPE_MEM:
1791 ZYAN_CHECK(
1792 ZydisDecodeOperandMemory(
1793 context, instruction, &operands[i], ZYDIS_REGCLASS_INVALID));
1794 break;
1795 case ZYDIS_SEMANTIC_OPTYPE_MEM_VSIBX:
1796 ZYAN_CHECK(
1797 ZydisDecodeOperandMemory(
1798 context, instruction, &operands[i], ZYDIS_REGCLASS_XMM));
1799 operands[i].mem.type = ZYDIS_MEMOP_TYPE_VSIB;
1800 break;
1801 case ZYDIS_SEMANTIC_OPTYPE_MEM_VSIBY:
1802 ZYAN_CHECK(
1803 ZydisDecodeOperandMemory(
1804 context, instruction, &operands[i], ZYDIS_REGCLASS_YMM));
1805 operands[i].mem.type = ZYDIS_MEMOP_TYPE_VSIB;
1806 break;
1807 case ZYDIS_SEMANTIC_OPTYPE_MEM_VSIBZ:
1808 ZYAN_CHECK(
1809 ZydisDecodeOperandMemory(
1810 context, instruction, &operands[i], ZYDIS_REGCLASS_ZMM));
1811 operands[i].mem.type = ZYDIS_MEMOP_TYPE_VSIB;
1812 break;
1813 case ZYDIS_SEMANTIC_OPTYPE_PTR:
1814 ZYAN_ASSERT((instruction->raw.imm[0].size == 16) ||
1815 (instruction->raw.imm[0].size == 32));
1816 ZYAN_ASSERT(instruction->raw.imm[1].size == 16);
1817 operands[i].type = ZYDIS_OPERAND_TYPE_POINTER;
1818 operands[i].ptr.offset = (ZyanU32)instruction->raw.imm[0].value.u;
1819 operands[i].ptr.segment = (ZyanU16)instruction->raw.imm[1].value.u;
1820 break;
1821 case ZYDIS_SEMANTIC_OPTYPE_AGEN:
1822 operands[i].actions = 0; // TODO: Remove after generator update
1823 ZYAN_CHECK(
1824 ZydisDecodeOperandMemory(
1825 context, instruction, &operands[i], ZYDIS_REGCLASS_INVALID));
1826 operands[i].mem.type = ZYDIS_MEMOP_TYPE_AGEN;
1827 break;
1828 case ZYDIS_SEMANTIC_OPTYPE_MOFFS:
1829 ZYAN_ASSERT(instruction->raw.disp.size);
1830 operands[i].type = ZYDIS_OPERAND_TYPE_MEMORY;
1831 operands[i].mem.type = ZYDIS_MEMOP_TYPE_MEM;
1832 operands[i].mem.disp.has_displacement = ZYAN_TRUE;
1833 operands[i].mem.disp.value = instruction->raw.disp.value;
1834 break;
1835 case ZYDIS_SEMANTIC_OPTYPE_MIB:
1836 operands[i].actions = 0; // TODO: Remove after generator update
1837 ZYAN_CHECK(
1838 ZydisDecodeOperandMemory(
1839 context, instruction, &operands[i], ZYDIS_REGCLASS_INVALID));
1840 operands[i].mem.type = ZYDIS_MEMOP_TYPE_MIB;
1841 break;
1842 default:
1843 break;
1844 }
1845 if (operands[i].type)
1846 {
1847 #if !defined(ZYDIS_DISABLE_AVX512) || !defined(ZYDIS_DISABLE_KNC)
1848 // Handle compressed 8-bit displacement
1849 if (((instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_EVEX) ||
1850 (instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_MVEX)) &&
1851 (instruction->raw.disp.size == 8))
1852 {
1853 operands[i].mem.disp.value *= context->cd8_scale;
1854 }
1855 #endif
1856
1857 goto FinalizeOperand;
1858 }
1859
1860 // Immediate operands
1861 switch (operand->type)
1862 {
1863 case ZYDIS_SEMANTIC_OPTYPE_REL:
1864 ZYAN_ASSERT(instruction->raw.imm[imm_id].is_relative);
1865 ZYAN_FALLTHROUGH;
1866 case ZYDIS_SEMANTIC_OPTYPE_IMM:
1867 ZYAN_ASSERT((imm_id == 0) || (imm_id == 1));
1868 operands[i].type = ZYDIS_OPERAND_TYPE_IMMEDIATE;
1869 operands[i].size = operand->size[context->eosz_index] * 8;
1870 if (operand->op.encoding == ZYDIS_OPERAND_ENCODING_IS4)
1871 {
1872 // The upper half of the 8-bit immediate is used to encode a register specifier
1873 ZYAN_ASSERT(instruction->raw.imm[imm_id].size == 8);
1874 operands[i].imm.value.u = (ZyanU8)instruction->raw.imm[imm_id].value.u & 0x0F;
1875 }
1876 else
1877 {
1878 operands[i].imm.value.u = instruction->raw.imm[imm_id].value.u;
1879 }
1880 operands[i].imm.is_signed = instruction->raw.imm[imm_id].is_signed;
1881 operands[i].imm.is_relative = instruction->raw.imm[imm_id].is_relative;
1882 ++imm_id;
1883 break;
1884 default:
1885 break;
1886 }
1887 ZYAN_ASSERT(operands[i].type == ZYDIS_OPERAND_TYPE_IMMEDIATE);
1888
1889 FinalizeOperand:
1890 // Set segment-register for memory operands
1891 if (operands[i].type == ZYDIS_OPERAND_TYPE_MEMORY)
1892 {
1893 if (!operand->ignore_seg_override &&
1894 instruction->attributes & ZYDIS_ATTRIB_HAS_SEGMENT_CS)
1895 {
1896 operands[i].mem.segment = ZYDIS_REGISTER_CS;
1897 }
1898 else
1899 if (!operand->ignore_seg_override &&
1900 instruction->attributes & ZYDIS_ATTRIB_HAS_SEGMENT_SS)
1901 {
1902 operands[i].mem.segment = ZYDIS_REGISTER_SS;
1903 }
1904 else
1905 if (!operand->ignore_seg_override &&
1906 instruction->attributes & ZYDIS_ATTRIB_HAS_SEGMENT_DS)
1907 {
1908 operands[i].mem.segment = ZYDIS_REGISTER_DS;
1909 }
1910 else
1911 if (!operand->ignore_seg_override &&
1912 instruction->attributes & ZYDIS_ATTRIB_HAS_SEGMENT_ES)
1913 {
1914 operands[i].mem.segment = ZYDIS_REGISTER_ES;
1915 }
1916 else
1917 if (!operand->ignore_seg_override &&
1918 instruction->attributes & ZYDIS_ATTRIB_HAS_SEGMENT_FS)
1919 {
1920 operands[i].mem.segment = ZYDIS_REGISTER_FS;
1921 }
1922 else
1923 if (!operand->ignore_seg_override &&
1924 instruction->attributes & ZYDIS_ATTRIB_HAS_SEGMENT_GS)
1925 {
1926 operands[i].mem.segment = ZYDIS_REGISTER_GS;
1927 }
1928 else
1929 {
1930 if (operands[i].mem.segment == ZYDIS_REGISTER_NONE)
1931 {
1932 if ((operands[i].mem.base == ZYDIS_REGISTER_RSP) ||
1933 (operands[i].mem.base == ZYDIS_REGISTER_RBP) ||
1934 (operands[i].mem.base == ZYDIS_REGISTER_ESP) ||
1935 (operands[i].mem.base == ZYDIS_REGISTER_EBP) ||
1936 (operands[i].mem.base == ZYDIS_REGISTER_SP) ||
1937 (operands[i].mem.base == ZYDIS_REGISTER_BP))
1938 {
1939 operands[i].mem.segment = ZYDIS_REGISTER_SS;
1940 }
1941 else
1942 {
1943 operands[i].mem.segment = ZYDIS_REGISTER_DS;
1944 }
1945 }
1946 }
1947 }
1948
1949 ZydisSetOperandSizeAndElementInfo(context, instruction, &operands[i], operand);
1950 ++operand;
1951 }
1952
1953 #if !defined(ZYDIS_DISABLE_AVX512) || !defined(ZYDIS_DISABLE_KNC)
1954 // Fix operand-action for EVEX/MVEX instructions with merge-mask
1955 if (instruction->avx.mask.mode == ZYDIS_MASK_MODE_MERGING)
1956 {
1957 ZYAN_ASSERT(operand_count >= 1);
1958 switch (operands[0].actions)
1959 {
1960 case ZYDIS_OPERAND_ACTION_WRITE:
1961 if (operands[0].type == ZYDIS_OPERAND_TYPE_MEMORY)
1962 {
1963 operands[0].actions = ZYDIS_OPERAND_ACTION_CONDWRITE;
1964 }
1965 else
1966 {
1967 operands[0].actions = ZYDIS_OPERAND_ACTION_READ_CONDWRITE;
1968 }
1969 break;
1970 case ZYDIS_OPERAND_ACTION_READWRITE:
1971 operands[0].actions = ZYDIS_OPERAND_ACTION_READ_CONDWRITE;
1972 break;
1973 default:
1974 break;
1975 }
1976 }
1977 #endif
1978
1979 return ZYAN_STATUS_SUCCESS;
1980 }
1981 #endif
1982
1983 /* ---------------------------------------------------------------------------------------------- */
1984
1985 #ifndef ZYDIS_MINIMAL_MODE
1986 /**
1987 * Sets attributes for the given instruction.
1988 *
1989 * @param state A pointer to the `ZydisDecoderState` struct.
1990 * @param instruction A pointer to the `ZydisDecodedInstruction` struct.
1991 * @param definition A pointer to the `ZydisInstructionDefinition` struct.
1992 */
ZydisSetAttributes(ZydisDecoderState * state,ZydisDecodedInstruction * instruction,const ZydisInstructionDefinition * definition)1993 static void ZydisSetAttributes(ZydisDecoderState* state, ZydisDecodedInstruction* instruction,
1994 const ZydisInstructionDefinition* definition)
1995 {
1996 ZYAN_ASSERT(state);
1997 ZYAN_ASSERT(instruction);
1998 ZYAN_ASSERT(definition);
1999
2000 if (definition->cpu_state != ZYDIS_RW_ACTION_NONE)
2001 {
2002 static const ZydisInstructionAttributes mapping[ZYDIS_RW_ACTION_MAX_VALUE + 1] =
2003 {
2004 /* NONE */ 0,
2005 /* READ */ ZYDIS_ATTRIB_CPU_STATE_CR,
2006 /* WRITE */ ZYDIS_ATTRIB_CPU_STATE_CW,
2007 /* READWRITE */ ZYDIS_ATTRIB_CPU_STATE_CR | ZYDIS_ATTRIB_CPU_STATE_CW
2008 };
2009 ZYAN_ASSERT(definition->cpu_state < ZYAN_ARRAY_LENGTH(mapping));
2010 instruction->attributes |= mapping[definition->cpu_state];
2011 }
2012
2013 if (definition->fpu_state != ZYDIS_RW_ACTION_NONE)
2014 {
2015 static const ZydisInstructionAttributes mapping[ZYDIS_RW_ACTION_MAX_VALUE + 1] =
2016 {
2017 /* NONE */ 0,
2018 /* READ */ ZYDIS_ATTRIB_FPU_STATE_CR,
2019 /* WRITE */ ZYDIS_ATTRIB_FPU_STATE_CW,
2020 /* READWRITE */ ZYDIS_ATTRIB_FPU_STATE_CR | ZYDIS_ATTRIB_FPU_STATE_CW
2021 };
2022 ZYAN_ASSERT(definition->fpu_state < ZYAN_ARRAY_LENGTH(mapping));
2023 instruction->attributes |= mapping[definition->fpu_state];
2024 }
2025
2026 if (definition->xmm_state != ZYDIS_RW_ACTION_NONE)
2027 {
2028 static const ZydisInstructionAttributes mapping[ZYDIS_RW_ACTION_MAX_VALUE + 1] =
2029 {
2030 /* NONE */ 0,
2031 /* READ */ ZYDIS_ATTRIB_XMM_STATE_CR,
2032 /* WRITE */ ZYDIS_ATTRIB_XMM_STATE_CW,
2033 /* READWRITE */ ZYDIS_ATTRIB_XMM_STATE_CR | ZYDIS_ATTRIB_XMM_STATE_CW
2034 };
2035 ZYAN_ASSERT(definition->xmm_state < ZYAN_ARRAY_LENGTH(mapping));
2036 instruction->attributes |= mapping[definition->xmm_state];
2037 }
2038
2039 switch (instruction->encoding)
2040 {
2041 case ZYDIS_INSTRUCTION_ENCODING_LEGACY:
2042 {
2043 const ZydisInstructionDefinitionLEGACY* def =
2044 (const ZydisInstructionDefinitionLEGACY*)definition;
2045
2046 if (def->is_privileged)
2047 {
2048 instruction->attributes |= ZYDIS_ATTRIB_IS_PRIVILEGED;
2049 }
2050 if (def->accepts_LOCK)
2051 {
2052 instruction->attributes |= ZYDIS_ATTRIB_ACCEPTS_LOCK;
2053 if (state->prefixes.has_lock)
2054 {
2055 instruction->attributes |= ZYDIS_ATTRIB_HAS_LOCK;
2056 instruction->raw.prefixes[state->prefixes.offset_lock].type =
2057 ZYDIS_PREFIX_TYPE_EFFECTIVE;
2058 }
2059 }
2060 if (def->accepts_REP)
2061 {
2062 instruction->attributes |= ZYDIS_ATTRIB_ACCEPTS_REP;
2063 }
2064 if (def->accepts_REPEREPZ)
2065 {
2066 instruction->attributes |= ZYDIS_ATTRIB_ACCEPTS_REPE;
2067 }
2068 if (def->accepts_REPNEREPNZ)
2069 {
2070 instruction->attributes |= ZYDIS_ATTRIB_ACCEPTS_REPNE;
2071 }
2072 if (def->accepts_BOUND)
2073 {
2074 instruction->attributes |= ZYDIS_ATTRIB_ACCEPTS_BND;
2075 }
2076 if (def->accepts_XACQUIRE)
2077 {
2078 instruction->attributes |= ZYDIS_ATTRIB_ACCEPTS_XACQUIRE;
2079 }
2080 if (def->accepts_XRELEASE)
2081 {
2082 instruction->attributes |= ZYDIS_ATTRIB_ACCEPTS_XRELEASE;
2083 }
2084 if (def->accepts_hle_without_lock)
2085 {
2086 instruction->attributes |= ZYDIS_ATTRIB_ACCEPTS_HLE_WITHOUT_LOCK;
2087 }
2088
2089 switch (state->prefixes.group1)
2090 {
2091 case 0xF2:
2092 if (instruction->attributes & ZYDIS_ATTRIB_ACCEPTS_REPNE)
2093 {
2094 instruction->attributes |= ZYDIS_ATTRIB_HAS_REPNE;
2095 break;
2096 }
2097 if (instruction->attributes & ZYDIS_ATTRIB_ACCEPTS_XACQUIRE)
2098 {
2099 if ((instruction->attributes & ZYDIS_ATTRIB_HAS_LOCK) ||
2100 (def->accepts_hle_without_lock))
2101 {
2102 instruction->attributes |= ZYDIS_ATTRIB_HAS_XACQUIRE;
2103 break;
2104 }
2105 }
2106 if ((state->decoder->decoder_mode & (1 << ZYDIS_DECODER_MODE_MPX)) &&
2107 instruction->attributes & ZYDIS_ATTRIB_ACCEPTS_BND)
2108 {
2109 instruction->attributes |= ZYDIS_ATTRIB_HAS_BND;
2110 break;
2111 }
2112 break;
2113 case 0xF3:
2114 if (instruction->attributes & ZYDIS_ATTRIB_ACCEPTS_REP)
2115 {
2116 instruction->attributes |= ZYDIS_ATTRIB_HAS_REP;
2117 break;
2118 }
2119 if (instruction->attributes & ZYDIS_ATTRIB_ACCEPTS_REPE)
2120 {
2121 instruction->attributes |= ZYDIS_ATTRIB_HAS_REPE;
2122 break;
2123 }
2124 if (instruction->attributes & ZYDIS_ATTRIB_ACCEPTS_XRELEASE)
2125 {
2126 if ((instruction->attributes & ZYDIS_ATTRIB_HAS_LOCK) ||
2127 (def->accepts_hle_without_lock))
2128 {
2129 instruction->attributes |= ZYDIS_ATTRIB_HAS_XRELEASE;
2130 break;
2131 }
2132 }
2133 break;
2134 default:
2135 break;
2136 }
2137 if ((instruction->raw.prefixes[state->prefixes.offset_group1].type ==
2138 ZYDIS_PREFIX_TYPE_IGNORED) &&
2139 (instruction->attributes & (
2140 ZYDIS_ATTRIB_HAS_REP | ZYDIS_ATTRIB_HAS_REPE | ZYDIS_ATTRIB_HAS_REPNE |
2141 ZYDIS_ATTRIB_HAS_BND | ZYDIS_ATTRIB_HAS_XACQUIRE | ZYDIS_ATTRIB_HAS_XRELEASE)))
2142 {
2143 instruction->raw.prefixes[state->prefixes.offset_group1].type =
2144 ZYDIS_PREFIX_TYPE_EFFECTIVE;
2145 }
2146
2147 if (def->accepts_branch_hints)
2148 {
2149 instruction->attributes |= ZYDIS_ATTRIB_ACCEPTS_BRANCH_HINTS;
2150 switch (state->prefixes.group2)
2151 {
2152 case 0x2E:
2153 instruction->attributes |= ZYDIS_ATTRIB_HAS_BRANCH_NOT_TAKEN;
2154 instruction->raw.prefixes[state->prefixes.offset_group2].type =
2155 ZYDIS_PREFIX_TYPE_EFFECTIVE;
2156 break;
2157 case 0x3E:
2158 instruction->attributes |= ZYDIS_ATTRIB_HAS_BRANCH_TAKEN;
2159 instruction->raw.prefixes[state->prefixes.offset_group2].type =
2160 ZYDIS_PREFIX_TYPE_EFFECTIVE;
2161 break;
2162 default:
2163 break;
2164 }
2165 }
2166
2167 if (def->accepts_NOTRACK)
2168 {
2169 instruction->attributes |= ZYDIS_ATTRIB_ACCEPTS_NOTRACK;
2170 if ((state->decoder->decoder_mode & (1 << ZYDIS_DECODER_MODE_CET)) &&
2171 (state->prefixes.offset_notrack >= 0))
2172 {
2173 instruction->attributes |= ZYDIS_ATTRIB_HAS_NOTRACK;
2174 instruction->raw.prefixes[state->prefixes.offset_notrack].type =
2175 ZYDIS_PREFIX_TYPE_EFFECTIVE;
2176 }
2177 }
2178
2179 if (def->accepts_segment && !def->accepts_branch_hints)
2180 {
2181 instruction->attributes |= ZYDIS_ATTRIB_ACCEPTS_SEGMENT;
2182 if (state->prefixes.effective_segment &&
2183 !(instruction->attributes & ZYDIS_ATTRIB_HAS_NOTRACK))
2184 {
2185 switch (state->prefixes.effective_segment)
2186 {
2187 case 0x2E:
2188 instruction->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_CS;
2189 break;
2190 case 0x36:
2191 instruction->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_SS;
2192 break;
2193 case 0x3E:
2194 instruction->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_DS;
2195 break;
2196 case 0x26:
2197 instruction->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_ES;
2198 break;
2199 case 0x64:
2200 instruction->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_FS;
2201 break;
2202 case 0x65:
2203 instruction->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_GS;
2204 break;
2205 default:
2206 ZYAN_UNREACHABLE;
2207 }
2208 }
2209 if (instruction->attributes & ZYDIS_ATTRIB_HAS_SEGMENT)
2210 {
2211 instruction->raw.prefixes[state->prefixes.offset_segment].type =
2212 ZYDIS_PREFIX_TYPE_EFFECTIVE;
2213 }
2214 }
2215
2216 break;
2217 }
2218 case ZYDIS_INSTRUCTION_ENCODING_3DNOW:
2219 case ZYDIS_INSTRUCTION_ENCODING_XOP:
2220 case ZYDIS_INSTRUCTION_ENCODING_VEX:
2221 case ZYDIS_INSTRUCTION_ENCODING_EVEX:
2222 case ZYDIS_INSTRUCTION_ENCODING_MVEX:
2223 if (definition->accepts_segment)
2224 {
2225 instruction->attributes |= ZYDIS_ATTRIB_ACCEPTS_SEGMENT;
2226 if (state->prefixes.effective_segment)
2227 {
2228 switch (state->prefixes.effective_segment)
2229 {
2230 case 0x2E:
2231 instruction->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_CS;
2232 break;
2233 case 0x36:
2234 instruction->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_SS;
2235 break;
2236 case 0x3E:
2237 instruction->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_DS;
2238 break;
2239 case 0x26:
2240 instruction->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_ES;
2241 break;
2242 case 0x64:
2243 instruction->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_FS;
2244 break;
2245 case 0x65:
2246 instruction->attributes |= ZYDIS_ATTRIB_HAS_SEGMENT_GS;
2247 break;
2248 default:
2249 ZYAN_UNREACHABLE;
2250 }
2251 }
2252 if (instruction->attributes & ZYDIS_ATTRIB_HAS_SEGMENT)
2253 {
2254 instruction->raw.prefixes[state->prefixes.offset_segment].type =
2255 ZYDIS_PREFIX_TYPE_EFFECTIVE;
2256 }
2257 }
2258 break;
2259 default:
2260 ZYAN_UNREACHABLE;
2261 }
2262 }
2263 #endif
2264
2265 #ifndef ZYDIS_MINIMAL_MODE
2266 /**
2267 * Sets AVX-specific information for the given instruction.
2268 *
2269 * @param context A pointer to the `ZydisDecoderContext` struct.
2270 * @param instruction A pointer to the `ZydisDecodedInstruction` struct.
2271 * @param definition A pointer to the `ZydisInstructionDefinition` struct.
2272 *
2273 * Information set for `XOP`:
2274 * - Vector Length
2275 *
2276 * Information set for `VEX`:
2277 * - Vector length
2278 * - Static broadcast-factor
2279 *
2280 * Information set for `EVEX`:
2281 * - Vector length
2282 * - Broadcast-factor (static and dynamic)
2283 * - Rounding-mode and SAE
2284 * - Mask mode
2285 * - Compressed 8-bit displacement scale-factor
2286 *
2287 * Information set for `MVEX`:
2288 * - Vector length
2289 * - Broadcast-factor (static and dynamic)
2290 * - Rounding-mode and SAE
2291 * - Swizzle- and conversion-mode
2292 * - Mask mode
2293 * - Eviction hint
2294 * - Compressed 8-bit displacement scale-factor
2295 */
ZydisSetAVXInformation(ZydisDecoderContext * context,ZydisDecodedInstruction * instruction,const ZydisInstructionDefinition * definition)2296 static void ZydisSetAVXInformation(ZydisDecoderContext* context,
2297 ZydisDecodedInstruction* instruction, const ZydisInstructionDefinition* definition)
2298 {
2299 ZYAN_ASSERT(context);
2300 ZYAN_ASSERT(instruction);
2301 ZYAN_ASSERT(definition);
2302
2303 switch (instruction->encoding)
2304 {
2305 case ZYDIS_INSTRUCTION_ENCODING_XOP:
2306 {
2307 // Vector length
2308 static const ZyanU16 lookup[2] =
2309 {
2310 128,
2311 256
2312 };
2313 ZYAN_ASSERT(context->vector_unified.LL < ZYAN_ARRAY_LENGTH(lookup));
2314 instruction->avx.vector_length = lookup[context->vector_unified.LL];
2315 break;
2316 }
2317 case ZYDIS_INSTRUCTION_ENCODING_VEX:
2318 {
2319 // Vector length
2320 static const ZyanU16 lookup[2] =
2321 {
2322 128,
2323 256
2324 };
2325 ZYAN_ASSERT(context->vector_unified.LL < ZYAN_ARRAY_LENGTH(lookup));
2326 instruction->avx.vector_length = lookup[context->vector_unified.LL];
2327
2328 // Static broadcast-factor
2329 const ZydisInstructionDefinitionVEX* def =
2330 (const ZydisInstructionDefinitionVEX*)definition;
2331 if (def->broadcast)
2332 {
2333 instruction->avx.broadcast.is_static = ZYAN_TRUE;
2334 static ZydisBroadcastMode broadcasts[ZYDIS_VEX_STATIC_BROADCAST_MAX_VALUE + 1] =
2335 {
2336 ZYDIS_BROADCAST_MODE_INVALID,
2337 ZYDIS_BROADCAST_MODE_1_TO_2,
2338 ZYDIS_BROADCAST_MODE_1_TO_4,
2339 ZYDIS_BROADCAST_MODE_1_TO_8,
2340 ZYDIS_BROADCAST_MODE_1_TO_16,
2341 ZYDIS_BROADCAST_MODE_1_TO_32,
2342 ZYDIS_BROADCAST_MODE_2_TO_4
2343 };
2344 instruction->avx.broadcast.mode = broadcasts[def->broadcast];
2345 }
2346 break;
2347 }
2348 case ZYDIS_INSTRUCTION_ENCODING_EVEX:
2349 {
2350 #ifndef ZYDIS_DISABLE_AVX512
2351 const ZydisInstructionDefinitionEVEX* def =
2352 (const ZydisInstructionDefinitionEVEX*)definition;
2353
2354 // Vector length
2355 ZyanU8 vector_length = context->vector_unified.LL;
2356 if (def->vector_length)
2357 {
2358 vector_length = def->vector_length - 1;
2359 }
2360 static const ZyanU16 lookup[3] =
2361 {
2362 128,
2363 256,
2364 512
2365 };
2366 ZYAN_ASSERT(vector_length < ZYAN_ARRAY_LENGTH(lookup));
2367 instruction->avx.vector_length = lookup[vector_length];
2368
2369 context->evex.tuple_type = def->tuple_type;
2370 if (def->tuple_type)
2371 {
2372 ZYAN_ASSERT(instruction->raw.modrm.mod != 3);
2373 ZYAN_ASSERT(def->element_size);
2374
2375 // Element size
2376 static const ZyanU8 element_sizes[ZYDIS_IELEMENT_SIZE_MAX_VALUE + 1] =
2377 {
2378 0, 8, 16, 32, 64, 128
2379 };
2380 ZYAN_ASSERT(def->element_size < ZYAN_ARRAY_LENGTH(element_sizes));
2381 context->evex.element_size = element_sizes[def->element_size];
2382
2383 // Compressed disp8 scale and broadcast-factor
2384 switch (def->tuple_type)
2385 {
2386 case ZYDIS_TUPLETYPE_FV:
2387 {
2388 const ZyanU8 evex_b = instruction->raw.evex.b;
2389 ZYAN_ASSERT(evex_b < 2);
2390 ZYAN_ASSERT(!evex_b || ((!context->vector_unified.W && (context->evex.element_size == 16 ||
2391 context->evex.element_size == 32)) ||
2392 ( context->vector_unified.W && context->evex.element_size == 64)));
2393 ZYAN_ASSERT(!evex_b || def->functionality == ZYDIS_EVEX_FUNC_BC);
2394
2395 static const ZyanU8 scales[2][3][3] =
2396 {
2397 /*B0*/ { /*16*/ { 16, 32, 64 }, /*32*/ { 16, 32, 64 }, /*64*/ { 16, 32, 64 } },
2398 /*B1*/ { /*16*/ { 2, 2, 2 }, /*32*/ { 4, 4, 4 }, /*64*/ { 8, 8, 8 } }
2399 };
2400 static const ZydisBroadcastMode broadcasts[2][3][3] =
2401 {
2402 /*B0*/
2403 {
2404 /*16*/
2405 {
2406 ZYDIS_BROADCAST_MODE_INVALID,
2407 ZYDIS_BROADCAST_MODE_INVALID,
2408 ZYDIS_BROADCAST_MODE_INVALID
2409 },
2410 /*32*/
2411 {
2412 ZYDIS_BROADCAST_MODE_INVALID,
2413 ZYDIS_BROADCAST_MODE_INVALID,
2414 ZYDIS_BROADCAST_MODE_INVALID
2415 },
2416 /*64*/
2417 {
2418 ZYDIS_BROADCAST_MODE_INVALID,
2419 ZYDIS_BROADCAST_MODE_INVALID,
2420 ZYDIS_BROADCAST_MODE_INVALID
2421 }
2422 },
2423 /*B1*/
2424 {
2425 /*16*/
2426 {
2427 ZYDIS_BROADCAST_MODE_1_TO_8,
2428 ZYDIS_BROADCAST_MODE_1_TO_16,
2429 ZYDIS_BROADCAST_MODE_1_TO_32
2430 },
2431 /*32*/
2432 {
2433 ZYDIS_BROADCAST_MODE_1_TO_4,
2434 ZYDIS_BROADCAST_MODE_1_TO_8,
2435 ZYDIS_BROADCAST_MODE_1_TO_16
2436 },
2437 /*64*/
2438 {
2439 ZYDIS_BROADCAST_MODE_1_TO_2,
2440 ZYDIS_BROADCAST_MODE_1_TO_4,
2441 ZYDIS_BROADCAST_MODE_1_TO_8
2442 }
2443 }
2444 };
2445
2446 const ZyanU8 size_index = context->evex.element_size >> 5;
2447 ZYAN_ASSERT(size_index < 3);
2448
2449 context->cd8_scale = scales[evex_b][size_index][vector_length];
2450 instruction->avx.broadcast.mode = broadcasts[evex_b][size_index][vector_length];
2451 break;
2452 }
2453 case ZYDIS_TUPLETYPE_HV:
2454 {
2455 const ZyanU8 evex_b = instruction->raw.evex.b;
2456 ZYAN_ASSERT(evex_b < 2);
2457 ZYAN_ASSERT(!context->vector_unified.W);
2458 ZYAN_ASSERT((context->evex.element_size == 16) ||
2459 (context->evex.element_size == 32));
2460 ZYAN_ASSERT(!evex_b || def->functionality == ZYDIS_EVEX_FUNC_BC);
2461
2462 static const ZyanU8 scales[2][2][3] =
2463 {
2464 /*B0*/ { /*16*/ { 8, 16, 32 }, /*32*/ { 8, 16, 32 } },
2465 /*B1*/ { /*16*/ { 2, 2, 2 }, /*32*/ { 4, 4, 4 } }
2466 };
2467 static const ZydisBroadcastMode broadcasts[2][2][3] =
2468 {
2469 /*B0*/
2470 {
2471 /*16*/
2472 {
2473 ZYDIS_BROADCAST_MODE_INVALID,
2474 ZYDIS_BROADCAST_MODE_INVALID,
2475 ZYDIS_BROADCAST_MODE_INVALID
2476 },
2477 /*32*/
2478 {
2479 ZYDIS_BROADCAST_MODE_INVALID,
2480 ZYDIS_BROADCAST_MODE_INVALID,
2481 ZYDIS_BROADCAST_MODE_INVALID
2482 }
2483 },
2484 /*B1*/
2485 {
2486 /*16*/
2487 {
2488 ZYDIS_BROADCAST_MODE_1_TO_4,
2489 ZYDIS_BROADCAST_MODE_1_TO_8,
2490 ZYDIS_BROADCAST_MODE_1_TO_16
2491 },
2492 /*32*/
2493 {
2494 ZYDIS_BROADCAST_MODE_1_TO_2,
2495 ZYDIS_BROADCAST_MODE_1_TO_4,
2496 ZYDIS_BROADCAST_MODE_1_TO_8
2497 }
2498 }
2499 };
2500
2501 const ZyanU8 size_index = context->evex.element_size >> 5;
2502 ZYAN_ASSERT(size_index < 3);
2503
2504 context->cd8_scale = scales[evex_b][size_index][vector_length];
2505 instruction->avx.broadcast.mode = broadcasts[evex_b][size_index][vector_length];
2506 break;
2507 }
2508 case ZYDIS_TUPLETYPE_FVM:
2509 {
2510 static const ZyanU8 scales[3] =
2511 {
2512 16, 32, 64
2513 };
2514 context->cd8_scale = scales[vector_length];
2515 break;
2516 }
2517 case ZYDIS_TUPLETYPE_GSCAT:
2518 switch (context->vector_unified.W)
2519 {
2520 case 0:
2521 ZYAN_ASSERT(context->evex.element_size == 32);
2522 break;
2523 case 1:
2524 ZYAN_ASSERT(context->evex.element_size == 64);
2525 break;
2526 default:
2527 ZYAN_UNREACHABLE;
2528 }
2529 ZYAN_FALLTHROUGH;
2530 case ZYDIS_TUPLETYPE_T1S:
2531 {
2532 static const ZyanU8 scales[6] =
2533 {
2534 /* */ 0,
2535 /* 8*/ 1,
2536 /* 16*/ 2,
2537 /* 32*/ 4,
2538 /* 64*/ 8,
2539 /*128*/ 16,
2540 };
2541 ZYAN_ASSERT(def->element_size < ZYAN_ARRAY_LENGTH(scales));
2542 context->cd8_scale = scales[def->element_size];
2543 break;
2544 };
2545 case ZYDIS_TUPLETYPE_T1F:
2546 {
2547 static const ZyanU8 scales[3] =
2548 {
2549 /* 16*/ 2,
2550 /* 32*/ 4,
2551 /* 64*/ 8
2552 };
2553
2554 const ZyanU8 size_index = context->evex.element_size >> 5;
2555 ZYAN_ASSERT(size_index < 3);
2556
2557 context->cd8_scale = scales[size_index];
2558 break;
2559 }
2560 case ZYDIS_TUPLETYPE_T1_4X:
2561 ZYAN_ASSERT(context->evex.element_size == 32);
2562 ZYAN_ASSERT(context->vector_unified.W == 0);
2563 context->cd8_scale = 16;
2564 break;
2565 case ZYDIS_TUPLETYPE_T2:
2566 switch (context->vector_unified.W)
2567 {
2568 case 0:
2569 ZYAN_ASSERT(context->evex.element_size == 32);
2570 context->cd8_scale = 8;
2571 break;
2572 case 1:
2573 ZYAN_ASSERT(context->evex.element_size == 64);
2574 ZYAN_ASSERT((instruction->avx.vector_length == 256) ||
2575 (instruction->avx.vector_length == 512));
2576 context->cd8_scale = 16;
2577 break;
2578 default:
2579 ZYAN_UNREACHABLE;
2580 }
2581 break;
2582 case ZYDIS_TUPLETYPE_T4:
2583 switch (context->vector_unified.W)
2584 {
2585 case 0:
2586 ZYAN_ASSERT(context->evex.element_size == 32);
2587 ZYAN_ASSERT((instruction->avx.vector_length == 256) ||
2588 (instruction->avx.vector_length == 512));
2589 context->cd8_scale = 16;
2590 break;
2591 case 1:
2592 ZYAN_ASSERT(context->evex.element_size == 64);
2593 ZYAN_ASSERT(instruction->avx.vector_length == 512);
2594 context->cd8_scale = 32;
2595 break;
2596 default:
2597 ZYAN_UNREACHABLE;
2598 }
2599 break;
2600 case ZYDIS_TUPLETYPE_T8:
2601 ZYAN_ASSERT(!context->vector_unified.W);
2602 ZYAN_ASSERT(instruction->avx.vector_length == 512);
2603 ZYAN_ASSERT(context->evex.element_size == 32);
2604 context->cd8_scale = 32;
2605 break;
2606 case ZYDIS_TUPLETYPE_HVM:
2607 {
2608 static const ZyanU8 scales[3] =
2609 {
2610 8, 16, 32
2611 };
2612 context->cd8_scale = scales[vector_length];
2613 break;
2614 }
2615 case ZYDIS_TUPLETYPE_QVM:
2616 {
2617 static const ZyanU8 scales[3] =
2618 {
2619 4, 8, 16
2620 };
2621 context->cd8_scale = scales[vector_length];
2622 break;
2623 }
2624 case ZYDIS_TUPLETYPE_OVM:
2625 {
2626 static const ZyanU8 scales[3] =
2627 {
2628 2, 4, 8
2629 };
2630 context->cd8_scale = scales[vector_length];
2631 break;
2632 }
2633 case ZYDIS_TUPLETYPE_M128:
2634 context->cd8_scale = 16;
2635 break;
2636 case ZYDIS_TUPLETYPE_DUP:
2637 {
2638 static const ZyanU8 scales[3] =
2639 {
2640 8, 32, 64
2641 };
2642 context->cd8_scale = scales[vector_length];
2643 break;
2644 }
2645 case ZYDIS_TUPLETYPE_QUARTER:
2646 {
2647 const ZyanU8 evex_b = instruction->raw.evex.b;
2648 ZYAN_ASSERT(evex_b < 2);
2649 ZYAN_ASSERT(!context->vector_unified.W);
2650 ZYAN_ASSERT(context->evex.element_size == 16);
2651 ZYAN_ASSERT(!evex_b || def->functionality == ZYDIS_EVEX_FUNC_BC);
2652
2653 static const ZyanU8 scales[2][3] =
2654 {
2655 /*B0*/ { 4, 8, 16 },
2656 /*B1*/ { 2, 2, 2 }
2657 };
2658 static const ZydisBroadcastMode broadcasts[2][3] =
2659 {
2660 /*B0*/
2661 {
2662 ZYDIS_BROADCAST_MODE_INVALID,
2663 ZYDIS_BROADCAST_MODE_INVALID,
2664 ZYDIS_BROADCAST_MODE_INVALID
2665 },
2666 /*B1*/
2667 {
2668 ZYDIS_BROADCAST_MODE_1_TO_2,
2669 ZYDIS_BROADCAST_MODE_1_TO_4,
2670 ZYDIS_BROADCAST_MODE_1_TO_8
2671 }
2672 };
2673 context->cd8_scale = scales[evex_b][vector_length];
2674 instruction->avx.broadcast.mode = broadcasts[evex_b][vector_length];
2675 break;
2676 }
2677 default:
2678 ZYAN_UNREACHABLE;
2679 }
2680 } else
2681 {
2682 ZYAN_ASSERT(instruction->raw.modrm.mod == 3);
2683 }
2684
2685 // Static broadcast-factor
2686 if (def->broadcast)
2687 {
2688 ZYAN_ASSERT(!instruction->avx.broadcast.mode);
2689 instruction->avx.broadcast.is_static = ZYAN_TRUE;
2690 static const ZydisBroadcastMode broadcasts[ZYDIS_EVEX_STATIC_BROADCAST_MAX_VALUE + 1] =
2691 {
2692 ZYDIS_BROADCAST_MODE_INVALID,
2693 ZYDIS_BROADCAST_MODE_1_TO_2,
2694 ZYDIS_BROADCAST_MODE_1_TO_4,
2695 ZYDIS_BROADCAST_MODE_1_TO_8,
2696 ZYDIS_BROADCAST_MODE_1_TO_16,
2697 ZYDIS_BROADCAST_MODE_1_TO_32,
2698 ZYDIS_BROADCAST_MODE_1_TO_64,
2699 ZYDIS_BROADCAST_MODE_2_TO_4,
2700 ZYDIS_BROADCAST_MODE_2_TO_8,
2701 ZYDIS_BROADCAST_MODE_2_TO_16,
2702 ZYDIS_BROADCAST_MODE_4_TO_8,
2703 ZYDIS_BROADCAST_MODE_4_TO_16,
2704 ZYDIS_BROADCAST_MODE_8_TO_16
2705 };
2706 ZYAN_ASSERT(def->broadcast < ZYAN_ARRAY_LENGTH(broadcasts));
2707 instruction->avx.broadcast.mode = broadcasts[def->broadcast];
2708 }
2709
2710 // Rounding mode and SAE
2711 if (instruction->raw.evex.b)
2712 {
2713 switch (def->functionality)
2714 {
2715 case ZYDIS_EVEX_FUNC_INVALID:
2716 case ZYDIS_EVEX_FUNC_BC:
2717 // Noting to do here
2718 break;
2719 case ZYDIS_EVEX_FUNC_RC:
2720 instruction->avx.rounding.mode = ZYDIS_ROUNDING_MODE_RN + context->vector_unified.LL;
2721 ZYAN_FALLTHROUGH;
2722 case ZYDIS_EVEX_FUNC_SAE:
2723 instruction->avx.has_sae = ZYAN_TRUE;
2724 break;
2725 default:
2726 ZYAN_UNREACHABLE;
2727 }
2728 }
2729
2730 // Mask
2731 instruction->avx.mask.reg = ZYDIS_REGISTER_K0 + instruction->raw.evex.aaa;
2732 switch (def->mask_override)
2733 {
2734 case ZYDIS_MASK_OVERRIDE_DEFAULT:
2735 instruction->avx.mask.mode = ZYDIS_MASK_MODE_MERGING + instruction->raw.evex.z;
2736 break;
2737 case ZYDIS_MASK_OVERRIDE_ZEROING:
2738 instruction->avx.mask.mode = ZYDIS_MASK_MODE_ZEROING;
2739 break;
2740 case ZYDIS_MASK_OVERRIDE_CONTROL:
2741 instruction->avx.mask.mode = ZYDIS_MASK_MODE_CONTROL + instruction->raw.evex.z;
2742 break;
2743 default:
2744 ZYAN_UNREACHABLE;
2745 }
2746 if (!instruction->raw.evex.aaa)
2747 {
2748 instruction->avx.mask.mode = ZYDIS_MASK_MODE_DISABLED;
2749 }
2750 #else
2751 ZYAN_UNREACHABLE;
2752 #endif
2753 break;
2754 }
2755 case ZYDIS_INSTRUCTION_ENCODING_MVEX:
2756 {
2757 #ifndef ZYDIS_DISABLE_KNC
2758 // Vector length
2759 instruction->avx.vector_length = 512;
2760
2761 const ZydisInstructionDefinitionMVEX* def =
2762 (const ZydisInstructionDefinitionMVEX*)definition;
2763
2764 // Static broadcast-factor
2765 ZyanU8 index = def->has_element_granularity;
2766 ZYAN_ASSERT(!index || !def->broadcast);
2767 if (!index && def->broadcast)
2768 {
2769 instruction->avx.broadcast.is_static = ZYAN_TRUE;
2770 switch (def->broadcast)
2771 {
2772 case ZYDIS_MVEX_STATIC_BROADCAST_1_TO_8:
2773 instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_1_TO_8;
2774 index = 1;
2775 break;
2776 case ZYDIS_MVEX_STATIC_BROADCAST_1_TO_16:
2777 instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_1_TO_16;
2778 index = 1;
2779 break;
2780 case ZYDIS_MVEX_STATIC_BROADCAST_4_TO_8:
2781 instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_4_TO_8;
2782 index = 2;
2783 break;
2784 case ZYDIS_MVEX_STATIC_BROADCAST_4_TO_16:
2785 instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_4_TO_16;
2786 index = 2;
2787 break;
2788 default:
2789 ZYAN_UNREACHABLE;
2790 }
2791 }
2792
2793 // Compressed disp8 scale and broadcast-factor
2794 switch (def->functionality)
2795 {
2796 case ZYDIS_MVEX_FUNC_IGNORED:
2797 case ZYDIS_MVEX_FUNC_INVALID:
2798 case ZYDIS_MVEX_FUNC_RC:
2799 case ZYDIS_MVEX_FUNC_SAE:
2800 case ZYDIS_MVEX_FUNC_SWIZZLE_32:
2801 case ZYDIS_MVEX_FUNC_SWIZZLE_64:
2802 // Nothing to do here
2803 break;
2804 case ZYDIS_MVEX_FUNC_F_32:
2805 case ZYDIS_MVEX_FUNC_I_32:
2806 case ZYDIS_MVEX_FUNC_F_64:
2807 case ZYDIS_MVEX_FUNC_I_64:
2808 context->cd8_scale = 64;
2809 break;
2810 case ZYDIS_MVEX_FUNC_SF_32:
2811 case ZYDIS_MVEX_FUNC_SF_32_BCST:
2812 case ZYDIS_MVEX_FUNC_SF_32_BCST_4TO16:
2813 case ZYDIS_MVEX_FUNC_UF_32:
2814 {
2815 static const ZyanU8 lookup[3][8] =
2816 {
2817 { 64, 4, 16, 32, 16, 16, 32, 32 },
2818 { 4, 0, 0, 2, 1, 1, 2, 2 },
2819 { 16, 0, 0, 8, 4, 4, 8, 8 }
2820 };
2821 ZYAN_ASSERT(instruction->raw.mvex.SSS < ZYAN_ARRAY_LENGTH(lookup[index]));
2822 context->cd8_scale = lookup[index][instruction->raw.mvex.SSS];
2823 break;
2824 }
2825 case ZYDIS_MVEX_FUNC_SI_32:
2826 case ZYDIS_MVEX_FUNC_UI_32:
2827 case ZYDIS_MVEX_FUNC_SI_32_BCST:
2828 case ZYDIS_MVEX_FUNC_SI_32_BCST_4TO16:
2829 {
2830 static const ZyanU8 lookup[3][8] =
2831 {
2832 { 64, 4, 16, 0, 16, 16, 32, 32 },
2833 { 4, 0, 0, 0, 1, 1, 2, 2 },
2834 { 16, 0, 0, 0, 4, 4, 8, 8 }
2835 };
2836 ZYAN_ASSERT(instruction->raw.mvex.SSS < ZYAN_ARRAY_LENGTH(lookup[index]));
2837 context->cd8_scale = lookup[index][instruction->raw.mvex.SSS];
2838 break;
2839 }
2840 case ZYDIS_MVEX_FUNC_SF_64:
2841 case ZYDIS_MVEX_FUNC_UF_64:
2842 case ZYDIS_MVEX_FUNC_SI_64:
2843 case ZYDIS_MVEX_FUNC_UI_64:
2844 {
2845 static const ZyanU8 lookup[3][3] =
2846 {
2847 { 64, 8, 32 },
2848 { 8, 0, 0 },
2849 { 32, 0, 0 }
2850 };
2851 ZYAN_ASSERT(instruction->raw.mvex.SSS < ZYAN_ARRAY_LENGTH(lookup[index]));
2852 context->cd8_scale = lookup[index][instruction->raw.mvex.SSS];
2853 break;
2854 }
2855 case ZYDIS_MVEX_FUNC_DF_32:
2856 case ZYDIS_MVEX_FUNC_DI_32:
2857 {
2858 static const ZyanU8 lookup[2][8] =
2859 {
2860 { 64, 0, 0, 32, 16, 16, 32, 32 },
2861 { 4, 0, 0, 2, 1, 1, 2, 2 }
2862 };
2863 ZYAN_ASSERT(index < 2);
2864 ZYAN_ASSERT(instruction->raw.mvex.SSS < ZYAN_ARRAY_LENGTH(lookup[index]));
2865 context->cd8_scale = lookup[index][instruction->raw.mvex.SSS];
2866 break;
2867 }
2868 case ZYDIS_MVEX_FUNC_DF_64:
2869 case ZYDIS_MVEX_FUNC_DI_64:
2870 {
2871 static const ZyanU8 lookup[2][1] =
2872 {
2873 { 64 },
2874 { 8 }
2875 };
2876 ZYAN_ASSERT(index < 2);
2877 ZYAN_ASSERT(instruction->raw.mvex.SSS < ZYAN_ARRAY_LENGTH(lookup[index]));
2878 context->cd8_scale = lookup[index][instruction->raw.mvex.SSS];
2879 break;
2880 }
2881 default:
2882 ZYAN_UNREACHABLE;
2883 }
2884
2885 // Rounding mode, sae, swizzle, convert
2886 context->mvex.functionality = def->functionality;
2887 switch (def->functionality)
2888 {
2889 case ZYDIS_MVEX_FUNC_IGNORED:
2890 case ZYDIS_MVEX_FUNC_INVALID:
2891 case ZYDIS_MVEX_FUNC_F_32:
2892 case ZYDIS_MVEX_FUNC_I_32:
2893 case ZYDIS_MVEX_FUNC_F_64:
2894 case ZYDIS_MVEX_FUNC_I_64:
2895 // Nothing to do here
2896 break;
2897 case ZYDIS_MVEX_FUNC_RC:
2898 instruction->avx.rounding.mode = ZYDIS_ROUNDING_MODE_RN + (instruction->raw.mvex.SSS & 3);
2899 ZYAN_FALLTHROUGH;
2900 case ZYDIS_MVEX_FUNC_SAE:
2901 if (instruction->raw.mvex.SSS >= 4)
2902 {
2903 instruction->avx.has_sae = ZYAN_TRUE;
2904 }
2905 break;
2906 case ZYDIS_MVEX_FUNC_SWIZZLE_32:
2907 case ZYDIS_MVEX_FUNC_SWIZZLE_64:
2908 instruction->avx.swizzle.mode = ZYDIS_SWIZZLE_MODE_DCBA + instruction->raw.mvex.SSS;
2909 break;
2910 case ZYDIS_MVEX_FUNC_SF_32:
2911 case ZYDIS_MVEX_FUNC_SF_32_BCST:
2912 case ZYDIS_MVEX_FUNC_SF_32_BCST_4TO16:
2913 switch (instruction->raw.mvex.SSS)
2914 {
2915 case 0:
2916 break;
2917 case 1:
2918 instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_1_TO_16;
2919 break;
2920 case 2:
2921 instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_4_TO_16;
2922 break;
2923 case 3:
2924 instruction->avx.conversion.mode = ZYDIS_CONVERSION_MODE_FLOAT16;
2925 break;
2926 case 4:
2927 instruction->avx.conversion.mode = ZYDIS_CONVERSION_MODE_UINT8;
2928 break;
2929 case 5:
2930 instruction->avx.conversion.mode = ZYDIS_CONVERSION_MODE_SINT8;
2931 break;
2932 case 6:
2933 instruction->avx.conversion.mode = ZYDIS_CONVERSION_MODE_UINT16;
2934 break;
2935 case 7:
2936 instruction->avx.conversion.mode = ZYDIS_CONVERSION_MODE_SINT16;
2937 break;
2938 default:
2939 ZYAN_UNREACHABLE;
2940 }
2941 break;
2942 case ZYDIS_MVEX_FUNC_SI_32:
2943 case ZYDIS_MVEX_FUNC_SI_32_BCST:
2944 case ZYDIS_MVEX_FUNC_SI_32_BCST_4TO16:
2945 switch (instruction->raw.mvex.SSS)
2946 {
2947 case 0:
2948 break;
2949 case 1:
2950 instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_1_TO_16;
2951 break;
2952 case 2:
2953 instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_4_TO_16;
2954 break;
2955 case 4:
2956 instruction->avx.conversion.mode = ZYDIS_CONVERSION_MODE_UINT8;
2957 break;
2958 case 5:
2959 instruction->avx.conversion.mode = ZYDIS_CONVERSION_MODE_SINT8;
2960 break;
2961 case 6:
2962 instruction->avx.conversion.mode = ZYDIS_CONVERSION_MODE_UINT16;
2963 break;
2964 case 7:
2965 instruction->avx.conversion.mode = ZYDIS_CONVERSION_MODE_SINT16;
2966 break;
2967 default:
2968 ZYAN_UNREACHABLE;
2969 }
2970 break;
2971 case ZYDIS_MVEX_FUNC_SF_64:
2972 case ZYDIS_MVEX_FUNC_SI_64:
2973 switch (instruction->raw.mvex.SSS)
2974 {
2975 case 0:
2976 break;
2977 case 1:
2978 instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_1_TO_8;
2979 break;
2980 case 2:
2981 instruction->avx.broadcast.mode = ZYDIS_BROADCAST_MODE_4_TO_8;
2982 break;
2983 default:
2984 ZYAN_UNREACHABLE;
2985 }
2986 break;
2987 case ZYDIS_MVEX_FUNC_UF_32:
2988 case ZYDIS_MVEX_FUNC_DF_32:
2989 switch (instruction->raw.mvex.SSS)
2990 {
2991 case 0:
2992 break;
2993 case 3:
2994 instruction->avx.conversion.mode = ZYDIS_CONVERSION_MODE_FLOAT16;
2995 break;
2996 case 4:
2997 instruction->avx.conversion.mode = ZYDIS_CONVERSION_MODE_UINT8;
2998 break;
2999 case 5:
3000 instruction->avx.conversion.mode = ZYDIS_CONVERSION_MODE_SINT8;
3001 break;
3002 case 6:
3003 instruction->avx.conversion.mode = ZYDIS_CONVERSION_MODE_UINT16;
3004 break;
3005 case 7:
3006 instruction->avx.conversion.mode = ZYDIS_CONVERSION_MODE_SINT16;
3007 break;
3008 default:
3009 ZYAN_UNREACHABLE;
3010 }
3011 break;
3012 case ZYDIS_MVEX_FUNC_UF_64:
3013 case ZYDIS_MVEX_FUNC_DF_64:
3014 break;
3015 case ZYDIS_MVEX_FUNC_UI_32:
3016 case ZYDIS_MVEX_FUNC_DI_32:
3017 switch (instruction->raw.mvex.SSS)
3018 {
3019 case 0:
3020 break;
3021 case 4:
3022 instruction->avx.conversion.mode = ZYDIS_CONVERSION_MODE_UINT8;
3023 break;
3024 case 5:
3025 instruction->avx.conversion.mode = ZYDIS_CONVERSION_MODE_SINT8;
3026 break;
3027 case 6:
3028 instruction->avx.conversion.mode = ZYDIS_CONVERSION_MODE_UINT16;
3029 break;
3030 case 7:
3031 instruction->avx.conversion.mode = ZYDIS_CONVERSION_MODE_SINT16;
3032 break;
3033 default:
3034 ZYAN_UNREACHABLE;
3035 }
3036 break;
3037 case ZYDIS_MVEX_FUNC_UI_64:
3038 case ZYDIS_MVEX_FUNC_DI_64:
3039 break;
3040 default:
3041 ZYAN_UNREACHABLE;
3042 }
3043
3044 // Eviction hint
3045 if ((instruction->raw.modrm.mod != 3) && instruction->raw.mvex.E)
3046 {
3047 instruction->avx.has_eviction_hint = ZYAN_TRUE;
3048 }
3049
3050 // Mask
3051 instruction->avx.mask.mode = ZYDIS_MASK_MODE_MERGING;
3052 instruction->avx.mask.reg = ZYDIS_REGISTER_K0 + instruction->raw.mvex.kkk;
3053 #else
3054 ZYAN_UNREACHABLE;
3055 #endif
3056 break;
3057 }
3058 default:
3059 // Nothing to do here
3060 break;
3061 }
3062 }
3063 #endif
3064
3065 /* ---------------------------------------------------------------------------------------------- */
3066 /* Physical instruction decoding */
3067 /* ---------------------------------------------------------------------------------------------- */
3068
3069 /**
3070 * Collects optional instruction prefixes.
3071 *
3072 * @param state A pointer to the `ZydisDecoderState` struct.
3073 * @param instruction A pointer to the `ZydisDecodedInstruction` struct.
3074 *
3075 * @return A zyan status code.
3076 *
3077 * This function sets the corresponding flag for each prefix and automatically decodes the last
3078 * `REX`-prefix (if exists).
3079 */
ZydisCollectOptionalPrefixes(ZydisDecoderState * state,ZydisDecodedInstruction * instruction)3080 static ZyanStatus ZydisCollectOptionalPrefixes(ZydisDecoderState* state,
3081 ZydisDecodedInstruction* instruction)
3082 {
3083 ZYAN_ASSERT(state);
3084 ZYAN_ASSERT(instruction);
3085 ZYAN_ASSERT(instruction->raw.prefix_count == 0);
3086
3087 ZyanU8 rex = 0x00;
3088 ZyanU8 offset = 0;
3089 ZyanBool done = ZYAN_FALSE;
3090 do
3091 {
3092 ZyanU8 prefix_byte;
3093 ZYAN_CHECK(ZydisInputPeek(state, instruction, &prefix_byte));
3094 switch (prefix_byte)
3095 {
3096 case 0xF0:
3097 state->prefixes.has_lock = ZYAN_TRUE;
3098 state->prefixes.offset_lock = offset;
3099 break;
3100 case 0xF2:
3101 ZYAN_FALLTHROUGH;
3102 case 0xF3:
3103 state->prefixes.group1 = prefix_byte;
3104 state->prefixes.mandatory_candidate = prefix_byte;
3105 state->prefixes.offset_group1 = offset;
3106 state->prefixes.offset_mandatory = offset;
3107 break;
3108 case 0x2E:
3109 ZYAN_FALLTHROUGH;
3110 case 0x36:
3111 ZYAN_FALLTHROUGH;
3112 case 0x3E:
3113 ZYAN_FALLTHROUGH;
3114 case 0x26:
3115 if (state->decoder->machine_mode == ZYDIS_MACHINE_MODE_LONG_64)
3116 {
3117 if ((prefix_byte == 0x3E) &&
3118 (state->prefixes.effective_segment != 0x64) &&
3119 (state->prefixes.effective_segment != 0x65))
3120 {
3121 state->prefixes.offset_notrack = offset;
3122 }
3123 state->prefixes.group2 = prefix_byte;
3124 state->prefixes.offset_group2 = offset;
3125 break;
3126 }
3127 ZYAN_FALLTHROUGH;
3128 case 0x64:
3129 ZYAN_FALLTHROUGH;
3130 case 0x65:
3131 state->prefixes.group2 = prefix_byte;
3132 state->prefixes.offset_group2 = offset;
3133 state->prefixes.effective_segment = prefix_byte;
3134 state->prefixes.offset_segment = offset;
3135 state->prefixes.offset_notrack = -1;
3136 break;
3137 case 0x66:
3138 // context->prefixes.has_osz_override = ZYAN_TRUE;
3139 state->prefixes.offset_osz_override = offset;
3140 if (!state->prefixes.mandatory_candidate)
3141 {
3142 state->prefixes.mandatory_candidate = 0x66;
3143 state->prefixes.offset_mandatory = offset;
3144 }
3145 instruction->attributes |= ZYDIS_ATTRIB_HAS_OPERANDSIZE;
3146 break;
3147 case 0x67:
3148 // context->prefixes.has_asz_override = ZYAN_TRUE;
3149 state->prefixes.offset_asz_override = offset;
3150 instruction->attributes |= ZYDIS_ATTRIB_HAS_ADDRESSSIZE;
3151 break;
3152 default:
3153 if ((state->decoder->machine_mode == ZYDIS_MACHINE_MODE_LONG_64) &&
3154 (prefix_byte & 0xF0) == 0x40)
3155 {
3156 rex = prefix_byte;
3157 instruction->raw.rex.offset = offset;
3158 } else
3159 {
3160 done = ZYAN_TRUE;
3161 }
3162 break;
3163 }
3164 if (!done)
3165 {
3166 // Invalidate `REX`, if it's not the last legacy prefix
3167 if (rex && (rex != prefix_byte))
3168 {
3169 rex = 0x00;
3170 instruction->raw.rex.offset = 0;
3171 }
3172 instruction->raw.prefixes[instruction->raw.prefix_count++].value = prefix_byte;
3173 ZydisInputSkip(state, instruction);
3174 ++offset;
3175 }
3176 } while (!done);
3177
3178 if (instruction->attributes & ZYDIS_ATTRIB_HAS_OPERANDSIZE)
3179 {
3180 instruction->raw.prefixes[state->prefixes.offset_osz_override].type =
3181 ZYDIS_PREFIX_TYPE_EFFECTIVE;
3182 }
3183 if (instruction->attributes & ZYDIS_ATTRIB_HAS_ADDRESSSIZE)
3184 {
3185 instruction->raw.prefixes[state->prefixes.offset_asz_override].type =
3186 ZYDIS_PREFIX_TYPE_EFFECTIVE;
3187 }
3188 if (rex)
3189 {
3190 instruction->raw.prefixes[instruction->raw.rex.offset].type = ZYDIS_PREFIX_TYPE_EFFECTIVE;
3191 ZydisDecodeREX(state->context, instruction, rex);
3192 }
3193 if ((state->decoder->machine_mode != ZYDIS_MACHINE_MODE_LONG_64) &&
3194 (state->prefixes.group2 == 0x3E))
3195 {
3196 state->prefixes.offset_notrack = state->prefixes.offset_group2;
3197 }
3198
3199 return ZYAN_STATUS_SUCCESS;
3200 }
3201
3202 /**
3203 * Decodes optional instruction parts like the ModRM byte, the SIB byte and
3204 * additional displacements and/or immediate values.
3205 *
3206 * @param state A pointer to the `ZydisDecoderState` struct.
3207 * @param instruction A pointer to the `ZydisDecodedInstruction` struct.
3208 * @param info A pointer to the `ZydisInstructionEncodingInfo` struct.
3209 *
3210 * @return A zyan status code.
3211 */
ZydisDecodeOptionalInstructionParts(ZydisDecoderState * state,ZydisDecodedInstruction * instruction,const ZydisInstructionEncodingInfo * info)3212 static ZyanStatus ZydisDecodeOptionalInstructionParts(ZydisDecoderState* state,
3213 ZydisDecodedInstruction* instruction, const ZydisInstructionEncodingInfo* info)
3214 {
3215 ZYAN_ASSERT(state);
3216 ZYAN_ASSERT(instruction);
3217 ZYAN_ASSERT(info);
3218
3219 ZydisDecoderContext* context = state->context;
3220
3221 if (info->flags & ZYDIS_INSTR_ENC_FLAG_HAS_MODRM)
3222 {
3223 if (!instruction->raw.modrm.offset)
3224 {
3225 instruction->raw.modrm.offset = instruction->length;
3226 ZyanU8 modrm_byte;
3227 ZYAN_CHECK(ZydisInputNext(state, instruction, &modrm_byte));
3228 ZydisDecodeModRM(instruction, modrm_byte);
3229 }
3230
3231 if (!(info->flags & ZYDIS_INSTR_ENC_FLAG_FORCE_REG_FORM))
3232 {
3233 ZyanU8 has_sib = 0;
3234 ZyanU8 displacement_size = 0;
3235 switch (instruction->address_width)
3236 {
3237 case 16:
3238 switch (instruction->raw.modrm.mod)
3239 {
3240 case 0:
3241 if (instruction->raw.modrm.rm == 6)
3242 {
3243 displacement_size = 16;
3244 }
3245 break;
3246 case 1:
3247 displacement_size = 8;
3248 break;
3249 case 2:
3250 displacement_size = 16;
3251 break;
3252 case 3:
3253 break;
3254 default:
3255 ZYAN_UNREACHABLE;
3256 }
3257 break;
3258 case 32:
3259 case 64:
3260 has_sib =
3261 (instruction->raw.modrm.mod != 3) && (instruction->raw.modrm.rm == 4);
3262 switch (instruction->raw.modrm.mod)
3263 {
3264 case 0:
3265 if (instruction->raw.modrm.rm == 5)
3266 {
3267 if (instruction->machine_mode == ZYDIS_MACHINE_MODE_LONG_64)
3268 {
3269 instruction->attributes |= ZYDIS_ATTRIB_IS_RELATIVE;
3270 }
3271 displacement_size = 32;
3272 }
3273 break;
3274 case 1:
3275 displacement_size = 8;
3276 break;
3277 case 2:
3278 displacement_size = 32;
3279 break;
3280 case 3:
3281 break;
3282 default:
3283 ZYAN_UNREACHABLE;
3284 }
3285 break;
3286 default:
3287 ZYAN_UNREACHABLE;
3288 }
3289 if (has_sib)
3290 {
3291 instruction->raw.sib.offset = instruction->length;
3292 ZyanU8 sib_byte;
3293 ZYAN_CHECK(ZydisInputNext(state, instruction, &sib_byte));
3294 ZydisDecodeSIB(instruction, sib_byte);
3295 if (instruction->raw.sib.base == 5)
3296 {
3297 displacement_size = (instruction->raw.modrm.mod == 1) ? 8 : 32;
3298 }
3299 }
3300 if (displacement_size)
3301 {
3302 ZYAN_CHECK(ZydisReadDisplacement(state, instruction, displacement_size));
3303 }
3304 }
3305
3306 context->reg_info.is_mod_reg = (instruction->raw.modrm.mod == 3) ||
3307 (info->flags & ZYDIS_INSTR_ENC_FLAG_FORCE_REG_FORM);
3308 }
3309
3310 if (info->flags & ZYDIS_INSTR_ENC_FLAG_HAS_DISP)
3311 {
3312 ZYAN_CHECK(ZydisReadDisplacement(
3313 state, instruction, info->disp.size[context->easz_index]));
3314 }
3315
3316 if (info->flags & ZYDIS_INSTR_ENC_FLAG_HAS_IMM0)
3317 {
3318 if (info->imm[0].is_relative)
3319 {
3320 instruction->attributes |= ZYDIS_ATTRIB_IS_RELATIVE;
3321 }
3322 ZYAN_CHECK(ZydisReadImmediate(state, instruction, 0,
3323 info->imm[0].size[context->eosz_index], info->imm[0].is_signed,
3324 info->imm[0].is_relative));
3325 }
3326
3327 if (info->flags & ZYDIS_INSTR_ENC_FLAG_HAS_IMM1)
3328 {
3329 ZYAN_ASSERT(!(info->flags & ZYDIS_INSTR_ENC_FLAG_HAS_DISP));
3330 ZYAN_CHECK(ZydisReadImmediate(state, instruction, 1,
3331 info->imm[1].size[context->eosz_index], info->imm[1].is_signed,
3332 info->imm[1].is_relative));
3333 }
3334
3335 return ZYAN_STATUS_SUCCESS;
3336 }
3337
3338 /* ---------------------------------------------------------------------------------------------- */
3339
3340 /**
3341 * Sets the effective operand size for the given instruction.
3342 *
3343 * @param context A pointer to the `ZydisDecoderContext` struct
3344 * @param instruction A pointer to the `ZydisDecodedInstruction` struct.
3345 * @param definition A pointer to the `ZydisInstructionDefinition` struct.
3346 */
ZydisSetEffectiveOperandWidth(ZydisDecoderContext * context,ZydisDecodedInstruction * instruction,const ZydisInstructionDefinition * definition)3347 static void ZydisSetEffectiveOperandWidth(ZydisDecoderContext* context,
3348 ZydisDecodedInstruction* instruction, const ZydisInstructionDefinition* definition)
3349 {
3350 ZYAN_ASSERT(context);
3351 ZYAN_ASSERT(instruction);
3352 ZYAN_ASSERT(definition);
3353
3354 static const ZyanU8 operand_size_map[8][8] =
3355 {
3356 // Default for most instructions
3357 {
3358 16, // 16 __ W0
3359 32, // 16 66 W0
3360 32, // 32 __ W0
3361 16, // 32 66 W0
3362 32, // 64 __ W0
3363 16, // 64 66 W0
3364 64, // 64 __ W1
3365 64 // 64 66 W1
3366 },
3367 // Operand size is forced to 8-bit (this is done later to preserve the `eosz_index`)
3368 {
3369 16, // 16 __ W0
3370 32, // 16 66 W0
3371 32, // 32 __ W0
3372 16, // 32 66 W0
3373 32, // 64 __ W0
3374 16, // 64 66 W0
3375 64, // 64 __ W1
3376 64 // 64 66 W1
3377 },
3378 // Operand size override 0x66 is ignored
3379 {
3380 16, // 16 __ W0
3381 16, // 16 66 W0
3382 32, // 32 __ W0
3383 32, // 32 66 W0
3384 32, // 64 __ W0
3385 32, // 64 66 W0
3386 64, // 64 __ W1
3387 64 // 64 66 W1
3388 },
3389 // REX.W promotes to 32-bit instead of 64-bit
3390 {
3391 16, // 16 __ W0
3392 32, // 16 66 W0
3393 32, // 32 __ W0
3394 16, // 32 66 W0
3395 32, // 64 __ W0
3396 16, // 64 66 W0
3397 32, // 64 __ W1
3398 32 // 64 66 W1
3399 },
3400 // Operand size defaults to 64-bit in 64-bit mode
3401 {
3402 16, // 16 __ W0
3403 32, // 16 66 W0
3404 32, // 32 __ W0
3405 16, // 32 66 W0
3406 64, // 64 __ W0
3407 16, // 64 66 W0
3408 64, // 64 __ W1
3409 64 // 64 66 W1
3410 },
3411 // Operand size is forced to 64-bit in 64-bit mode
3412 {
3413 16, // 16 __ W0
3414 32, // 16 66 W0
3415 32, // 32 __ W0
3416 16, // 32 66 W0
3417 64, // 64 __ W0
3418 64, // 64 66 W0
3419 64, // 64 __ W1
3420 64 // 64 66 W1
3421 },
3422 // Operand size is forced to 32-bit, if no REX.W is present.
3423 {
3424 32, // 16 __ W0
3425 32, // 16 66 W0
3426 32, // 32 __ W0
3427 32, // 32 66 W0
3428 32, // 64 __ W0
3429 32, // 64 66 W0
3430 64, // 64 __ W1
3431 64 // 64 66 W1
3432 },
3433 // Operand size is forced to 64-bit in 64-bit mode and forced to 32-bit in all other modes.
3434 // This is used for e.g. `mov CR, GPR` and `mov GPR, CR`.
3435 {
3436 32, // 16 __ W0
3437 32, // 16 66 W0
3438 32, // 32 __ W0
3439 32, // 32 66 W0
3440 64, // 64 __ W0
3441 64, // 64 66 W0
3442 64, // 64 __ W1
3443 64 // 64 66 W1
3444 }
3445 };
3446
3447 ZyanU8 index = (instruction->attributes & ZYDIS_ATTRIB_HAS_OPERANDSIZE) ? 1 : 0;
3448 if ((instruction->machine_mode == ZYDIS_MACHINE_MODE_LONG_COMPAT_32) ||
3449 (instruction->machine_mode == ZYDIS_MACHINE_MODE_LEGACY_32))
3450 {
3451 index += 2;
3452 }
3453 else if (instruction->machine_mode == ZYDIS_MACHINE_MODE_LONG_64)
3454 {
3455 index += 4;
3456 index += (context->vector_unified.W & 0x01) << 1;
3457 }
3458
3459 ZYAN_ASSERT(definition->operand_size_map < ZYAN_ARRAY_LENGTH(operand_size_map));
3460 ZYAN_ASSERT(index < ZYAN_ARRAY_LENGTH(operand_size_map[definition->operand_size_map]));
3461
3462 instruction->operand_width = operand_size_map[definition->operand_size_map][index];
3463 context->eosz_index = instruction->operand_width >> 5;
3464
3465 // TODO: Cleanup code and remove hardcoded condition
3466 if (definition->operand_size_map == 1)
3467 {
3468 instruction->operand_width = 8;
3469 }
3470 }
3471
3472 /**
3473 * Sets the effective address width for the given instruction.
3474 *
3475 * @param context A pointer to the `ZydisDecoderContext` struct.
3476 * @param instruction A pointer to the `ZydisDecodedInstruction` struct.
3477 * @param definition A pointer to the `ZydisInstructionDefinition` struct.
3478 */
ZydisSetEffectiveAddressWidth(ZydisDecoderContext * context,ZydisDecodedInstruction * instruction,const ZydisInstructionDefinition * definition)3479 static void ZydisSetEffectiveAddressWidth(ZydisDecoderContext* context,
3480 ZydisDecodedInstruction* instruction, const ZydisInstructionDefinition* definition)
3481 {
3482 ZYAN_ASSERT(context);
3483 ZYAN_ASSERT(instruction);
3484
3485 static const ZyanU8 address_size_map[3][8] =
3486 {
3487 // Default for most instructions
3488 {
3489 16, // 16 __
3490 32, // 16 67
3491 32, // 32 __
3492 16, // 32 67
3493 64, // 64 __
3494 32 // 64 67
3495 },
3496 // The address-size override is ignored
3497 {
3498 16, // 16 __
3499 16, // 16 67
3500 32, // 32 __
3501 32, // 32 67
3502 64, // 64 __
3503 64 // 64 67
3504 },
3505 // The address-size is forced to 64-bit in 64-bit mode and 32-bit in non 64-bit mode. This
3506 // is used by e.g. `ENCLS`, `ENCLV`, `ENCLU`.
3507 {
3508 32, // 16 __
3509 32, // 16 67
3510 32, // 32 __
3511 32, // 32 67
3512 64, // 64 __
3513 64 // 64 67
3514 }
3515 };
3516
3517 ZyanU8 index = (instruction->attributes & ZYDIS_ATTRIB_HAS_ADDRESSSIZE) ? 1 : 0;
3518 if ((instruction->machine_mode == ZYDIS_MACHINE_MODE_LONG_COMPAT_32) ||
3519 (instruction->machine_mode == ZYDIS_MACHINE_MODE_LEGACY_32))
3520 {
3521 index += 2;
3522 }
3523 else if (instruction->machine_mode == ZYDIS_MACHINE_MODE_LONG_64)
3524 {
3525 index += 4;
3526 }
3527
3528 ZYAN_ASSERT(definition->address_size_map < ZYAN_ARRAY_LENGTH(address_size_map));
3529 ZYAN_ASSERT(index < ZYAN_ARRAY_LENGTH(address_size_map[definition->address_size_map]));
3530
3531 instruction->address_width = address_size_map[definition->address_size_map][index];
3532 context->easz_index = instruction->address_width >> 5;
3533 }
3534
3535 /* ---------------------------------------------------------------------------------------------- */
3536
ZydisNodeHandlerXOP(const ZydisDecodedInstruction * instruction,ZyanU16 * index)3537 static ZyanStatus ZydisNodeHandlerXOP(const ZydisDecodedInstruction* instruction, ZyanU16* index)
3538 {
3539 ZYAN_ASSERT(instruction);
3540 ZYAN_ASSERT(index);
3541
3542 switch (instruction->encoding)
3543 {
3544 case ZYDIS_INSTRUCTION_ENCODING_LEGACY:
3545 *index = 0;
3546 break;
3547 case ZYDIS_INSTRUCTION_ENCODING_XOP:
3548 ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_XOP);
3549 *index = (instruction->raw.xop.m_mmmm - 0x08) + (instruction->raw.xop.pp * 3) + 1;
3550 break;
3551 default:
3552 ZYAN_UNREACHABLE;
3553 }
3554 return ZYAN_STATUS_SUCCESS;
3555 }
3556
ZydisNodeHandlerVEX(const ZydisDecodedInstruction * instruction,ZyanU16 * index)3557 static ZyanStatus ZydisNodeHandlerVEX(const ZydisDecodedInstruction* instruction, ZyanU16* index)
3558 {
3559 ZYAN_ASSERT(instruction);
3560 ZYAN_ASSERT(index);
3561
3562 switch (instruction->encoding)
3563 {
3564 case ZYDIS_INSTRUCTION_ENCODING_LEGACY:
3565 *index = 0;
3566 break;
3567 case ZYDIS_INSTRUCTION_ENCODING_VEX:
3568 ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_VEX);
3569 *index = instruction->raw.vex.m_mmmm + (instruction->raw.vex.pp << 2) + 1;
3570 break;
3571 default:
3572 ZYAN_UNREACHABLE;
3573 }
3574 return ZYAN_STATUS_SUCCESS;
3575 }
3576
ZydisNodeHandlerEMVEX(const ZydisDecodedInstruction * instruction,ZyanU16 * index)3577 static ZyanStatus ZydisNodeHandlerEMVEX(const ZydisDecodedInstruction* instruction, ZyanU16* index)
3578 {
3579 ZYAN_ASSERT(instruction);
3580 ZYAN_ASSERT(index);
3581
3582 switch (instruction->encoding)
3583 {
3584 case ZYDIS_INSTRUCTION_ENCODING_LEGACY:
3585 *index = 0;
3586 break;
3587 case ZYDIS_INSTRUCTION_ENCODING_EVEX:
3588 ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_EVEX);
3589 *index = instruction->raw.evex.mmm + (instruction->raw.evex.pp << 3) + 1;
3590 break;
3591 case ZYDIS_INSTRUCTION_ENCODING_MVEX:
3592 ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_MVEX);
3593 *index = instruction->raw.mvex.mmmm + (instruction->raw.mvex.pp << 2) + 33;
3594 break;
3595 default:
3596 ZYAN_UNREACHABLE;
3597 }
3598 return ZYAN_STATUS_SUCCESS;
3599 }
3600
ZydisNodeHandlerOpcode(ZydisDecoderState * state,ZydisDecodedInstruction * instruction,ZyanU16 * index)3601 static ZyanStatus ZydisNodeHandlerOpcode(ZydisDecoderState* state,
3602 ZydisDecodedInstruction* instruction, ZyanU16* index)
3603 {
3604 ZYAN_ASSERT(state);
3605 ZYAN_ASSERT(instruction);
3606 ZYAN_ASSERT(index);
3607
3608 // Handle possible encoding-prefix and opcode-map changes
3609 switch (instruction->encoding)
3610 {
3611 case ZYDIS_INSTRUCTION_ENCODING_LEGACY:
3612 ZYAN_CHECK(ZydisInputNext(state, instruction, &instruction->opcode));
3613 switch (instruction->opcode_map)
3614 {
3615 case ZYDIS_OPCODE_MAP_DEFAULT:
3616 switch (instruction->opcode)
3617 {
3618 case 0x0F:
3619 instruction->opcode_map = ZYDIS_OPCODE_MAP_0F;
3620 break;
3621 case 0xC4:
3622 case 0xC5:
3623 case 0x62:
3624 {
3625 ZyanU8 next_input;
3626 ZYAN_CHECK(ZydisInputPeek(state, instruction, &next_input));
3627 if (((next_input & 0xF0) >= 0xC0) ||
3628 (instruction->machine_mode == ZYDIS_MACHINE_MODE_LONG_64))
3629 {
3630 if (instruction->attributes & ZYDIS_ATTRIB_HAS_REX)
3631 {
3632 return ZYDIS_STATUS_ILLEGAL_REX;
3633 }
3634 if (state->prefixes.has_lock)
3635 {
3636 return ZYDIS_STATUS_ILLEGAL_LOCK;
3637 }
3638 if (state->prefixes.mandatory_candidate)
3639 {
3640 return ZYDIS_STATUS_ILLEGAL_LEGACY_PFX;
3641 }
3642 ZyanU8 prefix_bytes[4] = { 0, 0, 0, 0 };
3643 prefix_bytes[0] = instruction->opcode;
3644 switch (instruction->opcode)
3645 {
3646 case 0xC4:
3647 instruction->raw.vex.offset = instruction->length - 1;
3648 // Read additional 3-byte VEX-prefix data
3649 ZYAN_ASSERT(!(instruction->attributes & ZYDIS_ATTRIB_HAS_VEX));
3650 ZYAN_CHECK(ZydisInputNextBytes(state, instruction, &prefix_bytes[1], 2));
3651 break;
3652 case 0xC5:
3653 instruction->raw.vex.offset = instruction->length - 1;
3654 // Read additional 2-byte VEX-prefix data
3655 ZYAN_ASSERT(!(instruction->attributes & ZYDIS_ATTRIB_HAS_VEX));
3656 ZYAN_CHECK(ZydisInputNext(state, instruction, &prefix_bytes[1]));
3657 break;
3658 case 0x62:
3659 #if !defined(ZYDIS_DISABLE_AVX512) || !defined(ZYDIS_DISABLE_KNC)
3660 // Read additional EVEX/MVEX-prefix data
3661 ZYAN_ASSERT(!(instruction->attributes & ZYDIS_ATTRIB_HAS_EVEX));
3662 ZYAN_ASSERT(!(instruction->attributes & ZYDIS_ATTRIB_HAS_MVEX));
3663 ZYAN_CHECK(ZydisInputNextBytes(state, instruction, &prefix_bytes[1], 3));
3664 break;
3665 #else
3666 return ZYDIS_STATUS_DECODING_ERROR;
3667 #endif
3668 default:
3669 ZYAN_UNREACHABLE;
3670 }
3671 switch (instruction->opcode)
3672 {
3673 case 0xC4:
3674 case 0xC5:
3675 // Decode VEX-prefix
3676 instruction->encoding = ZYDIS_INSTRUCTION_ENCODING_VEX;
3677 ZYAN_CHECK(ZydisDecodeVEX(state->context, instruction, prefix_bytes));
3678 instruction->opcode_map =
3679 ZYDIS_OPCODE_MAP_DEFAULT + instruction->raw.vex.m_mmmm;
3680 break;
3681 case 0x62:
3682 #if defined(ZYDIS_DISABLE_AVX512) && defined(ZYDIS_DISABLE_KNC)
3683 return ZYDIS_STATUS_DECODING_ERROR;
3684 #else
3685 switch ((prefix_bytes[2] >> 2) & 0x01)
3686 {
3687 case 0:
3688 #ifndef ZYDIS_DISABLE_KNC
3689 instruction->raw.mvex.offset = instruction->length - 4;
3690 // `KNC` instructions are only valid in 64-bit mode.
3691 // This condition catches the `MVEX` encoded ones to save a bunch of
3692 // `mode` filters in the data-tables.
3693 // `KNC` instructions with `VEX` encoding still require a `mode` filter.
3694 if (state->decoder->machine_mode != ZYDIS_MACHINE_MODE_LONG_64)
3695 {
3696 return ZYDIS_STATUS_DECODING_ERROR;
3697 }
3698 // Decode MVEX-prefix
3699 instruction->encoding = ZYDIS_INSTRUCTION_ENCODING_MVEX;
3700 ZYAN_CHECK(ZydisDecodeMVEX(state->context, instruction, prefix_bytes));
3701 instruction->opcode_map =
3702 ZYDIS_OPCODE_MAP_DEFAULT + instruction->raw.mvex.mmmm;
3703 break;
3704 #else
3705 return ZYDIS_STATUS_DECODING_ERROR;
3706 #endif
3707 case 1:
3708 #ifndef ZYDIS_DISABLE_AVX512
3709 instruction->raw.evex.offset = instruction->length - 4;
3710 // Decode EVEX-prefix
3711 instruction->encoding = ZYDIS_INSTRUCTION_ENCODING_EVEX;
3712 ZYAN_CHECK(ZydisDecodeEVEX(state->context, instruction, prefix_bytes));
3713 instruction->opcode_map =
3714 ZYDIS_OPCODE_MAP_DEFAULT + instruction->raw.evex.mmm;
3715 break;
3716 #else
3717 return ZYDIS_STATUS_DECODING_ERROR;
3718 #endif
3719 default:
3720 ZYAN_UNREACHABLE;
3721 }
3722 break;
3723 #endif
3724 default:
3725 ZYAN_UNREACHABLE;
3726 }
3727 }
3728 break;
3729 }
3730 case 0x8F:
3731 {
3732 ZyanU8 next_input;
3733 ZYAN_CHECK(ZydisInputPeek(state, instruction, &next_input));
3734 if ((next_input & 0x1F) >= 8)
3735 {
3736 if (instruction->attributes & ZYDIS_ATTRIB_HAS_REX)
3737 {
3738 return ZYDIS_STATUS_ILLEGAL_REX;
3739 }
3740 if (state->prefixes.has_lock)
3741 {
3742 return ZYDIS_STATUS_ILLEGAL_LOCK;
3743 }
3744 if (state->prefixes.mandatory_candidate)
3745 {
3746 return ZYDIS_STATUS_ILLEGAL_LEGACY_PFX;
3747 }
3748 instruction->raw.xop.offset = instruction->length - 1;
3749 ZyanU8 prefixBytes[3] = { 0x8F, 0x00, 0x00 };
3750 // Read additional xop-prefix data
3751 ZYAN_CHECK(ZydisInputNextBytes(state, instruction, &prefixBytes[1], 2));
3752 // Decode xop-prefix
3753 instruction->encoding = ZYDIS_INSTRUCTION_ENCODING_XOP;
3754 ZYAN_CHECK(ZydisDecodeXOP(state->context, instruction, prefixBytes));
3755 instruction->opcode_map =
3756 ZYDIS_OPCODE_MAP_XOP8 + instruction->raw.xop.m_mmmm - 0x08;
3757 }
3758 break;
3759 }
3760 default:
3761 break;
3762 }
3763 break;
3764 case ZYDIS_OPCODE_MAP_0F:
3765 switch (instruction->opcode)
3766 {
3767 case 0x0F:
3768 if (state->prefixes.has_lock)
3769 {
3770 return ZYDIS_STATUS_ILLEGAL_LOCK;
3771 }
3772 instruction->encoding = ZYDIS_INSTRUCTION_ENCODING_3DNOW;
3773 instruction->opcode_map = ZYDIS_OPCODE_MAP_0F0F;
3774 break;
3775 case 0x38:
3776 instruction->opcode_map = ZYDIS_OPCODE_MAP_0F38;
3777 break;
3778 case 0x3A:
3779 instruction->opcode_map = ZYDIS_OPCODE_MAP_0F3A;
3780 break;
3781 default:
3782 break;
3783 }
3784 break;
3785 case ZYDIS_OPCODE_MAP_0F38:
3786 case ZYDIS_OPCODE_MAP_0F3A:
3787 case ZYDIS_OPCODE_MAP_XOP8:
3788 case ZYDIS_OPCODE_MAP_XOP9:
3789 case ZYDIS_OPCODE_MAP_XOPA:
3790 // Nothing to do here
3791 break;
3792 default:
3793 ZYAN_UNREACHABLE;
3794 }
3795 break;
3796 case ZYDIS_INSTRUCTION_ENCODING_3DNOW:
3797 // All 3DNOW (0x0F 0x0F) instructions are using the same operand encoding. We just
3798 // decode a random (pi2fw) instruction and extract the actual opcode later.
3799 *index = 0x0C;
3800 return ZYAN_STATUS_SUCCESS;
3801 default:
3802 ZYAN_CHECK(ZydisInputNext(state, instruction, &instruction->opcode));
3803 break;
3804 }
3805
3806 *index = instruction->opcode;
3807 return ZYAN_STATUS_SUCCESS;
3808 }
3809
ZydisNodeHandlerMode(const ZydisDecodedInstruction * instruction,ZyanU16 * index)3810 static ZyanStatus ZydisNodeHandlerMode(const ZydisDecodedInstruction* instruction, ZyanU16* index)
3811 {
3812 ZYAN_ASSERT(instruction);
3813 ZYAN_ASSERT(index);
3814
3815 switch (instruction->machine_mode)
3816 {
3817 case ZYDIS_MACHINE_MODE_LONG_COMPAT_16:
3818 case ZYDIS_MACHINE_MODE_LEGACY_16:
3819 case ZYDIS_MACHINE_MODE_REAL_16:
3820 *index = 0;
3821 break;
3822 case ZYDIS_MACHINE_MODE_LONG_COMPAT_32:
3823 case ZYDIS_MACHINE_MODE_LEGACY_32:
3824 *index = 1;
3825 break;
3826 case ZYDIS_MACHINE_MODE_LONG_64:
3827 *index = 2;
3828 break;
3829 default:
3830 ZYAN_UNREACHABLE;
3831 }
3832 return ZYAN_STATUS_SUCCESS;
3833 }
3834
ZydisNodeHandlerModeCompact(const ZydisDecodedInstruction * instruction,ZyanU16 * index)3835 static ZyanStatus ZydisNodeHandlerModeCompact(const ZydisDecodedInstruction* instruction,
3836 ZyanU16* index)
3837 {
3838 ZYAN_ASSERT(instruction);
3839 ZYAN_ASSERT(index);
3840
3841 *index = (instruction->machine_mode == ZYDIS_MACHINE_MODE_LONG_64) ? 0 : 1;
3842 return ZYAN_STATUS_SUCCESS;
3843 }
3844
ZydisNodeHandlerModrmMod(ZydisDecoderState * state,ZydisDecodedInstruction * instruction,ZyanU16 * index)3845 static ZyanStatus ZydisNodeHandlerModrmMod(ZydisDecoderState* state,
3846 ZydisDecodedInstruction* instruction, ZyanU16* index)
3847 {
3848 ZYAN_ASSERT(state);
3849 ZYAN_ASSERT(instruction);
3850 ZYAN_ASSERT(index);
3851
3852 if (!instruction->raw.modrm.offset)
3853 {
3854 instruction->raw.modrm.offset = instruction->length;
3855 ZyanU8 modrm_byte;
3856 ZYAN_CHECK(ZydisInputNext(state, instruction, &modrm_byte));
3857 ZydisDecodeModRM(instruction, modrm_byte);
3858 }
3859 *index = instruction->raw.modrm.mod;
3860 return ZYAN_STATUS_SUCCESS;
3861 }
3862
ZydisNodeHandlerModrmModCompact(ZydisDecoderState * state,ZydisDecodedInstruction * instruction,ZyanU16 * index)3863 static ZyanStatus ZydisNodeHandlerModrmModCompact(ZydisDecoderState* state,
3864 ZydisDecodedInstruction* instruction, ZyanU16* index)
3865 {
3866 ZYAN_CHECK(ZydisNodeHandlerModrmMod(state, instruction, index));
3867 *index = (*index == 0x3) ? 0 : 1;
3868 return ZYAN_STATUS_SUCCESS;
3869 }
3870
ZydisNodeHandlerModrmReg(ZydisDecoderState * state,ZydisDecodedInstruction * instruction,ZyanU16 * index)3871 static ZyanStatus ZydisNodeHandlerModrmReg(ZydisDecoderState* state,
3872 ZydisDecodedInstruction* instruction, ZyanU16* index)
3873 {
3874 ZYAN_ASSERT(state);
3875 ZYAN_ASSERT(instruction);
3876 ZYAN_ASSERT(index);
3877
3878 if (!instruction->raw.modrm.offset)
3879 {
3880 instruction->raw.modrm.offset = instruction->length;
3881 ZyanU8 modrm_byte;
3882 ZYAN_CHECK(ZydisInputNext(state, instruction, &modrm_byte));
3883 ZydisDecodeModRM(instruction, modrm_byte);
3884 }
3885 *index = instruction->raw.modrm.reg;
3886 return ZYAN_STATUS_SUCCESS;
3887 }
3888
ZydisNodeHandlerModrmRm(ZydisDecoderState * state,ZydisDecodedInstruction * instruction,ZyanU16 * index)3889 static ZyanStatus ZydisNodeHandlerModrmRm(ZydisDecoderState* state,
3890 ZydisDecodedInstruction* instruction, ZyanU16* index)
3891 {
3892 ZYAN_ASSERT(state);
3893 ZYAN_ASSERT(instruction);
3894 ZYAN_ASSERT(index);
3895
3896 if (!instruction->raw.modrm.offset)
3897 {
3898 instruction->raw.modrm.offset = instruction->length;
3899 ZyanU8 modrm_byte;
3900 ZYAN_CHECK(ZydisInputNext(state, instruction, &modrm_byte));
3901 ZydisDecodeModRM(instruction, modrm_byte);
3902 }
3903 *index = instruction->raw.modrm.rm;
3904 return ZYAN_STATUS_SUCCESS;
3905 }
3906
ZydisNodeHandlerMandatoryPrefix(const ZydisDecoderState * state,ZydisDecodedInstruction * instruction,ZyanU16 * index)3907 static ZyanStatus ZydisNodeHandlerMandatoryPrefix(const ZydisDecoderState* state,
3908 ZydisDecodedInstruction* instruction, ZyanU16* index)
3909 {
3910 ZYAN_ASSERT(state);
3911 ZYAN_ASSERT(instruction);
3912 ZYAN_ASSERT(index);
3913
3914 switch (state->prefixes.mandatory_candidate)
3915 {
3916 case 0x66:
3917 instruction->raw.prefixes[state->prefixes.offset_mandatory].type =
3918 ZYDIS_PREFIX_TYPE_MANDATORY;
3919 instruction->attributes &= ~ZYDIS_ATTRIB_HAS_OPERANDSIZE;
3920 *index = 2;
3921 break;
3922 case 0xF3:
3923 instruction->raw.prefixes[state->prefixes.offset_mandatory].type =
3924 ZYDIS_PREFIX_TYPE_MANDATORY;
3925 *index = 3;
3926 break;
3927 case 0xF2:
3928 instruction->raw.prefixes[state->prefixes.offset_mandatory].type =
3929 ZYDIS_PREFIX_TYPE_MANDATORY;
3930 *index = 4;
3931 break;
3932 default:
3933 *index = 1;
3934 break;
3935 }
3936 // TODO: Consume prefix and make sure it's available again, if we need to fallback
3937
3938 return ZYAN_STATUS_SUCCESS;
3939 }
3940
ZydisNodeHandlerOperandSize(const ZydisDecoderState * state,ZydisDecodedInstruction * instruction,ZyanU16 * index)3941 static ZyanStatus ZydisNodeHandlerOperandSize(const ZydisDecoderState* state,
3942 ZydisDecodedInstruction* instruction, ZyanU16* index)
3943 {
3944 ZYAN_ASSERT(state);
3945 ZYAN_ASSERT(instruction);
3946 ZYAN_ASSERT(index);
3947
3948 if ((instruction->machine_mode == ZYDIS_MACHINE_MODE_LONG_64) &&
3949 (state->context->vector_unified.W))
3950 {
3951 *index = 2;
3952 } else
3953 {
3954 if (instruction->attributes & ZYDIS_ATTRIB_HAS_OPERANDSIZE)
3955 {
3956 instruction->raw.prefixes[state->prefixes.offset_osz_override].type =
3957 ZYDIS_PREFIX_TYPE_EFFECTIVE;
3958 }
3959 switch (instruction->machine_mode)
3960 {
3961 case ZYDIS_MACHINE_MODE_LONG_COMPAT_16:
3962 case ZYDIS_MACHINE_MODE_LEGACY_16:
3963 case ZYDIS_MACHINE_MODE_REAL_16:
3964 *index = (instruction->attributes & ZYDIS_ATTRIB_HAS_OPERANDSIZE) ? 1 : 0;
3965 break;
3966 case ZYDIS_MACHINE_MODE_LONG_COMPAT_32:
3967 case ZYDIS_MACHINE_MODE_LEGACY_32:
3968 case ZYDIS_MACHINE_MODE_LONG_64:
3969 *index = (instruction->attributes & ZYDIS_ATTRIB_HAS_OPERANDSIZE) ? 0 : 1;
3970 break;
3971 default:
3972 ZYAN_UNREACHABLE;
3973 }
3974 }
3975
3976 return ZYAN_STATUS_SUCCESS;
3977 }
3978
ZydisNodeHandlerAddressSize(ZydisDecodedInstruction * instruction,ZyanU16 * index)3979 static ZyanStatus ZydisNodeHandlerAddressSize(ZydisDecodedInstruction* instruction, ZyanU16* index)
3980 {
3981 ZYAN_ASSERT(instruction);
3982 ZYAN_ASSERT(index);
3983
3984 /*if (instruction->attributes & ZYDIS_ATTRIB_HAS_ADDRESSSIZE)
3985 {
3986 instruction->raw.prefixes[context->prefixes.offset_asz_override].type =
3987 ZYDIS_PREFIX_TYPE_EFFECTIVE;
3988 }*/
3989 switch (instruction->machine_mode)
3990 {
3991 case ZYDIS_MACHINE_MODE_LONG_COMPAT_16:
3992 case ZYDIS_MACHINE_MODE_LEGACY_16:
3993 case ZYDIS_MACHINE_MODE_REAL_16:
3994 *index = (instruction->attributes & ZYDIS_ATTRIB_HAS_ADDRESSSIZE) ? 1 : 0;
3995 break;
3996 case ZYDIS_MACHINE_MODE_LONG_COMPAT_32:
3997 case ZYDIS_MACHINE_MODE_LEGACY_32:
3998 *index = (instruction->attributes & ZYDIS_ATTRIB_HAS_ADDRESSSIZE) ? 0 : 1;
3999 break;
4000 case ZYDIS_MACHINE_MODE_LONG_64:
4001 *index = (instruction->attributes & ZYDIS_ATTRIB_HAS_ADDRESSSIZE) ? 1 : 2;
4002 break;
4003 default:
4004 ZYAN_UNREACHABLE;
4005 }
4006
4007 return ZYAN_STATUS_SUCCESS;
4008 }
4009
ZydisNodeHandlerVectorLength(const ZydisDecoderContext * context,const ZydisDecodedInstruction * instruction,ZyanU16 * index)4010 static ZyanStatus ZydisNodeHandlerVectorLength(const ZydisDecoderContext* context,
4011 const ZydisDecodedInstruction* instruction, ZyanU16* index)
4012 {
4013 ZYAN_ASSERT(context);
4014 ZYAN_ASSERT(instruction);
4015 ZYAN_ASSERT(index);
4016
4017 switch (instruction->encoding)
4018 {
4019 case ZYDIS_INSTRUCTION_ENCODING_XOP:
4020 ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_XOP);
4021 break;
4022 case ZYDIS_INSTRUCTION_ENCODING_VEX:
4023 ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_VEX);
4024 break;
4025 case ZYDIS_INSTRUCTION_ENCODING_EVEX:
4026 ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_EVEX);
4027 break;
4028 case ZYDIS_INSTRUCTION_ENCODING_MVEX:
4029 ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_MVEX);
4030 break;
4031 default:
4032 ZYAN_UNREACHABLE;
4033 }
4034
4035 *index = context->vector_unified.LL;
4036 if (*index == 3)
4037 {
4038 return ZYDIS_STATUS_DECODING_ERROR;
4039 }
4040 return ZYAN_STATUS_SUCCESS;
4041 }
4042
ZydisNodeHandlerRexW(const ZydisDecoderContext * context,const ZydisDecodedInstruction * instruction,ZyanU16 * index)4043 static ZyanStatus ZydisNodeHandlerRexW(const ZydisDecoderContext* context,
4044 const ZydisDecodedInstruction* instruction, ZyanU16* index)
4045 {
4046 ZYAN_ASSERT(context);
4047 ZYAN_ASSERT(instruction);
4048 ZYAN_ASSERT(index);
4049
4050 switch (instruction->encoding)
4051 {
4052 case ZYDIS_INSTRUCTION_ENCODING_LEGACY:
4053 // nothing to do here
4054 break;
4055 case ZYDIS_INSTRUCTION_ENCODING_XOP:
4056 ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_XOP);
4057 break;
4058 case ZYDIS_INSTRUCTION_ENCODING_VEX:
4059 ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_VEX);
4060 break;
4061 case ZYDIS_INSTRUCTION_ENCODING_EVEX:
4062 ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_EVEX);
4063 break;
4064 case ZYDIS_INSTRUCTION_ENCODING_MVEX:
4065 ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_MVEX);
4066 break;
4067 default:
4068 ZYAN_UNREACHABLE;
4069 }
4070 *index = context->vector_unified.W;
4071 return ZYAN_STATUS_SUCCESS;
4072 }
4073
ZydisNodeHandlerRexB(const ZydisDecoderContext * context,const ZydisDecodedInstruction * instruction,ZyanU16 * index)4074 static ZyanStatus ZydisNodeHandlerRexB(const ZydisDecoderContext* context,
4075 const ZydisDecodedInstruction* instruction, ZyanU16* index)
4076 {
4077 ZYAN_ASSERT(context);
4078 ZYAN_ASSERT(instruction);
4079 ZYAN_ASSERT(index);
4080
4081 switch (instruction->encoding)
4082 {
4083 case ZYDIS_INSTRUCTION_ENCODING_LEGACY:
4084 // nothing to do here
4085 break;
4086 case ZYDIS_INSTRUCTION_ENCODING_XOP:
4087 ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_XOP);
4088 break;
4089 case ZYDIS_INSTRUCTION_ENCODING_VEX:
4090 ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_VEX);
4091 break;
4092 case ZYDIS_INSTRUCTION_ENCODING_EVEX:
4093 ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_EVEX);
4094 break;
4095 case ZYDIS_INSTRUCTION_ENCODING_MVEX:
4096 ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_MVEX);
4097 break;
4098 default:
4099 ZYAN_UNREACHABLE;
4100 }
4101 *index = context->vector_unified.B;
4102 return ZYAN_STATUS_SUCCESS;
4103 }
4104
4105 #ifndef ZYDIS_DISABLE_AVX512
ZydisNodeHandlerEvexB(const ZydisDecodedInstruction * instruction,ZyanU16 * index)4106 static ZyanStatus ZydisNodeHandlerEvexB(const ZydisDecodedInstruction* instruction, ZyanU16* index)
4107 {
4108 ZYAN_ASSERT(instruction);
4109 ZYAN_ASSERT(index);
4110
4111 ZYAN_ASSERT(instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_EVEX);
4112 ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_EVEX);
4113 *index = instruction->raw.evex.b;
4114 return ZYAN_STATUS_SUCCESS;
4115 }
4116 #endif
4117
4118 #ifndef ZYDIS_DISABLE_KNC
ZydisNodeHandlerMvexE(const ZydisDecodedInstruction * instruction,ZyanU16 * index)4119 static ZyanStatus ZydisNodeHandlerMvexE(const ZydisDecodedInstruction* instruction, ZyanU16* index)
4120 {
4121 ZYAN_ASSERT(instruction);
4122 ZYAN_ASSERT(index);
4123
4124 ZYAN_ASSERT(instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_MVEX);
4125 ZYAN_ASSERT(instruction->attributes & ZYDIS_ATTRIB_HAS_MVEX);
4126 *index = instruction->raw.mvex.E;
4127 return ZYAN_STATUS_SUCCESS;
4128 }
4129 #endif
4130
4131 /* ---------------------------------------------------------------------------------------------- */
4132
4133 /**
4134 * Populates the internal register id fields for `REG`, `RM`, `NDSNDD`, `BASE` and `INDEX`/`VIDX`
4135 * encoded operands and performs sanity checks.
4136 *
4137 * @param context A pointer to the `ZydisDecoderContext` struct.
4138 * @param instruction A pointer to the `ZydisDecodedInstruction` struct.
4139 * @param def_reg The type definition for the `.reg` encoded operand.
4140 * @param def_rm The type definition for the `.rm` encoded operand.
4141 * @param def_ndsndd The type definition for the `.vvvv` encoded operand.
4142 *
4143 * @return A zyan status code.
4144 *
4145 * This function sets all unused register ids to `-1`. This rule does currently not apply to
4146 * `base` and `index`.
4147 *
4148 * Definition encoding:
4149 * - `def_reg` -> `ZydisRegisterKind`
4150 * - `def_ndsndd` -> `ZydisRegisterKind`
4151 * - `def_rm` -> `ZydisRegisterKind` (`.mod == 3`) or ZydisMemoryOperandType (`.mod != 3`)
4152 */
ZydisPopulateRegisterIds(ZydisDecoderContext * context,const ZydisDecodedInstruction * instruction,ZyanU8 def_reg,ZyanU8 def_rm,ZyanU8 def_ndsndd)4153 static ZyanStatus ZydisPopulateRegisterIds(ZydisDecoderContext* context,
4154 const ZydisDecodedInstruction* instruction, ZyanU8 def_reg, ZyanU8 def_rm, ZyanU8 def_ndsndd)
4155 {
4156 ZYAN_ASSERT(context);
4157 ZYAN_ASSERT(instruction);
4158
4159 const ZyanBool is_64_bit = (instruction->machine_mode == ZYDIS_MACHINE_MODE_LONG_64);
4160 const ZyanBool is_reg = context->reg_info.is_mod_reg;
4161 const ZyanBool has_sib = !is_reg && (instruction->raw.modrm.rm == 4);
4162 const ZyanBool has_vsib = has_sib && (def_rm == ZYDIS_MEMOP_TYPE_VSIB);
4163
4164 ZyanU8 id_reg = instruction->raw.modrm.reg;
4165 ZyanU8 id_rm = instruction->raw.modrm.rm;
4166 ZyanU8 id_ndsndd = is_64_bit ? context->vector_unified.vvvv : context->vector_unified.vvvv & 0x07;
4167 ZyanU8 id_base = has_sib ? instruction->raw.sib.base : instruction->raw.modrm.rm;
4168 ZyanU8 id_index = instruction->raw.sib.index;
4169
4170 if (instruction->machine_mode == ZYDIS_MACHINE_MODE_LONG_64)
4171 {
4172 const ZyanBool is_emvex = (instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_EVEX) ||
4173 (instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_MVEX);
4174
4175 // The `index` extension by `.v'` is only valid for VSIB operands
4176 const ZyanU8 vsib_v2 = has_vsib ? context->vector_unified.V2 : 0;
4177 // The `rm` extension by `.X` is only valid for EVEX/MVEX instructions
4178 const ZyanU8 evex_x = is_emvex ? context->vector_unified.X : 0;
4179
4180 id_reg |= (context->vector_unified.R2 << 4) | (context->vector_unified.R << 3);
4181 id_rm |= (evex_x << 4) | (context->vector_unified.B << 3);
4182 id_ndsndd |= (context->vector_unified.V2 << 4) ;
4183 id_base |= (context->vector_unified.B << 3);
4184 id_index |= (vsib_v2 << 4) | (context->vector_unified.X << 3);
4185
4186 // The masking emulates the actual CPU behavior and does not verify if the resulting ids
4187 // are actually valid for the given register kind.
4188
4189 static const ZyanU8 mask_reg[ZYDIS_REGKIND_MAX_VALUE + 1] =
4190 {
4191 /* INVALID */ 0,
4192 /* GPR */ (1 << 5) - 1,
4193 /* X87 */ (1 << 3) - 1, // ignore `.R`, ignore `.R'`
4194 /* MMX */ (1 << 3) - 1, // ignore `.R`, ignore `.R'`
4195 /* VR */ (1 << 5) - 1,
4196 /* TMM */ (1 << 5) - 1,
4197 /* SEGMENT */ (1 << 3) - 1, // ignore `.R`, ignore `.R'`
4198 /* TEST */ (1 << 3) - 1, // ignore `.R`, ignore `.R'`
4199 /* CONTROL */ (1 << 4) - 1, // ignore `.R'`
4200 /* DEBUG */ (1 << 4) - 1, // ignore `.R'`
4201 /* MASK */ (1 << 5) - 1,
4202 /* BOUND */ (1 << 4) - 1 // ignore `.R'`
4203 };
4204 id_reg &= mask_reg[def_reg];
4205
4206 static const ZyanU8 mask_rm[ZYDIS_REGKIND_MAX_VALUE + 1] =
4207 {
4208 /* INVALID */ 0,
4209 /* GPR */ (1 << 4) - 1, // ignore `.X`
4210 /* X87 */ (1 << 3) - 1, // ignore `.B`, ignore `.X`
4211 /* MMX */ (1 << 3) - 1, // ignore `.B`, ignore `.X`
4212 /* VR */ (1 << 5) - 1,
4213 /* TMM */ (1 << 4) - 1, // ignore `.X`
4214 /* SEGMENT */ (1 << 3) - 1, // ignore `.B`, ignore `.X`
4215 /* TEST */ (1 << 3) - 1, // ignore `.B`, ignore `.X`
4216 /* CONTROL */ (1 << 4) - 1, // ignore `.X`
4217 /* DEBUG */ (1 << 4) - 1, // ignore `.X`
4218 /* MASK */ (1 << 3) - 1, // ignore `.B`, ignore `.X`
4219 /* BOUND */ (1 << 4) - 1 // ignore `.X`
4220 };
4221 id_rm &= (is_reg ? mask_rm[def_rm] : 0xFF);
4222
4223 // Commented out for future reference. Not required at the moment as it's always either
4224 // a "take all" or "take nothing" situation.
4225
4226 //static const ZyanU8 mask_ndsndd[ZYDIS_REGKIND_MAX_VALUE + 1] =
4227 //{
4228 // /* INVALID */ 0,
4229 // /* GPR */ (1 << 5) - 1,
4230 // /* X87 */ 0, // never encoded in `.vvvv`
4231 // /* MMX */ 0, // never encoded in `.vvvv`
4232 // /* VR */ (1 << 5) - 1,
4233 // /* TMM */ (1 << 5) - 1,
4234 // /* SEGMENT */ 0, // never encoded in `.vvvv`
4235 // /* TEST */ 0, // never encoded in `.vvvv`
4236 // /* CONTROL */ 0, // never encoded in `.vvvv`
4237 // /* DEBUG */ 0, // never encoded in `.vvvv`
4238 // /* MASK */ (1 << 5) - 1,
4239 // /* BOUND */ 0 // never encoded in `.vvvv`
4240 //};
4241 }
4242
4243 // Validate
4244
4245 // `.vvvv` is not allowed, if the instruction does not encode a NDS/NDD operand
4246 if (!def_ndsndd && context->vector_unified.vvvv)
4247 {
4248 return ZYDIS_STATUS_BAD_REGISTER;
4249 }
4250 // `.v'` is not allowed, if the instruction does not encode a NDS/NDD or VSIB operand
4251 if (!def_ndsndd && !has_vsib && context->vector_unified.V2)
4252 {
4253 return ZYDIS_STATUS_BAD_REGISTER;
4254 }
4255
4256 static const ZyanU8 available_regs[2][ZYDIS_REGKIND_MAX_VALUE + 1] =
4257 {
4258 // 16/32 bit mode
4259 {
4260 /* INVALID */ 255,
4261 /* GPR */ 8,
4262 /* X87 */ 8,
4263 /* MMX */ 8,
4264 /* VR */ 8,
4265 /* TMM */ 8,
4266 /* SEGMENT */ 6,
4267 /* TEST */ 8,
4268 /* CONTROL */ 8,
4269 /* DEBUG */ 8,
4270 /* MASK */ 8,
4271 /* BOUND */ 4
4272 },
4273 // 64 bit mode
4274 {
4275 /* INVALID */ 255,
4276 /* GPR */ 16,
4277 /* X87 */ 8,
4278 /* MMX */ 8,
4279 /* VR */ 32,
4280 /* TMM */ 8,
4281 /* SEGMENT */ 6,
4282 /* TEST */ 8,
4283 /* CONTROL */ 16,
4284 // Attempts to reference DR8..DR15 result in undefined opcode (#UD) exceptions. DR4 and
4285 // DR5 are only valid, if the debug extension (DE) flag in CR4 is set. As we can't
4286 // check this at runtime we just allow them.
4287 /* DEBUG */ 8,
4288 /* MASK */ 8,
4289 /* BOUND */ 4
4290 }
4291 };
4292
4293 if ((id_reg >= available_regs[is_64_bit][def_reg]) ||
4294 (id_ndsndd >= available_regs[is_64_bit][def_ndsndd]) ||
4295 (is_reg && (id_rm >= available_regs[is_64_bit][def_rm])))
4296 {
4297 return ZYDIS_STATUS_BAD_REGISTER;
4298 }
4299
4300 ZyanI8 id_cr = -1;
4301 if (def_reg == ZYDIS_REGKIND_CONTROL)
4302 {
4303 id_cr = id_reg;
4304 }
4305 if (is_reg && (def_rm == ZYDIS_REGKIND_CONTROL))
4306 {
4307 id_cr = id_rm;
4308 }
4309 if (id_cr >= 0)
4310 {
4311 // Attempts to reference CR1, CR5, CR6, CR7, and CR9..CR15 result in undefined opcode (#UD)
4312 // exceptions
4313 static const ZyanU8 lookup[16] =
4314 {
4315 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0
4316 };
4317 ZYAN_ASSERT((ZyanUSize)id_cr < ZYAN_ARRAY_LENGTH(lookup));
4318 if (!lookup[id_cr])
4319 {
4320 return ZYDIS_STATUS_BAD_REGISTER;
4321 }
4322 }
4323
4324 // Assign to context
4325
4326 context->reg_info.id_reg = def_reg ? id_reg : -1;
4327 context->reg_info.id_rm = def_rm && is_reg ? id_rm : -1;
4328 context->reg_info.id_ndsndd = def_ndsndd ? id_ndsndd : -1;
4329 context->reg_info.id_base = id_base; // TODO: Set unused register to -1 as well
4330 context->reg_info.id_index = id_index; // TODO: Set unused register to -1 as well
4331
4332 return ZYAN_STATUS_SUCCESS;
4333 }
4334
4335 /**
4336 * Checks for certain post-decode error-conditions.
4337 *
4338 * @param state A pointer to the `ZydisDecoderState` struct.
4339 * @param instruction A pointer to the `ZydisDecodedInstruction` struct.
4340 * @param definition A pointer to the `ZydisInstructionDefinition` struct.
4341 *
4342 * @return A zyan status code.
4343 *
4344 * This function is called immediately after a valid instruction-definition was found.
4345 */
ZydisCheckErrorConditions(ZydisDecoderState * state,const ZydisDecodedInstruction * instruction,const ZydisInstructionDefinition * definition)4346 static ZyanStatus ZydisCheckErrorConditions(ZydisDecoderState* state,
4347 const ZydisDecodedInstruction* instruction, const ZydisInstructionDefinition* definition)
4348 {
4349 ZYAN_ASSERT(state);
4350 ZYAN_ASSERT(instruction);
4351 ZYAN_ASSERT(definition);
4352
4353 ZyanU8 def_reg = definition->op_reg;
4354 ZyanU8 def_rm = definition->op_rm;
4355 ZyanU8 def_ndsndd = ZYDIS_REGKIND_INVALID;
4356 ZyanBool is_gather = ZYAN_FALSE;
4357 ZyanBool no_source_dest_match = ZYAN_FALSE;
4358 ZyanBool no_source_source_match = ZYAN_FALSE;
4359 #if !defined(ZYDIS_DISABLE_AVX512) || !defined(ZYDIS_DISABLE_KNC)
4360 ZydisMaskPolicy mask_policy = ZYDIS_MASK_POLICY_INVALID;
4361 #endif
4362
4363 switch (instruction->encoding)
4364 {
4365 case ZYDIS_INSTRUCTION_ENCODING_LEGACY:
4366 {
4367 const ZydisInstructionDefinitionLEGACY* def =
4368 (const ZydisInstructionDefinitionLEGACY*)definition;
4369
4370 if (def->requires_protected_mode &&
4371 (instruction->machine_mode == ZYDIS_MACHINE_MODE_REAL_16))
4372 {
4373 return ZYDIS_STATUS_DECODING_ERROR;
4374 }
4375
4376 if (def->no_compat_mode &&
4377 ((instruction->machine_mode == ZYDIS_MACHINE_MODE_LONG_COMPAT_16) ||
4378 (instruction->machine_mode == ZYDIS_MACHINE_MODE_LONG_COMPAT_32)))
4379 {
4380 return ZYDIS_STATUS_DECODING_ERROR;
4381 }
4382
4383 if (state->prefixes.has_lock && !def->accepts_LOCK)
4384 {
4385 return ZYDIS_STATUS_ILLEGAL_LOCK;
4386 }
4387 break;
4388 }
4389 case ZYDIS_INSTRUCTION_ENCODING_3DNOW:
4390 {
4391 break;
4392 }
4393 case ZYDIS_INSTRUCTION_ENCODING_XOP:
4394 {
4395 const ZydisInstructionDefinitionXOP* def =
4396 (const ZydisInstructionDefinitionXOP*)definition;
4397 def_ndsndd = def->op_ndsndd;
4398 break;
4399 }
4400 case ZYDIS_INSTRUCTION_ENCODING_VEX:
4401 {
4402 const ZydisInstructionDefinitionVEX* def =
4403 (const ZydisInstructionDefinitionVEX*)definition;
4404 def_ndsndd = def->op_ndsndd;
4405 is_gather = def->is_gather;
4406 no_source_source_match = def->no_source_source_match;
4407 break;
4408 }
4409 case ZYDIS_INSTRUCTION_ENCODING_EVEX:
4410 {
4411 #ifndef ZYDIS_DISABLE_AVX512
4412 const ZydisInstructionDefinitionEVEX* def =
4413 (const ZydisInstructionDefinitionEVEX*)definition;
4414 def_ndsndd = def->op_ndsndd;
4415 is_gather = def->is_gather;
4416 no_source_dest_match = def->no_source_dest_match;
4417 mask_policy = def->mask_policy;
4418
4419 // Check for invalid zero-mask
4420 if ((instruction->raw.evex.z) && (!def->accepts_zero_mask))
4421 {
4422 return ZYDIS_STATUS_INVALID_MASK; // TODO: Dedicated status code
4423 }
4424 #else
4425 ZYAN_UNREACHABLE;
4426 #endif
4427 break;
4428 }
4429 case ZYDIS_INSTRUCTION_ENCODING_MVEX:
4430 {
4431 #ifndef ZYDIS_DISABLE_KNC
4432 const ZydisInstructionDefinitionMVEX* def =
4433 (const ZydisInstructionDefinitionMVEX*)definition;
4434 def_ndsndd = def->op_ndsndd;
4435 is_gather = def->is_gather;
4436 mask_policy = def->mask_policy;
4437
4438 // Check for invalid MVEX.SSS values
4439 static const ZyanU8 lookup[26][8] =
4440 {
4441 // ZYDIS_MVEX_FUNC_IGNORED
4442 { 1, 1, 1, 1, 1, 1, 1, 1 },
4443 // ZYDIS_MVEX_FUNC_INVALID
4444 { 1, 0, 0, 0, 0, 0, 0, 0 },
4445 // ZYDIS_MVEX_FUNC_RC
4446 { 1, 1, 1, 1, 1, 1, 1, 1 },
4447 // ZYDIS_MVEX_FUNC_SAE
4448 { 1, 1, 1, 1, 1, 1, 1, 1 },
4449 // ZYDIS_MVEX_FUNC_F_32
4450 { 1, 0, 0, 0, 0, 0, 0, 0 },
4451 // ZYDIS_MVEX_FUNC_I_32
4452 { 1, 0, 0, 0, 0, 0, 0, 0 },
4453 // ZYDIS_MVEX_FUNC_F_64
4454 { 1, 0, 0, 0, 0, 0, 0, 0 },
4455 // ZYDIS_MVEX_FUNC_I_64
4456 { 1, 0, 0, 0, 0, 0, 0, 0 },
4457 // ZYDIS_MVEX_FUNC_SWIZZLE_32
4458 { 1, 1, 1, 1, 1, 1, 1, 1 },
4459 // ZYDIS_MVEX_FUNC_SWIZZLE_64
4460 { 1, 1, 1, 1, 1, 1, 1, 1 },
4461 // ZYDIS_MVEX_FUNC_SF_32
4462 { 1, 1, 1, 1, 1, 0, 1, 1 },
4463 // ZYDIS_MVEX_FUNC_SF_32_BCST
4464 { 1, 1, 1, 0, 0, 0, 0, 0 },
4465 // ZYDIS_MVEX_FUNC_SF_32_BCST_4TO16
4466 { 1, 0, 1, 0, 0, 0, 0, 0 },
4467 // ZYDIS_MVEX_FUNC_SF_64
4468 { 1, 1, 1, 0, 0, 0, 0, 0 },
4469 // ZYDIS_MVEX_FUNC_SI_32
4470 { 1, 1, 1, 0, 1, 1, 1, 1 },
4471 // ZYDIS_MVEX_FUNC_SI_32_BCST
4472 { 1, 1, 1, 0, 0, 0, 0, 0 },
4473 // ZYDIS_MVEX_FUNC_SI_32_BCST_4TO16
4474 { 1, 0, 1, 0, 0, 0, 0, 0 },
4475 // ZYDIS_MVEX_FUNC_SI_64
4476 { 1, 1, 1, 0, 0, 0, 0, 0 },
4477 // ZYDIS_MVEX_FUNC_UF_32
4478 { 1, 0, 0, 1, 1, 1, 1, 1 },
4479 // ZYDIS_MVEX_FUNC_UF_64
4480 { 1, 0, 0, 0, 0, 0, 0, 0 },
4481 // ZYDIS_MVEX_FUNC_UI_32
4482 { 1, 0, 0, 0, 1, 1, 1, 1 },
4483 // ZYDIS_MVEX_FUNC_UI_64
4484 { 1, 0, 0, 0, 0, 0, 0, 0 },
4485 // ZYDIS_MVEX_FUNC_DF_32
4486 { 1, 0, 0, 1, 1, 1, 1, 1 },
4487 // ZYDIS_MVEX_FUNC_DF_64
4488 { 1, 0, 0, 0, 0, 0, 0, 0 },
4489 // ZYDIS_MVEX_FUNC_DI_32
4490 { 1, 0, 0, 0, 1, 1, 1, 1 },
4491 // ZYDIS_MVEX_FUNC_DI_64
4492 { 1, 0, 0, 0, 0, 0, 0, 0 }
4493 };
4494 ZYAN_ASSERT(def->functionality < ZYAN_ARRAY_LENGTH(lookup));
4495 ZYAN_ASSERT(instruction->raw.mvex.SSS < 8);
4496 if (!lookup[def->functionality][instruction->raw.mvex.SSS])
4497 {
4498 return ZYDIS_STATUS_DECODING_ERROR;
4499 }
4500 #else
4501 ZYAN_UNREACHABLE;
4502 #endif
4503 break;
4504 }
4505 default:
4506 ZYAN_UNREACHABLE;
4507 }
4508
4509 ZydisDecoderContext* context = state->context;
4510 const ZyanBool is_reg = context->reg_info.is_mod_reg;
4511
4512 ZyanU8 no_rip_rel = ZYAN_FALSE;
4513 ZyanU8 is_sr_dest_reg = ZYAN_FALSE;
4514 ZyanU8 is_sr_dest_rm = ZYAN_FALSE;
4515 if (def_reg)
4516 {
4517 is_sr_dest_reg = ZYDIS_OPDEF_GET_REG_HIGH_BIT(def_reg);
4518 def_reg = ZYDIS_OPDEF_GET_REG(def_reg);
4519 }
4520 if (def_rm)
4521 {
4522 if (is_reg)
4523 {
4524 is_sr_dest_rm = ZYDIS_OPDEF_GET_REG_HIGH_BIT(def_rm);
4525 def_rm = ZYDIS_OPDEF_GET_REG(def_rm);
4526 }
4527 else
4528 {
4529 no_rip_rel = ZYDIS_OPDEF_GET_MEM_HIGH_BIT(def_rm);
4530 def_rm = ZYDIS_OPDEF_GET_MEM(def_rm);
4531 }
4532 }
4533
4534 // Check RIP-relative memory addressing
4535 if (no_rip_rel)
4536 {
4537 const ZyanBool is_rip_rel =
4538 (state->decoder->machine_mode == ZYDIS_MACHINE_MODE_LONG_64) &&
4539 (instruction->raw.modrm.mod == 0) && (instruction->raw.modrm.rm == 5);
4540 if (is_rip_rel)
4541 {
4542 return ZYDIS_STATUS_BAD_REGISTER;
4543 }
4544 }
4545
4546 // Populate- and validate register constraints
4547 ZYAN_CHECK(ZydisPopulateRegisterIds(context, instruction, def_reg, def_rm, def_ndsndd));
4548
4549 // `ZYDIS_REGISTER_CS` is not allowed as `MOV` target
4550 if (is_sr_dest_reg && (context->reg_info.id_reg == 1))
4551 {
4552 return ZYDIS_STATUS_BAD_REGISTER;
4553 }
4554 if (is_sr_dest_rm && (context->reg_info.id_rm == 1))
4555 {
4556 return ZYDIS_STATUS_BAD_REGISTER;
4557 }
4558
4559 // Check gather registers
4560 if (is_gather)
4561 {
4562 // ZYAN_ASSERT(has_VSIB);
4563 ZYAN_ASSERT(instruction->raw.modrm.mod != 3);
4564 ZYAN_ASSERT(instruction->raw.modrm.rm == 4);
4565
4566 const ZyanU8 index = context->reg_info.id_index;
4567 ZyanU8 dest = context->reg_info.id_reg;
4568 ZyanU8 mask = 0xF0;
4569
4570 if (instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_VEX)
4571 {
4572 ZYAN_ASSERT((def_reg == ZYDIS_REGKIND_VR) &&
4573 (def_rm == ZYDIS_MEMOP_TYPE_VSIB) &&
4574 (def_ndsndd == ZYDIS_REGKIND_VR));
4575 mask = context->reg_info.id_ndsndd;
4576 }
4577
4578 if ((instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_EVEX) ||
4579 (instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_MVEX))
4580 {
4581 ZYAN_ASSERT(((def_reg == ZYDIS_REGKIND_INVALID) ||
4582 (def_reg == ZYDIS_REGKIND_VR)) &&
4583 (def_rm == ZYDIS_MEMOP_TYPE_VSIB) &&
4584 (def_ndsndd == ZYDIS_REGKIND_INVALID));
4585
4586 // Some gather instructions (like `VGATHERPF0{D|Q}{PS|PD}`) do not have a destination
4587 // operand
4588 if (!def_reg)
4589 {
4590 dest = 0xF1;
4591 }
4592 }
4593
4594 // If any pair of the index, mask, or destination registers are the same, the instruction
4595 // results a UD fault
4596 if ((dest == index) || (dest == mask) || (index == mask))
4597 {
4598 return ZYDIS_STATUS_BAD_REGISTER;
4599 }
4600 }
4601
4602 // Check if any source register matches the destination register
4603 if (no_source_dest_match)
4604 {
4605 ZYAN_ASSERT((instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_EVEX) ||
4606 (instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_VEX));
4607
4608 const ZyanU8 dest = context->reg_info.id_reg;
4609 const ZyanU8 source1 = context->reg_info.id_ndsndd;
4610 const ZyanU8 source2 = context->reg_info.id_rm;
4611
4612 if ((dest == source1) || (is_reg && (dest == source2)))
4613 {
4614 return ZYDIS_STATUS_BAD_REGISTER;
4615 }
4616 }
4617
4618 // If any pair of the source or destination registers are the same, the instruction results a
4619 // UD fault
4620 if (no_source_source_match) // TODO: Find better name
4621 {
4622 ZYAN_ASSERT(instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_VEX);
4623 ZYAN_ASSERT(is_reg);
4624
4625 const ZyanU8 dest = context->reg_info.id_reg;
4626 const ZyanU8 source1 = context->reg_info.id_ndsndd;
4627 const ZyanU8 source2 = context->reg_info.id_rm;
4628
4629 if ((dest == source1) || (dest == source2) || (source1 == source2))
4630 {
4631 return ZYDIS_STATUS_BAD_REGISTER;
4632 }
4633 }
4634
4635 #if !defined(ZYDIS_DISABLE_AVX512) || !defined(ZYDIS_DISABLE_KNC)
4636 // Check for invalid MASK registers
4637 switch (mask_policy)
4638 {
4639 case ZYDIS_MASK_POLICY_INVALID:
4640 case ZYDIS_MASK_POLICY_ALLOWED:
4641 // Nothing to do here
4642 break;
4643 case ZYDIS_MASK_POLICY_REQUIRED:
4644 if (!context->vector_unified.mask)
4645 {
4646 return ZYDIS_STATUS_INVALID_MASK;
4647 }
4648 break;
4649 case ZYDIS_MASK_POLICY_FORBIDDEN:
4650 if (context->vector_unified.mask)
4651 {
4652 return ZYDIS_STATUS_INVALID_MASK;
4653 }
4654 break;
4655 default:
4656 ZYAN_UNREACHABLE;
4657 }
4658 #endif
4659
4660 return ZYAN_STATUS_SUCCESS;
4661 }
4662
4663 /* ---------------------------------------------------------------------------------------------- */
4664
4665 /**
4666 * Uses the decoder-tree to decode the current instruction.
4667 *
4668 * @param state A pointer to the `ZydisDecoderState` struct.
4669 * @param instruction A pointer to the `ZydisDecodedInstruction` struct.
4670 *
4671 * @return A zyan status code.
4672 */
ZydisDecodeInstruction(ZydisDecoderState * state,ZydisDecodedInstruction * instruction)4673 static ZyanStatus ZydisDecodeInstruction(ZydisDecoderState* state,
4674 ZydisDecodedInstruction* instruction)
4675 {
4676 ZYAN_ASSERT(state);
4677 ZYAN_ASSERT(instruction);
4678
4679 // Iterate through the decoder tree
4680 const ZydisDecoderTreeNode* node = ZydisDecoderTreeGetRootNode();
4681 const ZydisDecoderTreeNode* temp = ZYAN_NULL;
4682 ZydisDecoderTreeNodeType node_type;
4683 do
4684 {
4685 node_type = node->type;
4686 ZyanU16 index = 0;
4687 ZyanStatus status = 0;
4688 switch (node_type)
4689 {
4690 case ZYDIS_NODETYPE_INVALID:
4691 if (temp)
4692 {
4693 node = temp;
4694 temp = ZYAN_NULL;
4695 node_type = ZYDIS_NODETYPE_FILTER_MANDATORY_PREFIX;
4696 if (state->prefixes.mandatory_candidate != 0x00)
4697 {
4698 instruction->raw.prefixes[state->prefixes.offset_mandatory].type =
4699 ZYDIS_PREFIX_TYPE_IGNORED;
4700 }
4701 if (state->prefixes.mandatory_candidate == 0x66)
4702 {
4703 if (state->prefixes.offset_osz_override ==
4704 state->prefixes.offset_mandatory)
4705 {
4706 instruction->raw.prefixes[state->prefixes.offset_mandatory].type =
4707 ZYDIS_PREFIX_TYPE_EFFECTIVE;
4708 }
4709 instruction->attributes |= ZYDIS_ATTRIB_HAS_OPERANDSIZE;
4710 }
4711 continue;
4712 }
4713 return ZYDIS_STATUS_DECODING_ERROR;
4714 case ZYDIS_NODETYPE_FILTER_XOP:
4715 status = ZydisNodeHandlerXOP(instruction, &index);
4716 break;
4717 case ZYDIS_NODETYPE_FILTER_VEX:
4718 status = ZydisNodeHandlerVEX(instruction, &index);
4719 break;
4720 case ZYDIS_NODETYPE_FILTER_EMVEX:
4721 status = ZydisNodeHandlerEMVEX(instruction, &index);
4722 break;
4723 case ZYDIS_NODETYPE_FILTER_OPCODE:
4724 status = ZydisNodeHandlerOpcode(state, instruction, &index);
4725 break;
4726 case ZYDIS_NODETYPE_FILTER_MODE:
4727 status = ZydisNodeHandlerMode(instruction, &index);
4728 break;
4729 case ZYDIS_NODETYPE_FILTER_MODE_COMPACT:
4730 status = ZydisNodeHandlerModeCompact(instruction, &index);
4731 break;
4732 case ZYDIS_NODETYPE_FILTER_MODRM_MOD:
4733 status = ZydisNodeHandlerModrmMod(state, instruction, &index);
4734 break;
4735 case ZYDIS_NODETYPE_FILTER_MODRM_MOD_COMPACT:
4736 status = ZydisNodeHandlerModrmModCompact(state, instruction, &index);
4737 break;
4738 case ZYDIS_NODETYPE_FILTER_MODRM_REG:
4739 status = ZydisNodeHandlerModrmReg(state, instruction, &index);
4740 break;
4741 case ZYDIS_NODETYPE_FILTER_MODRM_RM:
4742 status = ZydisNodeHandlerModrmRm(state, instruction, &index);
4743 break;
4744 case ZYDIS_NODETYPE_FILTER_PREFIX_GROUP1:
4745 index = state->prefixes.group1 ? 1 : 0;
4746 break;
4747 case ZYDIS_NODETYPE_FILTER_MANDATORY_PREFIX:
4748 status = ZydisNodeHandlerMandatoryPrefix(state, instruction, &index);
4749 temp = ZydisDecoderTreeGetChildNode(node, 0);
4750 // TODO: Return to this point, if index == 0 contains a value and the previous path
4751 // TODO: was not successful
4752 // TODO: Restore consumed prefix
4753 break;
4754 case ZYDIS_NODETYPE_FILTER_OPERAND_SIZE:
4755 status = ZydisNodeHandlerOperandSize(state, instruction, &index);
4756 break;
4757 case ZYDIS_NODETYPE_FILTER_ADDRESS_SIZE:
4758 status = ZydisNodeHandlerAddressSize(instruction, &index);
4759 break;
4760 case ZYDIS_NODETYPE_FILTER_VECTOR_LENGTH:
4761 status = ZydisNodeHandlerVectorLength(state->context, instruction, &index);
4762 break;
4763 case ZYDIS_NODETYPE_FILTER_REX_W:
4764 status = ZydisNodeHandlerRexW(state->context, instruction, &index);
4765 break;
4766 case ZYDIS_NODETYPE_FILTER_REX_B:
4767 status = ZydisNodeHandlerRexB(state->context, instruction, &index);
4768 break;
4769 #ifndef ZYDIS_DISABLE_AVX512
4770 case ZYDIS_NODETYPE_FILTER_EVEX_B:
4771 status = ZydisNodeHandlerEvexB(instruction, &index);
4772 break;
4773 #endif
4774 #ifndef ZYDIS_DISABLE_KNC
4775 case ZYDIS_NODETYPE_FILTER_MVEX_E:
4776 status = ZydisNodeHandlerMvexE(instruction, &index);
4777 break;
4778 #endif
4779 case ZYDIS_NODETYPE_FILTER_MODE_AMD:
4780 index = !!(state->decoder->decoder_mode & (1 << ZYDIS_DECODER_MODE_AMD_BRANCHES));
4781 break;
4782 case ZYDIS_NODETYPE_FILTER_MODE_KNC:
4783 index = !!(state->decoder->decoder_mode & (1 << ZYDIS_DECODER_MODE_KNC));
4784 break;
4785 case ZYDIS_NODETYPE_FILTER_MODE_MPX:
4786 index = !!(state->decoder->decoder_mode & (1 << ZYDIS_DECODER_MODE_MPX));
4787 break;
4788 case ZYDIS_NODETYPE_FILTER_MODE_CET:
4789 index = !!(state->decoder->decoder_mode & (1 << ZYDIS_DECODER_MODE_CET));
4790 break;
4791 case ZYDIS_NODETYPE_FILTER_MODE_LZCNT:
4792 index = !!(state->decoder->decoder_mode & (1 << ZYDIS_DECODER_MODE_LZCNT));
4793 break;
4794 case ZYDIS_NODETYPE_FILTER_MODE_TZCNT:
4795 index = !!(state->decoder->decoder_mode & (1 << ZYDIS_DECODER_MODE_TZCNT));
4796 break;
4797 case ZYDIS_NODETYPE_FILTER_MODE_WBNOINVD:
4798 index = !!(state->decoder->decoder_mode & (1 << ZYDIS_DECODER_MODE_WBNOINVD));
4799 break;
4800 case ZYDIS_NODETYPE_FILTER_MODE_CLDEMOTE:
4801 index = !!(state->decoder->decoder_mode & (1 << ZYDIS_DECODER_MODE_CLDEMOTE));
4802 break;
4803 case ZYDIS_NODETYPE_FILTER_MODE_IPREFETCH:
4804 index = !!(state->decoder->decoder_mode & (1 << ZYDIS_DECODER_MODE_IPREFETCH));
4805 break;
4806 case ZYDIS_NODETYPE_FILTER_MODE_UD0_COMPAT:
4807 index = !!(state->decoder->decoder_mode & (1 << ZYDIS_DECODER_MODE_UD0_COMPAT));
4808 break;
4809 default:
4810 if (node_type & ZYDIS_NODETYPE_DEFINITION_MASK)
4811 {
4812 const ZydisInstructionDefinition* definition;
4813 ZydisGetInstructionDefinition(instruction->encoding, node->value, &definition);
4814 ZydisSetEffectiveOperandWidth(state->context, instruction, definition);
4815 ZydisSetEffectiveAddressWidth(state->context, instruction, definition);
4816
4817 const ZydisInstructionEncodingInfo* info;
4818 ZydisGetInstructionEncodingInfo(node, &info);
4819 ZYAN_CHECK(ZydisDecodeOptionalInstructionParts(state, instruction, info));
4820 ZYAN_CHECK(ZydisCheckErrorConditions(state, instruction, definition));
4821
4822 if (instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_3DNOW)
4823 {
4824 // Get actual 3DNOW opcode and definition
4825 ZYAN_CHECK(ZydisInputNext(state, instruction, &instruction->opcode));
4826 node = ZydisDecoderTreeGetRootNode();
4827 node = ZydisDecoderTreeGetChildNode(node, 0x0F);
4828 node = ZydisDecoderTreeGetChildNode(node, 0x0F);
4829 node = ZydisDecoderTreeGetChildNode(node, instruction->opcode);
4830 if (node->type == ZYDIS_NODETYPE_INVALID)
4831 {
4832 return ZYDIS_STATUS_DECODING_ERROR;
4833 }
4834 ZYAN_ASSERT(node->type == ZYDIS_NODETYPE_FILTER_MODRM_MOD_COMPACT);
4835 node = ZydisDecoderTreeGetChildNode(
4836 node, (instruction->raw.modrm.mod == 0x3) ? 0 : 1);
4837 ZYAN_ASSERT(node->type & ZYDIS_NODETYPE_DEFINITION_MASK);
4838 ZydisGetInstructionDefinition(instruction->encoding, node->value, &definition);
4839 }
4840
4841 instruction->mnemonic = definition->mnemonic;
4842
4843 #ifndef ZYDIS_MINIMAL_MODE
4844
4845 instruction->operand_count = definition->operand_count;
4846 instruction->operand_count_visible = definition->operand_count_visible;
4847 state->context->definition = definition;
4848
4849 instruction->meta.category = definition->category;
4850 instruction->meta.isa_set = definition->isa_set;
4851 instruction->meta.isa_ext = definition->isa_ext;
4852 instruction->meta.branch_type = definition->branch_type;
4853 ZYAN_ASSERT((instruction->meta.branch_type == ZYDIS_BRANCH_TYPE_NONE) ||
4854 ((instruction->meta.category == ZYDIS_CATEGORY_CALL) ||
4855 (instruction->meta.category == ZYDIS_CATEGORY_COND_BR) ||
4856 (instruction->meta.category == ZYDIS_CATEGORY_UNCOND_BR) ||
4857 (instruction->meta.category == ZYDIS_CATEGORY_RET)));
4858 instruction->meta.exception_class = definition->exception_class;
4859
4860 if (!(state->decoder->decoder_mode & (1 << ZYDIS_DECODER_MODE_MINIMAL)))
4861 {
4862 ZydisSetAttributes(state, instruction, definition);
4863 switch (instruction->encoding)
4864 {
4865 case ZYDIS_INSTRUCTION_ENCODING_XOP:
4866 case ZYDIS_INSTRUCTION_ENCODING_VEX:
4867 case ZYDIS_INSTRUCTION_ENCODING_EVEX:
4868 case ZYDIS_INSTRUCTION_ENCODING_MVEX:
4869 ZydisSetAVXInformation(state->context, instruction, definition);
4870 break;
4871 default:
4872 break;
4873 }
4874
4875 const ZydisDefinitionAccessedFlags* flags;
4876 if (ZydisGetAccessedFlags(definition, &flags))
4877 {
4878 instruction->attributes |= ZYDIS_ATTRIB_CPUFLAG_ACCESS;
4879 }
4880 instruction->cpu_flags = &flags->cpu_flags;
4881 instruction->fpu_flags = &flags->fpu_flags;
4882 }
4883
4884 #endif
4885
4886 return ZYAN_STATUS_SUCCESS;
4887 }
4888 ZYAN_UNREACHABLE;
4889 }
4890 ZYAN_CHECK(status);
4891 node = ZydisDecoderTreeGetChildNode(node, index);
4892 } while ((node_type != ZYDIS_NODETYPE_INVALID) && !(node_type & ZYDIS_NODETYPE_DEFINITION_MASK));
4893 return ZYAN_STATUS_SUCCESS;
4894 }
4895
4896 /* ---------------------------------------------------------------------------------------------- */
4897
4898 /* ============================================================================================== */
4899 /* Exported functions */
4900 /* ============================================================================================== */
4901
ZydisDecoderInit(ZydisDecoder * decoder,ZydisMachineMode machine_mode,ZydisStackWidth stack_width)4902 ZyanStatus ZydisDecoderInit(ZydisDecoder* decoder, ZydisMachineMode machine_mode,
4903 ZydisStackWidth stack_width)
4904 {
4905 ZYAN_STATIC_ASSERT(ZYDIS_DECODER_MODE_MAX_VALUE <= 32);
4906
4907 static const ZyanU32 decoder_modes =
4908 #ifdef ZYDIS_MINIMAL_MODE
4909 (1 << ZYDIS_DECODER_MODE_MINIMAL) |
4910 #endif
4911 (1 << ZYDIS_DECODER_MODE_MPX) |
4912 (1 << ZYDIS_DECODER_MODE_CET) |
4913 (1 << ZYDIS_DECODER_MODE_LZCNT) |
4914 (1 << ZYDIS_DECODER_MODE_TZCNT) |
4915 (1 << ZYDIS_DECODER_MODE_CLDEMOTE) |
4916 (1 << ZYDIS_DECODER_MODE_IPREFETCH);
4917
4918 if (!decoder)
4919 {
4920 return ZYAN_STATUS_INVALID_ARGUMENT;
4921 }
4922 switch (machine_mode)
4923 {
4924 case ZYDIS_MACHINE_MODE_LONG_64:
4925 if (stack_width != ZYDIS_STACK_WIDTH_64)
4926 {
4927 return ZYAN_STATUS_INVALID_ARGUMENT;
4928 }
4929 break;
4930 case ZYDIS_MACHINE_MODE_LONG_COMPAT_32:
4931 case ZYDIS_MACHINE_MODE_LONG_COMPAT_16:
4932 case ZYDIS_MACHINE_MODE_LEGACY_32:
4933 case ZYDIS_MACHINE_MODE_LEGACY_16:
4934 case ZYDIS_MACHINE_MODE_REAL_16:
4935 if ((stack_width != ZYDIS_STACK_WIDTH_16) && (stack_width != ZYDIS_STACK_WIDTH_32))
4936 {
4937 return ZYAN_STATUS_INVALID_ARGUMENT;
4938 }
4939 break;
4940 default:
4941 return ZYAN_STATUS_INVALID_ARGUMENT;
4942 }
4943
4944 decoder->machine_mode = machine_mode;
4945 decoder->stack_width = stack_width;
4946 decoder->decoder_mode = decoder_modes;
4947
4948 return ZYAN_STATUS_SUCCESS;
4949 }
4950
ZydisDecoderEnableMode(ZydisDecoder * decoder,ZydisDecoderMode mode,ZyanBool enabled)4951 ZyanStatus ZydisDecoderEnableMode(ZydisDecoder* decoder, ZydisDecoderMode mode, ZyanBool enabled)
4952 {
4953 if (!decoder || ((ZyanUSize)mode > ZYDIS_DECODER_MODE_MAX_VALUE))
4954 {
4955 return ZYAN_STATUS_INVALID_ARGUMENT;
4956 }
4957
4958 #ifdef ZYDIS_MINIMAL_MODE
4959 if ((mode == ZYDIS_DECODER_MODE_MINIMAL) && !enabled)
4960 {
4961 return ZYAN_STATUS_INVALID_OPERATION;
4962 }
4963 #endif
4964
4965 if (enabled)
4966 {
4967 decoder->decoder_mode |= (1 << mode);
4968 }
4969 else
4970 {
4971 decoder->decoder_mode &= ~(1 << mode);
4972 }
4973
4974 return ZYAN_STATUS_SUCCESS;
4975 }
4976
ZydisDecoderDecodeFull(const ZydisDecoder * decoder,const void * buffer,ZyanUSize length,ZydisDecodedInstruction * instruction,ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT])4977 ZyanStatus ZydisDecoderDecodeFull(const ZydisDecoder* decoder,
4978 const void* buffer, ZyanUSize length, ZydisDecodedInstruction* instruction,
4979 ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT])
4980 {
4981 if (!decoder || !instruction || !buffer || !operands)
4982 {
4983 return ZYAN_STATUS_INVALID_ARGUMENT;
4984 }
4985 if (!length)
4986 {
4987 return ZYDIS_STATUS_NO_MORE_DATA;
4988 }
4989 if (decoder->decoder_mode & (1 << ZYDIS_DECODER_MODE_MINIMAL))
4990 {
4991 return ZYAN_STATUS_MISSING_DEPENDENCY; // TODO: Introduce better status code
4992 }
4993
4994 ZydisDecoderContext context;
4995 ZYAN_CHECK(ZydisDecoderDecodeInstruction(decoder, &context, buffer, length, instruction));
4996 ZYAN_CHECK(ZydisDecoderDecodeOperands(decoder, &context, instruction, operands,
4997 instruction->operand_count));
4998 ZYAN_MEMSET(&operands[instruction->operand_count], 0,
4999 (ZYDIS_MAX_OPERAND_COUNT - instruction->operand_count) * sizeof(operands[0]));
5000
5001 return ZYAN_STATUS_SUCCESS;
5002 }
5003
ZydisDecoderDecodeInstruction(const ZydisDecoder * decoder,ZydisDecoderContext * context,const void * buffer,ZyanUSize length,ZydisDecodedInstruction * instruction)5004 ZyanStatus ZydisDecoderDecodeInstruction(const ZydisDecoder* decoder, ZydisDecoderContext* context,
5005 const void* buffer, ZyanUSize length, ZydisDecodedInstruction* instruction)
5006 {
5007 if (!decoder || !instruction || !buffer)
5008 {
5009 return ZYAN_STATUS_INVALID_ARGUMENT;
5010 }
5011
5012 if (!length)
5013 {
5014 return ZYDIS_STATUS_NO_MORE_DATA;
5015 }
5016
5017 ZydisDecoderState state;
5018 ZYAN_MEMSET(&state, 0, sizeof(state));
5019 state.decoder = decoder;
5020 state.buffer = (const ZyanU8*)buffer;
5021 state.buffer_len = length;
5022 state.prefixes.offset_notrack = -1;
5023
5024 ZydisDecoderContext default_context;
5025 if (!context)
5026 {
5027 // Use a fallback context if no custom one has been provided
5028 context = &default_context;
5029 }
5030 ZYAN_MEMSET(context, 0, sizeof(*context));
5031 state.context = context;
5032
5033 ZYAN_MEMSET(instruction, 0, sizeof(*instruction));
5034 instruction->machine_mode = decoder->machine_mode;
5035 instruction->stack_width = 16 << decoder->stack_width;
5036
5037 ZYAN_CHECK(ZydisCollectOptionalPrefixes(&state, instruction));
5038 ZYAN_CHECK(ZydisDecodeInstruction(&state, instruction));
5039
5040 instruction->raw.encoding2 = instruction->encoding;
5041
5042 return ZYAN_STATUS_SUCCESS;
5043 }
5044
ZydisDecoderDecodeOperands(const ZydisDecoder * decoder,const ZydisDecoderContext * context,const ZydisDecodedInstruction * instruction,ZydisDecodedOperand * operands,ZyanU8 operand_count)5045 ZyanStatus ZydisDecoderDecodeOperands(const ZydisDecoder* decoder,
5046 const ZydisDecoderContext* context, const ZydisDecodedInstruction* instruction,
5047 ZydisDecodedOperand* operands, ZyanU8 operand_count)
5048 {
5049 #ifdef ZYDIS_MINIMAL_MODE
5050
5051 ZYAN_UNUSED(decoder);
5052 ZYAN_UNUSED(context);
5053 ZYAN_UNUSED(instruction);
5054 ZYAN_UNUSED(operands);
5055 ZYAN_UNUSED(operand_count);
5056
5057 return ZYAN_STATUS_MISSING_DEPENDENCY; // TODO: Introduce better status code
5058
5059 #else
5060
5061 if (!decoder || !context || !context->definition || !instruction ||
5062 (operand_count && !operands) || (operand_count > ZYDIS_MAX_OPERAND_COUNT))
5063 {
5064 return ZYAN_STATUS_INVALID_ARGUMENT;
5065 }
5066
5067 if (decoder->decoder_mode & (1 << ZYDIS_DECODER_MODE_MINIMAL))
5068 {
5069 return ZYAN_STATUS_MISSING_DEPENDENCY; // TODO: Introduce better status code
5070 }
5071
5072 operand_count = ZYAN_MIN(operand_count, instruction->operand_count);
5073 if (!operand_count)
5074 {
5075 return ZYAN_STATUS_SUCCESS;
5076 }
5077
5078 return ZydisDecodeOperands(decoder, context, instruction, operands, operand_count);
5079
5080 #endif
5081 }
5082
5083 /* ============================================================================================== */
5084