Linux Perf
insn-x86.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/types.h>
3 
4 #include "debug.h"
5 #include "tests/tests.h"
6 #include "arch-tests.h"
7 
10 
11 struct test_data {
15  const char *expected_op_str;
16  const char *expected_branch_str;
17  const char *asm_rep;
18 };
19 
20 struct test_data test_data_32[] = {
21 #include "insn-x86-dat-32.c"
22  {{0x0f, 0x01, 0xee}, 3, 0, NULL, NULL, "0f 01 ee \trdpkru"},
23  {{0x0f, 0x01, 0xef}, 3, 0, NULL, NULL, "0f 01 ef \twrpkru"},
24  {{0}, 0, 0, NULL, NULL, NULL},
25 };
26 
27 struct test_data test_data_64[] = {
28 #include "insn-x86-dat-64.c"
29  {{0x0f, 0x01, 0xee}, 3, 0, NULL, NULL, "0f 01 ee \trdpkru"},
30  {{0x0f, 0x01, 0xef}, 3, 0, NULL, NULL, "0f 01 ef \twrpkru"},
31  {{0}, 0, 0, NULL, NULL, NULL},
32 };
33 
34 static int get_op(const char *op_str)
35 {
36  struct val_data {
37  const char *name;
38  int val;
39  } vals[] = {
40  {"other", INTEL_PT_OP_OTHER},
41  {"call", INTEL_PT_OP_CALL},
42  {"ret", INTEL_PT_OP_RET},
43  {"jcc", INTEL_PT_OP_JCC},
44  {"jmp", INTEL_PT_OP_JMP},
45  {"loop", INTEL_PT_OP_LOOP},
46  {"iret", INTEL_PT_OP_IRET},
47  {"int", INTEL_PT_OP_INT},
48  {"syscall", INTEL_PT_OP_SYSCALL},
49  {"sysret", INTEL_PT_OP_SYSRET},
50  {NULL, 0},
51  };
52  struct val_data *val;
53 
54  if (!op_str || !strlen(op_str))
55  return 0;
56 
57  for (val = vals; val->name; val++) {
58  if (!strcmp(val->name, op_str))
59  return val->val;
60  }
61 
62  pr_debug("Failed to get op\n");
63 
64  return -1;
65 }
66 
67 static int get_branch(const char *branch_str)
68 {
69  struct val_data {
70  const char *name;
71  int val;
72  } vals[] = {
73  {"no_branch", INTEL_PT_BR_NO_BRANCH},
74  {"indirect", INTEL_PT_BR_INDIRECT},
75  {"conditional", INTEL_PT_BR_CONDITIONAL},
76  {"unconditional", INTEL_PT_BR_UNCONDITIONAL},
77  {NULL, 0},
78  };
79  struct val_data *val;
80 
81  if (!branch_str || !strlen(branch_str))
82  return 0;
83 
84  for (val = vals; val->name; val++) {
85  if (!strcmp(val->name, branch_str))
86  return val->val;
87  }
88 
89  pr_debug("Failed to get branch\n");
90 
91  return -1;
92 }
93 
94 static int test_data_item(struct test_data *dat, int x86_64)
95 {
96  struct intel_pt_insn intel_pt_insn;
97  struct insn insn;
98  int op, branch;
99 
100  insn_init(&insn, dat->data, MAX_INSN_SIZE, x86_64);
101  insn_get_length(&insn);
102 
103  if (!insn_complete(&insn)) {
104  pr_debug("Failed to decode: %s\n", dat->asm_rep);
105  return -1;
106  }
107 
108  if (insn.length != dat->expected_length) {
109  pr_debug("Failed to decode length (%d vs expected %d): %s\n",
110  insn.length, dat->expected_length, dat->asm_rep);
111  return -1;
112  }
113 
114  op = get_op(dat->expected_op_str);
115  branch = get_branch(dat->expected_branch_str);
116 
117  if (intel_pt_get_insn(dat->data, MAX_INSN_SIZE, x86_64, &intel_pt_insn)) {
118  pr_debug("Intel PT failed to decode: %s\n", dat->asm_rep);
119  return -1;
120  }
121 
122  if ((int)intel_pt_insn.op != op) {
123  pr_debug("Failed to decode 'op' value (%d vs expected %d): %s\n",
124  intel_pt_insn.op, op, dat->asm_rep);
125  return -1;
126  }
127 
128  if ((int)intel_pt_insn.branch != branch) {
129  pr_debug("Failed to decode 'branch' value (%d vs expected %d): %s\n",
130  intel_pt_insn.branch, branch, dat->asm_rep);
131  return -1;
132  }
133 
134  if (intel_pt_insn.rel != dat->expected_rel) {
135  pr_debug("Failed to decode 'rel' value (%#x vs expected %#x): %s\n",
136  intel_pt_insn.rel, dat->expected_rel, dat->asm_rep);
137  return -1;
138  }
139 
140  pr_debug("Decoded ok: %s\n", dat->asm_rep);
141 
142  return 0;
143 }
144 
145 static int test_data_set(struct test_data *dat_set, int x86_64)
146 {
147  struct test_data *dat;
148  int ret = 0;
149 
150  for (dat = dat_set; dat->expected_length; dat++) {
151  if (test_data_item(dat, x86_64))
152  ret = -1;
153  }
154 
155  return ret;
156 }
157 
175 int test__insn_x86(struct test *test __maybe_unused, int subtest __maybe_unused)
176 {
177  int ret = 0;
178 
179  if (test_data_set(test_data_32, 0))
180  ret = -1;
181 
182  if (test_data_set(test_data_64, 1))
183  ret = -1;
184 
185  return ret;
186 }
Definition: insn.h:36
const char * expected_op_str
Definition: insn-x86.c:15
static int get_branch(const char *branch_str)
Definition: insn-x86.c:67
void insn_init(struct insn *insn, const void *kaddr, int buf_len, int x86_64)
Definition: insn.c:53
const char * asm_rep
Definition: insn-x86.c:17
enum intel_pt_insn_branch branch
const char * expected_branch_str
Definition: insn-x86.c:16
int expected_rel
Definition: insn-x86.c:14
u8 data[MAX_INSN_SIZE]
Definition: insn-x86.c:12
enum intel_pt_insn_op op
struct test_data test_data_32[]
Definition: insn-x86.c:20
const char * name
void insn_get_length(struct insn *insn)
Definition: insn.c:598
#define pr_debug(fmt,...)
Definition: json.h:27
static int insn_complete(struct insn *insn)
Definition: insn.h:145
int test__insn_x86(struct test *test __maybe_unused, int subtest __maybe_unused)
Definition: insn-x86.c:175
static int test_data_item(struct test_data *dat, int x86_64)
Definition: insn-x86.c:94
int intel_pt_get_insn(const unsigned char *buf, size_t len, int x86_64, struct intel_pt_insn *intel_pt_insn)
static int test_data_set(struct test_data *dat_set, int x86_64)
Definition: insn-x86.c:145
unsigned char length
Definition: insn.h:64
#define MAX_INSN_SIZE
Definition: insn.h:72
static int get_op(const char *op_str)
Definition: insn-x86.c:34
Definition: tests.h:30
unsigned char x86_64
Definition: insn.h:65
struct test_data test_data_64[]
Definition: insn-x86.c:27
int expected_length
Definition: insn-x86.c:13