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