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