1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * builtin-list.c 4 * 5 * Builtin list command: list all event types 6 * 7 * Copyright (C) 2009, Thomas Gleixner <tglx@linutronix.de> 8 * Copyright (C) 2008-2009, Red Hat Inc, Ingo Molnar <mingo@redhat.com> 9 * Copyright (C) 2011, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com> 10 */ 11 #include "builtin.h" 12 13 #include "util/print-events.h" 14 #include "util/pmus.h" 15 #include "util/pmu.h" 16 #include "util/debug.h" 17 #include "util/metricgroup.h" 18 #include "util/pfm.h" 19 #include "util/string2.h" 20 #include "util/strlist.h" 21 #include "util/strbuf.h" 22 #include "util/tool_pmu.h" 23 #include <subcmd/pager.h> 24 #include <subcmd/parse-options.h> 25 #include <linux/zalloc.h> 26 #include <ctype.h> 27 #include <stdarg.h> 28 #include <stdio.h> 29 30 /** 31 * struct print_state - State and configuration passed to the default_print 32 * functions. 33 */ 34 struct print_state { 35 /** @fp: File to write output to. */ 36 FILE *fp; 37 /** 38 * @pmu_glob: Optionally restrict PMU and metric matching to PMU or 39 * debugfs subsystem name. 40 */ 41 char *pmu_glob; 42 /** @event_glob: Optional pattern matching glob. */ 43 char *event_glob; 44 /** @name_only: Print event or metric names only. */ 45 bool name_only; 46 /** @desc: Print the event or metric description. */ 47 bool desc; 48 /** @long_desc: Print longer event or metric description. */ 49 bool long_desc; 50 /** @deprecated: Print deprecated events or metrics. */ 51 bool deprecated; 52 /** 53 * @detailed: Print extra information on the perf event such as names 54 * and expressions used internally by events. 55 */ 56 bool detailed; 57 /** @metrics: Controls printing of metric and metric groups. */ 58 bool metrics; 59 /** @metricgroups: Controls printing of metric and metric groups. */ 60 bool metricgroups; 61 /** @exclude_abi: Exclude PMUs with types less than PERF_TYPE_MAX except PERF_TYPE_RAW. */ 62 bool exclude_abi; 63 /** @last_topic: The last printed event topic. */ 64 char *last_topic; 65 /** @last_metricgroups: The last printed metric group. */ 66 char *last_metricgroups; 67 /** @visited_metrics: Metrics that are printed to avoid duplicates. */ 68 struct strlist *visited_metrics; 69 }; 70 71 static void default_print_start(void *ps) 72 { 73 struct print_state *print_state = ps; 74 75 if (!print_state->name_only && pager_in_use()) { 76 fprintf(print_state->fp, 77 "\nList of pre-defined events (to be used in -e or -M):\n\n"); 78 } 79 } 80 81 static void default_print_end(void *print_state __maybe_unused) {} 82 83 static const char *skip_spaces_or_commas(const char *str) 84 { 85 while (isspace(*str) || *str == ',') 86 ++str; 87 return str; 88 } 89 90 static void wordwrap(FILE *fp, const char *s, int start, int max, int corr) 91 { 92 int column = start; 93 int n; 94 bool saw_newline = false; 95 bool comma = false; 96 97 while (*s) { 98 int wlen = strcspn(s, " ,\t\n"); 99 const char *sep = comma ? "," : " "; 100 101 if ((column + wlen >= max && column > start) || saw_newline) { 102 fprintf(fp, comma ? ",\n%*s" : "\n%*s", start, ""); 103 column = start + corr; 104 } 105 if (column <= start) 106 sep = ""; 107 n = fprintf(fp, "%s%.*s", sep, wlen, s); 108 if (n <= 0) 109 break; 110 saw_newline = s[wlen] == '\n'; 111 s += wlen; 112 comma = s[0] == ','; 113 column += n; 114 s = skip_spaces_or_commas(s); 115 } 116 } 117 118 static void default_print_event(void *ps, const char *topic, 119 const char *pmu_name, u32 pmu_type, 120 const char *event_name, const char *event_alias, 121 const char *scale_unit __maybe_unused, 122 bool deprecated, const char *event_type_desc, 123 const char *desc, const char *long_desc, 124 const char *encoding_desc) 125 { 126 struct print_state *print_state = ps; 127 int pos; 128 FILE *fp = print_state->fp; 129 130 if (deprecated && !print_state->deprecated) 131 return; 132 133 if (print_state->pmu_glob && pmu_name && !strglobmatch(pmu_name, print_state->pmu_glob)) 134 return; 135 136 if (print_state->exclude_abi && pmu_type < PERF_TYPE_MAX && pmu_type != PERF_TYPE_RAW) 137 return; 138 139 if (print_state->event_glob && 140 (!event_name || !strglobmatch(event_name, print_state->event_glob)) && 141 (!event_alias || !strglobmatch(event_alias, print_state->event_glob)) && 142 (!topic || !strglobmatch_nocase(topic, print_state->event_glob))) 143 return; 144 145 if (print_state->name_only) { 146 if (event_alias && strlen(event_alias)) 147 fprintf(fp, "%s ", event_alias); 148 else 149 fprintf(fp, "%s ", event_name); 150 return; 151 } 152 153 if (strcmp(print_state->last_topic, topic ?: "")) { 154 if (topic) 155 fprintf(fp, "\n%s:\n", topic); 156 zfree(&print_state->last_topic); 157 print_state->last_topic = strdup(topic ?: ""); 158 } 159 160 if (event_alias && strlen(event_alias)) 161 pos = fprintf(fp, " %s OR %s", event_name, event_alias); 162 else 163 pos = fprintf(fp, " %s", event_name); 164 165 if (!topic && event_type_desc) { 166 for (; pos < 53; pos++) 167 fputc(' ', fp); 168 fprintf(fp, "[%s]\n", event_type_desc); 169 } else 170 fputc('\n', fp); 171 172 if (long_desc && print_state->long_desc) 173 desc = long_desc; 174 175 if (desc && (print_state->desc || print_state->long_desc)) { 176 char *desc_with_unit = NULL; 177 int desc_len = -1; 178 179 if (pmu_name && strcmp(pmu_name, "default_core")) { 180 desc_len = strlen(desc); 181 desc_len = asprintf(&desc_with_unit, 182 desc_len > 0 && desc[desc_len - 1] != '.' 183 ? "%s. Unit: %s" : "%s Unit: %s", 184 desc, pmu_name); 185 } 186 fprintf(fp, "%*s", 8, "["); 187 wordwrap(fp, desc_len > 0 ? desc_with_unit : desc, 8, pager_get_columns(), 0); 188 fprintf(fp, "]\n"); 189 free(desc_with_unit); 190 } 191 192 if (print_state->detailed && encoding_desc) { 193 fprintf(fp, "%*s", 8, ""); 194 wordwrap(fp, encoding_desc, 8, pager_get_columns(), 0); 195 fputc('\n', fp); 196 } 197 } 198 199 static void default_print_metric(void *ps, 200 const char *group, 201 const char *name, 202 const char *desc, 203 const char *long_desc, 204 const char *expr, 205 const char *threshold, 206 const char *unit __maybe_unused, 207 const char *pmu_name __maybe_unused) 208 { 209 struct print_state *print_state = ps; 210 FILE *fp = print_state->fp; 211 212 if (print_state->event_glob && 213 (!print_state->metrics || !name || !strglobmatch(name, print_state->event_glob)) && 214 (!print_state->metricgroups || !group || !strglobmatch(group, print_state->event_glob))) 215 return; 216 217 if (!print_state->name_only && !print_state->last_metricgroups) { 218 if (print_state->metricgroups) { 219 fprintf(fp, "\nMetric Groups:\n"); 220 if (!print_state->metrics) 221 fputc('\n', fp); 222 } else { 223 fprintf(fp, "\nMetrics:\n\n"); 224 } 225 } 226 if (!print_state->last_metricgroups || 227 strcmp(print_state->last_metricgroups, group ?: "")) { 228 if (group && print_state->metricgroups) { 229 if (print_state->name_only) { 230 fprintf(fp, "%s ", group); 231 } else { 232 const char *gdesc = print_state->desc 233 ? describe_metricgroup(group) 234 : NULL; 235 const char *print_colon = ""; 236 237 if (print_state->metrics) { 238 print_colon = ":"; 239 fputc('\n', fp); 240 } 241 242 if (gdesc) 243 fprintf(fp, "%s%s [%s]\n", group, print_colon, gdesc); 244 else 245 fprintf(fp, "%s%s\n", group, print_colon); 246 } 247 } 248 zfree(&print_state->last_metricgroups); 249 print_state->last_metricgroups = strdup(group ?: ""); 250 } 251 if (!print_state->metrics) 252 return; 253 254 if (print_state->name_only) { 255 if (print_state->metrics && 256 !strlist__has_entry(print_state->visited_metrics, name)) { 257 fprintf(fp, "%s ", name); 258 strlist__add(print_state->visited_metrics, name); 259 } 260 return; 261 } 262 fprintf(fp, " %s\n", name); 263 264 if (long_desc && print_state->long_desc) { 265 fprintf(fp, "%*s", 8, "["); 266 wordwrap(fp, long_desc, 8, pager_get_columns(), 0); 267 fprintf(fp, "]\n"); 268 } else if (desc && print_state->desc) { 269 fprintf(fp, "%*s", 8, "["); 270 wordwrap(fp, desc, 8, pager_get_columns(), 0); 271 fprintf(fp, "]\n"); 272 } 273 if (expr && print_state->detailed) { 274 fprintf(fp, "%*s", 8, "["); 275 wordwrap(fp, expr, 8, pager_get_columns(), 0); 276 fprintf(fp, "]\n"); 277 } 278 if (threshold && print_state->detailed) { 279 fprintf(fp, "%*s", 8, "["); 280 wordwrap(fp, threshold, 8, pager_get_columns(), 0); 281 fprintf(fp, "]\n"); 282 } 283 } 284 285 struct json_print_state { 286 /** @fp: File to write output to. */ 287 FILE *fp; 288 /** Should a separator be printed prior to the next item? */ 289 bool need_sep; 290 }; 291 292 static void json_print_start(void *ps) 293 { 294 struct json_print_state *print_state = ps; 295 FILE *fp = print_state->fp; 296 297 fprintf(fp, "[\n"); 298 } 299 300 static void json_print_end(void *ps) 301 { 302 struct json_print_state *print_state = ps; 303 FILE *fp = print_state->fp; 304 305 fprintf(fp, "%s]\n", print_state->need_sep ? "\n" : ""); 306 } 307 308 static void fix_escape_fprintf(FILE *fp, struct strbuf *buf, const char *fmt, ...) 309 { 310 va_list args; 311 312 va_start(args, fmt); 313 strbuf_setlen(buf, 0); 314 for (size_t fmt_pos = 0; fmt_pos < strlen(fmt); fmt_pos++) { 315 switch (fmt[fmt_pos]) { 316 case '%': 317 fmt_pos++; 318 switch (fmt[fmt_pos]) { 319 case 's': { 320 const char *s = va_arg(args, const char*); 321 322 strbuf_addstr(buf, s); 323 break; 324 } 325 case 'S': { 326 const char *s = va_arg(args, const char*); 327 328 for (size_t s_pos = 0; s_pos < strlen(s); s_pos++) { 329 switch (s[s_pos]) { 330 case '\n': 331 strbuf_addstr(buf, "\\n"); 332 break; 333 case '\r': 334 strbuf_addstr(buf, "\\r"); 335 break; 336 case '\\': 337 fallthrough; 338 case '\"': 339 strbuf_addch(buf, '\\'); 340 fallthrough; 341 default: 342 strbuf_addch(buf, s[s_pos]); 343 break; 344 } 345 } 346 break; 347 } 348 default: 349 pr_err("Unexpected format character '%c'\n", fmt[fmt_pos]); 350 strbuf_addch(buf, '%'); 351 strbuf_addch(buf, fmt[fmt_pos]); 352 } 353 break; 354 default: 355 strbuf_addch(buf, fmt[fmt_pos]); 356 break; 357 } 358 } 359 va_end(args); 360 fputs(buf->buf, fp); 361 } 362 363 static void json_print_event(void *ps, const char *topic, 364 const char *pmu_name, u32 pmu_type __maybe_unused, 365 const char *event_name, const char *event_alias, 366 const char *scale_unit, 367 bool deprecated, const char *event_type_desc, 368 const char *desc, const char *long_desc, 369 const char *encoding_desc) 370 { 371 struct json_print_state *print_state = ps; 372 bool need_sep = false; 373 FILE *fp = print_state->fp; 374 struct strbuf buf; 375 376 strbuf_init(&buf, 0); 377 fprintf(fp, "%s{\n", print_state->need_sep ? ",\n" : ""); 378 print_state->need_sep = true; 379 if (pmu_name) { 380 fix_escape_fprintf(fp, &buf, "\t\"Unit\": \"%S\"", pmu_name); 381 need_sep = true; 382 } 383 if (topic) { 384 fix_escape_fprintf(fp, &buf, "%s\t\"Topic\": \"%S\"", 385 need_sep ? ",\n" : "", 386 topic); 387 need_sep = true; 388 } 389 if (event_name) { 390 fix_escape_fprintf(fp, &buf, "%s\t\"EventName\": \"%S\"", 391 need_sep ? ",\n" : "", 392 event_name); 393 need_sep = true; 394 } 395 if (event_alias && strlen(event_alias)) { 396 fix_escape_fprintf(fp, &buf, "%s\t\"EventAlias\": \"%S\"", 397 need_sep ? ",\n" : "", 398 event_alias); 399 need_sep = true; 400 } 401 if (scale_unit && strlen(scale_unit)) { 402 fix_escape_fprintf(fp, &buf, "%s\t\"ScaleUnit\": \"%S\"", 403 need_sep ? ",\n" : "", 404 scale_unit); 405 need_sep = true; 406 } 407 if (event_type_desc) { 408 fix_escape_fprintf(fp, &buf, "%s\t\"EventType\": \"%S\"", 409 need_sep ? ",\n" : "", 410 event_type_desc); 411 need_sep = true; 412 } 413 if (deprecated) { 414 fix_escape_fprintf(fp, &buf, "%s\t\"Deprecated\": \"%S\"", 415 need_sep ? ",\n" : "", 416 deprecated ? "1" : "0"); 417 need_sep = true; 418 } 419 if (desc) { 420 fix_escape_fprintf(fp, &buf, "%s\t\"BriefDescription\": \"%S\"", 421 need_sep ? ",\n" : "", 422 desc); 423 need_sep = true; 424 } 425 if (long_desc) { 426 fix_escape_fprintf(fp, &buf, "%s\t\"PublicDescription\": \"%S\"", 427 need_sep ? ",\n" : "", 428 long_desc); 429 need_sep = true; 430 } 431 if (encoding_desc) { 432 fix_escape_fprintf(fp, &buf, "%s\t\"Encoding\": \"%S\"", 433 need_sep ? ",\n" : "", 434 encoding_desc); 435 need_sep = true; 436 } 437 fprintf(fp, "%s}", need_sep ? "\n" : ""); 438 strbuf_release(&buf); 439 } 440 441 static void json_print_metric(void *ps __maybe_unused, const char *group, 442 const char *name, const char *desc, 443 const char *long_desc, const char *expr, 444 const char *threshold, const char *unit, 445 const char *pmu_name) 446 { 447 struct json_print_state *print_state = ps; 448 bool need_sep = false; 449 FILE *fp = print_state->fp; 450 struct strbuf buf; 451 452 strbuf_init(&buf, 0); 453 fprintf(fp, "%s{\n", print_state->need_sep ? ",\n" : ""); 454 print_state->need_sep = true; 455 if (group) { 456 fix_escape_fprintf(fp, &buf, "\t\"MetricGroup\": \"%S\"", group); 457 need_sep = true; 458 } 459 if (name) { 460 fix_escape_fprintf(fp, &buf, "%s\t\"MetricName\": \"%S\"", 461 need_sep ? ",\n" : "", 462 name); 463 need_sep = true; 464 } 465 if (expr) { 466 fix_escape_fprintf(fp, &buf, "%s\t\"MetricExpr\": \"%S\"", 467 need_sep ? ",\n" : "", 468 expr); 469 need_sep = true; 470 } 471 if (threshold) { 472 fix_escape_fprintf(fp, &buf, "%s\t\"MetricThreshold\": \"%S\"", 473 need_sep ? ",\n" : "", 474 threshold); 475 need_sep = true; 476 } 477 if (unit) { 478 fix_escape_fprintf(fp, &buf, "%s\t\"ScaleUnit\": \"%S\"", 479 need_sep ? ",\n" : "", 480 unit); 481 need_sep = true; 482 } 483 if (desc) { 484 fix_escape_fprintf(fp, &buf, "%s\t\"BriefDescription\": \"%S\"", 485 need_sep ? ",\n" : "", 486 desc); 487 need_sep = true; 488 } 489 if (long_desc) { 490 fix_escape_fprintf(fp, &buf, "%s\t\"PublicDescription\": \"%S\"", 491 need_sep ? ",\n" : "", 492 long_desc); 493 need_sep = true; 494 } 495 if (pmu_name) { 496 fix_escape_fprintf(fp, &buf, "%s\t\"Unit\": \"%S\"", 497 need_sep ? ",\n" : "", 498 pmu_name); 499 need_sep = true; 500 } 501 fprintf(fp, "%s}", need_sep ? "\n" : ""); 502 strbuf_release(&buf); 503 } 504 505 static bool json_skip_duplicate_pmus(void *ps __maybe_unused) 506 { 507 return false; 508 } 509 510 static bool default_skip_duplicate_pmus(void *ps) 511 { 512 struct print_state *print_state = ps; 513 514 return !print_state->long_desc; 515 } 516 517 int cmd_list(int argc, const char **argv) 518 { 519 int i, ret = 0; 520 struct print_state default_ps = { 521 .fp = stdout, 522 .desc = true, 523 }; 524 struct print_state json_ps = { 525 .fp = stdout, 526 }; 527 void *ps = &default_ps; 528 struct print_callbacks print_cb = { 529 .print_start = default_print_start, 530 .print_end = default_print_end, 531 .print_event = default_print_event, 532 .print_metric = default_print_metric, 533 .skip_duplicate_pmus = default_skip_duplicate_pmus, 534 }; 535 const char *cputype = NULL; 536 const char *unit_name = NULL; 537 const char *output_path = NULL; 538 bool json = false; 539 struct option list_options[] = { 540 OPT_BOOLEAN(0, "raw-dump", &default_ps.name_only, "Dump raw events"), 541 OPT_BOOLEAN('j', "json", &json, "JSON encode events and metrics"), 542 OPT_BOOLEAN('d', "desc", &default_ps.desc, 543 "Print extra event descriptions. --no-desc to not print."), 544 OPT_BOOLEAN('v', "long-desc", &default_ps.long_desc, 545 "Print longer event descriptions and all similar PMUs with alphanumeric suffixes."), 546 OPT_BOOLEAN(0, "details", &default_ps.detailed, 547 "Print information on the perf event names and expressions used internally by events."), 548 OPT_STRING('o', "output", &output_path, "file", "output file name"), 549 OPT_BOOLEAN(0, "deprecated", &default_ps.deprecated, 550 "Print deprecated events."), 551 OPT_STRING(0, "cputype", &cputype, "cpu type", 552 "Limit PMU or metric printing to the given PMU (e.g. cpu, core or atom)."), 553 OPT_STRING(0, "unit", &unit_name, "PMU name", 554 "Limit PMU or metric printing to the specified PMU."), 555 OPT_INCR(0, "debug", &verbose, 556 "Enable debugging output"), 557 OPT_END() 558 }; 559 const char * const list_usage[] = { 560 #ifdef HAVE_LIBPFM 561 "perf list [<options>] [hw|sw|cache|tracepoint|pmu|sdt|metric|metricgroup|event_glob|pfm]", 562 #else 563 "perf list [<options>] [hw|sw|cache|tracepoint|pmu|sdt|metric|metricgroup|event_glob]", 564 #endif 565 NULL 566 }; 567 568 set_option_flag(list_options, 0, "raw-dump", PARSE_OPT_HIDDEN); 569 /* Hide hybrid flag for the more generic 'unit' flag. */ 570 set_option_flag(list_options, 0, "cputype", PARSE_OPT_HIDDEN); 571 572 argc = parse_options(argc, argv, list_options, list_usage, 573 PARSE_OPT_STOP_AT_NON_OPTION); 574 575 if (output_path) { 576 default_ps.fp = fopen(output_path, "w"); 577 json_ps.fp = default_ps.fp; 578 } 579 580 setup_pager(); 581 582 if (!default_ps.name_only) 583 setup_pager(); 584 585 if (json) { 586 print_cb = (struct print_callbacks){ 587 .print_start = json_print_start, 588 .print_end = json_print_end, 589 .print_event = json_print_event, 590 .print_metric = json_print_metric, 591 .skip_duplicate_pmus = json_skip_duplicate_pmus, 592 }; 593 ps = &json_ps; 594 } else { 595 default_ps.last_topic = strdup(""); 596 assert(default_ps.last_topic); 597 default_ps.visited_metrics = strlist__new(NULL, NULL); 598 assert(default_ps.visited_metrics); 599 if (unit_name) 600 default_ps.pmu_glob = strdup(unit_name); 601 else if (cputype) { 602 const struct perf_pmu *pmu = perf_pmus__pmu_for_pmu_filter(cputype); 603 604 if (!pmu) { 605 pr_err("ERROR: cputype is not supported!\n"); 606 ret = -1; 607 goto out; 608 } 609 default_ps.pmu_glob = strdup(pmu->name); 610 } 611 } 612 print_cb.print_start(ps); 613 614 if (argc == 0) { 615 default_ps.metrics = true; 616 default_ps.metricgroups = true; 617 print_events(&print_cb, ps); 618 goto out; 619 } 620 621 for (i = 0; i < argc; ++i) { 622 char *sep, *s; 623 624 if (strcmp(argv[i], "tracepoint") == 0) { 625 char *old_pmu_glob = default_ps.pmu_glob; 626 627 default_ps.pmu_glob = strdup("tracepoint"); 628 if (!default_ps.pmu_glob) { 629 ret = -1; 630 goto out; 631 } 632 perf_pmus__print_pmu_events(&print_cb, ps); 633 zfree(&default_ps.pmu_glob); 634 default_ps.pmu_glob = old_pmu_glob; 635 } else if (strcmp(argv[i], "hw") == 0 || 636 strcmp(argv[i], "hardware") == 0) 637 print_symbol_events(&print_cb, ps, PERF_TYPE_HARDWARE, 638 event_symbols_hw, PERF_COUNT_HW_MAX); 639 else if (strcmp(argv[i], "sw") == 0 || 640 strcmp(argv[i], "software") == 0) { 641 char *old_pmu_glob = default_ps.pmu_glob; 642 static const char * const sw_globs[] = { "software", "tool" }; 643 644 for (size_t j = 0; j < ARRAY_SIZE(sw_globs); j++) { 645 default_ps.pmu_glob = strdup(sw_globs[j]); 646 if (!default_ps.pmu_glob) { 647 ret = -1; 648 goto out; 649 } 650 perf_pmus__print_pmu_events(&print_cb, ps); 651 zfree(&default_ps.pmu_glob); 652 } 653 default_ps.pmu_glob = old_pmu_glob; 654 } else if (strcmp(argv[i], "cache") == 0 || 655 strcmp(argv[i], "hwcache") == 0) 656 print_hwcache_events(&print_cb, ps); 657 else if (strcmp(argv[i], "pmu") == 0) { 658 default_ps.exclude_abi = true; 659 perf_pmus__print_pmu_events(&print_cb, ps); 660 default_ps.exclude_abi = false; 661 } else if (strcmp(argv[i], "sdt") == 0) 662 print_sdt_events(&print_cb, ps); 663 else if (strcmp(argv[i], "metric") == 0 || strcmp(argv[i], "metrics") == 0) { 664 default_ps.metricgroups = false; 665 default_ps.metrics = true; 666 metricgroup__print(&print_cb, ps); 667 } else if (strcmp(argv[i], "metricgroup") == 0 || 668 strcmp(argv[i], "metricgroups") == 0) { 669 default_ps.metricgroups = true; 670 default_ps.metrics = false; 671 metricgroup__print(&print_cb, ps); 672 } 673 #ifdef HAVE_LIBPFM 674 else if (strcmp(argv[i], "pfm") == 0) 675 print_libpfm_events(&print_cb, ps); 676 #endif 677 else if ((sep = strchr(argv[i], ':')) != NULL) { 678 char *old_pmu_glob = default_ps.pmu_glob; 679 char *old_event_glob = default_ps.event_glob; 680 681 default_ps.event_glob = strdup(argv[i]); 682 if (!default_ps.event_glob) { 683 ret = -1; 684 goto out; 685 } 686 687 default_ps.pmu_glob = strdup("tracepoint"); 688 if (!default_ps.pmu_glob) { 689 zfree(&default_ps.event_glob); 690 ret = -1; 691 goto out; 692 } 693 perf_pmus__print_pmu_events(&print_cb, ps); 694 zfree(&default_ps.pmu_glob); 695 default_ps.pmu_glob = old_pmu_glob; 696 print_sdt_events(&print_cb, ps); 697 default_ps.metrics = true; 698 default_ps.metricgroups = true; 699 metricgroup__print(&print_cb, ps); 700 zfree(&default_ps.event_glob); 701 default_ps.event_glob = old_event_glob; 702 } else { 703 if (asprintf(&s, "*%s*", argv[i]) < 0) { 704 printf("Critical: Not enough memory! Trying to continue...\n"); 705 continue; 706 } 707 default_ps.event_glob = s; 708 print_symbol_events(&print_cb, ps, PERF_TYPE_HARDWARE, 709 event_symbols_hw, PERF_COUNT_HW_MAX); 710 print_hwcache_events(&print_cb, ps); 711 perf_pmus__print_pmu_events(&print_cb, ps); 712 print_sdt_events(&print_cb, ps); 713 default_ps.metrics = true; 714 default_ps.metricgroups = true; 715 metricgroup__print(&print_cb, ps); 716 free(s); 717 } 718 } 719 720 out: 721 print_cb.print_end(ps); 722 free(default_ps.pmu_glob); 723 free(default_ps.last_topic); 724 free(default_ps.last_metricgroups); 725 strlist__delete(default_ps.visited_metrics); 726 if (output_path) 727 fclose(default_ps.fp); 728 729 return ret; 730 } 731