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