From: Arnaldo Carvalho de Melo <acme@kernel.org>
To: Ian Rogers <irogers@google.com>
Cc: Peter Zijlstra <peterz@infradead.org>,
Ingo Molnar <mingo@redhat.com>,
Mark Rutland <mark.rutland@arm.com>,
Alexander Shishkin <alexander.shishkin@linux.intel.com>,
Jiri Olsa <jolsa@redhat.com>, Namhyung Kim <namhyung@kernel.org>,
linux-kernel@vger.kernel.org,
Stephane Eranian <eranian@google.com>
Subject: Re: [PATCH 2/2] perf parse-events: Break out tracepoint and printing.
Date: Wed, 3 Feb 2021 13:20:58 -0300 [thread overview]
Message-ID: <20210203162058.GE854763@kernel.org> (raw)
In-Reply-To: <20210203052659.2975736-2-irogers@google.com>
Em Tue, Feb 02, 2021 at 09:26:59PM -0800, Ian Rogers escreveu:
> Move print_*_events functions out of parse-events.c into a new
> print-events.c. Move tracepoint code into tracepoint.c or
> trace-event-info.c (sole user). This reduces the dependencies of
> parse-events.c and makes it more amenable to being a library in the
> future.
> Remove some unnecessary definitions from parse-events.h. Fix a
> checkpatch.pl warning on using unsigned rather than unsigned int.
Thanks, applied.
- Arnaldo
> Signed-off-by: Ian Rogers <irogers@google.com>
> ---
> tools/perf/builtin-list.c | 2 +-
> tools/perf/builtin-lock.c | 1 +
> tools/perf/builtin-timechart.c | 1 +
> tools/perf/builtin-trace.c | 1 +
> tools/perf/util/Build | 2 +
> tools/perf/util/parse-events.c | 620 +----------------------------
> tools/perf/util/parse-events.h | 29 --
> tools/perf/util/print-events.c | 472 ++++++++++++++++++++++
> tools/perf/util/print-events.h | 21 +
> tools/perf/util/trace-event-info.c | 94 +++++
> tools/perf/util/tracepoint.c | 63 +++
> tools/perf/util/tracepoint.h | 25 ++
> 12 files changed, 687 insertions(+), 644 deletions(-)
> create mode 100644 tools/perf/util/print-events.c
> create mode 100644 tools/perf/util/print-events.h
> create mode 100644 tools/perf/util/tracepoint.c
> create mode 100644 tools/perf/util/tracepoint.h
>
> diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c
> index 10ab5e40a34f..91327a321c36 100644
> --- a/tools/perf/builtin-list.c
> +++ b/tools/perf/builtin-list.c
> @@ -10,7 +10,7 @@
> */
> #include "builtin.h"
>
> -#include "util/parse-events.h"
> +#include "util/print-events.h"
> #include "util/pmu.h"
> #include "util/debug.h"
> #include "util/metricgroup.h"
> diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
> index a2f1e53f37a7..486123cb106e 100644
> --- a/tools/perf/builtin-lock.c
> +++ b/tools/perf/builtin-lock.c
> @@ -13,6 +13,7 @@
> #include <subcmd/pager.h>
> #include <subcmd/parse-options.h>
> #include "util/trace-event.h"
> +#include "util/tracepoint.h"
>
> #include "util/debug.h"
> #include "util/session.h"
> diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
> index 4e380e7b5230..cdebcf26f408 100644
> --- a/tools/perf/builtin-timechart.c
> +++ b/tools/perf/builtin-timechart.c
> @@ -35,6 +35,7 @@
> #include "util/tool.h"
> #include "util/data.h"
> #include "util/debug.h"
> +#include "util/tracepoint.h"
> #include <linux/err.h>
>
> #ifdef LACKS_OPEN_MEMSTREAM_PROTOTYPE
> diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
> index 85b6a46e85b6..b3b9fa1c7731 100644
> --- a/tools/perf/builtin-trace.c
> +++ b/tools/perf/builtin-trace.c
> @@ -53,6 +53,7 @@
> #include "trace-event.h"
> #include "util/parse-events.h"
> #include "util/bpf-loader.h"
> +#include "util/tracepoint.h"
> #include "callchain.h"
> #include "print_binary.h"
> #include "string2.h"
> diff --git a/tools/perf/util/Build b/tools/perf/util/Build
> index 188521f34347..c2c9f3f490e8 100644
> --- a/tools/perf/util/Build
> +++ b/tools/perf/util/Build
> @@ -23,6 +23,8 @@ perf-y += llvm-utils.o
> perf-y += mmap.o
> perf-y += memswap.o
> perf-y += parse-events.o
> +perf-y += print-events.o
> +perf-y += tracepoint.o
> perf-y += perf_regs.o
> perf-y += path.o
> perf-y += print_binary.o
> diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
> index 42c84adeb2fb..5d5ebb700ef2 100644
> --- a/tools/perf/util/parse-events.c
> +++ b/tools/perf/util/parse-events.c
> @@ -5,42 +5,34 @@
> #include <dirent.h>
> #include <errno.h>
> #include <sys/ioctl.h>
> -#include <sys/types.h>
> -#include <sys/stat.h>
> -#include <fcntl.h>
> #include <sys/param.h>
> #include "term.h"
> -#include "build-id.h"
> #include "evlist.h"
> #include "evsel.h"
> -#include <subcmd/pager.h>
> #include <subcmd/parse-options.h>
> #include "parse-events.h"
> -#include <subcmd/exec-cmd.h>
> #include "string2.h"
> -#include "strlist.h"
> -#include "symbol.h"
> -#include "header.h"
> #include "bpf-loader.h"
> #include "debug.h"
> #include <api/fs/tracing_path.h>
> #include <perf/cpumap.h>
> #include "parse-events-bison.h"
> -#define YY_EXTRA_TYPE void*
> #include "parse-events-flex.h"
> #include "pmu.h"
> -#include "thread_map.h"
> -#include "probe-file.h"
> #include "asm/bug.h"
> #include "util/parse-branch-options.h"
> -#include "metricgroup.h"
> #include "util/evsel_config.h"
> #include "util/event.h"
> -#include "util/pfm.h"
> #include "perf.h"
> +#include "tracepoint.h"
>
> #define MAX_NAME_LEN 100
>
> +struct perf_pmu_event_symbol {
> + char *symbol;
> + enum perf_pmu_event_symbol_type type;
> +};
> +
> #ifdef PARSER_DEBUG
> extern int parse_events_debug;
> #endif
> @@ -155,35 +147,6 @@ struct event_symbol event_symbols_sw[PERF_COUNT_SW_MAX] = {
> #define PERF_EVENT_TYPE(config) __PERF_EVENT_FIELD(config, TYPE)
> #define PERF_EVENT_ID(config) __PERF_EVENT_FIELD(config, EVENT)
>
> -#define for_each_subsystem(sys_dir, sys_dirent) \
> - while ((sys_dirent = readdir(sys_dir)) != NULL) \
> - if (sys_dirent->d_type == DT_DIR && \
> - (strcmp(sys_dirent->d_name, ".")) && \
> - (strcmp(sys_dirent->d_name, "..")))
> -
> -static int tp_event_has_id(const char *dir_path, struct dirent *evt_dir)
> -{
> - char evt_path[MAXPATHLEN];
> - int fd;
> -
> - snprintf(evt_path, MAXPATHLEN, "%s/%s/id", dir_path, evt_dir->d_name);
> - fd = open(evt_path, O_RDONLY);
> - if (fd < 0)
> - return -EINVAL;
> - close(fd);
> -
> - return 0;
> -}
> -
> -#define for_each_event(dir_path, evt_dir, evt_dirent) \
> - while ((evt_dirent = readdir(evt_dir)) != NULL) \
> - if (evt_dirent->d_type == DT_DIR && \
> - (strcmp(evt_dirent->d_name, ".")) && \
> - (strcmp(evt_dirent->d_name, "..")) && \
> - (!tp_event_has_id(dir_path, evt_dirent)))
> -
> -#define MAX_EVENT_LENGTH 512
> -
> void parse_events__handle_error(struct parse_events_error *err, int idx,
> char *str, char *help)
> {
> @@ -217,92 +180,6 @@ void parse_events__handle_error(struct parse_events_error *err, int idx,
> err->num_errors++;
> }
>
> -struct tracepoint_path *tracepoint_id_to_path(u64 config)
> -{
> - struct tracepoint_path *path = NULL;
> - DIR *sys_dir, *evt_dir;
> - struct dirent *sys_dirent, *evt_dirent;
> - char id_buf[24];
> - int fd;
> - u64 id;
> - char evt_path[MAXPATHLEN];
> - char *dir_path;
> -
> - sys_dir = tracing_events__opendir();
> - if (!sys_dir)
> - return NULL;
> -
> - for_each_subsystem(sys_dir, sys_dirent) {
> - dir_path = get_events_file(sys_dirent->d_name);
> - if (!dir_path)
> - continue;
> - evt_dir = opendir(dir_path);
> - if (!evt_dir)
> - goto next;
> -
> - for_each_event(dir_path, evt_dir, evt_dirent) {
> -
> - scnprintf(evt_path, MAXPATHLEN, "%s/%s/id", dir_path,
> - evt_dirent->d_name);
> - fd = open(evt_path, O_RDONLY);
> - if (fd < 0)
> - continue;
> - if (read(fd, id_buf, sizeof(id_buf)) < 0) {
> - close(fd);
> - continue;
> - }
> - close(fd);
> - id = atoll(id_buf);
> - if (id == config) {
> - put_events_file(dir_path);
> - closedir(evt_dir);
> - closedir(sys_dir);
> - path = zalloc(sizeof(*path));
> - if (!path)
> - return NULL;
> - if (asprintf(&path->system, "%.*s", MAX_EVENT_LENGTH, sys_dirent->d_name) < 0) {
> - free(path);
> - return NULL;
> - }
> - if (asprintf(&path->name, "%.*s", MAX_EVENT_LENGTH, evt_dirent->d_name) < 0) {
> - zfree(&path->system);
> - free(path);
> - return NULL;
> - }
> - return path;
> - }
> - }
> - closedir(evt_dir);
> -next:
> - put_events_file(dir_path);
> - }
> -
> - closedir(sys_dir);
> - return NULL;
> -}
> -
> -struct tracepoint_path *tracepoint_name_to_path(const char *name)
> -{
> - struct tracepoint_path *path = zalloc(sizeof(*path));
> - char *str = strchr(name, ':');
> -
> - if (path == NULL || str == NULL) {
> - free(path);
> - return NULL;
> - }
> -
> - path->system = strndup(name, str - name);
> - path->name = strdup(str+1);
> -
> - if (path->system == NULL || path->name == NULL) {
> - zfree(&path->system);
> - zfree(&path->name);
> - zfree(&path);
> - }
> -
> - return path;
> -}
> -
> const char *event_type(int type)
> {
> switch (type) {
> @@ -2451,491 +2328,6 @@ int exclude_perf(const struct option *opt,
> NULL);
> }
>
> -static const char * const event_type_descriptors[] = {
> - "Hardware event",
> - "Software event",
> - "Tracepoint event",
> - "Hardware cache event",
> - "Raw hardware event descriptor",
> - "Hardware breakpoint",
> -};
> -
> -static int cmp_string(const void *a, const void *b)
> -{
> - const char * const *as = a;
> - const char * const *bs = b;
> -
> - return strcmp(*as, *bs);
> -}
> -
> -/*
> - * Print the events from <debugfs_mount_point>/tracing/events
> - */
> -
> -void print_tracepoint_events(const char *subsys_glob, const char *event_glob,
> - bool name_only)
> -{
> - DIR *sys_dir, *evt_dir;
> - struct dirent *sys_dirent, *evt_dirent;
> - char evt_path[MAXPATHLEN];
> - char *dir_path;
> - char **evt_list = NULL;
> - unsigned int evt_i = 0, evt_num = 0;
> - bool evt_num_known = false;
> -
> -restart:
> - sys_dir = tracing_events__opendir();
> - if (!sys_dir)
> - return;
> -
> - if (evt_num_known) {
> - evt_list = zalloc(sizeof(char *) * evt_num);
> - if (!evt_list)
> - goto out_close_sys_dir;
> - }
> -
> - for_each_subsystem(sys_dir, sys_dirent) {
> - if (subsys_glob != NULL &&
> - !strglobmatch(sys_dirent->d_name, subsys_glob))
> - continue;
> -
> - dir_path = get_events_file(sys_dirent->d_name);
> - if (!dir_path)
> - continue;
> - evt_dir = opendir(dir_path);
> - if (!evt_dir)
> - goto next;
> -
> - for_each_event(dir_path, evt_dir, evt_dirent) {
> - if (event_glob != NULL &&
> - !strglobmatch(evt_dirent->d_name, event_glob))
> - continue;
> -
> - if (!evt_num_known) {
> - evt_num++;
> - continue;
> - }
> -
> - snprintf(evt_path, MAXPATHLEN, "%s:%s",
> - sys_dirent->d_name, evt_dirent->d_name);
> -
> - evt_list[evt_i] = strdup(evt_path);
> - if (evt_list[evt_i] == NULL) {
> - put_events_file(dir_path);
> - goto out_close_evt_dir;
> - }
> - evt_i++;
> - }
> - closedir(evt_dir);
> -next:
> - put_events_file(dir_path);
> - }
> - closedir(sys_dir);
> -
> - if (!evt_num_known) {
> - evt_num_known = true;
> - goto restart;
> - }
> - qsort(evt_list, evt_num, sizeof(char *), cmp_string);
> - evt_i = 0;
> - while (evt_i < evt_num) {
> - if (name_only) {
> - printf("%s ", evt_list[evt_i++]);
> - continue;
> - }
> - printf(" %-50s [%s]\n", evt_list[evt_i++],
> - event_type_descriptors[PERF_TYPE_TRACEPOINT]);
> - }
> - if (evt_num && pager_in_use())
> - printf("\n");
> -
> -out_free:
> - evt_num = evt_i;
> - for (evt_i = 0; evt_i < evt_num; evt_i++)
> - zfree(&evt_list[evt_i]);
> - zfree(&evt_list);
> - return;
> -
> -out_close_evt_dir:
> - closedir(evt_dir);
> -out_close_sys_dir:
> - closedir(sys_dir);
> -
> - printf("FATAL: not enough memory to print %s\n",
> - event_type_descriptors[PERF_TYPE_TRACEPOINT]);
> - if (evt_list)
> - goto out_free;
> -}
> -
> -/*
> - * Check whether event is in <debugfs_mount_point>/tracing/events
> - */
> -
> -int is_valid_tracepoint(const char *event_string)
> -{
> - DIR *sys_dir, *evt_dir;
> - struct dirent *sys_dirent, *evt_dirent;
> - char evt_path[MAXPATHLEN];
> - char *dir_path;
> -
> - sys_dir = tracing_events__opendir();
> - if (!sys_dir)
> - return 0;
> -
> - for_each_subsystem(sys_dir, sys_dirent) {
> - dir_path = get_events_file(sys_dirent->d_name);
> - if (!dir_path)
> - continue;
> - evt_dir = opendir(dir_path);
> - if (!evt_dir)
> - goto next;
> -
> - for_each_event(dir_path, evt_dir, evt_dirent) {
> - snprintf(evt_path, MAXPATHLEN, "%s:%s",
> - sys_dirent->d_name, evt_dirent->d_name);
> - if (!strcmp(evt_path, event_string)) {
> - closedir(evt_dir);
> - closedir(sys_dir);
> - return 1;
> - }
> - }
> - closedir(evt_dir);
> -next:
> - put_events_file(dir_path);
> - }
> - closedir(sys_dir);
> - return 0;
> -}
> -
> -static bool is_event_supported(u8 type, unsigned config)
> -{
> - bool ret = true;
> - int open_return;
> - struct evsel *evsel;
> - struct perf_event_attr attr = {
> - .type = type,
> - .config = config,
> - .disabled = 1,
> - };
> - struct perf_thread_map *tmap = thread_map__new_by_tid(0);
> -
> - if (tmap == NULL)
> - return false;
> -
> - evsel = evsel__new(&attr);
> - if (evsel) {
> - open_return = evsel__open(evsel, NULL, tmap);
> - ret = open_return >= 0;
> -
> - if (open_return == -EACCES) {
> - /*
> - * This happens if the paranoid value
> - * /proc/sys/kernel/perf_event_paranoid is set to 2
> - * Re-run with exclude_kernel set; we don't do that
> - * by default as some ARM machines do not support it.
> - *
> - */
> - evsel->core.attr.exclude_kernel = 1;
> - ret = evsel__open(evsel, NULL, tmap) >= 0;
> - }
> - evsel__delete(evsel);
> - }
> -
> - perf_thread_map__put(tmap);
> - return ret;
> -}
> -
> -void print_sdt_events(const char *subsys_glob, const char *event_glob,
> - bool name_only)
> -{
> - struct probe_cache *pcache;
> - struct probe_cache_entry *ent;
> - struct strlist *bidlist, *sdtlist;
> - struct strlist_config cfg = {.dont_dupstr = true};
> - struct str_node *nd, *nd2;
> - char *buf, *path, *ptr = NULL;
> - bool show_detail = false;
> - int ret;
> -
> - sdtlist = strlist__new(NULL, &cfg);
> - if (!sdtlist) {
> - pr_debug("Failed to allocate new strlist for SDT\n");
> - return;
> - }
> - bidlist = build_id_cache__list_all(true);
> - if (!bidlist) {
> - pr_debug("Failed to get buildids: %d\n", errno);
> - return;
> - }
> - strlist__for_each_entry(nd, bidlist) {
> - pcache = probe_cache__new(nd->s, NULL);
> - if (!pcache)
> - continue;
> - list_for_each_entry(ent, &pcache->entries, node) {
> - if (!ent->sdt)
> - continue;
> - if (subsys_glob &&
> - !strglobmatch(ent->pev.group, subsys_glob))
> - continue;
> - if (event_glob &&
> - !strglobmatch(ent->pev.event, event_glob))
> - continue;
> - ret = asprintf(&buf, "%s:%s@%s", ent->pev.group,
> - ent->pev.event, nd->s);
> - if (ret > 0)
> - strlist__add(sdtlist, buf);
> - }
> - probe_cache__delete(pcache);
> - }
> - strlist__delete(bidlist);
> -
> - strlist__for_each_entry(nd, sdtlist) {
> - buf = strchr(nd->s, '@');
> - if (buf)
> - *(buf++) = '\0';
> - if (name_only) {
> - printf("%s ", nd->s);
> - continue;
> - }
> - nd2 = strlist__next(nd);
> - if (nd2) {
> - ptr = strchr(nd2->s, '@');
> - if (ptr)
> - *ptr = '\0';
> - if (strcmp(nd->s, nd2->s) == 0)
> - show_detail = true;
> - }
> - if (show_detail) {
> - path = build_id_cache__origname(buf);
> - ret = asprintf(&buf, "%s@%s(%.12s)", nd->s, path, buf);
> - if (ret > 0) {
> - printf(" %-50s [%s]\n", buf, "SDT event");
> - free(buf);
> - }
> - free(path);
> - } else
> - printf(" %-50s [%s]\n", nd->s, "SDT event");
> - if (nd2) {
> - if (strcmp(nd->s, nd2->s) != 0)
> - show_detail = false;
> - if (ptr)
> - *ptr = '@';
> - }
> - }
> - strlist__delete(sdtlist);
> -}
> -
> -int print_hwcache_events(const char *event_glob, bool name_only)
> -{
> - unsigned int type, op, i, evt_i = 0, evt_num = 0;
> - char name[64];
> - char **evt_list = NULL;
> - bool evt_num_known = false;
> -
> -restart:
> - if (evt_num_known) {
> - evt_list = zalloc(sizeof(char *) * evt_num);
> - if (!evt_list)
> - goto out_enomem;
> - }
> -
> - for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
> - for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
> - /* skip invalid cache type */
> - if (!evsel__is_cache_op_valid(type, op))
> - continue;
> -
> - for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
> - __evsel__hw_cache_type_op_res_name(type, op, i, name, sizeof(name));
> - if (event_glob != NULL && !strglobmatch(name, event_glob))
> - continue;
> -
> - if (!is_event_supported(PERF_TYPE_HW_CACHE,
> - type | (op << 8) | (i << 16)))
> - continue;
> -
> - if (!evt_num_known) {
> - evt_num++;
> - continue;
> - }
> -
> - evt_list[evt_i] = strdup(name);
> - if (evt_list[evt_i] == NULL)
> - goto out_enomem;
> - evt_i++;
> - }
> - }
> - }
> -
> - if (!evt_num_known) {
> - evt_num_known = true;
> - goto restart;
> - }
> - qsort(evt_list, evt_num, sizeof(char *), cmp_string);
> - evt_i = 0;
> - while (evt_i < evt_num) {
> - if (name_only) {
> - printf("%s ", evt_list[evt_i++]);
> - continue;
> - }
> - printf(" %-50s [%s]\n", evt_list[evt_i++],
> - event_type_descriptors[PERF_TYPE_HW_CACHE]);
> - }
> - if (evt_num && pager_in_use())
> - printf("\n");
> -
> -out_free:
> - evt_num = evt_i;
> - for (evt_i = 0; evt_i < evt_num; evt_i++)
> - zfree(&evt_list[evt_i]);
> - zfree(&evt_list);
> - return evt_num;
> -
> -out_enomem:
> - printf("FATAL: not enough memory to print %s\n", event_type_descriptors[PERF_TYPE_HW_CACHE]);
> - if (evt_list)
> - goto out_free;
> - return evt_num;
> -}
> -
> -static void print_tool_event(const char *name, const char *event_glob,
> - bool name_only)
> -{
> - if (event_glob && !strglobmatch(name, event_glob))
> - return;
> - if (name_only)
> - printf("%s ", name);
> - else
> - printf(" %-50s [%s]\n", name, "Tool event");
> -
> -}
> -
> -void print_tool_events(const char *event_glob, bool name_only)
> -{
> - print_tool_event("duration_time", event_glob, name_only);
> - if (pager_in_use())
> - printf("\n");
> -}
> -
> -void print_symbol_events(const char *event_glob, unsigned type,
> - struct event_symbol *syms, unsigned max,
> - bool name_only)
> -{
> - unsigned int i, evt_i = 0, evt_num = 0;
> - char name[MAX_NAME_LEN];
> - char **evt_list = NULL;
> - bool evt_num_known = false;
> -
> -restart:
> - if (evt_num_known) {
> - evt_list = zalloc(sizeof(char *) * evt_num);
> - if (!evt_list)
> - goto out_enomem;
> - syms -= max;
> - }
> -
> - for (i = 0; i < max; i++, syms++) {
> -
> - if (event_glob != NULL && syms->symbol != NULL &&
> - !(strglobmatch(syms->symbol, event_glob) ||
> - (syms->alias && strglobmatch(syms->alias, event_glob))))
> - continue;
> -
> - if (!is_event_supported(type, i))
> - continue;
> -
> - if (!evt_num_known) {
> - evt_num++;
> - continue;
> - }
> -
> - if (!name_only && strlen(syms->alias))
> - snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias);
> - else
> - strlcpy(name, syms->symbol, MAX_NAME_LEN);
> -
> - evt_list[evt_i] = strdup(name);
> - if (evt_list[evt_i] == NULL)
> - goto out_enomem;
> - evt_i++;
> - }
> -
> - if (!evt_num_known) {
> - evt_num_known = true;
> - goto restart;
> - }
> - qsort(evt_list, evt_num, sizeof(char *), cmp_string);
> - evt_i = 0;
> - while (evt_i < evt_num) {
> - if (name_only) {
> - printf("%s ", evt_list[evt_i++]);
> - continue;
> - }
> - printf(" %-50s [%s]\n", evt_list[evt_i++], event_type_descriptors[type]);
> - }
> - if (evt_num && pager_in_use())
> - printf("\n");
> -
> -out_free:
> - evt_num = evt_i;
> - for (evt_i = 0; evt_i < evt_num; evt_i++)
> - zfree(&evt_list[evt_i]);
> - zfree(&evt_list);
> - return;
> -
> -out_enomem:
> - printf("FATAL: not enough memory to print %s\n", event_type_descriptors[type]);
> - if (evt_list)
> - goto out_free;
> -}
> -
> -/*
> - * Print the help text for the event symbols:
> - */
> -void print_events(const char *event_glob, bool name_only, bool quiet_flag,
> - bool long_desc, bool details_flag, bool deprecated)
> -{
> - print_symbol_events(event_glob, PERF_TYPE_HARDWARE,
> - event_symbols_hw, PERF_COUNT_HW_MAX, name_only);
> -
> - print_symbol_events(event_glob, PERF_TYPE_SOFTWARE,
> - event_symbols_sw, PERF_COUNT_SW_MAX, name_only);
> - print_tool_events(event_glob, name_only);
> -
> - print_hwcache_events(event_glob, name_only);
> -
> - print_pmu_events(event_glob, name_only, quiet_flag, long_desc,
> - details_flag, deprecated);
> -
> - if (event_glob != NULL)
> - return;
> -
> - if (!name_only) {
> - printf(" %-50s [%s]\n",
> - "rNNN",
> - event_type_descriptors[PERF_TYPE_RAW]);
> - printf(" %-50s [%s]\n",
> - "cpu/t1=v1[,t2=v2,t3 ...]/modifier",
> - event_type_descriptors[PERF_TYPE_RAW]);
> - if (pager_in_use())
> - printf(" (see 'man perf-list' on how to encode it)\n\n");
> -
> - printf(" %-50s [%s]\n",
> - "mem:<addr>[/len][:access]",
> - event_type_descriptors[PERF_TYPE_BREAKPOINT]);
> - if (pager_in_use())
> - printf("\n");
> - }
> -
> - print_tracepoint_events(NULL, NULL, name_only);
> -
> - print_sdt_events(NULL, NULL, name_only);
> -
> - metricgroup__print(true, true, NULL, name_only, details_flag);
> -
> - print_libpfm_events(name_only, long_desc);
> -}
> -
> int parse_events__is_hardcoded_term(struct parse_events_term *term)
> {
> return term->type_term != PARSE_EVENTS__TERM_TYPE_USER;
> diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
> index e80c9b74f2f2..7cea425e80f9 100644
> --- a/tools/perf/util/parse-events.h
> +++ b/tools/perf/util/parse-events.h
> @@ -11,7 +11,6 @@
> #include <linux/perf_event.h>
> #include <string.h>
>
> -struct list_head;
> struct evsel;
> struct evlist;
> struct parse_events_error;
> @@ -19,14 +18,6 @@ struct parse_events_error;
> struct option;
> struct perf_pmu;
>
> -struct tracepoint_path {
> - char *system;
> - char *name;
> - struct tracepoint_path *next;
> -};
> -
> -struct tracepoint_path *tracepoint_id_to_path(u64 config);
> -struct tracepoint_path *tracepoint_name_to_path(const char *name);
> bool have_tracepoints(struct list_head *evlist);
>
> const char *event_type(int type);
> @@ -46,8 +37,6 @@ int parse_events_terms(struct list_head *terms, const char *str);
> int parse_filter(const struct option *opt, const char *str, int unset);
> int exclude_perf(const struct option *opt, const char *arg, int unset);
>
> -#define EVENTS_HELP_MAX (128*1024)
> -
> enum perf_pmu_event_symbol_type {
> PMU_EVENT_SYMBOL_ERR, /* not a PMU EVENT */
> PMU_EVENT_SYMBOL, /* normal style PMU event */
> @@ -55,11 +44,6 @@ enum perf_pmu_event_symbol_type {
> PMU_EVENT_SYMBOL_SUFFIX, /* suffix of pre-suf style event */
> };
>
> -struct perf_pmu_event_symbol {
> - char *symbol;
> - enum perf_pmu_event_symbol_type type;
> -};
> -
> enum {
> PARSE_EVENTS__TERM_TYPE_NUM,
> PARSE_EVENTS__TERM_TYPE_STR,
> @@ -216,8 +200,6 @@ void parse_events_update_lists(struct list_head *list_event,
> void parse_events_evlist_error(struct parse_events_state *parse_state,
> int idx, const char *str);
>
> -void print_events(const char *event_glob, bool name_only, bool quiet,
> - bool long_desc, bool details_flag, bool deprecated);
>
> struct event_symbol {
> const char *symbol;
> @@ -225,18 +207,7 @@ struct event_symbol {
> };
> extern struct event_symbol event_symbols_hw[];
> extern struct event_symbol event_symbols_sw[];
> -void print_symbol_events(const char *event_glob, unsigned type,
> - struct event_symbol *syms, unsigned max,
> - bool name_only);
> -void print_tool_events(const char *event_glob, bool name_only);
> -void print_tracepoint_events(const char *subsys_glob, const char *event_glob,
> - bool name_only);
> -int print_hwcache_events(const char *event_glob, bool name_only);
> -void print_sdt_events(const char *subsys_glob, const char *event_glob,
> - bool name_only);
> -int is_valid_tracepoint(const char *event_string);
>
> -int valid_event_mount(const char *eventfs);
> char *parse_events_formats_error_string(char *additional_terms);
>
> void parse_events_print_error(struct parse_events_error *err,
> diff --git a/tools/perf/util/print-events.c b/tools/perf/util/print-events.c
> new file mode 100644
> index 000000000000..584888353d13
> --- /dev/null
> +++ b/tools/perf/util/print-events.c
> @@ -0,0 +1,472 @@
> +// SPDX-License-Identifier: GPL-2.0
> +#include <dirent.h>
> +#include <errno.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <sys/param.h>
> +
> +#include <api/fs/tracing_path.h>
> +#include <linux/perf_event.h>
> +#include <linux/zalloc.h>
> +#include <subcmd/pager.h>
> +
> +#include "build-id.h"
> +#include "debug.h"
> +#include "evsel.h"
> +#include "metricgroup.h"
> +#include "parse-events.h"
> +#include "pmu.h"
> +#include "print-events.h"
> +#include "probe-file.h"
> +#include "string2.h"
> +#include "strlist.h"
> +#include "thread_map.h"
> +#include "tracepoint.h"
> +#include "pfm.h"
> +
> +#define MAX_NAME_LEN 100
> +
> +static int cmp_string(const void *a, const void *b)
> +{
> + const char * const *as = a;
> + const char * const *bs = b;
> +
> + return strcmp(*as, *bs);
> +}
> +
> +static const char * const event_type_descriptors[] = {
> + "Hardware event",
> + "Software event",
> + "Tracepoint event",
> + "Hardware cache event",
> + "Raw hardware event descriptor",
> + "Hardware breakpoint",
> +};
> +
> +/*
> + * Print the events from <debugfs_mount_point>/tracing/events
> + */
> +void print_tracepoint_events(const char *subsys_glob,
> + const char *event_glob, bool name_only)
> +{
> + DIR *sys_dir, *evt_dir;
> + struct dirent *sys_dirent, *evt_dirent;
> + char evt_path[MAXPATHLEN];
> + char *dir_path;
> + char **evt_list = NULL;
> + unsigned int evt_i = 0, evt_num = 0;
> + bool evt_num_known = false;
> +
> +restart:
> + sys_dir = tracing_events__opendir();
> + if (!sys_dir)
> + return;
> +
> + if (evt_num_known) {
> + evt_list = zalloc(sizeof(char *) * evt_num);
> + if (!evt_list)
> + goto out_close_sys_dir;
> + }
> +
> + for_each_subsystem(sys_dir, sys_dirent) {
> + if (subsys_glob != NULL &&
> + !strglobmatch(sys_dirent->d_name, subsys_glob))
> + continue;
> +
> + dir_path = get_events_file(sys_dirent->d_name);
> + if (!dir_path)
> + continue;
> + evt_dir = opendir(dir_path);
> + if (!evt_dir)
> + goto next;
> +
> + for_each_event(dir_path, evt_dir, evt_dirent) {
> + if (event_glob != NULL &&
> + !strglobmatch(evt_dirent->d_name, event_glob))
> + continue;
> +
> + if (!evt_num_known) {
> + evt_num++;
> + continue;
> + }
> +
> + snprintf(evt_path, MAXPATHLEN, "%s:%s",
> + sys_dirent->d_name, evt_dirent->d_name);
> +
> + evt_list[evt_i] = strdup(evt_path);
> + if (evt_list[evt_i] == NULL) {
> + put_events_file(dir_path);
> + goto out_close_evt_dir;
> + }
> + evt_i++;
> + }
> + closedir(evt_dir);
> +next:
> + put_events_file(dir_path);
> + }
> + closedir(sys_dir);
> +
> + if (!evt_num_known) {
> + evt_num_known = true;
> + goto restart;
> + }
> + qsort(evt_list, evt_num, sizeof(char *), cmp_string);
> + evt_i = 0;
> + while (evt_i < evt_num) {
> + if (name_only) {
> + printf("%s ", evt_list[evt_i++]);
> + continue;
> + }
> + printf(" %-50s [%s]\n", evt_list[evt_i++],
> + event_type_descriptors[PERF_TYPE_TRACEPOINT]);
> + }
> + if (evt_num && pager_in_use())
> + printf("\n");
> +
> +out_free:
> + evt_num = evt_i;
> + for (evt_i = 0; evt_i < evt_num; evt_i++)
> + zfree(&evt_list[evt_i]);
> + zfree(&evt_list);
> + return;
> +
> +out_close_evt_dir:
> + closedir(evt_dir);
> +out_close_sys_dir:
> + closedir(sys_dir);
> +
> + printf("FATAL: not enough memory to print %s\n",
> + event_type_descriptors[PERF_TYPE_TRACEPOINT]);
> + if (evt_list)
> + goto out_free;
> +}
> +
> +void print_sdt_events(const char *subsys_glob, const char *event_glob,
> + bool name_only)
> +{
> + struct probe_cache *pcache;
> + struct probe_cache_entry *ent;
> + struct strlist *bidlist, *sdtlist;
> + struct strlist_config cfg = {.dont_dupstr = true};
> + struct str_node *nd, *nd2;
> + char *buf, *path, *ptr = NULL;
> + bool show_detail = false;
> + int ret;
> +
> + sdtlist = strlist__new(NULL, &cfg);
> + if (!sdtlist) {
> + pr_debug("Failed to allocate new strlist for SDT\n");
> + return;
> + }
> + bidlist = build_id_cache__list_all(true);
> + if (!bidlist) {
> + pr_debug("Failed to get buildids: %d\n", errno);
> + return;
> + }
> + strlist__for_each_entry(nd, bidlist) {
> + pcache = probe_cache__new(nd->s, NULL);
> + if (!pcache)
> + continue;
> + list_for_each_entry(ent, &pcache->entries, node) {
> + if (!ent->sdt)
> + continue;
> + if (subsys_glob &&
> + !strglobmatch(ent->pev.group, subsys_glob))
> + continue;
> + if (event_glob &&
> + !strglobmatch(ent->pev.event, event_glob))
> + continue;
> + ret = asprintf(&buf, "%s:%s@%s", ent->pev.group,
> + ent->pev.event, nd->s);
> + if (ret > 0)
> + strlist__add(sdtlist, buf);
> + }
> + probe_cache__delete(pcache);
> + }
> + strlist__delete(bidlist);
> +
> + strlist__for_each_entry(nd, sdtlist) {
> + buf = strchr(nd->s, '@');
> + if (buf)
> + *(buf++) = '\0';
> + if (name_only) {
> + printf("%s ", nd->s);
> + continue;
> + }
> + nd2 = strlist__next(nd);
> + if (nd2) {
> + ptr = strchr(nd2->s, '@');
> + if (ptr)
> + *ptr = '\0';
> + if (strcmp(nd->s, nd2->s) == 0)
> + show_detail = true;
> + }
> + if (show_detail) {
> + path = build_id_cache__origname(buf);
> + ret = asprintf(&buf, "%s@%s(%.12s)", nd->s, path, buf);
> + if (ret > 0) {
> + printf(" %-50s [%s]\n", buf, "SDT event");
> + free(buf);
> + }
> + free(path);
> + } else
> + printf(" %-50s [%s]\n", nd->s, "SDT event");
> + if (nd2) {
> + if (strcmp(nd->s, nd2->s) != 0)
> + show_detail = false;
> + if (ptr)
> + *ptr = '@';
> + }
> + }
> + strlist__delete(sdtlist);
> +}
> +
> +static bool is_event_supported(u8 type, unsigned int config)
> +{
> + bool ret = true;
> + int open_return;
> + struct evsel *evsel;
> + struct perf_event_attr attr = {
> + .type = type,
> + .config = config,
> + .disabled = 1,
> + };
> + struct perf_thread_map *tmap = thread_map__new_by_tid(0);
> +
> + if (tmap == NULL)
> + return false;
> +
> + evsel = evsel__new(&attr);
> + if (evsel) {
> + open_return = evsel__open(evsel, NULL, tmap);
> + ret = open_return >= 0;
> +
> + if (open_return == -EACCES) {
> + /*
> + * This happens if the paranoid value
> + * /proc/sys/kernel/perf_event_paranoid is set to 2
> + * Re-run with exclude_kernel set; we don't do that
> + * by default as some ARM machines do not support it.
> + *
> + */
> + evsel->core.attr.exclude_kernel = 1;
> + ret = evsel__open(evsel, NULL, tmap) >= 0;
> + }
> + evsel__delete(evsel);
> + }
> +
> + perf_thread_map__put(tmap);
> + return ret;
> +}
> +
> +int print_hwcache_events(const char *event_glob, bool name_only)
> +{
> + unsigned int type, op, i, evt_i = 0, evt_num = 0;
> + char name[64];
> + char **evt_list = NULL;
> + bool evt_num_known = false;
> +
> +restart:
> + if (evt_num_known) {
> + evt_list = zalloc(sizeof(char *) * evt_num);
> + if (!evt_list)
> + goto out_enomem;
> + }
> +
> + for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
> + for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
> + /* skip invalid cache type */
> + if (!evsel__is_cache_op_valid(type, op))
> + continue;
> +
> + for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
> + __evsel__hw_cache_type_op_res_name(type, op, i, name, sizeof(name));
> + if (event_glob != NULL && !strglobmatch(name, event_glob))
> + continue;
> +
> + if (!is_event_supported(PERF_TYPE_HW_CACHE,
> + type | (op << 8) | (i << 16)))
> + continue;
> +
> + if (!evt_num_known) {
> + evt_num++;
> + continue;
> + }
> +
> + evt_list[evt_i] = strdup(name);
> + if (evt_list[evt_i] == NULL)
> + goto out_enomem;
> + evt_i++;
> + }
> + }
> + }
> +
> + if (!evt_num_known) {
> + evt_num_known = true;
> + goto restart;
> + }
> + qsort(evt_list, evt_num, sizeof(char *), cmp_string);
> + evt_i = 0;
> + while (evt_i < evt_num) {
> + if (name_only) {
> + printf("%s ", evt_list[evt_i++]);
> + continue;
> + }
> + printf(" %-50s [%s]\n", evt_list[evt_i++],
> + event_type_descriptors[PERF_TYPE_HW_CACHE]);
> + }
> + if (evt_num && pager_in_use())
> + printf("\n");
> +
> +out_free:
> + evt_num = evt_i;
> + for (evt_i = 0; evt_i < evt_num; evt_i++)
> + zfree(&evt_list[evt_i]);
> + zfree(&evt_list);
> + return evt_num;
> +
> +out_enomem:
> + printf("FATAL: not enough memory to print %s\n", event_type_descriptors[PERF_TYPE_HW_CACHE]);
> + if (evt_list)
> + goto out_free;
> + return evt_num;
> +}
> +
> +static void print_tool_event(const char *name, const char *event_glob,
> + bool name_only)
> +{
> + if (event_glob && !strglobmatch(name, event_glob))
> + return;
> + if (name_only)
> + printf("%s ", name);
> + else
> + printf(" %-50s [%s]\n", name, "Tool event");
> +
> +}
> +
> +void print_tool_events(const char *event_glob, bool name_only)
> +{
> + print_tool_event("duration_time", event_glob, name_only);
> + if (pager_in_use())
> + printf("\n");
> +}
> +
> +void print_symbol_events(const char *event_glob, unsigned int type,
> + struct event_symbol *syms, unsigned int max,
> + bool name_only)
> +{
> + unsigned int i, evt_i = 0, evt_num = 0;
> + char name[MAX_NAME_LEN];
> + char **evt_list = NULL;
> + bool evt_num_known = false;
> +
> +restart:
> + if (evt_num_known) {
> + evt_list = zalloc(sizeof(char *) * evt_num);
> + if (!evt_list)
> + goto out_enomem;
> + syms -= max;
> + }
> +
> + for (i = 0; i < max; i++, syms++) {
> +
> + if (event_glob != NULL && syms->symbol != NULL &&
> + !(strglobmatch(syms->symbol, event_glob) ||
> + (syms->alias && strglobmatch(syms->alias, event_glob))))
> + continue;
> +
> + if (!is_event_supported(type, i))
> + continue;
> +
> + if (!evt_num_known) {
> + evt_num++;
> + continue;
> + }
> +
> + if (!name_only && strlen(syms->alias))
> + snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias);
> + else
> + strlcpy(name, syms->symbol, MAX_NAME_LEN);
> +
> + evt_list[evt_i] = strdup(name);
> + if (evt_list[evt_i] == NULL)
> + goto out_enomem;
> + evt_i++;
> + }
> +
> + if (!evt_num_known) {
> + evt_num_known = true;
> + goto restart;
> + }
> + qsort(evt_list, evt_num, sizeof(char *), cmp_string);
> + evt_i = 0;
> + while (evt_i < evt_num) {
> + if (name_only) {
> + printf("%s ", evt_list[evt_i++]);
> + continue;
> + }
> + printf(" %-50s [%s]\n", evt_list[evt_i++], event_type_descriptors[type]);
> + }
> + if (evt_num && pager_in_use())
> + printf("\n");
> +
> +out_free:
> + evt_num = evt_i;
> + for (evt_i = 0; evt_i < evt_num; evt_i++)
> + zfree(&evt_list[evt_i]);
> + zfree(&evt_list);
> + return;
> +
> +out_enomem:
> + printf("FATAL: not enough memory to print %s\n", event_type_descriptors[type]);
> + if (evt_list)
> + goto out_free;
> +}
> +
> +/*
> + * Print the help text for the event symbols:
> + */
> +void print_events(const char *event_glob, bool name_only, bool quiet_flag,
> + bool long_desc, bool details_flag, bool deprecated)
> +{
> + print_symbol_events(event_glob, PERF_TYPE_HARDWARE,
> + event_symbols_hw, PERF_COUNT_HW_MAX, name_only);
> +
> + print_symbol_events(event_glob, PERF_TYPE_SOFTWARE,
> + event_symbols_sw, PERF_COUNT_SW_MAX, name_only);
> + print_tool_events(event_glob, name_only);
> +
> + print_hwcache_events(event_glob, name_only);
> +
> + print_pmu_events(event_glob, name_only, quiet_flag, long_desc,
> + details_flag, deprecated);
> +
> + if (event_glob != NULL)
> + return;
> +
> + if (!name_only) {
> + printf(" %-50s [%s]\n",
> + "rNNN",
> + event_type_descriptors[PERF_TYPE_RAW]);
> + printf(" %-50s [%s]\n",
> + "cpu/t1=v1[,t2=v2,t3 ...]/modifier",
> + event_type_descriptors[PERF_TYPE_RAW]);
> + if (pager_in_use())
> + printf(" (see 'man perf-list' on how to encode it)\n\n");
> +
> + printf(" %-50s [%s]\n",
> + "mem:<addr>[/len][:access]",
> + event_type_descriptors[PERF_TYPE_BREAKPOINT]);
> + if (pager_in_use())
> + printf("\n");
> + }
> +
> + print_tracepoint_events(NULL, NULL, name_only);
> +
> + print_sdt_events(NULL, NULL, name_only);
> +
> + metricgroup__print(true, true, NULL, name_only, details_flag);
> +
> + print_libpfm_events(name_only, long_desc);
> +}
> diff --git a/tools/perf/util/print-events.h b/tools/perf/util/print-events.h
> new file mode 100644
> index 000000000000..cf64e8129c1b
> --- /dev/null
> +++ b/tools/perf/util/print-events.h
> @@ -0,0 +1,21 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +#ifndef __PERF_PRINT_EVENTS_H
> +#define __PERF_PRINT_EVENTS_H
> +
> +#include <stdbool.h>
> +
> +struct event_symbol;
> +
> +void print_events(const char *event_glob, bool name_only, bool quiet,
> + bool long_desc, bool details_flag, bool deprecated);
> +int print_hwcache_events(const char *event_glob, bool name_only);
> +void print_sdt_events(const char *subsys_glob, const char *event_glob,
> + bool name_only);
> +void print_symbol_events(const char *event_glob, unsigned int type,
> + struct event_symbol *syms, unsigned int max,
> + bool name_only);
> +void print_tool_events(const char *event_glob, bool name_only);
> +void print_tracepoint_events(const char *subsys_glob, const char *event_glob,
> + bool name_only);
> +
> +#endif /* __PERF_PRINT_EVENTS_H */
> diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c
> index a65f65d0857e..fbc6d14aabbb 100644
> --- a/tools/perf/util/trace-event-info.c
> +++ b/tools/perf/util/trace-event-info.c
> @@ -19,16 +19,24 @@
> #include <linux/kernel.h>
> #include <linux/zalloc.h>
> #include <internal/lib.h> // page_size
> +#include <sys/param.h>
>
> #include "trace-event.h"
> +#include "tracepoint.h"
> #include <api/fs/tracing_path.h>
> #include "evsel.h"
> #include "debug.h"
>
> #define VERSION "0.6"
> +#define MAX_EVENT_LENGTH 512
>
> static int output_fd;
>
> +struct tracepoint_path {
> + char *system;
> + char *name;
> + struct tracepoint_path *next;
> +};
>
> int bigendian(void)
> {
> @@ -400,6 +408,92 @@ put_tracepoints_path(struct tracepoint_path *tps)
> }
> }
>
> +static struct tracepoint_path *tracepoint_id_to_path(u64 config)
> +{
> + struct tracepoint_path *path = NULL;
> + DIR *sys_dir, *evt_dir;
> + struct dirent *sys_dirent, *evt_dirent;
> + char id_buf[24];
> + int fd;
> + u64 id;
> + char evt_path[MAXPATHLEN];
> + char *dir_path;
> +
> + sys_dir = tracing_events__opendir();
> + if (!sys_dir)
> + return NULL;
> +
> + for_each_subsystem(sys_dir, sys_dirent) {
> + dir_path = get_events_file(sys_dirent->d_name);
> + if (!dir_path)
> + continue;
> + evt_dir = opendir(dir_path);
> + if (!evt_dir)
> + goto next;
> +
> + for_each_event(dir_path, evt_dir, evt_dirent) {
> +
> + scnprintf(evt_path, MAXPATHLEN, "%s/%s/id", dir_path,
> + evt_dirent->d_name);
> + fd = open(evt_path, O_RDONLY);
> + if (fd < 0)
> + continue;
> + if (read(fd, id_buf, sizeof(id_buf)) < 0) {
> + close(fd);
> + continue;
> + }
> + close(fd);
> + id = atoll(id_buf);
> + if (id == config) {
> + put_events_file(dir_path);
> + closedir(evt_dir);
> + closedir(sys_dir);
> + path = zalloc(sizeof(*path));
> + if (!path)
> + return NULL;
> + if (asprintf(&path->system, "%.*s", MAX_EVENT_LENGTH, sys_dirent->d_name) < 0) {
> + free(path);
> + return NULL;
> + }
> + if (asprintf(&path->name, "%.*s", MAX_EVENT_LENGTH, evt_dirent->d_name) < 0) {
> + zfree(&path->system);
> + free(path);
> + return NULL;
> + }
> + return path;
> + }
> + }
> + closedir(evt_dir);
> +next:
> + put_events_file(dir_path);
> + }
> +
> + closedir(sys_dir);
> + return NULL;
> +}
> +
> +static struct tracepoint_path *tracepoint_name_to_path(const char *name)
> +{
> + struct tracepoint_path *path = zalloc(sizeof(*path));
> + char *str = strchr(name, ':');
> +
> + if (path == NULL || str == NULL) {
> + free(path);
> + return NULL;
> + }
> +
> + path->system = strndup(name, str - name);
> + path->name = strdup(str+1);
> +
> + if (path->system == NULL || path->name == NULL) {
> + zfree(&path->system);
> + zfree(&path->name);
> + zfree(&path);
> + }
> +
> + return path;
> +}
> +
> static struct tracepoint_path *
> get_tracepoints_path(struct list_head *pattrs)
> {
> diff --git a/tools/perf/util/tracepoint.c b/tools/perf/util/tracepoint.c
> new file mode 100644
> index 000000000000..89ef56c43311
> --- /dev/null
> +++ b/tools/perf/util/tracepoint.c
> @@ -0,0 +1,63 @@
> +// SPDX-License-Identifier: GPL-2.0
> +#include "tracepoint.h"
> +
> +#include <errno.h>
> +#include <fcntl.h>
> +#include <stdio.h>
> +#include <sys/param.h>
> +#include <unistd.h>
> +
> +#include <api/fs/tracing_path.h>
> +
> +int tp_event_has_id(const char *dir_path, struct dirent *evt_dir)
> +{
> + char evt_path[MAXPATHLEN];
> + int fd;
> +
> + snprintf(evt_path, MAXPATHLEN, "%s/%s/id", dir_path, evt_dir->d_name);
> + fd = open(evt_path, O_RDONLY);
> + if (fd < 0)
> + return -EINVAL;
> + close(fd);
> +
> + return 0;
> +}
> +
> +/*
> + * Check whether event is in <debugfs_mount_point>/tracing/events
> + */
> +int is_valid_tracepoint(const char *event_string)
> +{
> + DIR *sys_dir, *evt_dir;
> + struct dirent *sys_dirent, *evt_dirent;
> + char evt_path[MAXPATHLEN];
> + char *dir_path;
> +
> + sys_dir = tracing_events__opendir();
> + if (!sys_dir)
> + return 0;
> +
> + for_each_subsystem(sys_dir, sys_dirent) {
> + dir_path = get_events_file(sys_dirent->d_name);
> + if (!dir_path)
> + continue;
> + evt_dir = opendir(dir_path);
> + if (!evt_dir)
> + goto next;
> +
> + for_each_event(dir_path, evt_dir, evt_dirent) {
> + snprintf(evt_path, MAXPATHLEN, "%s:%s",
> + sys_dirent->d_name, evt_dirent->d_name);
> + if (!strcmp(evt_path, event_string)) {
> + closedir(evt_dir);
> + closedir(sys_dir);
> + return 1;
> + }
> + }
> + closedir(evt_dir);
> +next:
> + put_events_file(dir_path);
> + }
> + closedir(sys_dir);
> + return 0;
> +}
> diff --git a/tools/perf/util/tracepoint.h b/tools/perf/util/tracepoint.h
> new file mode 100644
> index 000000000000..c4a110fe87d7
> --- /dev/null
> +++ b/tools/perf/util/tracepoint.h
> @@ -0,0 +1,25 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +#ifndef __PERF_TRACEPOINT_H
> +#define __PERF_TRACEPOINT_H
> +
> +#include <dirent.h>
> +#include <string.h>
> +
> +int tp_event_has_id(const char *dir_path, struct dirent *evt_dir);
> +
> +#define for_each_event(dir_path, evt_dir, evt_dirent) \
> + while ((evt_dirent = readdir(evt_dir)) != NULL) \
> + if (evt_dirent->d_type == DT_DIR && \
> + (strcmp(evt_dirent->d_name, ".")) && \
> + (strcmp(evt_dirent->d_name, "..")) && \
> + (!tp_event_has_id(dir_path, evt_dirent)))
> +
> +#define for_each_subsystem(sys_dir, sys_dirent) \
> + while ((sys_dirent = readdir(sys_dir)) != NULL) \
> + if (sys_dirent->d_type == DT_DIR && \
> + (strcmp(sys_dirent->d_name, ".")) && \
> + (strcmp(sys_dirent->d_name, "..")))
> +
> +int is_valid_tracepoint(const char *event_string);
> +
> +#endif /* __PERF_TRACEPOINT_H */
> --
> 2.30.0.365.g02bc693789-goog
>
--
- Arnaldo
next prev parent reply other threads:[~2021-02-03 16:22 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-02-03 5:26 [PATCH 1/2] perf trace-event-info: Rename for_each_event Ian Rogers
2021-02-03 5:26 ` [PATCH 2/2] perf parse-events: Break out tracepoint and printing Ian Rogers
2021-02-03 16:20 ` Arnaldo Carvalho de Melo [this message]
2021-02-03 19:02 ` Ian Rogers
[not found] ` <CAP-5=fVFeT6YtXJGHX0OC1BCa121bTC+ER7XDVO2g5rr8DYfDw@mail.gmail.com>
2021-02-03 20:50 ` Arnaldo Carvalho de Melo
2021-02-04 0:58 ` Arnaldo Carvalho de Melo
2021-02-04 1:21 ` Ian Rogers
2021-06-08 20:41 ` Ian Rogers
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210203162058.GE854763@kernel.org \
--to=acme@kernel.org \
--cc=alexander.shishkin@linux.intel.com \
--cc=eranian@google.com \
--cc=irogers@google.com \
--cc=jolsa@redhat.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mark.rutland@arm.com \
--cc=mingo@redhat.com \
--cc=namhyung@kernel.org \
--cc=peterz@infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.