1 /*
2 * Check verbose decoding of perf_event_open syscall.
3 *
4 * Copyright (c) 2016 Eugene Syromyatnikov <evgsyr@gmail.com>
5 * Copyright (c) 2016-2018 The strace developers.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include "tests.h"
32 #include <asm/unistd.h>
33
34 #if defined(__NR_perf_event_open) && defined(HAVE_LINUX_PERF_EVENT_H)
35
36 # include <inttypes.h>
37 # include <limits.h>
38 # include <stddef.h>
39 # include <stdio.h>
40 # include <stdlib.h>
41 # include <string.h>
42 # include <unistd.h>
43
44 # include <linux/perf_event.h>
45
46 # include "xlat.h"
47 # include "xlat/perf_event_open_flags.h"
48 # include "xlat/perf_attr_size.h"
49
50 # if ULONG_MAX > UINT_MAX /* Poor man's "whether long is 8 bytes?" */
51 # define LONG_STR_PREFIX "ffffffff"
52 # else /* !(ULONG_MAX > UINT_MAX) */
53 # define LONG_STR_PREFIX ""
54 # endif /* ULONG_MAX > UINT_MAX */
55
56 # ifndef PERF_TYPE_BREAKPOINT
57 # define PERF_TYPE_BREAKPOINT 5
58 # endif
59
60 struct s32_val_str {
61 int32_t val;
62 const char *str;
63 };
64
65 struct u32_val_str {
66 uint32_t val;
67 const char *str;
68 };
69
70 struct u64_val_str {
71 uint64_t val;
72 const char *str;
73 };
74
75 /* In order to avoid endianness-specific hackery. */
76 struct pea_flags {
77 uint64_t disabled :1,
78 inherit :1,
79 pinned :1,
80 exclusive :1,
81 exclude_user :1,
82 exclude_kernel :1,
83 exclude_hv :1,
84 exclude_idle :1,
85 mmap :1,
86 comm :1,
87 freq :1,
88 inherit_stat :1,
89 enable_on_exec :1,
90 task :1,
91 watermark :1,
92 precise_ip :2,
93 mmap_data :1,
94 sample_id_all :1,
95 exclude_host :1,
96 exclude_guest :1,
97 exclude_callchain_kernel :1,
98 exclude_callchain_user :1,
99 mmap2 :1,
100 comm_exec :1,
101 use_clockid :1,
102 context_switch :1,
103 write_backward :1,
104 namespaces :1,
105 __reserved_1 :35;
106 };
107
108 static const char *
printaddr(void * ptr)109 printaddr(void *ptr)
110 {
111 static char buf[sizeof("0x") + sizeof(void *) * 2];
112
113 if (ptr == NULL)
114 return "NULL";
115
116 snprintf(buf, sizeof(buf), "%#lx", (unsigned long)ptr);
117
118 return buf;
119 }
120
121 /*
122 * Checklist:
123 *
124 * type - 8 IDs
125 * config - 13 IDs (0..11 + random), depends on type
126 * sample type - bitmask, up to 20 bits
127 * read_format - 5 IDs
128 * bp_type - 6, weird semantics (invalid/unknown)
129 * branch_sample_type - bitmask, 16 bits
130 * clockid - 13 values
131 *
132 * Unions:
133 * sample_period/sample_freq
134 * wakeup_event/wakeup_watermark
135 * bp_addr/config1
136 * bp_len/config2
137 */
138
139 /*
140 * The main idea behind all those numerous ifdefs is checking against version of
141 * structure provided in kernel headers and not use one defined in strace
142 * headers (assume the case when suddenly we add flag without proper update of
143 * __reserved_1 field or something like this).
144 */
145 static void
print_event_attr(struct perf_event_attr * attr_ptr,size_t size,const char * type,const char * config,const char * sample_type,const char * read_format,const char * precise_ip_desc,const char * bp_type,const char * branch_sample_type,const char * clockid,uint32_t available_size)146 print_event_attr(struct perf_event_attr *attr_ptr, size_t size,
147 const char *type, const char *config, const char *sample_type,
148 const char *read_format, const char *precise_ip_desc,
149 const char *bp_type, const char *branch_sample_type,
150 const char *clockid, uint32_t available_size)
151 {
152 /*
153 * Currently, strace supports version 5 of the structure, which is
154 * 112 bytes in size.
155 */
156 enum {
157 STRACE_PEA_ABBREV_SIZE =
158 offsetof(struct perf_event_attr, config) +
159 sizeof(attr_ptr->config),
160 STRACE_PEA_SIZE = 112,
161 };
162
163 uint32_t read_size;
164 struct perf_event_attr *attr;
165 # if VERBOSE
166 uint32_t cutoff;
167 uint64_t val;
168 uint64_t use_clockid;
169 union {
170 struct pea_flags flags;
171 uint64_t raw;
172 } flags_data;
173 # endif
174
175 read_size =
176 # if !VERBOSE
177 STRACE_PEA_ABBREV_SIZE;
178 # else
179 size < STRACE_PEA_SIZE ?
180 (size ? size : PERF_ATTR_SIZE_VER0) : STRACE_PEA_SIZE;
181 # endif
182
183 if (read_size > available_size) {
184 printf("%s", printaddr(attr_ptr));
185 return;
186 }
187
188 /*
189 * Replicate kernel's behaviour regarding copying structure from
190 * userspace.
191 */
192 attr = calloc(1, STRACE_PEA_SIZE);
193
194 if (!attr)
195 error_msg_and_fail("calloc");
196
197
198 memcpy(attr, attr_ptr, read_size);
199
200 if (size && (size < PERF_ATTR_SIZE_VER0)) {
201 printf("%s", printaddr(attr_ptr));
202 free(attr);
203 return;
204 }
205
206 printf("{type=%s, size=", type);
207 if (size != attr->size) {
208 printxval(perf_attr_size, size, "PERF_ATTR_SIZE_???");
209 printf(" => ");
210 }
211 printxval(perf_attr_size, attr->size, "PERF_ATTR_SIZE_???");
212 printf(", config=%s, ", config);
213
214 if (!size)
215 size = PERF_ATTR_SIZE_VER0;
216
217 # if !VERBOSE
218 printf("...}");
219 # else /* !VERBOSE */
220 printf("%s=%" PRI__u64", sample_type=%s, read_format=%s",
221 attr->freq ? "sample_freq" : "sample_period",
222 attr->freq ? attr->sample_freq : attr->sample_period,
223 sample_type, read_format);
224
225 printf(", disabled=%u"
226 ", inherit=%u"
227 ", pinned=%u"
228 ", exclusive=%u"
229 ", exclusive_user=%u"
230 ", exclude_kernel=%u"
231 ", exclude_hv=%u"
232 ", exclude_idle=%u"
233 ", mmap=%u"
234 ", comm=%u"
235 ", freq=%u"
236 ", inherit_stat=%u"
237 ", enable_on_exec=%u"
238 ", task=%u"
239 ", watermark=%u",
240 attr->disabled,
241 attr->inherit,
242 attr->pinned,
243 attr->exclusive,
244 attr->exclude_user,
245 attr->exclude_kernel,
246 attr->exclude_hv,
247 attr->exclude_idle,
248 attr->mmap,
249 attr->comm,
250 attr->freq,
251 attr->inherit_stat,
252 attr->enable_on_exec,
253 attr->task,
254 attr->watermark);
255
256 flags_data.raw = ((uint64_t *) attr)[5];
257
258 val =
259 # ifdef HAVE_STRUCT_PERF_EVENT_ATTR_PRECISE_IP
260 attr->precise_ip;
261 # else
262 flags_data.flags.precise_ip;
263 # endif
264 printf(", precise_ip=%" PRIu64 " /* %s */", val, precise_ip_desc);
265
266 val =
267 # ifdef HAVE_STRUCT_PERF_EVENT_ATTR_MMAP_DATA
268 attr->mmap_data;
269 # else
270 flags_data.flags.mmap_data;
271 # endif
272 printf(", mmap_data=%" PRIu64, val);
273
274 val =
275 # ifdef HAVE_STRUCT_PERF_EVENT_ATTR_SAMPLE_ID_ALL
276 attr->sample_id_all;
277 # else
278 flags_data.flags.sample_id_all;
279 # endif
280 printf(", sample_id_all=%" PRIu64, val);
281
282 val =
283 # ifdef HAVE_STRUCT_PERF_EVENT_ATTR_EXCLUDE_HOST
284 attr->exclude_host;
285 # else
286 flags_data.flags.exclude_host;
287 # endif
288 printf(", exclude_host=%" PRIu64, val);
289
290 val =
291 # ifdef HAVE_STRUCT_PERF_EVENT_ATTR_EXCLUDE_GUEST
292 attr->exclude_guest;
293 # else
294 flags_data.flags.exclude_guest;
295 # endif
296 printf(", exclude_guest=%" PRIu64, val);
297
298 val =
299 # ifdef HAVE_STRUCT_PERF_EVENT_ATTR_EXCLUDE_CALLCHAIN_KERNEL
300 attr->exclude_callchain_kernel;
301 # else
302 flags_data.flags.exclude_callchain_kernel;
303 # endif
304 printf(", exclude_callchain_kernel=%" PRIu64, val);
305
306 val =
307 # ifdef HAVE_STRUCT_PERF_EVENT_ATTR_EXCLUDE_CALLCHAIN_USER
308 attr->exclude_callchain_user;
309 # else
310 flags_data.flags.exclude_callchain_user;
311 # endif
312 printf(", exclude_callchain_user=%" PRIu64, val);
313
314 val =
315 # ifdef HAVE_STRUCT_PERF_EVENT_ATTR_MMAP2
316 attr->mmap2;
317 # else
318 flags_data.flags.mmap2;
319 # endif
320 printf(", mmap2=%" PRIu64, val);
321
322 val =
323 # ifdef HAVE_STRUCT_PERF_EVENT_ATTR_COMM_EXEC
324 attr->comm_exec;
325 # else
326 flags_data.flags.comm_exec;
327 # endif
328 printf(", comm_exec=%" PRIu64, val);
329
330 use_clockid = val =
331 # ifdef HAVE_STRUCT_PERF_EVENT_ATTR_USE_CLOCKID
332 attr->use_clockid;
333 # else
334 flags_data.flags.use_clockid;
335 # endif
336 printf(", use_clockid=%" PRIu64, val);
337
338 val =
339 # ifdef HAVE_STRUCT_PERF_EVENT_ATTR_CONTEXT_SWITCH
340 attr->context_switch;
341 # else
342 flags_data.flags.context_switch;
343 # endif
344 printf(", context_switch=%" PRIu64, val);
345
346 val =
347 # ifdef HAVE_STRUCT_PERF_EVENT_ATTR_WRITE_BACKWARD
348 attr->write_backward;
349 # else
350 flags_data.flags.write_backward;
351 # endif
352 printf(", write_backward=%" PRIu64, val);
353
354 val =
355 # ifdef HAVE_STRUCT_PERF_EVENT_ATTR_NAMESPACES
356 attr->namespaces;
357 # else
358 flags_data.flags.namespaces;
359 # endif
360 printf(", namespaces=%" PRIu64, val);
361
362 val = flags_data.flags.__reserved_1;
363 if (val)
364 printf(", __reserved_1=%#" PRIx64 " /* Bits 63..29 */", val);
365
366 printf(", %s=%u",
367 attr->watermark ? "wakeup_watermark" : "wakeup_events",
368 attr->watermark ? attr->wakeup_watermark : attr->wakeup_events);
369
370 if (attr->type == PERF_TYPE_BREAKPOINT)
371 printf(", bp_type=%s", bp_type);
372
373 val =
374 # ifdef HAVE_STRUCT_PERF_EVENT_ATTR_CONFIG1
375 attr->config1;
376 # else
377 ((uint64_t *) attr)[56 / sizeof(uint64_t)];
378 # endif
379 printf(", %s=%#" PRIx64,
380 attr->type == PERF_TYPE_BREAKPOINT ? "bp_addr" : "config1",
381 val);
382
383 /* End of version 0 of the structure */
384 if (size <= 64) {
385 cutoff = 64;
386 goto end;
387 }
388
389 val =
390 # ifdef HAVE_STRUCT_PERF_EVENT_ATTR_CONFIG2
391 attr->config2;
392 # else
393 ((uint64_t *) attr)[64 / sizeof(uint64_t)];
394 # endif
395 if (attr->type == PERF_TYPE_BREAKPOINT)
396 printf(", bp_len=%" PRIu64, val);
397 else
398 printf(", config2=%#" PRIx64, val);
399
400 /* End of version 1 of the structure */
401 if (size <= 72) {
402 cutoff = 72;
403 goto end;
404 }
405
406 /*
407 * Print branch sample type only in case PERF_SAMPLE_BRANCH_STACK
408 * is set in the sample_type field.
409 */
410 if (attr->sample_type & (1 << 11))
411 printf(", branch_sample_type=%s", branch_sample_type);
412
413 /* End of version 2 of the structure */
414 if (size <= 80) {
415 cutoff = 80;
416 goto end;
417 }
418
419 val =
420 # ifdef HAVE_STRUCT_PERF_EVENT_ATTR_SAMPLE_REGS_USER
421 attr->sample_regs_user;
422 # else
423 ((uint64_t *) attr)[80 / sizeof(uint64_t)];
424 # endif
425 printf(", sample_regs_user=%#" PRIx64, val);
426
427 if (size <= 88) {
428 cutoff = 88;
429 goto end;
430 }
431
432 val =
433 # ifdef HAVE_STRUCT_PERF_EVENT_ATTR_SAMPLE_STACK_USER
434 attr->sample_stack_user;
435 # else
436 ((uint32_t *) attr)[88 / sizeof(uint32_t)];
437 # endif
438 /*
439 * Print branch sample type only in case PERF_SAMPLE_STACK_USER
440 * is set in the sample_type field.
441 */
442 if (attr->sample_type & (1 << 13))
443 printf(", sample_stack_user=%#" PRIx32, (uint32_t) val);
444
445 if (size <= 92) {
446 cutoff = 92;
447 goto end;
448 }
449
450 if (use_clockid)
451 printf(", clockid=%s", clockid);
452
453 /* End of version 3 of the structure */
454 if (size <= 96) {
455 cutoff = 96;
456 goto end;
457 }
458
459 val =
460 # ifdef HAVE_STRUCT_PERF_EVENT_ATTR_SAMPLE_REGS_INTR
461 attr->sample_regs_intr;
462 # else
463 ((uint64_t *) attr)[96 / sizeof(uint64_t)];
464 # endif
465 printf(", sample_regs_intr=%#" PRIx64, val);
466
467 /* End of version 4 of the structure */
468 if (size <= 104) {
469 cutoff = 104;
470 goto end;
471 }
472
473 val =
474 # ifdef HAVE_STRUCT_PERF_EVENT_ATTR_AUX_WATERMARK
475 attr->aux_watermark;
476 # else
477 ((uint32_t *) attr)[104 / sizeof(uint32_t)];
478 # endif
479 printf(", aux_watermark=%" PRIu32, (uint32_t) val);
480
481 if (size <= 108) {
482 cutoff = 108;
483 goto end;
484 }
485
486 val =
487 # ifdef HAVE_STRUCT_PERF_EVENT_ATTR_SAMPLE_MAX_STACK
488 attr->sample_max_stack;
489 # else
490 ((uint16_t *) attr)[108 / sizeof(uint16_t)];
491 # endif
492 printf(", sample_max_stack=%" PRIu16, (uint16_t) val);
493
494 if (size <= 110) {
495 cutoff = 110;
496 goto end;
497 }
498
499 cutoff = STRACE_PEA_SIZE;
500
501 end:
502 if (size > cutoff)
503 printf(", ...");
504
505 printf("}");
506 # endif /* !VERBOSE */
507
508 free(attr);
509 }
510
511 /* These require aligned access, so no byte-grain checks possible */
512 # if defined SPARC || defined SPARC64 || defined POWERPC || defined POWERPC64
513 # define ATTR_REC(sz) { tail_alloc((sz + 7) & ~7), sz }
514 # else
515 # define ATTR_REC(sz) { tail_alloc(sz), sz }
516 # endif
517
518 # define BRANCH_TYPE_ALL \
519 "PERF_SAMPLE_BRANCH_USER|" \
520 "PERF_SAMPLE_BRANCH_KERNEL|" \
521 "PERF_SAMPLE_BRANCH_HV|" \
522 "PERF_SAMPLE_BRANCH_ANY|" \
523 "PERF_SAMPLE_BRANCH_ANY_CALL|" \
524 "PERF_SAMPLE_BRANCH_ANY_RETURN|" \
525 "PERF_SAMPLE_BRANCH_IND_CALL|" \
526 "PERF_SAMPLE_BRANCH_ABORT_TX|" \
527 "PERF_SAMPLE_BRANCH_IN_TX|" \
528 "PERF_SAMPLE_BRANCH_NO_TX|" \
529 "PERF_SAMPLE_BRANCH_COND|" \
530 "PERF_SAMPLE_BRANCH_CALL_STACK|" \
531 "PERF_SAMPLE_BRANCH_IND_JUMP|" \
532 "PERF_SAMPLE_BRANCH_CALL|" \
533 "PERF_SAMPLE_BRANCH_NO_FLAGS|" \
534 "PERF_SAMPLE_BRANCH_NO_CYCLES|" \
535 "PERF_SAMPLE_BRANCH_TYPE_SAVE"
536
537 int
main(void)538 main(void)
539 {
540 static const size_t attr_small_size = PERF_ATTR_SIZE_VER0 - 8;
541 static const size_t attr_v0_size = PERF_ATTR_SIZE_VER0;
542 static const size_t attr_v1_size = PERF_ATTR_SIZE_VER1;
543 static const size_t attr_v2_size = PERF_ATTR_SIZE_VER2;
544 static const size_t attr_v2_5_size = PERF_ATTR_SIZE_VER2 + 8;
545 static const size_t attr_v2_75_size = PERF_ATTR_SIZE_VER2 + 12;
546 static const size_t attr_v3_size = PERF_ATTR_SIZE_VER3;
547 static const size_t attr_v4_size = PERF_ATTR_SIZE_VER4;
548 static const size_t attr_v4_5_size = PERF_ATTR_SIZE_VER4 + 4;
549 static const size_t attr_v4_625_size = PERF_ATTR_SIZE_VER4 + 5;
550 static const size_t attr_v4_875_size = PERF_ATTR_SIZE_VER4 + 7;
551 static const size_t attr_v5_size = PERF_ATTR_SIZE_VER5;
552 static const size_t attr_big_size = PERF_ATTR_SIZE_VER5 + 32;
553
554 static const struct u64_val_str attr_types[] = {
555 { ARG_STR(PERF_TYPE_HARDWARE) },
556 { ARG_STR(PERF_TYPE_SOFTWARE) },
557 { ARG_STR(PERF_TYPE_TRACEPOINT) },
558 { ARG_STR(PERF_TYPE_HW_CACHE) },
559 { ARG_STR(PERF_TYPE_RAW) },
560 { ARG_STR(PERF_TYPE_BREAKPOINT) },
561 { ARG_STR(0x6) " /* PERF_TYPE_??? */" },
562 { ARG_STR(0xdeadc0de) " /* PERF_TYPE_??? */" },
563 };
564 static const struct u64_val_str
565 attr_configs[ARRAY_SIZE(attr_types)][3] = {
566 /* PERF_TYPE_HARDWARE */ {
567 { 9, "PERF_COUNT_HW_REF_CPU_CYCLES" },
568 { 10, "0xa /* PERF_COUNT_HW_??? */" },
569 { ARG_ULL_STR(0xfaceca75deadb0d4)
570 " /* PERF_COUNT_HW_??? */" },
571 },
572 /* PERF_TYPE_SOFTWARE */ {
573 { 10, "PERF_COUNT_SW_BPF_OUTPUT" },
574 { 11, "0xb /* PERF_COUNT_SW_??? */" },
575 { ARG_ULL_STR(0xdec0ded1dec0ded2)
576 " /* PERF_COUNT_SW_??? */" },
577 },
578 /* PERF_TYPE_TRACEPOINT */ {
579 { ARG_STR(0) },
580 { 4207856245U, "4207856245" },
581 { ARG_ULL_STR(16051074073505095380) },
582 },
583 /* PERF_TYPE_HW_CACHE */ {
584 { 0, "PERF_COUNT_HW_CACHE_L1D|"
585 "PERF_COUNT_HW_CACHE_OP_READ<<8|"
586 "PERF_COUNT_HW_CACHE_RESULT_ACCESS<<16" },
587 { 0x020207, "0x7 /* PERF_COUNT_HW_CACHE_??? */|"
588 "PERF_COUNT_HW_CACHE_OP_PREFETCH<<8|"
589 "0x2 /* PERF_COUNT_HW_CACHE_RESULT_??? */<<16" },
590 { 0xdeadf157ed010306ULL, "PERF_COUNT_HW_CACHE_NODE|"
591 "0x3 /* PERF_COUNT_HW_CACHE_OP_??? */<<8|"
592 "PERF_COUNT_HW_CACHE_RESULT_MISS<<16|"
593 "0xdeadf157ed<<24 "
594 "/* PERF_COUNT_HW_CACHE_??? */" },
595 },
596 /* PERF_TYPE_RAW */ {
597 { ARG_STR(0) },
598 { ARG_STR(0xda7a1057) },
599 { ARG_ULL_STR(0xdec0ded7dec0ded8) },
600 },
601 /* PERF_TYPE_BREAKPOINT */ {
602 { ARG_STR(0) },
603 { ARG_STR(0xbadc0ded) },
604 { ARG_ULL_STR(0xdec0ded9dec0deda) },
605 },
606 /* invalid 1 */ {
607 { ARG_STR(0) },
608 { ARG_STR(0xbeeff00d) },
609 { ARG_ULL_STR(0xdec0dedbdec0dedc) },
610 },
611 /* invalid 2 */ {
612 { ARG_STR(0) },
613 { ARG_STR(0xca75dead) },
614 { ARG_ULL_STR(0xdec0dedddec0dede) },
615 },
616 };
617 static const struct u64_val_str sample_types[] = {
618 { ARG_STR(0) },
619 { 0x800, "PERF_SAMPLE_BRANCH_STACK" },
620 { ARG_ULL_STR(0xdeadc0deda700000) " /* PERF_SAMPLE_??? */" },
621 { 0xffffffffffffffffULL,
622 "PERF_SAMPLE_IP|PERF_SAMPLE_TID|PERF_SAMPLE_TIME|"
623 "PERF_SAMPLE_ADDR|PERF_SAMPLE_READ|"
624 "PERF_SAMPLE_CALLCHAIN|PERF_SAMPLE_ID|PERF_SAMPLE_CPU|"
625 "PERF_SAMPLE_PERIOD|PERF_SAMPLE_STREAM_ID|"
626 "PERF_SAMPLE_RAW|PERF_SAMPLE_BRANCH_STACK|"
627 "PERF_SAMPLE_REGS_USER|PERF_SAMPLE_STACK_USER|"
628 "PERF_SAMPLE_WEIGHT|PERF_SAMPLE_DATA_SRC|"
629 "PERF_SAMPLE_IDENTIFIER|PERF_SAMPLE_TRANSACTION|"
630 "PERF_SAMPLE_REGS_INTR|PERF_SAMPLE_PHYS_ADDR|"
631 "0xfffffffffff00000" },
632 };
633 static const struct u64_val_str read_formats[] = {
634 { ARG_STR(0) },
635 { ARG_STR(PERF_FORMAT_TOTAL_TIME_ENABLED) },
636 { 0xf, "PERF_FORMAT_TOTAL_TIME_ENABLED|"
637 "PERF_FORMAT_TOTAL_TIME_RUNNING|"
638 "PERF_FORMAT_ID|PERF_FORMAT_GROUP" },
639 { ARG_ULL_STR(0xdeadf157dec0ded0) " /* PERF_FORMAT_??? */" },
640 { 0xffffffffffffffffULL,
641 "PERF_FORMAT_TOTAL_TIME_ENABLED|"
642 "PERF_FORMAT_TOTAL_TIME_RUNNING|"
643 "PERF_FORMAT_ID|PERF_FORMAT_GROUP|"
644 "0xfffffffffffffff0" },
645 };
646 static const char *precise_ip_descs[] = {
647 "arbitrary skid",
648 "constant skid",
649 "requested to have 0 skid",
650 "must have 0 skid",
651 };
652 static const struct u32_val_str bp_types[] = {
653 { 0, "HW_BREAKPOINT_EMPTY" },
654 { 1, "HW_BREAKPOINT_R" },
655 { 3, "HW_BREAKPOINT_RW" },
656 { 5, "0x5 /* HW_BREAKPOINT_INVALID */" },
657 { 8, "0x8 /* HW_BREAKPOINT_??? */" },
658 { ARG_STR(0xface1e55) " /* HW_BREAKPOINT_??? */" },
659 };
660 static const struct u64_val_str branch_sample_types[] = {
661 { ARG_STR(0) },
662 { 0x80, "PERF_SAMPLE_BRANCH_ABORT_TX" },
663 { 0x1ffff, BRANCH_TYPE_ALL },
664 { ARG_ULL_STR(0xdeadcaffeeec0000)
665 " /* PERF_SAMPLE_BRANCH_??? */" },
666 { 0xffffffffffffffffULL,
667 BRANCH_TYPE_ALL "|0xfffffffffffe0000" }
668 };
669 static const struct s32_val_str clockids[] = {
670 { 11, "CLOCK_TAI" },
671 { ARG_STR(0xc) " /* CLOCK_??? */" },
672 { ARG_STR(0xbeeffeed) " /* CLOCK_??? */" },
673 };
674
675
676 struct {
677 struct perf_event_attr *ptr;
678 size_t size;
679 } attrs[] = {
680 ATTR_REC(sizeof(struct perf_event_attr)),
681 ATTR_REC(attr_v0_size),
682 ATTR_REC(attr_v1_size),
683 ATTR_REC(attr_v2_size),
684 ATTR_REC(attr_v2_5_size),
685 ATTR_REC(attr_v2_75_size),
686 ATTR_REC(attr_v3_size),
687 ATTR_REC(attr_v4_size),
688 ATTR_REC(attr_v4_5_size),
689 ATTR_REC(attr_v4_625_size),
690 ATTR_REC(attr_v4_875_size),
691 ATTR_REC(attr_v5_size),
692 ATTR_REC(attr_big_size),
693 };
694
695 TAIL_ALLOC_OBJECT_CONST_PTR(struct perf_event_attr, small_attr);
696
697 struct {
698 struct perf_event_attr *attr;
699 pid_t pid;
700 int cpu;
701 int group_fd;
702 unsigned long flags;
703 const char *flags_str;
704 } args[] = {
705 { NULL, 0xfacef00d, 0xbadabba7, -1,
706 (unsigned long) 0xFFFFFFFFFFFFFFFFLLU,
707 "PERF_FLAG_FD_NO_GROUP|PERF_FLAG_FD_OUTPUT|"
708 "PERF_FLAG_PID_CGROUP|PERF_FLAG_FD_CLOEXEC|"
709 "0x" LONG_STR_PREFIX "fffffff0"
710 },
711 { small_attr + 1, 0, 0, 0,
712 0, "0" },
713 { small_attr, -1, -1, 1,
714 PERF_FLAG_FD_NO_GROUP | PERF_FLAG_FD_OUTPUT |
715 PERF_FLAG_PID_CGROUP | PERF_FLAG_FD_CLOEXEC,
716 "PERF_FLAG_FD_NO_GROUP|PERF_FLAG_FD_OUTPUT|"
717 "PERF_FLAG_PID_CGROUP|PERF_FLAG_FD_CLOEXEC" },
718 { (struct perf_event_attr *) (uintptr_t) 0xfffffacefffffeedULL,
719 -100, 100, 0xface1e55,
720 PERF_FLAG_FD_CLOEXEC, "PERF_FLAG_FD_CLOEXEC" },
721 };
722
723 size_t i;
724 int rc;
725
726 fill_memory(small_attr, sizeof(*small_attr));
727 small_attr->size = attr_small_size;
728
729 for (i = 0; i < ARRAY_SIZE(args); i++) {
730 rc = syscall(__NR_perf_event_open, args[i].attr, args[i].pid,
731 args[i].cpu, args[i].group_fd, args[i].flags);
732 printf("perf_event_open(%s, %d, %d, %d, %s) = %s\n",
733 printaddr(args[i].attr), args[i].pid, args[i].cpu,
734 args[i].group_fd, args[i].flags_str, sprintrc(rc));
735 }
736
737 for (i = 0; i < ARRAY_SIZE(attrs) * ARRAY_SIZE(attr_types) *
738 ARRAY_SIZE(attr_configs[0]) + 1; i++) {
739 struct perf_event_attr *attr = attrs[i % ARRAY_SIZE(attrs)].ptr;
740 uint32_t size = attrs[i % ARRAY_SIZE(attrs)].size;
741 unsigned char fill_start = 0x80 + i;
742 size_t type_idx = i % ARRAY_SIZE(attr_types);
743 size_t config_idx = i % ARRAY_SIZE(attr_configs[0]);
744 size_t sample_type_idx = i % ARRAY_SIZE(sample_types);
745 size_t read_format_idx = i % ARRAY_SIZE(read_formats);
746 size_t bp_type_idx = (i / ARRAY_SIZE(attr_configs[0])) %
747 ARRAY_SIZE(bp_types);
748 size_t branch_sample_type_idx = (i / ARRAY_SIZE(sample_types)) %
749 ARRAY_SIZE(branch_sample_types);
750 size_t clockid_idx = i % ARRAY_SIZE(clockids);
751 size_t args_idx = i % ARRAY_SIZE(args);
752 const char *ip_desc_str;
753
754 fill_memory_ex(attr, size, fill_start, 0xff);
755
756 attr->type = attr_types[type_idx].val;
757 attr->size = size;
758 attr->config = attr_configs[type_idx][config_idx].val;
759 attr->sample_type = sample_types[sample_type_idx].val;
760 attr->read_format = read_formats[read_format_idx].val;
761
762 if ((i % 11) == 5)
763 attr->__reserved_1 = 0;
764
765 # ifdef HAVE_STRUCT_PERF_EVENT_ATTR_BP_TYPE
766 attr->bp_type =
767 # else
768 ((uint32_t *) attr)[52 / sizeof(uint32_t)] =
769 # endif
770 bp_types[bp_type_idx].val;
771
772 if (size >= 80)
773 # ifdef HAVE_STRUCT_PERF_EVENT_ATTR_BRANCH_SAMPLE_TYPE
774 attr->branch_sample_type =
775 # else
776 ((uint64_t *) attr)[72 / sizeof(uint64_t)] =
777 # endif
778 branch_sample_types[branch_sample_type_idx].val;
779
780 if (size >= 96)
781 # ifdef HAVE_STRUCT_PERF_EVENT_ATTR_CLOCKID
782 attr->clockid =
783 # else
784 ((uint32_t *) attr)[92 / sizeof(uint32_t)] =
785 # endif
786 clockids[clockid_idx].val;
787
788 # ifdef HAVE_STRUCT_PERF_EVENT_ATTR_PRECISE_IP
789 ip_desc_str = precise_ip_descs[attr->precise_ip];
790 # else
791 union {
792 struct pea_flags flags;
793 uint64_t raw;
794 } flags_data = { .raw = ((uint64_t *) attr)[5] };
795
796 ip_desc_str = precise_ip_descs[flags_data.flags.precise_ip];
797 # endif
798
799 if (i == 0)
800 attr->size = size + 8;
801
802 if (i == 1)
803 attr->size = 0;
804
805 rc = syscall(__NR_perf_event_open, attr, args[args_idx].pid,
806 args[args_idx].cpu, args[args_idx].group_fd,
807 args[args_idx].flags);
808
809 printf("perf_event_open(");
810 print_event_attr(attr, i ? ((i == 1) ? 0 : size) : size + 8,
811 attr_types[type_idx].str,
812 attr_configs[type_idx][config_idx].str,
813 sample_types[sample_type_idx].str,
814 read_formats[read_format_idx].str,
815 ip_desc_str,
816 bp_types[bp_type_idx].str,
817 branch_sample_types[branch_sample_type_idx].str,
818 clockids[clockid_idx].str, size);
819 printf(", %d, %d, %d, %s) = %s\n", args[args_idx].pid,
820 args[args_idx].cpu, args[args_idx].group_fd,
821 args[args_idx].flags_str, sprintrc(rc));
822 }
823
824 puts("+++ exited with 0 +++");
825 return 0;
826 }
827
828 #else
829
830 SKIP_MAIN_UNDEFINED("__NR_perf_event_open && HAVE_LINUX_PERF_EVENT_H");
831
832 #endif
833