2 * Copyright (c) 2013-2018, Intel Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
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.
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.
36 /* Check that an instruction is decoded correctly. */
37 static struct ptunit_result ptunit_ild_decode(uint8_t *raw, uint8_t size,
38 enum pt_exec_mode mode)
40 struct pt_insn_ext iext;
44 memset(&iext, 0, sizeof(iext));
45 memset(&insn, 0, sizeof(insn));
47 memcpy(insn.raw, raw, size);
51 errcode = pt_ild_decode(&insn, &iext);
52 ptu_int_eq(errcode, 0);
54 ptu_uint_eq(insn.size, size);
55 ptu_int_eq(insn.iclass, ptic_other);
56 ptu_int_eq(iext.iclass, PTI_INST_INVALID);
61 /* Check that an instruction is decoded and classified correctly. */
62 static struct ptunit_result ptunit_ild_classify(uint8_t *raw, uint8_t size,
63 enum pt_exec_mode mode,
64 pti_inst_enum_t iclass)
66 struct pt_insn_ext iext;
70 memset(&iext, 0, sizeof(iext));
71 memset(&insn, 0, sizeof(insn));
73 memcpy(insn.raw, raw, size);
77 errcode = pt_ild_decode(&insn, &iext);
78 ptu_int_eq(errcode, 0);
80 ptu_uint_eq(insn.size, size);
81 ptu_int_eq(iext.iclass, iclass);
86 /* Check that an invalid instruction is detected correctly.
88 * Note that we intentionally do not detect all invalid instructions. This test
89 * therefore only covers some that we care about.
91 static struct ptunit_result ptunit_ild_invalid(uint8_t *raw, uint8_t size,
92 enum pt_exec_mode mode)
94 struct pt_insn_ext iext;
98 memset(&iext, 0, sizeof(iext));
99 memset(&insn, 0, sizeof(insn));
101 memcpy(insn.raw, raw, size);
105 errcode = pt_ild_decode(&insn, &iext);
106 ptu_int_eq(errcode, -pte_bad_insn);
112 /* Macros to automatically update the test location. */
113 #define ptu_decode(insn, size, mode) \
114 ptu_check(ptunit_ild_decode, insn, size, mode)
116 #define ptu_classify(insn, size, mode, iclass) \
117 ptu_check(ptunit_ild_classify, insn, size, mode, iclass)
119 /* Macros to also automatically supply the instruction size. */
120 #define ptu_decode_s(insn, mode) \
121 ptu_decode(insn, sizeof(insn), mode)
123 #define ptu_classify_s(insn, mode, iclass) \
124 ptu_classify(insn, sizeof(insn), mode, iclass)
126 #define ptu_invalid_s(insn, mode) \
127 ptu_check(ptunit_ild_invalid, insn, sizeof(insn), mode)
130 static struct ptunit_result push(void)
132 uint8_t insn[] = { 0x68, 0x11, 0x22, 0x33, 0x44 };
134 ptu_decode_s(insn, ptem_64bit);
139 static struct ptunit_result jmp_rel(void)
141 uint8_t insn[] = { 0xE9, 0x60, 0xF9, 0xFF, 0xFF };
143 ptu_classify_s(insn, ptem_64bit, PTI_INST_JMP_E9);
148 static struct ptunit_result long_nop(void)
150 uint8_t insn[] = { 0x66, 0x66, 0x66, 0x66,
151 0x66, 0x66, 0X2E, 0X0F,
152 0X1F, 0x84, 0x00, 0x00,
155 ptu_decode_s(insn, ptem_64bit);
160 static struct ptunit_result mov_al_64(void)
162 uint8_t insn[] = { 0x48, 0xa0, 0x3f, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
165 ptu_decode_s(insn, ptem_64bit);
170 static struct ptunit_result mov_al_32_em64(void)
172 uint8_t insn[] = { 0x67, 0xa0, 0x3f, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
175 ptu_decode(insn, 6, ptem_64bit);
180 static struct ptunit_result mov_al_32(void)
182 uint8_t insn[] = { 0xa0, 0x3f, 0xaa, 0xbb, 0xcc, 0xdd, 0xee };
184 ptu_decode(insn, 5, ptem_32bit);
189 static struct ptunit_result mov_al_32_em16(void)
191 uint8_t insn[] = { 0x67, 0xa0, 0x3f, 0xaa, 0xbb, 0xcc, 0xdd, 0xee };
193 ptu_decode(insn, 6, ptem_16bit);
198 static struct ptunit_result mov_al_16_em32(void)
200 uint8_t insn[] = { 0x67, 0xa0, 0x3f, 0xaa, 0xbb, 0xcc, 0xdd, 0xee };
202 ptu_decode(insn, 4, ptem_32bit);
207 static struct ptunit_result mov_al_16(void)
209 uint8_t insn[] = { 0xa0, 0x3f, 0xaa, 0xbb, 0xcc, 0xdd, 0xee };
211 ptu_decode(insn, 3, ptem_16bit);
216 static struct ptunit_result rdtsc(void)
218 uint8_t insn[] = { 0x0f, 0x31 };
220 ptu_decode_s(insn, ptem_64bit);
225 static struct ptunit_result pcmpistri(void)
227 uint8_t insn[] = { 0x66, 0x0f, 0x3a, 0x63, 0x04, 0x16, 0x1a };
229 ptu_decode_s(insn, ptem_64bit);
234 static struct ptunit_result vmovdqa(void)
236 uint8_t insn[] = { 0xc5, 0xf9, 0x6f, 0x25, 0xa9, 0x55, 0x04, 0x00 };
238 ptu_decode_s(insn, ptem_64bit);
243 static struct ptunit_result vpandn(void)
245 uint8_t insn[] = { 0xc4, 0x41, 0x29, 0xdf, 0xd1 };
247 ptu_decode_s(insn, ptem_64bit);
252 static struct ptunit_result syscall(void)
254 uint8_t insn[] = { 0x0f, 0x05 };
256 ptu_classify_s(insn, ptem_64bit, PTI_INST_SYSCALL);
261 static struct ptunit_result sysret(void)
263 uint8_t insn[] = { 0x0f, 0x07 };
265 ptu_classify_s(insn, ptem_64bit, PTI_INST_SYSRET);
270 static struct ptunit_result sysenter(void)
272 uint8_t insn[] = { 0x0f, 0x34 };
274 ptu_classify_s(insn, ptem_64bit, PTI_INST_SYSENTER);
279 static struct ptunit_result sysexit(void)
281 uint8_t insn[] = { 0x0f, 0x35 };
283 ptu_classify_s(insn, ptem_64bit, PTI_INST_SYSEXIT);
288 static struct ptunit_result int3(void)
290 uint8_t insn[] = { 0xcc };
292 ptu_classify_s(insn, ptem_64bit, PTI_INST_INT3);
297 static struct ptunit_result intn(void)
299 uint8_t insn[] = { 0xcd, 0x06 };
301 ptu_classify_s(insn, ptem_64bit, PTI_INST_INT);
306 static struct ptunit_result iret(void)
308 uint8_t insn[] = { 0xcf };
310 ptu_classify_s(insn, ptem_64bit, PTI_INST_IRET);
315 static struct ptunit_result call_9a_cd(void)
317 uint8_t insn[] = { 0x9a, 0x00, 0x00, 0x00, 0x00 };
319 ptu_classify_s(insn, ptem_16bit, PTI_INST_CALL_9A);
324 static struct ptunit_result call_9a_cp(void)
326 uint8_t insn[] = { 0x9a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
328 ptu_classify_s(insn, ptem_32bit, PTI_INST_CALL_9A);
333 static struct ptunit_result call_ff_3(void)
335 uint8_t insn[] = { 0xff, 0x1c, 0x25, 0x00, 0x00, 0x00, 0x00 };
337 ptu_classify_s(insn, ptem_64bit, PTI_INST_CALL_FFr3);
342 static struct ptunit_result jmp_ff_5(void)
344 uint8_t insn[] = { 0xff, 0x2c, 0x25, 0x00, 0x00, 0x00, 0x00 };
346 ptu_classify_s(insn, ptem_64bit, PTI_INST_JMP_FFr5);
351 static struct ptunit_result jmp_ea_cd(void)
353 uint8_t insn[] = { 0xea, 0x00, 0x00, 0x00, 0x00 };
355 ptu_classify_s(insn, ptem_16bit, PTI_INST_JMP_EA);
360 static struct ptunit_result jmp_ea_cp(void)
362 uint8_t insn[] = { 0xea, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
364 ptu_classify_s(insn, ptem_32bit, PTI_INST_JMP_EA);
369 static struct ptunit_result ret_ca(void)
371 uint8_t insn[] = { 0xca, 0x00, 0x00 };
373 ptu_classify_s(insn, ptem_64bit, PTI_INST_RET_CA);
378 static struct ptunit_result vmlaunch(void)
380 uint8_t insn[] = { 0x0f, 0x01, 0xc2 };
382 ptu_classify_s(insn, ptem_64bit, PTI_INST_VMLAUNCH);
387 static struct ptunit_result vmresume(void)
389 uint8_t insn[] = { 0x0f, 0x01, 0xc3 };
391 ptu_classify_s(insn, ptem_64bit, PTI_INST_VMRESUME);
396 static struct ptunit_result vmcall(void)
398 uint8_t insn[] = { 0x0f, 0x01, 0xc1 };
400 ptu_classify_s(insn, ptem_64bit, PTI_INST_VMCALL);
405 static struct ptunit_result vmptrld(void)
407 uint8_t insn[] = { 0x0f, 0xc7, 0x30 };
409 ptu_classify_s(insn, ptem_64bit, PTI_INST_VMPTRLD);
414 static struct ptunit_result jrcxz(void)
416 uint8_t insn[] = { 0xe3, 0x00 };
418 ptu_classify_s(insn, ptem_64bit, PTI_INST_JrCXZ);
423 static struct ptunit_result mov_eax_moffs64(void)
425 uint8_t insn[] = { 0xa1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
428 ptu_decode_s(insn, ptem_64bit);
433 static struct ptunit_result mov_eax_moffs64_32(void)
435 uint8_t insn[] = { 0x67, 0xa1, 0x00, 0x00, 0x00, 0x00 };
437 ptu_decode_s(insn, ptem_64bit);
442 static struct ptunit_result mov_rax_moffs64(void)
444 uint8_t insn[] = { 0x48, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
447 ptu_decode_s(insn, ptem_64bit);
452 static struct ptunit_result mov_rax_moffs64_32(void)
454 uint8_t insn[] = { 0x67, 0x48, 0xa1, 0x00, 0x00, 0x00, 0x00 };
456 ptu_decode_s(insn, ptem_64bit);
461 static struct ptunit_result mov_ax_moffs64(void)
463 uint8_t insn[] = { 0x66, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
466 ptu_decode_s(insn, ptem_64bit);
471 static struct ptunit_result mov_ax_moffs64_32(void)
473 uint8_t insn[] = { 0x67, 0x66, 0xa1, 0x00, 0x00, 0x00, 0x00 };
475 ptu_decode_s(insn, ptem_64bit);
480 static struct ptunit_result mov_eax_moffs32(void)
482 uint8_t insn[] = { 0xa1, 0x00, 0x00, 0x00, 0x00 };
484 ptu_decode_s(insn, ptem_32bit);
489 static struct ptunit_result mov_ax_moffs32(void)
491 uint8_t insn[] = { 0x66, 0xa1, 0x00, 0x00, 0x00, 0x00 };
493 ptu_decode_s(insn, ptem_32bit);
498 static struct ptunit_result mov_ax_moffs16(void)
500 uint8_t insn[] = { 0xa1, 0x00, 0x00 };
502 ptu_decode_s(insn, ptem_16bit);
507 static struct ptunit_result les(void)
509 uint8_t insn[] = { 0xc4, 0x00 };
511 ptu_decode_s(insn, ptem_16bit);
512 ptu_decode_s(insn, ptem_32bit);
517 static struct ptunit_result les_disp16(void)
519 uint8_t insn[] = { 0xc4, 0x06, 0x00, 0x00 };
521 ptu_decode_s(insn, ptem_16bit);
526 static struct ptunit_result les_disp32(void)
528 uint8_t insn[] = { 0xc4, 0x05, 0x00, 0x00, 0x00, 0x00 };
530 ptu_decode_s(insn, ptem_32bit);
535 static struct ptunit_result les_ind_disp8(void)
537 uint8_t insn[] = { 0xc4, 0x40, 0x00 };
539 ptu_decode_s(insn, ptem_16bit);
540 ptu_decode_s(insn, ptem_32bit);
545 static struct ptunit_result les_ind_disp16(void)
547 uint8_t insn[] = { 0xc4, 0x80, 0x00, 0x00 };
549 ptu_decode_s(insn, ptem_16bit);
554 static struct ptunit_result les_ind_disp32(void)
556 uint8_t insn[] = { 0xc4, 0x80, 0x00, 0x00, 0x00, 0x00 };
558 ptu_decode_s(insn, ptem_32bit);
563 static struct ptunit_result lds(void)
565 uint8_t insn[] = { 0xc5, 0x00 };
567 ptu_decode_s(insn, ptem_16bit);
568 ptu_decode_s(insn, ptem_32bit);
573 static struct ptunit_result lds_disp16(void)
575 uint8_t insn[] = { 0xc5, 0x06, 0x00, 0x00 };
577 ptu_decode_s(insn, ptem_16bit);
582 static struct ptunit_result lds_disp32(void)
584 uint8_t insn[] = { 0xc5, 0x05, 0x00, 0x00, 0x00, 0x00 };
586 ptu_decode_s(insn, ptem_32bit);
591 static struct ptunit_result lds_ind_disp8(void)
593 uint8_t insn[] = { 0xc5, 0x40, 0x00 };
595 ptu_decode_s(insn, ptem_16bit);
596 ptu_decode_s(insn, ptem_32bit);
601 static struct ptunit_result lds_ind_disp16(void)
603 uint8_t insn[] = { 0xc5, 0x80, 0x00, 0x00 };
605 ptu_decode_s(insn, ptem_16bit);
610 static struct ptunit_result lds_ind_disp32(void)
612 uint8_t insn[] = { 0xc5, 0x80, 0x00, 0x00, 0x00, 0x00 };
614 ptu_decode_s(insn, ptem_32bit);
619 static struct ptunit_result vpshufb(void)
621 uint8_t insn[] = { 0x62, 0x02, 0x05, 0x00, 0x00, 0x00 };
623 ptu_decode_s(insn, ptem_64bit);
628 static struct ptunit_result bound(void)
630 uint8_t insn[] = { 0x62, 0x02 };
632 ptu_decode_s(insn, ptem_32bit);
633 ptu_decode_s(insn, ptem_16bit);
638 static struct ptunit_result evex_cutoff(void)
640 uint8_t insn[] = { 0x62 };
642 ptu_invalid_s(insn, ptem_64bit);
643 ptu_invalid_s(insn, ptem_32bit);
644 ptu_invalid_s(insn, ptem_16bit);
649 static struct ptunit_result ptwrite_r32(void)
651 uint8_t insn[] = { 0xf3, 0x0f, 0xae, 0xe7 };
653 ptu_classify_s(insn, ptem_64bit, PTI_INST_PTWRITE);
654 ptu_classify_s(insn, ptem_32bit, PTI_INST_PTWRITE);
655 ptu_classify_s(insn, ptem_16bit, PTI_INST_PTWRITE);
660 static struct ptunit_result ptwrite_m32(void)
662 uint8_t insn[] = { 0xf3, 0x0f, 0xae, 0x67, 0xcc };
664 ptu_classify_s(insn, ptem_64bit, PTI_INST_PTWRITE);
665 ptu_classify_s(insn, ptem_32bit, PTI_INST_PTWRITE);
666 ptu_classify_s(insn, ptem_16bit, PTI_INST_PTWRITE);
671 static struct ptunit_result ptwrite_r64(void)
673 uint8_t insn[] = { 0xf3, 0x48, 0x0f, 0xae, 0xe7 };
675 ptu_classify_s(insn, ptem_64bit, PTI_INST_PTWRITE);
680 static struct ptunit_result ptwrite_m64(void)
682 uint8_t insn[] = { 0xf3, 0x48, 0x0f, 0xae, 0x67, 0xcc };
684 ptu_classify_s(insn, ptem_64bit, PTI_INST_PTWRITE);
689 int main(int argc, char **argv)
691 struct ptunit_suite suite;
695 suite = ptunit_mk_suite(argc, argv);
697 ptu_run(suite, push);
698 ptu_run(suite, jmp_rel);
699 ptu_run(suite, long_nop);
700 ptu_run(suite, mov_al_64);
701 ptu_run(suite, mov_al_32);
702 ptu_run(suite, mov_al_32_em64);
703 ptu_run(suite, mov_al_32_em16);
704 ptu_run(suite, mov_al_16_em32);
705 ptu_run(suite, mov_al_16);
706 ptu_run(suite, rdtsc);
707 ptu_run(suite, pcmpistri);
708 ptu_run(suite, vmovdqa);
709 ptu_run(suite, vpandn);
710 ptu_run(suite, syscall);
711 ptu_run(suite, sysret);
712 ptu_run(suite, sysenter);
713 ptu_run(suite, sysexit);
714 ptu_run(suite, int3);
715 ptu_run(suite, intn);
716 ptu_run(suite, iret);
717 ptu_run(suite, call_9a_cd);
718 ptu_run(suite, call_9a_cp);
719 ptu_run(suite, call_ff_3);
720 ptu_run(suite, jmp_ff_5);
721 ptu_run(suite, jmp_ea_cd);
722 ptu_run(suite, jmp_ea_cp);
723 ptu_run(suite, ret_ca);
724 ptu_run(suite, vmlaunch);
725 ptu_run(suite, vmresume);
726 ptu_run(suite, vmcall);
727 ptu_run(suite, vmptrld);
728 ptu_run(suite, jrcxz);
729 ptu_run(suite, mov_eax_moffs64);
730 ptu_run(suite, mov_eax_moffs64_32);
731 ptu_run(suite, mov_rax_moffs64);
732 ptu_run(suite, mov_rax_moffs64_32);
733 ptu_run(suite, mov_ax_moffs64);
734 ptu_run(suite, mov_ax_moffs64_32);
735 ptu_run(suite, mov_eax_moffs32);
736 ptu_run(suite, mov_ax_moffs32);
737 ptu_run(suite, mov_ax_moffs16);
739 ptu_run(suite, les_disp16);
740 ptu_run(suite, les_disp32);
741 ptu_run(suite, les_ind_disp8);
742 ptu_run(suite, les_ind_disp16);
743 ptu_run(suite, les_ind_disp32);
745 ptu_run(suite, lds_disp16);
746 ptu_run(suite, lds_disp32);
747 ptu_run(suite, lds_ind_disp8);
748 ptu_run(suite, lds_ind_disp16);
749 ptu_run(suite, lds_ind_disp32);
750 ptu_run(suite, vpshufb);
751 ptu_run(suite, bound);
752 ptu_run(suite, evex_cutoff);
753 ptu_run(suite, ptwrite_r32);
754 ptu_run(suite, ptwrite_m32);
755 ptu_run(suite, ptwrite_r64);
756 ptu_run(suite, ptwrite_m64);
758 return ptunit_report(&suite);