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 <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 * 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 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 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