1 #include <stdbool.h>
2 #include <inttypes.h>
3 
4 #include "util.h"
5 #include "event.h"
6 #include "evsel.h"
7 
8 #include "tests.h"
9 
10 #define COMP(m) do {					\
11 	if (s1->m != s2->m) {				\
12 		pr_debug("Samples differ at '"#m"'\n");	\
13 		return false;				\
14 	}						\
15 } while (0)
16 
17 #define MCOMP(m) do {					\
18 	if (memcmp(&s1->m, &s2->m, sizeof(s1->m))) {	\
19 		pr_debug("Samples differ at '"#m"'\n");	\
20 		return false;				\
21 	}						\
22 } while (0)
23 
24 static bool samples_same(const struct perf_sample *s1,
25 			 const struct perf_sample *s2, u64 type, u64 regs_user,
26 			 u64 read_format)
27 {
28 	size_t i;
29 
30 	if (type & PERF_SAMPLE_IDENTIFIER)
31 		COMP(id);
32 
33 	if (type & PERF_SAMPLE_IP)
34 		COMP(ip);
35 
36 	if (type & PERF_SAMPLE_TID) {
37 		COMP(pid);
38 		COMP(tid);
39 	}
40 
41 	if (type & PERF_SAMPLE_TIME)
42 		COMP(time);
43 
44 	if (type & PERF_SAMPLE_ADDR)
45 		COMP(addr);
46 
47 	if (type & PERF_SAMPLE_ID)
48 		COMP(id);
49 
50 	if (type & PERF_SAMPLE_STREAM_ID)
51 		COMP(stream_id);
52 
53 	if (type & PERF_SAMPLE_CPU)
54 		COMP(cpu);
55 
56 	if (type & PERF_SAMPLE_PERIOD)
57 		COMP(period);
58 
59 	if (type & PERF_SAMPLE_READ) {
60 		if (read_format & PERF_FORMAT_GROUP)
61 			COMP(read.group.nr);
62 		else
63 			COMP(read.one.value);
64 		if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
65 			COMP(read.time_enabled);
66 		if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
67 			COMP(read.time_running);
68 		/* PERF_FORMAT_ID is forced for PERF_SAMPLE_READ */
69 		if (read_format & PERF_FORMAT_GROUP) {
70 			for (i = 0; i < s1->read.group.nr; i++)
71 				MCOMP(read.group.values[i]);
72 		} else {
73 			COMP(read.one.id);
74 		}
75 	}
76 
77 	if (type & PERF_SAMPLE_CALLCHAIN) {
78 		COMP(callchain->nr);
79 		for (i = 0; i < s1->callchain->nr; i++)
80 			COMP(callchain->ips[i]);
81 	}
82 
83 	if (type & PERF_SAMPLE_RAW) {
84 		COMP(raw_size);
85 		if (memcmp(s1->raw_data, s2->raw_data, s1->raw_size)) {
86 			pr_debug("Samples differ at 'raw_data'\n");
87 			return false;
88 		}
89 	}
90 
91 	if (type & PERF_SAMPLE_BRANCH_STACK) {
92 		COMP(branch_stack->nr);
93 		for (i = 0; i < s1->branch_stack->nr; i++)
94 			MCOMP(branch_stack->entries[i]);
95 	}
96 
97 	if (type & PERF_SAMPLE_REGS_USER) {
98 		size_t sz = hweight_long(regs_user) * sizeof(u64);
99 
100 		COMP(user_regs.abi);
101 		if (s1->user_regs.abi &&
102 		    (!s1->user_regs.regs || !s2->user_regs.regs ||
103 		     memcmp(s1->user_regs.regs, s2->user_regs.regs, sz))) {
104 			pr_debug("Samples differ at 'user_regs'\n");
105 			return false;
106 		}
107 	}
108 
109 	if (type & PERF_SAMPLE_STACK_USER) {
110 		COMP(user_stack.size);
111 		if (memcmp(s1->user_stack.data, s1->user_stack.data,
112 			   s1->user_stack.size)) {
113 			pr_debug("Samples differ at 'user_stack'\n");
114 			return false;
115 		}
116 	}
117 
118 	if (type & PERF_SAMPLE_WEIGHT)
119 		COMP(weight);
120 
121 	if (type & PERF_SAMPLE_DATA_SRC)
122 		COMP(data_src);
123 
124 	return true;
125 }
126 
127 static int do_test(u64 sample_type, u64 sample_regs_user, u64 read_format)
128 {
129 	struct perf_evsel evsel = {
130 		.needs_swap = false,
131 		.attr = {
132 			.sample_type = sample_type,
133 			.sample_regs_user = sample_regs_user,
134 			.read_format = read_format,
135 		},
136 	};
137 	union perf_event *event;
138 	union {
139 		struct ip_callchain callchain;
140 		u64 data[64];
141 	} callchain = {
142 		/* 3 ips */
143 		.data = {3, 201, 202, 203},
144 	};
145 	union {
146 		struct branch_stack branch_stack;
147 		u64 data[64];
148 	} branch_stack = {
149 		/* 1 branch_entry */
150 		.data = {1, 211, 212, 213},
151 	};
152 	u64 user_regs[64];
153 	const u64 raw_data[] = {0x123456780a0b0c0dULL, 0x1102030405060708ULL};
154 	const u64 data[] = {0x2211443366558877ULL, 0, 0xaabbccddeeff4321ULL};
155 	struct perf_sample sample = {
156 		.ip		= 101,
157 		.pid		= 102,
158 		.tid		= 103,
159 		.time		= 104,
160 		.addr		= 105,
161 		.id		= 106,
162 		.stream_id	= 107,
163 		.period		= 108,
164 		.weight		= 109,
165 		.cpu		= 110,
166 		.raw_size	= sizeof(raw_data),
167 		.data_src	= 111,
168 		.raw_data	= (void *)raw_data,
169 		.callchain	= &callchain.callchain,
170 		.branch_stack	= &branch_stack.branch_stack,
171 		.user_regs	= {
172 			.abi	= PERF_SAMPLE_REGS_ABI_64,
173 			.regs	= user_regs,
174 		},
175 		.user_stack	= {
176 			.size	= sizeof(data),
177 			.data	= (void *)data,
178 		},
179 		.read		= {
180 			.time_enabled = 0x030a59d664fca7deULL,
181 			.time_running = 0x011b6ae553eb98edULL,
182 		},
183 	};
184 	struct sample_read_value values[] = {{1, 5}, {9, 3}, {2, 7}, {6, 4},};
185 	struct perf_sample sample_out;
186 	size_t i, sz, bufsz;
187 	int err, ret = -1;
188 
189 	for (i = 0; i < sizeof(user_regs); i++)
190 		*(i + (u8 *)user_regs) = i & 0xfe;
191 
192 	if (read_format & PERF_FORMAT_GROUP) {
193 		sample.read.group.nr     = 4;
194 		sample.read.group.values = values;
195 	} else {
196 		sample.read.one.value = 0x08789faeb786aa87ULL;
197 		sample.read.one.id    = 99;
198 	}
199 
200 	sz = perf_event__sample_event_size(&sample, sample_type,
201 					   sample_regs_user, read_format);
202 	bufsz = sz + 4096; /* Add a bit for overrun checking */
203 	event = malloc(bufsz);
204 	if (!event) {
205 		pr_debug("malloc failed\n");
206 		return -1;
207 	}
208 
209 	memset(event, 0xff, bufsz);
210 	event->header.type = PERF_RECORD_SAMPLE;
211 	event->header.misc = 0;
212 	event->header.size = sz;
213 
214 	err = perf_event__synthesize_sample(event, sample_type,
215 					    sample_regs_user, read_format,
216 					    &sample, false);
217 	if (err) {
218 		pr_debug("%s failed for sample_type %#"PRIx64", error %d\n",
219 			 "perf_event__synthesize_sample", sample_type, err);
220 		goto out_free;
221 	}
222 
223 	/* The data does not contain 0xff so we use that to check the size */
224 	for (i = bufsz; i > 0; i--) {
225 		if (*(i - 1 + (u8 *)event) != 0xff)
226 			break;
227 	}
228 	if (i != sz) {
229 		pr_debug("Event size mismatch: actual %zu vs expected %zu\n",
230 			 i, sz);
231 		goto out_free;
232 	}
233 
234 	evsel.sample_size = __perf_evsel__sample_size(sample_type);
235 
236 	err = perf_evsel__parse_sample(&evsel, event, &sample_out);
237 	if (err) {
238 		pr_debug("%s failed for sample_type %#"PRIx64", error %d\n",
239 			 "perf_evsel__parse_sample", sample_type, err);
240 		goto out_free;
241 	}
242 
243 	if (!samples_same(&sample, &sample_out, sample_type,
244 			  sample_regs_user, read_format)) {
245 		pr_debug("parsing failed for sample_type %#"PRIx64"\n",
246 			 sample_type);
247 		goto out_free;
248 	}
249 
250 	ret = 0;
251 out_free:
252 	free(event);
253 	if (ret && read_format)
254 		pr_debug("read_format %#"PRIx64"\n", read_format);
255 	return ret;
256 }
257 
258 /**
259  * test__sample_parsing - test sample parsing.
260  *
261  * This function implements a test that synthesizes a sample event, parses it
262  * and then checks that the parsed sample matches the original sample.  The test
263  * checks sample format bits separately and together.  If the test passes %0 is
264  * returned, otherwise %-1 is returned.
265  */
266 int test__sample_parsing(void)
267 {
268 	const u64 rf[] = {4, 5, 6, 7, 12, 13, 14, 15};
269 	u64 sample_type;
270 	u64 sample_regs_user;
271 	size_t i;
272 	int err;
273 
274 	/*
275 	 * Fail the test if it has not been updated when new sample format bits
276 	 * were added.
277 	 */
278 	if (PERF_SAMPLE_MAX > PERF_SAMPLE_IDENTIFIER << 1) {
279 		pr_debug("sample format has changed - test needs updating\n");
280 		return -1;
281 	}
282 
283 	/* Test each sample format bit separately */
284 	for (sample_type = 1; sample_type != PERF_SAMPLE_MAX;
285 	     sample_type <<= 1) {
286 		/* Test read_format variations */
287 		if (sample_type == PERF_SAMPLE_READ) {
288 			for (i = 0; i < ARRAY_SIZE(rf); i++) {
289 				err = do_test(sample_type, 0, rf[i]);
290 				if (err)
291 					return err;
292 			}
293 			continue;
294 		}
295 
296 		if (sample_type == PERF_SAMPLE_REGS_USER)
297 			sample_regs_user = 0x3fff;
298 		else
299 			sample_regs_user = 0;
300 
301 		err = do_test(sample_type, sample_regs_user, 0);
302 		if (err)
303 			return err;
304 	}
305 
306 	/* Test all sample format bits together */
307 	sample_type = PERF_SAMPLE_MAX - 1;
308 	sample_regs_user = 0x3fff;
309 	for (i = 0; i < ARRAY_SIZE(rf); i++) {
310 		err = do_test(sample_type, sample_regs_user, rf[i]);
311 		if (err)
312 			return err;
313 	}
314 
315 	return 0;
316 }
317