xref: /freebsd/contrib/processor-trace/libipt/src/pt_ild.c (revision 85f87cf491bec6f90948a85b10f5523ea24db9e3)
1 /*
2  * Copyright (c) 2013-2019, Intel Corporation
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  *  * Redistributions of source code must retain the above copyright notice,
8  *    this list of conditions and the following disclaimer.
9  *  * Redistributions in binary form must reproduce the above copyright notice,
10  *    this list of conditions and the following disclaimer in the documentation
11  *    and/or other materials provided with the distribution.
12  *  * Neither the name of Intel Corporation nor the names of its contributors
13  *    may be used to endorse or promote products derived from this software
14  *    without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include "pt_ild.h"
30 #include "pti-imm-defs.h"
31 #include "pti-imm.h"
32 #include "pti-modrm-defs.h"
33 #include "pti-modrm.h"
34 #include "pti-disp-defs.h"
35 #include "pti-disp.h"
36 #include "pti-disp_default.h"
37 #include "pti-sib.h"
38 
39 #include <string.h>
40 
41 
42 static const uint8_t eamode_table[2][4] = {
43 	/* Default: */ {
44 		/* ptem_unknown = */	ptem_unknown,
45 		/* ptem_16bit = */	ptem_16bit,
46 		/* ptem_32bit = */	ptem_32bit,
47 		/* ptem_64bit = */	ptem_64bit
48 	},
49 
50 	/* With Address-size prefix (0x67): */ {
51 		/* ptem_unknown = */	ptem_unknown,
52 		/* ptem_16bit = */	ptem_32bit,
53 		/* ptem_32bit = */	ptem_16bit,
54 		/* ptem_64bit = */	ptem_32bit
55 	}
56 };
57 
58 /* SOME ACCESSORS */
59 
get_byte(const struct pt_ild * ild,uint8_t i)60 static inline uint8_t get_byte(const struct pt_ild *ild, uint8_t i)
61 {
62 	return ild->itext[i];
63 }
64 
get_byte_ptr(const struct pt_ild * ild,uint8_t i)65 static inline uint8_t const *get_byte_ptr(const struct pt_ild *ild, uint8_t i)
66 {
67 	return ild->itext + i;
68 }
69 
mode_64b(const struct pt_ild * ild)70 static inline int mode_64b(const struct pt_ild *ild)
71 {
72 	return ild->mode == ptem_64bit;
73 }
74 
mode_32b(const struct pt_ild * ild)75 static inline int mode_32b(const struct pt_ild *ild)
76 {
77 	return ild->mode == ptem_32bit;
78 }
79 
bits_match(uint8_t x,uint8_t mask,uint8_t target)80 static inline int bits_match(uint8_t x, uint8_t mask, uint8_t target)
81 {
82 	return (x & mask) == target;
83 }
84 
85 static inline enum pt_exec_mode
pti_get_nominal_eosz_non64(const struct pt_ild * ild)86 pti_get_nominal_eosz_non64(const struct pt_ild *ild)
87 {
88 	if (mode_32b(ild)) {
89 		if (ild->u.s.osz)
90 			return ptem_16bit;
91 		return ptem_32bit;
92 	}
93 	if (ild->u.s.osz)
94 		return ptem_32bit;
95 	return ptem_16bit;
96 }
97 
98 static inline enum pt_exec_mode
pti_get_nominal_eosz(const struct pt_ild * ild)99 pti_get_nominal_eosz(const struct pt_ild *ild)
100 {
101 	if (mode_64b(ild)) {
102 		if (ild->u.s.rex_w)
103 			return ptem_64bit;
104 		if (ild->u.s.osz)
105 			return ptem_16bit;
106 		return ptem_32bit;
107 	}
108 	return pti_get_nominal_eosz_non64(ild);
109 }
110 
111 static inline enum pt_exec_mode
pti_get_nominal_eosz_df64(const struct pt_ild * ild)112 pti_get_nominal_eosz_df64(const struct pt_ild *ild)
113 {
114 	if (mode_64b(ild)) {
115 		if (ild->u.s.rex_w)
116 			return ptem_64bit;
117 		if (ild->u.s.osz)
118 			return ptem_16bit;
119 		/* only this next line of code is different relative
120 		   to pti_get_nominal_eosz(), above */
121 		return ptem_64bit;
122 	}
123 	return pti_get_nominal_eosz_non64(ild);
124 }
125 
126 static inline enum pt_exec_mode
pti_get_nominal_easz_non64(const struct pt_ild * ild)127 pti_get_nominal_easz_non64(const struct pt_ild *ild)
128 {
129 	if (mode_32b(ild)) {
130 		if (ild->u.s.asz)
131 			return ptem_16bit;
132 		return ptem_32bit;
133 	}
134 	if (ild->u.s.asz)
135 		return ptem_32bit;
136 	return ptem_16bit;
137 }
138 
139 static inline enum pt_exec_mode
pti_get_nominal_easz(const struct pt_ild * ild)140 pti_get_nominal_easz(const struct pt_ild *ild)
141 {
142 	if (mode_64b(ild)) {
143 		if (ild->u.s.asz)
144 			return ptem_32bit;
145 		return ptem_64bit;
146 	}
147 	return pti_get_nominal_easz_non64(ild);
148 }
149 
resolve_z(uint8_t * pbytes,enum pt_exec_mode eosz)150 static inline int resolve_z(uint8_t *pbytes, enum pt_exec_mode eosz)
151 {
152 	static const uint8_t bytes[] = { 2, 4, 4 };
153 	unsigned int idx;
154 
155 	if (!pbytes)
156 		return -pte_internal;
157 
158 	idx = (unsigned int) eosz - 1;
159 	if (sizeof(bytes) <= idx)
160 		return -pte_bad_insn;
161 
162 	*pbytes = bytes[idx];
163 	return 0;
164 }
165 
resolve_v(uint8_t * pbytes,enum pt_exec_mode eosz)166 static inline int resolve_v(uint8_t *pbytes, enum pt_exec_mode eosz)
167 {
168 	static const uint8_t bytes[] = { 2, 4, 8 };
169 	unsigned int idx;
170 
171 	if (!pbytes)
172 		return -pte_internal;
173 
174 	idx = (unsigned int) eosz - 1;
175 	if (sizeof(bytes) <= idx)
176 		return -pte_bad_insn;
177 
178 	*pbytes = bytes[idx];
179 	return 0;
180 }
181 
182 /*  DECODERS */
183 
set_imm_bytes(struct pt_ild * ild)184 static int set_imm_bytes(struct pt_ild *ild)
185 {
186 	/*: set ild->imm1_bytes and  ild->imm2_bytes for maps 0/1 */
187 	static uint8_t const *const map_map[] = {
188 		/* map 0 */ imm_bytes_map_0x0,
189 		/* map 1 */ imm_bytes_map_0x0F
190 	};
191 	uint8_t map, imm_code;
192 
193 	if (!ild)
194 		return -pte_internal;
195 
196 	map = ild->map;
197 
198 	if ((sizeof(map_map) / sizeof(*map_map)) <= map)
199 		return 0;
200 
201 	imm_code = map_map[map][ild->nominal_opcode];
202 	switch (imm_code) {
203 	case PTI_IMM_NONE:
204 	case PTI_0_IMM_WIDTH_CONST_l2:
205 	default:
206 		return 0;
207 
208 	case PTI_UIMM8_IMM_WIDTH_CONST_l2:
209 		ild->imm1_bytes = 1;
210 		return 0;
211 
212 	case PTI_SIMM8_IMM_WIDTH_CONST_l2:
213 		ild->imm1_bytes = 1;
214 		return 0;
215 
216 	case PTI_SIMMz_IMM_WIDTH_OSZ_NONTERM_EOSZ_l2:
217 		/* SIMMz(eosz) */
218 		return resolve_z(&ild->imm1_bytes, pti_get_nominal_eosz(ild));
219 
220 	case PTI_UIMMv_IMM_WIDTH_OSZ_NONTERM_EOSZ_l2:
221 		/* UIMMv(eosz) */
222 		return resolve_v(&ild->imm1_bytes, pti_get_nominal_eosz(ild));
223 
224 	case PTI_UIMM16_IMM_WIDTH_CONST_l2:
225 		ild->imm1_bytes = 2;
226 		return 0;
227 
228 	case PTI_SIMMz_IMM_WIDTH_OSZ_NONTERM_DF64_EOSZ_l2:
229 		/* push defaults to eosz64 in 64b mode, then uses SIMMz */
230 		return resolve_z(&ild->imm1_bytes,
231 				 pti_get_nominal_eosz_df64(ild));
232 
233 	case PTI_RESOLVE_BYREG_IMM_WIDTH_map0x0_op0xf7_l1:
234 		if (ild->map == PTI_MAP_0 && pti_get_modrm_reg(ild) < 2) {
235 			return resolve_z(&ild->imm1_bytes,
236 					 pti_get_nominal_eosz(ild));
237 		}
238 		return 0;
239 
240 	case PTI_RESOLVE_BYREG_IMM_WIDTH_map0x0_op0xc7_l1:
241 		if (ild->map == PTI_MAP_0 && pti_get_modrm_reg(ild) == 0) {
242 			return resolve_z(&ild->imm1_bytes,
243 					 pti_get_nominal_eosz(ild));
244 		}
245 		return 0;
246 
247 	case PTI_RESOLVE_BYREG_IMM_WIDTH_map0x0_op0xf6_l1:
248 		if (ild->map == PTI_MAP_0 && pti_get_modrm_reg(ild) < 2)
249 			ild->imm1_bytes = 1;
250 
251 		return 0;
252 
253 	case PTI_IMM_hasimm_map0x0_op0xc8_l1:
254 		if (ild->map == PTI_MAP_0) {
255 			/*enter -> imm1=2, imm2=1 */
256 			ild->imm1_bytes = 2;
257 			ild->imm2_bytes = 1;
258 		}
259 		return 0;
260 
261 	case PTI_IMM_hasimm_map0x0F_op0x78_l1:
262 		/* AMD SSE4a (insertq/extrq use  osz/f2) vs vmread
263 		 * (no prefixes)
264 		 */
265 		if (ild->map == PTI_MAP_1) {
266 			if (ild->u.s.osz || ild->u.s.last_f2f3 == 2) {
267 				ild->imm1_bytes = 1;
268 				ild->imm2_bytes = 1;
269 			}
270 		}
271 		return 0;
272 	}
273 }
274 
imm_dec(struct pt_ild * ild,uint8_t length)275 static int imm_dec(struct pt_ild *ild, uint8_t length)
276 {
277 	int errcode;
278 
279 	if (!ild)
280 		return -pte_internal;
281 
282 	if (ild->map == PTI_MAP_AMD3DNOW) {
283 		if (ild->max_bytes <= length)
284 			return -pte_bad_insn;
285 
286 		ild->nominal_opcode = get_byte(ild, length);
287 		return length + 1;
288 	}
289 
290 	errcode = set_imm_bytes(ild);
291 	if (errcode < 0)
292 		return errcode;
293 
294 	length += ild->imm1_bytes;
295 	length += ild->imm2_bytes;
296 	if (ild->max_bytes < length)
297 		return -pte_bad_insn;
298 
299 	return length;
300 }
301 
compute_disp_dec(struct pt_ild * ild)302 static int compute_disp_dec(struct pt_ild *ild)
303 {
304 	/* set ild->disp_bytes for maps 0 and 1. */
305 	static uint8_t const *const map_map[] = {
306 		/* map 0 */ disp_bytes_map_0x0,
307 		/* map 1 */ disp_bytes_map_0x0F
308 	};
309 	uint8_t map, disp_kind;
310 
311 	if (!ild)
312 		return -pte_internal;
313 
314 	if (0 < ild->disp_bytes)
315 		return 0;
316 
317 	map = ild->map;
318 
319 	if ((sizeof(map_map) / sizeof(*map_map)) <= map)
320 		return 0;
321 
322 	disp_kind = map_map[map][ild->nominal_opcode];
323 	switch (disp_kind) {
324 	case PTI_DISP_NONE:
325 		ild->disp_bytes = 0;
326 		return 0;
327 
328 	case PTI_PRESERVE_DEFAULT:
329 		/* nothing to do */
330 		return 0;
331 
332 	case PTI_BRDISP8:
333 		ild->disp_bytes = 1;
334 		return 0;
335 
336 	case PTI_DISP_BUCKET_0_l1:
337 		/* BRDISPz(eosz) for 16/32 modes, and BRDISP32 for 64b mode */
338 		if (mode_64b(ild)) {
339 			ild->disp_bytes = 4;
340 			return 0;
341 		}
342 
343 		return resolve_z(&ild->disp_bytes,
344 				 pti_get_nominal_eosz(ild));
345 
346 	case PTI_MEMDISPv_DISP_WIDTH_ASZ_NONTERM_EASZ_l2:
347 		/* MEMDISPv(easz) */
348 		return resolve_v(&ild->disp_bytes, pti_get_nominal_easz(ild));
349 
350 	case PTI_BRDISPz_BRDISP_WIDTH_OSZ_NONTERM_EOSZ_l2:
351 		/* BRDISPz(eosz) for 16/32/64 modes */
352 		return resolve_z(&ild->disp_bytes, pti_get_nominal_eosz(ild));
353 
354 	case PTI_RESOLVE_BYREG_DISP_map0x0_op0xc7_l1:
355 		/* reg=0 -> preserve, reg=7 -> BRDISPz(eosz) */
356 		if (ild->map == PTI_MAP_0 && pti_get_modrm_reg(ild) == 7) {
357 			return resolve_z(&ild->disp_bytes,
358 					 pti_get_nominal_eosz(ild));
359 		}
360 		return 0;
361 
362 	default:
363 		return -pte_bad_insn;
364 	}
365 }
366 
disp_dec(struct pt_ild * ild,uint8_t length)367 static int disp_dec(struct pt_ild *ild, uint8_t length)
368 {
369 	uint8_t disp_bytes;
370 	int errcode;
371 
372 	if (!ild)
373 		return -pte_internal;
374 
375 	errcode = compute_disp_dec(ild);
376 	if (errcode < 0)
377 		return errcode;
378 
379 	disp_bytes = ild->disp_bytes;
380 	if (disp_bytes == 0)
381 		return imm_dec(ild, length);
382 
383 	if (length + disp_bytes > ild->max_bytes)
384 		return -pte_bad_insn;
385 
386 	/*Record only position; must be able to re-read itext bytes for actual
387 	   value. (SMC/CMC issue). */
388 	ild->disp_pos = length;
389 
390 	return imm_dec(ild, length + disp_bytes);
391 }
392 
sib_dec(struct pt_ild * ild,uint8_t length)393 static int sib_dec(struct pt_ild *ild, uint8_t length)
394 {
395 	uint8_t sib;
396 
397 	if (!ild)
398 		return -pte_internal;
399 
400 	if (ild->max_bytes <= length)
401 		return -pte_bad_insn;
402 
403 	sib = get_byte(ild, length);
404 	if ((sib & 0x07) == 0x05 && pti_get_modrm_mod(ild) == 0)
405 		ild->disp_bytes = 4;
406 
407 	return disp_dec(ild, length + 1);
408 }
409 
modrm_dec(struct pt_ild * ild,uint8_t length)410 static int modrm_dec(struct pt_ild *ild, uint8_t length)
411 {
412 	static uint8_t const *const has_modrm_2d[2] = {
413 		has_modrm_map_0x0,
414 		has_modrm_map_0x0F
415 	};
416 	int has_modrm = PTI_MODRM_FALSE;
417 	pti_map_enum_t map;
418 
419 	if (!ild)
420 		return -pte_internal;
421 
422 	map = pti_get_map(ild);
423 	if (map >= PTI_MAP_2)
424 		has_modrm = PTI_MODRM_TRUE;
425 	else
426 		has_modrm = has_modrm_2d[map][ild->nominal_opcode];
427 
428 	if (has_modrm == PTI_MODRM_FALSE || has_modrm == PTI_MODRM_UNDEF)
429 		return disp_dec(ild, length);
430 
431 	/* really >= here because we have not eaten the byte yet */
432 	if (length >= ild->max_bytes)
433 		return -pte_bad_insn;
434 
435 	ild->modrm_byte = get_byte(ild, length);
436 
437 	if (has_modrm != PTI_MODRM_IGNORE_MOD) {
438 		/* set disp_bytes and sib using simple tables */
439 
440 		uint8_t eamode = eamode_table[ild->u.s.asz][ild->mode];
441 		uint8_t mod = (uint8_t) pti_get_modrm_mod(ild);
442 		uint8_t rm = (uint8_t) pti_get_modrm_rm(ild);
443 		uint8_t sib;
444 
445 		ild->disp_bytes = disp_default[eamode][mod][rm];
446 
447 		sib = has_sib[eamode][mod][rm];
448 		if (sib)
449 			return sib_dec(ild, length + 1);
450 	}
451 
452 	return disp_dec(ild, length + 1);
453 }
454 
get_next_as_opcode(struct pt_ild * ild,uint8_t length)455 static inline int get_next_as_opcode(struct pt_ild *ild, uint8_t length)
456 {
457 	if (!ild)
458 		return -pte_internal;
459 
460 	if (ild->max_bytes <= length)
461 		return -pte_bad_insn;
462 
463 	ild->nominal_opcode = get_byte(ild, length);
464 
465 	return modrm_dec(ild, length + 1);
466 }
467 
opcode_dec(struct pt_ild * ild,uint8_t length)468 static int opcode_dec(struct pt_ild *ild, uint8_t length)
469 {
470 	uint8_t b, m;
471 
472 	if (!ild)
473 		return -pte_internal;
474 
475 	/*no need to check max_bytes - it was checked in previous scanners */
476 	b = get_byte(ild, length);
477 	if (b != 0x0F) {	/* 1B opcodes, map 0 */
478 		ild->map = PTI_MAP_0;
479 		ild->nominal_opcode = b;
480 
481 		return modrm_dec(ild, length + 1);
482 	}
483 
484 	length++;		/* eat the 0x0F */
485 
486 	if (ild->max_bytes <= length)
487 		return -pte_bad_insn;
488 
489 	/* 0x0F opcodes MAPS 1,2,3 */
490 	m = get_byte(ild, length);
491 	if (m == 0x38) {
492 		ild->map = PTI_MAP_2;
493 
494 		return get_next_as_opcode(ild, length + 1);
495 	} else if (m == 0x3A) {
496 		ild->map = PTI_MAP_3;
497 		ild->imm1_bytes = 1;
498 
499 		return get_next_as_opcode(ild, length + 1);
500 	} else if (bits_match(m, 0xf8, 0x38)) {
501 		ild->map = PTI_MAP_INVALID;
502 
503 		return get_next_as_opcode(ild, length + 1);
504 	} else if (m == 0x0F) {	/* 3dNow */
505 		ild->map = PTI_MAP_AMD3DNOW;
506 		ild->imm1_bytes = 1;
507 		/* real opcode is in immediate later on, but we need an
508 		 * opcode now. */
509 		ild->nominal_opcode = 0x0F;
510 
511 		return modrm_dec(ild, length + 1);
512 	} else {	/* map 1 (simple two byte opcodes) */
513 		ild->nominal_opcode = m;
514 		ild->map = PTI_MAP_1;
515 
516 		return modrm_dec(ild, length + 1);
517 	}
518 }
519 
520 typedef int (*prefix_decoder)(struct pt_ild *ild, uint8_t length, uint8_t rex);
521 
522 static int prefix_osz(struct pt_ild *ild, uint8_t length, uint8_t rex);
523 static int prefix_asz(struct pt_ild *ild, uint8_t length, uint8_t rex);
524 static int prefix_lock(struct pt_ild *ild, uint8_t length, uint8_t rex);
525 static int prefix_f2(struct pt_ild *ild, uint8_t length, uint8_t rex);
526 static int prefix_f3(struct pt_ild *ild, uint8_t length, uint8_t rex);
527 static int prefix_rex(struct pt_ild *ild, uint8_t length, uint8_t rex);
528 static int prefix_vex_c4(struct pt_ild *ild, uint8_t length, uint8_t rex);
529 static int prefix_vex_c5(struct pt_ild *ild, uint8_t length, uint8_t rex);
530 static int prefix_evex(struct pt_ild *ild, uint8_t length, uint8_t rex);
531 static int prefix_ignore(struct pt_ild *ild, uint8_t length, uint8_t rex);
532 static int prefix_done(struct pt_ild *ild, uint8_t length, uint8_t rex);
533 
534 static const prefix_decoder prefix_table[256] = {
535 	/* 00 = */ prefix_done,
536 	/* 01 = */ prefix_done,
537 	/* 02 = */ prefix_done,
538 	/* 03 = */ prefix_done,
539 	/* 04 = */ prefix_done,
540 	/* 05 = */ prefix_done,
541 	/* 06 = */ prefix_done,
542 	/* 07 = */ prefix_done,
543 	/* 08 = */ prefix_done,
544 	/* 09 = */ prefix_done,
545 	/* 0a = */ prefix_done,
546 	/* 0b = */ prefix_done,
547 	/* 0c = */ prefix_done,
548 	/* 0d = */ prefix_done,
549 	/* 0e = */ prefix_done,
550 	/* 0f = */ prefix_done,
551 
552 	/* 10 = */ prefix_done,
553 	/* 11 = */ prefix_done,
554 	/* 12 = */ prefix_done,
555 	/* 13 = */ prefix_done,
556 	/* 14 = */ prefix_done,
557 	/* 15 = */ prefix_done,
558 	/* 16 = */ prefix_done,
559 	/* 17 = */ prefix_done,
560 	/* 18 = */ prefix_done,
561 	/* 19 = */ prefix_done,
562 	/* 1a = */ prefix_done,
563 	/* 1b = */ prefix_done,
564 	/* 1c = */ prefix_done,
565 	/* 1d = */ prefix_done,
566 	/* 1e = */ prefix_done,
567 	/* 1f = */ prefix_done,
568 
569 	/* 20 = */ prefix_done,
570 	/* 21 = */ prefix_done,
571 	/* 22 = */ prefix_done,
572 	/* 23 = */ prefix_done,
573 	/* 24 = */ prefix_done,
574 	/* 25 = */ prefix_done,
575 	/* 26 = */ prefix_ignore,
576 	/* 27 = */ prefix_done,
577 	/* 28 = */ prefix_done,
578 	/* 29 = */ prefix_done,
579 	/* 2a = */ prefix_done,
580 	/* 2b = */ prefix_done,
581 	/* 2c = */ prefix_done,
582 	/* 2d = */ prefix_done,
583 	/* 2e = */ prefix_ignore,
584 	/* 2f = */ prefix_done,
585 
586 	/* 30 = */ prefix_done,
587 	/* 31 = */ prefix_done,
588 	/* 32 = */ prefix_done,
589 	/* 33 = */ prefix_done,
590 	/* 34 = */ prefix_done,
591 	/* 35 = */ prefix_done,
592 	/* 36 = */ prefix_ignore,
593 	/* 37 = */ prefix_done,
594 	/* 38 = */ prefix_done,
595 	/* 39 = */ prefix_done,
596 	/* 3a = */ prefix_done,
597 	/* 3b = */ prefix_done,
598 	/* 3c = */ prefix_done,
599 	/* 3d = */ prefix_done,
600 	/* 3e = */ prefix_ignore,
601 	/* 3f = */ prefix_done,
602 
603 	/* 40 = */ prefix_rex,
604 	/* 41 = */ prefix_rex,
605 	/* 42 = */ prefix_rex,
606 	/* 43 = */ prefix_rex,
607 	/* 44 = */ prefix_rex,
608 	/* 45 = */ prefix_rex,
609 	/* 46 = */ prefix_rex,
610 	/* 47 = */ prefix_rex,
611 	/* 48 = */ prefix_rex,
612 	/* 49 = */ prefix_rex,
613 	/* 4a = */ prefix_rex,
614 	/* 4b = */ prefix_rex,
615 	/* 4c = */ prefix_rex,
616 	/* 4d = */ prefix_rex,
617 	/* 4e = */ prefix_rex,
618 	/* 4f = */ prefix_rex,
619 
620 	/* 50 = */ prefix_done,
621 	/* 51 = */ prefix_done,
622 	/* 52 = */ prefix_done,
623 	/* 53 = */ prefix_done,
624 	/* 54 = */ prefix_done,
625 	/* 55 = */ prefix_done,
626 	/* 56 = */ prefix_done,
627 	/* 57 = */ prefix_done,
628 	/* 58 = */ prefix_done,
629 	/* 59 = */ prefix_done,
630 	/* 5a = */ prefix_done,
631 	/* 5b = */ prefix_done,
632 	/* 5c = */ prefix_done,
633 	/* 5d = */ prefix_done,
634 	/* 5e = */ prefix_done,
635 	/* 5f = */ prefix_done,
636 
637 	/* 60 = */ prefix_done,
638 	/* 61 = */ prefix_done,
639 	/* 62 = */ prefix_evex,
640 	/* 63 = */ prefix_done,
641 	/* 64 = */ prefix_ignore,
642 	/* 65 = */ prefix_ignore,
643 	/* 66 = */ prefix_osz,
644 	/* 67 = */ prefix_asz,
645 	/* 68 = */ prefix_done,
646 	/* 69 = */ prefix_done,
647 	/* 6a = */ prefix_done,
648 	/* 6b = */ prefix_done,
649 	/* 6c = */ prefix_done,
650 	/* 6d = */ prefix_done,
651 	/* 6e = */ prefix_done,
652 	/* 6f = */ prefix_done,
653 
654 	/* 70 = */ prefix_done,
655 	/* 71 = */ prefix_done,
656 	/* 72 = */ prefix_done,
657 	/* 73 = */ prefix_done,
658 	/* 74 = */ prefix_done,
659 	/* 75 = */ prefix_done,
660 	/* 76 = */ prefix_done,
661 	/* 77 = */ prefix_done,
662 	/* 78 = */ prefix_done,
663 	/* 79 = */ prefix_done,
664 	/* 7a = */ prefix_done,
665 	/* 7b = */ prefix_done,
666 	/* 7c = */ prefix_done,
667 	/* 7d = */ prefix_done,
668 	/* 7e = */ prefix_done,
669 	/* 7f = */ prefix_done,
670 
671 	/* 80 = */ prefix_done,
672 	/* 81 = */ prefix_done,
673 	/* 82 = */ prefix_done,
674 	/* 83 = */ prefix_done,
675 	/* 84 = */ prefix_done,
676 	/* 85 = */ prefix_done,
677 	/* 86 = */ prefix_done,
678 	/* 87 = */ prefix_done,
679 	/* 88 = */ prefix_done,
680 	/* 89 = */ prefix_done,
681 	/* 8a = */ prefix_done,
682 	/* 8b = */ prefix_done,
683 	/* 8c = */ prefix_done,
684 	/* 8d = */ prefix_done,
685 	/* 8e = */ prefix_done,
686 	/* 8f = */ prefix_done,
687 
688 	/* 90 = */ prefix_done,
689 	/* 91 = */ prefix_done,
690 	/* 92 = */ prefix_done,
691 	/* 93 = */ prefix_done,
692 	/* 94 = */ prefix_done,
693 	/* 95 = */ prefix_done,
694 	/* 96 = */ prefix_done,
695 	/* 97 = */ prefix_done,
696 	/* 98 = */ prefix_done,
697 	/* 99 = */ prefix_done,
698 	/* 9a = */ prefix_done,
699 	/* 9b = */ prefix_done,
700 	/* 9c = */ prefix_done,
701 	/* 9d = */ prefix_done,
702 	/* 9e = */ prefix_done,
703 	/* 9f = */ prefix_done,
704 
705 	/* a0 = */ prefix_done,
706 	/* a1 = */ prefix_done,
707 	/* a2 = */ prefix_done,
708 	/* a3 = */ prefix_done,
709 	/* a4 = */ prefix_done,
710 	/* a5 = */ prefix_done,
711 	/* a6 = */ prefix_done,
712 	/* a7 = */ prefix_done,
713 	/* a8 = */ prefix_done,
714 	/* a9 = */ prefix_done,
715 	/* aa = */ prefix_done,
716 	/* ab = */ prefix_done,
717 	/* ac = */ prefix_done,
718 	/* ad = */ prefix_done,
719 	/* ae = */ prefix_done,
720 	/* af = */ prefix_done,
721 
722 	/* b0 = */ prefix_done,
723 	/* b1 = */ prefix_done,
724 	/* b2 = */ prefix_done,
725 	/* b3 = */ prefix_done,
726 	/* b4 = */ prefix_done,
727 	/* b5 = */ prefix_done,
728 	/* b6 = */ prefix_done,
729 	/* b7 = */ prefix_done,
730 	/* b8 = */ prefix_done,
731 	/* b9 = */ prefix_done,
732 	/* ba = */ prefix_done,
733 	/* bb = */ prefix_done,
734 	/* bc = */ prefix_done,
735 	/* bd = */ prefix_done,
736 	/* be = */ prefix_done,
737 	/* bf = */ prefix_done,
738 
739 	/* c0 = */ prefix_done,
740 	/* c1 = */ prefix_done,
741 	/* c2 = */ prefix_done,
742 	/* c3 = */ prefix_done,
743 	/* c4 = */ prefix_vex_c4,
744 	/* c5 = */ prefix_vex_c5,
745 	/* c6 = */ prefix_done,
746 	/* c7 = */ prefix_done,
747 	/* c8 = */ prefix_done,
748 	/* c9 = */ prefix_done,
749 	/* ca = */ prefix_done,
750 	/* cb = */ prefix_done,
751 	/* cc = */ prefix_done,
752 	/* cd = */ prefix_done,
753 	/* ce = */ prefix_done,
754 	/* cf = */ prefix_done,
755 
756 	/* d0 = */ prefix_done,
757 	/* d1 = */ prefix_done,
758 	/* d2 = */ prefix_done,
759 	/* d3 = */ prefix_done,
760 	/* d4 = */ prefix_done,
761 	/* d5 = */ prefix_done,
762 	/* d6 = */ prefix_done,
763 	/* d7 = */ prefix_done,
764 	/* d8 = */ prefix_done,
765 	/* d9 = */ prefix_done,
766 	/* da = */ prefix_done,
767 	/* db = */ prefix_done,
768 	/* dc = */ prefix_done,
769 	/* dd = */ prefix_done,
770 	/* de = */ prefix_done,
771 	/* df = */ prefix_done,
772 
773 	/* e0 = */ prefix_done,
774 	/* e1 = */ prefix_done,
775 	/* e2 = */ prefix_done,
776 	/* e3 = */ prefix_done,
777 	/* e4 = */ prefix_done,
778 	/* e5 = */ prefix_done,
779 	/* e6 = */ prefix_done,
780 	/* e7 = */ prefix_done,
781 	/* e8 = */ prefix_done,
782 	/* e9 = */ prefix_done,
783 	/* ea = */ prefix_done,
784 	/* eb = */ prefix_done,
785 	/* ec = */ prefix_done,
786 	/* ed = */ prefix_done,
787 	/* ee = */ prefix_done,
788 	/* ef = */ prefix_done,
789 
790 	/* f0 = */ prefix_lock,
791 	/* f1 = */ prefix_done,
792 	/* f2 = */ prefix_f2,
793 	/* f3 = */ prefix_f3,
794 	/* f4 = */ prefix_done,
795 	/* f5 = */ prefix_done,
796 	/* f6 = */ prefix_done,
797 	/* f7 = */ prefix_done,
798 	/* f8 = */ prefix_done,
799 	/* f9 = */ prefix_done,
800 	/* fa = */ prefix_done,
801 	/* fb = */ prefix_done,
802 	/* fc = */ prefix_done,
803 	/* fd = */ prefix_done,
804 	/* fe = */ prefix_done,
805 	/* ff = */ prefix_done
806 };
807 
prefix_decode(struct pt_ild * ild,uint8_t length,uint8_t rex)808 static inline int prefix_decode(struct pt_ild *ild, uint8_t length, uint8_t rex)
809 {
810 	uint8_t byte;
811 
812 	if (!ild)
813 		return -pte_internal;
814 
815 	if (ild->max_bytes <= length)
816 		return -pte_bad_insn;
817 
818 	byte = get_byte(ild, length);
819 
820 	return prefix_table[byte](ild, length, rex);
821 }
822 
prefix_next(struct pt_ild * ild,uint8_t length,uint8_t rex)823 static inline int prefix_next(struct pt_ild *ild, uint8_t length, uint8_t rex)
824 {
825 	return prefix_decode(ild, length + 1, rex);
826 }
827 
prefix_osz(struct pt_ild * ild,uint8_t length,uint8_t rex)828 static int prefix_osz(struct pt_ild *ild, uint8_t length, uint8_t rex)
829 {
830 	(void) rex;
831 
832 	if (!ild)
833 		return -pte_internal;
834 
835 	ild->u.s.osz = 1;
836 
837 	return prefix_next(ild, length, 0);
838 }
839 
prefix_asz(struct pt_ild * ild,uint8_t length,uint8_t rex)840 static int prefix_asz(struct pt_ild *ild, uint8_t length, uint8_t rex)
841 {
842 	(void) rex;
843 
844 	if (!ild)
845 		return -pte_internal;
846 
847 	ild->u.s.asz = 1;
848 
849 	return prefix_next(ild, length, 0);
850 }
851 
prefix_lock(struct pt_ild * ild,uint8_t length,uint8_t rex)852 static int prefix_lock(struct pt_ild *ild, uint8_t length, uint8_t rex)
853 {
854 	(void) rex;
855 
856 	if (!ild)
857 		return -pte_internal;
858 
859 	ild->u.s.lock = 1;
860 
861 	return prefix_next(ild, length, 0);
862 }
863 
prefix_f2(struct pt_ild * ild,uint8_t length,uint8_t rex)864 static int prefix_f2(struct pt_ild *ild, uint8_t length, uint8_t rex)
865 {
866 	(void) rex;
867 
868 	if (!ild)
869 		return -pte_internal;
870 
871 	ild->u.s.f2 = 1;
872 	ild->u.s.last_f2f3 = 2;
873 
874 	return prefix_next(ild, length, 0);
875 }
876 
prefix_f3(struct pt_ild * ild,uint8_t length,uint8_t rex)877 static int prefix_f3(struct pt_ild *ild, uint8_t length, uint8_t rex)
878 {
879 	(void) rex;
880 
881 	if (!ild)
882 		return -pte_internal;
883 
884 	ild->u.s.f3 = 1;
885 	ild->u.s.last_f2f3 = 3;
886 
887 	return prefix_next(ild, length, 0);
888 }
889 
prefix_ignore(struct pt_ild * ild,uint8_t length,uint8_t rex)890 static int prefix_ignore(struct pt_ild *ild, uint8_t length, uint8_t rex)
891 {
892 	(void) rex;
893 
894 	return prefix_next(ild, length, 0);
895 }
896 
prefix_done(struct pt_ild * ild,uint8_t length,uint8_t rex)897 static int prefix_done(struct pt_ild *ild, uint8_t length, uint8_t rex)
898 {
899 	if (!ild)
900 		return -pte_internal;
901 
902 	if (rex & 0x04)
903 		ild->u.s.rex_r = 1;
904 	if (rex & 0x08)
905 		ild->u.s.rex_w = 1;
906 
907 	return opcode_dec(ild, length);
908 }
909 
prefix_rex(struct pt_ild * ild,uint8_t length,uint8_t rex)910 static int prefix_rex(struct pt_ild *ild, uint8_t length, uint8_t rex)
911 {
912 	(void) rex;
913 
914 	if (!ild)
915 		return -pte_internal;
916 
917 	if (mode_64b(ild))
918 		return prefix_next(ild, length, get_byte(ild, length));
919 	else
920 		return opcode_dec(ild, length);
921 }
922 
prefix_vex_done(struct pt_ild * ild,uint8_t length)923 static inline int prefix_vex_done(struct pt_ild *ild, uint8_t length)
924 {
925 	if (!ild)
926 		return -pte_internal;
927 
928 	ild->nominal_opcode = get_byte(ild, length);
929 
930 	return modrm_dec(ild, length + 1);
931 }
932 
prefix_vex_c5(struct pt_ild * ild,uint8_t length,uint8_t rex)933 static int prefix_vex_c5(struct pt_ild *ild, uint8_t length, uint8_t rex)
934 {
935 	uint8_t max_bytes;
936 	uint8_t p1;
937 
938 	(void) rex;
939 
940 	if (!ild)
941 		return -pte_internal;
942 
943 	max_bytes = ild->max_bytes;
944 
945 	/* Read the next byte to validate that this is indeed VEX. */
946 	if (max_bytes <= (length + 1))
947 		return -pte_bad_insn;
948 
949 	p1 = get_byte(ild, length + 1);
950 
951 	/* If p1[7:6] is not 11b in non-64-bit mode, this is LDS, not VEX. */
952 	if (!mode_64b(ild) && !bits_match(p1, 0xc0, 0xc0))
953 		return opcode_dec(ild, length);
954 
955 	/* We need at least 3 bytes
956 	 * - 2 for the VEX prefix and payload and
957 	 * - 1 for the opcode.
958 	 */
959 	if (max_bytes < (length + 3))
960 		return -pte_bad_insn;
961 
962 	ild->u.s.vex = 1;
963 	if (p1 & 0x80)
964 		ild->u.s.rex_r = 1;
965 
966 	ild->map = PTI_MAP_1;
967 
968 	/* Eat the VEX. */
969 	length += 2;
970 	return prefix_vex_done(ild, length);
971 }
972 
prefix_vex_c4(struct pt_ild * ild,uint8_t length,uint8_t rex)973 static int prefix_vex_c4(struct pt_ild *ild, uint8_t length, uint8_t rex)
974 {
975 	uint8_t max_bytes;
976 	uint8_t p1, p2, map;
977 
978 	(void) rex;
979 
980 	if (!ild)
981 		return -pte_internal;
982 
983 	max_bytes = ild->max_bytes;
984 
985 	/* Read the next byte to validate that this is indeed VEX. */
986 	if (max_bytes <= (length + 1))
987 		return -pte_bad_insn;
988 
989 	p1 = get_byte(ild, length + 1);
990 
991 	/* If p1[7:6] is not 11b in non-64-bit mode, this is LES, not VEX. */
992 	if (!mode_64b(ild) && !bits_match(p1, 0xc0, 0xc0))
993 		return opcode_dec(ild, length);
994 
995 	/* We need at least 4 bytes
996 	 * - 3 for the VEX prefix and payload and
997 	 * - 1 for the opcode.
998 	 */
999 	if (max_bytes < (length + 4))
1000 		return -pte_bad_insn;
1001 
1002 	p2 = get_byte(ild, length + 2);
1003 
1004 	ild->u.s.vex = 1;
1005 	if (p1 & 0x80)
1006 		ild->u.s.rex_r = 1;
1007 	if (p2 & 0x80)
1008 		ild->u.s.rex_w = 1;
1009 
1010 	map = p1 & 0x1f;
1011 	if (PTI_MAP_INVALID <= map)
1012 		return -pte_bad_insn;
1013 
1014 	ild->map = map;
1015 	if (map == PTI_MAP_3)
1016 		ild->imm1_bytes = 1;
1017 
1018 	/* Eat the VEX. */
1019 	length += 3;
1020 	return prefix_vex_done(ild, length);
1021 }
1022 
prefix_evex(struct pt_ild * ild,uint8_t length,uint8_t rex)1023 static int prefix_evex(struct pt_ild *ild, uint8_t length, uint8_t rex)
1024 {
1025 	uint8_t max_bytes;
1026 	uint8_t p1, p2, map;
1027 
1028 	(void) rex;
1029 
1030 	if (!ild)
1031 		return -pte_internal;
1032 
1033 	max_bytes = ild->max_bytes;
1034 
1035 	/* Read the next byte to validate that this is indeed EVEX. */
1036 	if (max_bytes <= (length + 1))
1037 		return -pte_bad_insn;
1038 
1039 	p1 = get_byte(ild, length + 1);
1040 
1041 	/* If p1[7:6] is not 11b in non-64-bit mode, this is BOUND, not EVEX. */
1042 	if (!mode_64b(ild) && !bits_match(p1, 0xc0, 0xc0))
1043 		return opcode_dec(ild, length);
1044 
1045 	/* We need at least 5 bytes
1046 	 * - 4 for the EVEX prefix and payload and
1047 	 * - 1 for the opcode.
1048 	 */
1049 	if (max_bytes < (length + 5))
1050 		return -pte_bad_insn;
1051 
1052 	p2 = get_byte(ild, length + 2);
1053 
1054 	ild->u.s.vex = 1;
1055 	if (p1 & 0x80)
1056 		ild->u.s.rex_r = 1;
1057 	if (p2 & 0x80)
1058 		ild->u.s.rex_w = 1;
1059 
1060 	map = p1 & 0x03;
1061 	ild->map = map;
1062 
1063 	if (map == PTI_MAP_3)
1064 		ild->imm1_bytes = 1;
1065 
1066 	/* Eat the EVEX. */
1067 	length += 4;
1068 	return prefix_vex_done(ild, length);
1069 }
1070 
decode(struct pt_ild * ild)1071 static int decode(struct pt_ild *ild)
1072 {
1073 	return prefix_decode(ild, 0, 0);
1074 }
1075 
set_branch_target(struct pt_insn_ext * iext,const struct pt_ild * ild)1076 static int set_branch_target(struct pt_insn_ext *iext, const struct pt_ild *ild)
1077 {
1078 	if (!iext || !ild)
1079 		return -pte_internal;
1080 
1081 	iext->variant.branch.is_direct = 1;
1082 
1083 	if (ild->disp_bytes == 1) {
1084 		const int8_t *b = (const int8_t *)
1085 			get_byte_ptr(ild, ild->disp_pos);
1086 
1087 		iext->variant.branch.displacement = *b;
1088 	} else if (ild->disp_bytes == 2) {
1089 		const int16_t *w = (const int16_t *)
1090 			get_byte_ptr(ild, ild->disp_pos);
1091 
1092 		iext->variant.branch.displacement = *w;
1093 	} else if (ild->disp_bytes == 4) {
1094 		const int32_t *d = (const int32_t *)
1095 			get_byte_ptr(ild, ild->disp_pos);
1096 
1097 		iext->variant.branch.displacement = *d;
1098 	} else
1099 		return -pte_bad_insn;
1100 
1101 	return 0;
1102 }
1103 
pt_instruction_length_decode(struct pt_ild * ild)1104 static int pt_instruction_length_decode(struct pt_ild *ild)
1105 {
1106 	if (!ild)
1107 		return -pte_internal;
1108 
1109 	ild->u.i = 0;
1110 	ild->imm1_bytes = 0;
1111 	ild->imm2_bytes = 0;
1112 	ild->disp_bytes = 0;
1113 	ild->modrm_byte = 0;
1114 	ild->map = PTI_MAP_INVALID;
1115 
1116 	if (!ild->mode)
1117 		return -pte_bad_insn;
1118 
1119 	return decode(ild);
1120 }
1121 
pt_instruction_decode(struct pt_insn * insn,struct pt_insn_ext * iext,const struct pt_ild * ild)1122 static int pt_instruction_decode(struct pt_insn *insn, struct pt_insn_ext *iext,
1123 				 const struct pt_ild *ild)
1124 {
1125 	uint8_t opcode, map;
1126 
1127 	if (!iext || !ild)
1128 		return -pte_internal;
1129 
1130 	iext->iclass = PTI_INST_INVALID;
1131 	memset(&iext->variant, 0, sizeof(iext->variant));
1132 
1133 	insn->iclass = ptic_other;
1134 
1135 	opcode = ild->nominal_opcode;
1136 	map = ild->map;
1137 
1138 	if (map > PTI_MAP_1)
1139 		return 0;	/* uninteresting */
1140 	if (ild->u.s.vex)
1141 		return 0;	/* uninteresting */
1142 
1143 	/* PTI_INST_JCC,   70...7F, 0F (0x80...0x8F) */
1144 	if (opcode >= 0x70 && opcode <= 0x7F) {
1145 		if (map == PTI_MAP_0) {
1146 			insn->iclass = ptic_cond_jump;
1147 			iext->iclass = PTI_INST_JCC;
1148 
1149 			return set_branch_target(iext, ild);
1150 		}
1151 		return 0;
1152 	}
1153 	if (opcode >= 0x80 && opcode <= 0x8F) {
1154 		if (map == PTI_MAP_1) {
1155 			insn->iclass = ptic_cond_jump;
1156 			iext->iclass = PTI_INST_JCC;
1157 
1158 			return set_branch_target(iext, ild);
1159 		}
1160 		return 0;
1161 	}
1162 
1163 	switch (ild->nominal_opcode) {
1164 	case 0x9A:
1165 		if (map == PTI_MAP_0) {
1166 			insn->iclass = ptic_far_call;
1167 			iext->iclass = PTI_INST_CALL_9A;
1168 		}
1169 		return 0;
1170 
1171 	case 0xFF:
1172 		if (map == PTI_MAP_0) {
1173 			uint8_t reg = pti_get_modrm_reg(ild);
1174 
1175 			if (reg == 2) {
1176 				insn->iclass = ptic_call;
1177 				iext->iclass = PTI_INST_CALL_FFr2;
1178 			} else if (reg == 3) {
1179 				insn->iclass = ptic_far_call;
1180 				iext->iclass = PTI_INST_CALL_FFr3;
1181 			} else if (reg == 4) {
1182 				insn->iclass = ptic_jump;
1183 				iext->iclass = PTI_INST_JMP_FFr4;
1184 			} else if (reg == 5) {
1185 				insn->iclass = ptic_far_jump;
1186 				iext->iclass = PTI_INST_JMP_FFr5;
1187 			}
1188 		}
1189 		return 0;
1190 
1191 	case 0xE8:
1192 		if (map == PTI_MAP_0) {
1193 			insn->iclass = ptic_call;
1194 			iext->iclass = PTI_INST_CALL_E8;
1195 
1196 			return set_branch_target(iext, ild);
1197 		}
1198 		return 0;
1199 
1200 	case 0xCD:
1201 		if (map == PTI_MAP_0) {
1202 			insn->iclass = ptic_far_call;
1203 			iext->iclass = PTI_INST_INT;
1204 		}
1205 
1206 		return 0;
1207 
1208 	case 0xCC:
1209 		if (map == PTI_MAP_0) {
1210 			insn->iclass = ptic_far_call;
1211 			iext->iclass = PTI_INST_INT3;
1212 		}
1213 
1214 		return 0;
1215 
1216 	case 0xCE:
1217 		if (map == PTI_MAP_0) {
1218 			insn->iclass = ptic_far_call;
1219 			iext->iclass = PTI_INST_INTO;
1220 		}
1221 
1222 		return 0;
1223 
1224 	case 0xF1:
1225 		if (map == PTI_MAP_0) {
1226 			insn->iclass = ptic_far_call;
1227 			iext->iclass = PTI_INST_INT1;
1228 		}
1229 
1230 		return 0;
1231 
1232 	case 0xCF:
1233 		if (map == PTI_MAP_0) {
1234 			insn->iclass = ptic_far_return;
1235 			iext->iclass = PTI_INST_IRET;
1236 		}
1237 		return 0;
1238 
1239 	case 0xE9:
1240 		if (map == PTI_MAP_0) {
1241 			insn->iclass = ptic_jump;
1242 			iext->iclass = PTI_INST_JMP_E9;
1243 
1244 			return set_branch_target(iext, ild);
1245 		}
1246 		return 0;
1247 
1248 	case 0xEA:
1249 		if (map == PTI_MAP_0) {
1250 			/* Far jumps are treated as indirect jumps. */
1251 			insn->iclass = ptic_far_jump;
1252 			iext->iclass = PTI_INST_JMP_EA;
1253 		}
1254 		return 0;
1255 
1256 	case 0xEB:
1257 		if (map == PTI_MAP_0) {
1258 			insn->iclass = ptic_jump;
1259 			iext->iclass = PTI_INST_JMP_EB;
1260 
1261 			return set_branch_target(iext, ild);
1262 		}
1263 		return 0;
1264 
1265 	case 0xE3:
1266 		if (map == PTI_MAP_0) {
1267 			insn->iclass = ptic_cond_jump;
1268 			iext->iclass = PTI_INST_JrCXZ;
1269 
1270 			return set_branch_target(iext, ild);
1271 		}
1272 		return 0;
1273 
1274 	case 0xE0:
1275 		if (map == PTI_MAP_0) {
1276 			insn->iclass = ptic_cond_jump;
1277 			iext->iclass = PTI_INST_LOOPNE;
1278 
1279 			return set_branch_target(iext, ild);
1280 		}
1281 		return 0;
1282 
1283 	case 0xE1:
1284 		if (map == PTI_MAP_0) {
1285 			insn->iclass = ptic_cond_jump;
1286 			iext->iclass = PTI_INST_LOOPE;
1287 
1288 			return set_branch_target(iext, ild);
1289 		}
1290 		return 0;
1291 
1292 	case 0xE2:
1293 		if (map == PTI_MAP_0) {
1294 			insn->iclass = ptic_cond_jump;
1295 			iext->iclass = PTI_INST_LOOP;
1296 
1297 			return set_branch_target(iext, ild);
1298 		}
1299 		return 0;
1300 
1301 	case 0x22:
1302 		if (map == PTI_MAP_1)
1303 			if (pti_get_modrm_reg(ild) == 3)
1304 				if (!ild->u.s.rex_r)
1305 					iext->iclass = PTI_INST_MOV_CR3;
1306 
1307 		return 0;
1308 
1309 	case 0xC3:
1310 		if (map == PTI_MAP_0) {
1311 			insn->iclass = ptic_return;
1312 			iext->iclass = PTI_INST_RET_C3;
1313 		}
1314 		return 0;
1315 
1316 	case 0xC2:
1317 		if (map == PTI_MAP_0) {
1318 			insn->iclass = ptic_return;
1319 			iext->iclass = PTI_INST_RET_C2;
1320 		}
1321 		return 0;
1322 
1323 	case 0xCB:
1324 		if (map == PTI_MAP_0) {
1325 			insn->iclass = ptic_far_return;
1326 			iext->iclass = PTI_INST_RET_CB;
1327 		}
1328 		return 0;
1329 
1330 	case 0xCA:
1331 		if (map == PTI_MAP_0) {
1332 			insn->iclass = ptic_far_return;
1333 			iext->iclass = PTI_INST_RET_CA;
1334 		}
1335 		return 0;
1336 
1337 	case 0x05:
1338 		if (map == PTI_MAP_1) {
1339 			insn->iclass = ptic_far_call;
1340 			iext->iclass = PTI_INST_SYSCALL;
1341 		}
1342 		return 0;
1343 
1344 	case 0x34:
1345 		if (map == PTI_MAP_1) {
1346 			insn->iclass = ptic_far_call;
1347 			iext->iclass = PTI_INST_SYSENTER;
1348 		}
1349 		return 0;
1350 
1351 	case 0x35:
1352 		if (map == PTI_MAP_1) {
1353 			insn->iclass = ptic_far_return;
1354 			iext->iclass = PTI_INST_SYSEXIT;
1355 		}
1356 		return 0;
1357 
1358 	case 0x07:
1359 		if (map == PTI_MAP_1) {
1360 			insn->iclass = ptic_far_return;
1361 			iext->iclass = PTI_INST_SYSRET;
1362 		}
1363 		return 0;
1364 
1365 	case 0x01:
1366 		if (map == PTI_MAP_1) {
1367 			switch (ild->modrm_byte) {
1368 			case 0xc1:
1369 				insn->iclass = ptic_far_call;
1370 				iext->iclass = PTI_INST_VMCALL;
1371 				break;
1372 
1373 			case 0xc2:
1374 				insn->iclass = ptic_far_return;
1375 				iext->iclass = PTI_INST_VMLAUNCH;
1376 				break;
1377 
1378 			case 0xc3:
1379 				insn->iclass = ptic_far_return;
1380 				iext->iclass = PTI_INST_VMRESUME;
1381 				break;
1382 
1383 			default:
1384 				break;
1385 			}
1386 		}
1387 		return 0;
1388 
1389 	case 0xc7:
1390 		if (map == PTI_MAP_1 &&
1391 		    pti_get_modrm_mod(ild) != 3 &&
1392 		    pti_get_modrm_reg(ild) == 6)
1393 			iext->iclass = PTI_INST_VMPTRLD;
1394 
1395 		return 0;
1396 
1397 	case 0xae:
1398 		if (map == PTI_MAP_1 && ild->u.s.f3 && !ild->u.s.osz &&
1399 		    pti_get_modrm_reg(ild) == 4) {
1400 			insn->iclass = ptic_ptwrite;
1401 			iext->iclass = PTI_INST_PTWRITE;
1402 		}
1403 		return 0;
1404 
1405 	default:
1406 		return 0;
1407 	}
1408 }
1409 
pt_ild_decode(struct pt_insn * insn,struct pt_insn_ext * iext)1410 int pt_ild_decode(struct pt_insn *insn, struct pt_insn_ext *iext)
1411 {
1412 	struct pt_ild ild;
1413 	int size;
1414 
1415 	if (!insn || !iext)
1416 		return -pte_internal;
1417 
1418 	ild.mode = insn->mode;
1419 	ild.itext = insn->raw;
1420 	ild.max_bytes = insn->size;
1421 
1422 	size = pt_instruction_length_decode(&ild);
1423 	if (size < 0)
1424 		return size;
1425 
1426 	insn->size = (uint8_t) size;
1427 
1428 	return pt_instruction_decode(insn, iext, &ild);
1429 }
1430