From c46d634a03a309df461294a001cdf71b77d43b57 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Mon, 18 Nov 2024 14:53:43 -0800 Subject: perf evsel: Add/use accessor for tp_format Add an accessor function for tp_format. Rather than search+replace uses try to use a variable and reuse it. Add additional NULL checks when accessing/using the value. Make sure the PTR_ERR is nulled out on error path in evsel__newtp_idx. Reviewed-by: Namhyung Kim Signed-off-by: Ian Rogers Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Andi Kleen Cc: Athira Rajeev Cc: Ben Gainey Cc: Colin Ian King Cc: Dominique Martinet Cc: Ilkka Koskinen Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Kan Liang Cc: Mark Rutland Cc: Oliver Upton Cc: Paran Lee Cc: Peter Zijlstra Cc: Steinar H. Gunderson Cc: Steven Rostedt (VMware) Cc: Thomas Falcon Cc: Weilin Wang Cc: Yang Jihong Cc: Yang Li Cc: Ze Gao Cc: Zixian Cai Cc: zhaimingbing Link: https://lore.kernel.org/r/20241118225345.889810-6-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-script.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'tools/perf/builtin-script.c') diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 9e47905f75a6..aad607b8918f 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -2289,8 +2289,13 @@ static void process_event(struct perf_script *script, } #ifdef HAVE_LIBTRACEEVENT if (PRINT_FIELD(TRACE) && sample->raw_data) { - event_format__fprintf(evsel->tp_format, sample->cpu, - sample->raw_data, sample->raw_size, fp); + const struct tep_event *tp_format = evsel__tp_format(evsel); + + if (tp_format) { + event_format__fprintf(tp_format, sample->cpu, + sample->raw_data, sample->raw_size, + fp); + } } #endif if (attr->type == PERF_TYPE_SYNTH && PRINT_FIELD(SYNTH)) -- cgit v1.2.3 From 702c7a4aec38a29d8a61a6e4af6cbfc9ca2c33a9 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Mon, 18 Nov 2024 17:16:26 -0800 Subject: perf script: Move scripting_max_stack out of builtin scripting_max_stack is used in util code which is linked into the python module. Move the variable declaration to util/trace-event-scripting.c to avoid conditional compilation. Signed-off-by: Ian Rogers Acked-by: Arnaldo Carvalho de Melo Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Andi Kleen Cc: Athira Rajeev Cc: Colin Ian King Cc: Dapeng Mi Cc: Howard Chu Cc: Ilya Leoshkevich Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Josh Poimboeuf Cc: Kan Liang Cc: Mark Rutland Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Thomas Richter Cc: Veronika Molnarova Cc: Weilin Wang Link: https://lore.kernel.org/r/20241119011644.971342-5-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-script.c | 2 -- tools/perf/util/python.c | 2 -- tools/perf/util/trace-event-scripting.c | 3 +++ 3 files changed, 3 insertions(+), 4 deletions(-) (limited to 'tools/perf/builtin-script.c') diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index aad607b8918f..cc42b472dfff 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -92,8 +92,6 @@ static struct dlfilter *dlfilter; static int dlargc; static char **dlargv; -unsigned int scripting_max_stack = PERF_MAX_STACK_DEPTH; - enum perf_output_field { PERF_OUTPUT_COMM = 1ULL << 0, PERF_OUTPUT_TID = 1ULL << 1, diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index 140437042a73..029536c1fabc 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -1307,8 +1307,6 @@ error: /* The following are stubs to avoid dragging in builtin-* objects. */ /* TODO: move the code out of the builtin-* file into util. */ -unsigned int scripting_max_stack = PERF_MAX_STACK_DEPTH; - #ifdef HAVE_KVM_STAT_SUPPORT bool kvm_entry_event(struct evsel *evsel __maybe_unused) { diff --git a/tools/perf/util/trace-event-scripting.c b/tools/perf/util/trace-event-scripting.c index edfde7056c99..a7f0a14c05b6 100644 --- a/tools/perf/util/trace-event-scripting.c +++ b/tools/perf/util/trace-event-scripting.c @@ -16,9 +16,12 @@ #include "debug.h" #include "trace-event.h" #include "evsel.h" +#include #include #include "util/sample.h" +unsigned int scripting_max_stack = PERF_MAX_STACK_DEPTH; + struct scripting_context *scripting_context; void scripting_context__update(struct scripting_context *c, -- cgit v1.2.3 From f76f94dc7885b5bd288532642690eab74cd06b03 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Mon, 18 Nov 2024 17:16:28 -0800 Subject: perf script: Use openat for directory iteration Rewrite the directory iteration to use openat so that large character arrays aren't needed. The arrays are warned about potential buffer overflows by GCC when the code exists in a single C file. Signed-off-by: Ian Rogers Tested-by: Arnaldo Carvalho de Melo Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Andi Kleen Cc: Athira Rajeev Cc: Colin Ian King Cc: Dapeng Mi Cc: Howard Chu Cc: Ilya Leoshkevich Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Josh Poimboeuf Cc: Kan Liang Cc: Mark Rutland Cc: Michael Petlan Cc: Peter Zijlstra Cc: Thomas Richter Cc: Veronika Molnarova Cc: Weilin Wang Link: https://lore.kernel.org/r/20241119011644.971342-7-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-script.c | 87 +++++++++++++++++++++++++++++++-------------- tools/perf/util/path.c | 10 ++++++ tools/perf/util/path.h | 1 + 3 files changed, 71 insertions(+), 27 deletions(-) (limited to 'tools/perf/builtin-script.c') diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index cc42b472dfff..196e2f3438c5 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -3535,27 +3535,35 @@ static void free_dlarg(void) * which is covered well now. And new parsing code should be added to * cover the future complex formats like event groups etc. */ -static int check_ev_match(char *dir_name, char *scriptname, - struct perf_session *session) +static int check_ev_match(int dir_fd, const char *scriptname, struct perf_session *session) { - char filename[MAXPATHLEN], evname[128]; - char line[BUFSIZ], *p; - struct evsel *pos; - int match, len; + char line[BUFSIZ]; FILE *fp; - scnprintf(filename, MAXPATHLEN, "%s/bin/%s-record", dir_name, scriptname); + { + char filename[FILENAME_MAX + 5]; + int fd; - fp = fopen(filename, "r"); - if (!fp) - return -1; + scnprintf(filename, sizeof(filename), "bin/%s-record", scriptname); + fd = openat(dir_fd, filename, O_RDONLY); + if (fd == -1) + return -1; + fp = fdopen(fd, "r"); + if (!fp) + return -1; + } while (fgets(line, sizeof(line), fp)) { - p = skip_spaces(line); + char *p = skip_spaces(line); + if (*p == '#') continue; while (strlen(p)) { + int match, len; + struct evsel *pos; + char evname[128]; + p = strstr(p, "-e"); if (!p) break; @@ -3598,7 +3606,7 @@ int find_scripts(char **scripts_array, char **scripts_path_array, int num, int pathlen) { struct dirent *script_dirent, *lang_dirent; - char scripts_path[MAXPATHLEN], lang_path[MAXPATHLEN]; + int scripts_dir_fd, lang_dir_fd; DIR *scripts_dir, *lang_dir; struct perf_session *session; struct perf_data data = { @@ -3607,51 +3615,76 @@ int find_scripts(char **scripts_array, char **scripts_path_array, int num, }; char *temp; int i = 0; + const char *exec_path = get_argv_exec_path(); session = perf_session__new(&data, NULL); if (IS_ERR(session)) return PTR_ERR(session); - snprintf(scripts_path, MAXPATHLEN, "%s/scripts", get_argv_exec_path()); + { + char scripts_path[PATH_MAX]; - scripts_dir = opendir(scripts_path); + snprintf(scripts_path, sizeof(scripts_path), "%s/scripts", exec_path); + scripts_dir_fd = open(scripts_path, O_DIRECTORY); + pr_err("Failed to open directory '%s'", scripts_path); + if (scripts_dir_fd == -1) { + perf_session__delete(session); + return -1; + } + } + scripts_dir = fdopendir(scripts_dir_fd); if (!scripts_dir) { + close(scripts_dir_fd); perf_session__delete(session); return -1; } - for_each_lang(scripts_path, scripts_dir, lang_dirent) { - scnprintf(lang_path, MAXPATHLEN, "%s/%s", scripts_path, - lang_dirent->d_name); + while ((lang_dirent = readdir(scripts_dir)) != NULL) { + if (lang_dirent->d_type != DT_DIR && + (lang_dirent->d_type == DT_UNKNOWN && + !is_directory_at(scripts_dir_fd, lang_dirent->d_name))) + continue; + if (!strcmp(lang_dirent->d_name, ".") || !strcmp(lang_dirent->d_name, "..")) + continue; + #ifndef HAVE_LIBPERL_SUPPORT - if (strstr(lang_path, "perl")) + if (strstr(lang_dirent->d_name, "perl")) continue; #endif #ifndef HAVE_LIBPYTHON_SUPPORT - if (strstr(lang_path, "python")) + if (strstr(lang_dirent->d_name, "python")) continue; #endif - lang_dir = opendir(lang_path); - if (!lang_dir) + lang_dir_fd = openat(scripts_dir_fd, lang_dirent->d_name, O_DIRECTORY); + if (lang_dir_fd == -1) continue; - - for_each_script(lang_path, lang_dir, script_dirent) { + lang_dir = fdopendir(lang_dir_fd); + if (!lang_dir) { + close(lang_dir_fd); + continue; + } + while ((script_dirent = readdir(lang_dir)) != NULL) { + if (script_dirent->d_type == DT_DIR) + continue; + if (script_dirent->d_type == DT_UNKNOWN && + is_directory_at(lang_dir_fd, script_dirent->d_name)) + continue; /* Skip those real time scripts: xxxtop.p[yl] */ if (strstr(script_dirent->d_name, "top.")) continue; if (i >= num) break; - snprintf(scripts_path_array[i], pathlen, "%s/%s", - lang_path, + scnprintf(scripts_path_array[i], pathlen, "%s/scripts/%s/%s", + exec_path, + lang_dirent->d_name, script_dirent->d_name); temp = strchr(script_dirent->d_name, '.'); snprintf(scripts_array[i], (temp - script_dirent->d_name) + 1, "%s", script_dirent->d_name); - if (check_ev_match(lang_path, - scripts_array[i], session)) + if (check_ev_match(lang_dir_fd, scripts_array[i], session)) continue; i++; diff --git a/tools/perf/util/path.c b/tools/perf/util/path.c index 00adf872bf00..9712466c51e2 100644 --- a/tools/perf/util/path.c +++ b/tools/perf/util/path.c @@ -68,6 +68,16 @@ bool is_directory(const char *base_path, const struct dirent *dent) return S_ISDIR(st.st_mode); } +bool is_directory_at(int dir_fd, const char *path) +{ + struct stat st; + + if (fstatat(dir_fd, path, &st, /*flags=*/0)) + return false; + + return S_ISDIR(st.st_mode); +} + bool is_executable_file(const char *base_path, const struct dirent *dent) { char path[PATH_MAX]; diff --git a/tools/perf/util/path.h b/tools/perf/util/path.h index d94902c22222..fbafbe7015dd 100644 --- a/tools/perf/util/path.h +++ b/tools/perf/util/path.h @@ -12,6 +12,7 @@ int path__join3(char *bf, size_t size, const char *path1, const char *path2, con bool is_regular_file(const char *file); bool is_directory(const char *base_path, const struct dirent *dent); +bool is_directory_at(int dir_fd, const char *path); bool is_executable_file(const char *base_path, const struct dirent *dent); #endif /* _PERF_PATH_H */ -- cgit v1.2.3 From d927e30ca0b130d81c61dd031eeae22328a778ba Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Mon, 18 Nov 2024 17:16:29 -0800 Subject: perf script: Move find_scripts to browser/scripts.c The only use of find_scripts is in browser/scripts.c but the definition in builtin causes linking problems requiring a stub in python.c. Move the function to allow the stub to be removed. Signed-off-by: Ian Rogers Tested-by: Arnaldo Carvalho de Melo Acked-by: Namhyung Kim Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Andi Kleen Cc: Athira Rajeev Cc: Colin Ian King Cc: Dapeng Mi Cc: Howard Chu Cc: Ilya Leoshkevich Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Josh Poimboeuf Cc: Kan Liang Cc: Mark Rutland Cc: Michael Petlan Cc: Peter Zijlstra Cc: Thomas Richter Cc: Veronika Molnarova Cc: Weilin Wang Link: https://lore.kernel.org/r/20241119011644.971342-8-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-script.c | 171 ------------------------------------- tools/perf/builtin.h | 6 -- tools/perf/ui/browsers/scripts.c | 177 ++++++++++++++++++++++++++++++++++++++- tools/perf/util/python.c | 6 -- 4 files changed, 175 insertions(+), 185 deletions(-) (limited to 'tools/perf/builtin-script.c') diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 196e2f3438c5..25c25058121a 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -3526,177 +3526,6 @@ static void free_dlarg(void) free(dlargv); } -/* - * Some scripts specify the required events in their "xxx-record" file, - * this function will check if the events in perf.data match those - * mentioned in the "xxx-record". - * - * Fixme: All existing "xxx-record" are all in good formats "-e event ", - * which is covered well now. And new parsing code should be added to - * cover the future complex formats like event groups etc. - */ -static int check_ev_match(int dir_fd, const char *scriptname, struct perf_session *session) -{ - char line[BUFSIZ]; - FILE *fp; - - { - char filename[FILENAME_MAX + 5]; - int fd; - - scnprintf(filename, sizeof(filename), "bin/%s-record", scriptname); - fd = openat(dir_fd, filename, O_RDONLY); - if (fd == -1) - return -1; - fp = fdopen(fd, "r"); - if (!fp) - return -1; - } - - while (fgets(line, sizeof(line), fp)) { - char *p = skip_spaces(line); - - if (*p == '#') - continue; - - while (strlen(p)) { - int match, len; - struct evsel *pos; - char evname[128]; - - p = strstr(p, "-e"); - if (!p) - break; - - p += 2; - p = skip_spaces(p); - len = strcspn(p, " \t"); - if (!len) - break; - - snprintf(evname, len + 1, "%s", p); - - match = 0; - evlist__for_each_entry(session->evlist, pos) { - if (evsel__name_is(pos, evname)) { - match = 1; - break; - } - } - - if (!match) { - fclose(fp); - return -1; - } - } - } - - fclose(fp); - return 0; -} - -/* - * Return -1 if none is found, otherwise the actual scripts number. - * - * Currently the only user of this function is the script browser, which - * will list all statically runnable scripts, select one, execute it and - * show the output in a perf browser. - */ -int find_scripts(char **scripts_array, char **scripts_path_array, int num, - int pathlen) -{ - struct dirent *script_dirent, *lang_dirent; - int scripts_dir_fd, lang_dir_fd; - DIR *scripts_dir, *lang_dir; - struct perf_session *session; - struct perf_data data = { - .path = input_name, - .mode = PERF_DATA_MODE_READ, - }; - char *temp; - int i = 0; - const char *exec_path = get_argv_exec_path(); - - session = perf_session__new(&data, NULL); - if (IS_ERR(session)) - return PTR_ERR(session); - - { - char scripts_path[PATH_MAX]; - - snprintf(scripts_path, sizeof(scripts_path), "%s/scripts", exec_path); - scripts_dir_fd = open(scripts_path, O_DIRECTORY); - pr_err("Failed to open directory '%s'", scripts_path); - if (scripts_dir_fd == -1) { - perf_session__delete(session); - return -1; - } - } - scripts_dir = fdopendir(scripts_dir_fd); - if (!scripts_dir) { - close(scripts_dir_fd); - perf_session__delete(session); - return -1; - } - - while ((lang_dirent = readdir(scripts_dir)) != NULL) { - if (lang_dirent->d_type != DT_DIR && - (lang_dirent->d_type == DT_UNKNOWN && - !is_directory_at(scripts_dir_fd, lang_dirent->d_name))) - continue; - if (!strcmp(lang_dirent->d_name, ".") || !strcmp(lang_dirent->d_name, "..")) - continue; - -#ifndef HAVE_LIBPERL_SUPPORT - if (strstr(lang_dirent->d_name, "perl")) - continue; -#endif -#ifndef HAVE_LIBPYTHON_SUPPORT - if (strstr(lang_dirent->d_name, "python")) - continue; -#endif - - lang_dir_fd = openat(scripts_dir_fd, lang_dirent->d_name, O_DIRECTORY); - if (lang_dir_fd == -1) - continue; - lang_dir = fdopendir(lang_dir_fd); - if (!lang_dir) { - close(lang_dir_fd); - continue; - } - while ((script_dirent = readdir(lang_dir)) != NULL) { - if (script_dirent->d_type == DT_DIR) - continue; - if (script_dirent->d_type == DT_UNKNOWN && - is_directory_at(lang_dir_fd, script_dirent->d_name)) - continue; - /* Skip those real time scripts: xxxtop.p[yl] */ - if (strstr(script_dirent->d_name, "top.")) - continue; - if (i >= num) - break; - scnprintf(scripts_path_array[i], pathlen, "%s/scripts/%s/%s", - exec_path, - lang_dirent->d_name, - script_dirent->d_name); - temp = strchr(script_dirent->d_name, '.'); - snprintf(scripts_array[i], - (temp - script_dirent->d_name) + 1, - "%s", script_dirent->d_name); - - if (check_ev_match(lang_dir_fd, scripts_array[i], session)) - continue; - - i++; - } - closedir(lang_dir); - } - - closedir(scripts_dir); - perf_session__delete(session); - return i; -} - static char *get_script_path(const char *script_root, const char *suffix) { struct dirent *script_dirent, *lang_dirent; diff --git a/tools/perf/builtin.h b/tools/perf/builtin.h index 94f4b3769bf7..a07e93c53848 100644 --- a/tools/perf/builtin.h +++ b/tools/perf/builtin.h @@ -2,10 +2,6 @@ #ifndef BUILTIN_H #define BUILTIN_H -#include -#include -#include - struct feature_status { const char *name; const char *macro; @@ -56,6 +52,4 @@ int cmd_ftrace(int argc, const char **argv); int cmd_daemon(int argc, const char **argv); int cmd_kwork(int argc, const char **argv); -int find_scripts(char **scripts_array, char **scripts_path_array, int num, - int pathlen); #endif diff --git a/tools/perf/ui/browsers/scripts.c b/tools/perf/ui/browsers/scripts.c index e437d7889de6..2d04ece833aa 100644 --- a/tools/perf/ui/browsers/scripts.c +++ b/tools/perf/ui/browsers/scripts.c @@ -1,16 +1,18 @@ // SPDX-License-Identifier: GPL-2.0 -#include "../../builtin.h" -#include "../../perf.h" #include "../../util/util.h" // perf_exe() #include "../util.h" +#include "../../util/evlist.h" #include "../../util/hist.h" #include "../../util/debug.h" +#include "../../util/session.h" #include "../../util/symbol.h" #include "../browser.h" #include "../libslang.h" #include "config.h" +#include #include #include +#include #include #define SCRIPT_NAMELEN 128 @@ -77,6 +79,177 @@ static int scripts_config(const char *var, const char *value, void *data) return 0; } +/* + * Some scripts specify the required events in their "xxx-record" file, + * this function will check if the events in perf.data match those + * mentioned in the "xxx-record". + * + * Fixme: All existing "xxx-record" are all in good formats "-e event ", + * which is covered well now. And new parsing code should be added to + * cover the future complex formats like event groups etc. + */ +static int check_ev_match(int dir_fd, const char *scriptname, struct perf_session *session) +{ + char line[BUFSIZ]; + FILE *fp; + + { + char filename[FILENAME_MAX + 5]; + int fd; + + scnprintf(filename, sizeof(filename), "bin/%s-record", scriptname); + fd = openat(dir_fd, filename, O_RDONLY); + if (fd == -1) + return -1; + fp = fdopen(fd, "r"); + if (!fp) + return -1; + } + + while (fgets(line, sizeof(line), fp)) { + char *p = skip_spaces(line); + + if (*p == '#') + continue; + + while (strlen(p)) { + int match, len; + struct evsel *pos; + char evname[128]; + + p = strstr(p, "-e"); + if (!p) + break; + + p += 2; + p = skip_spaces(p); + len = strcspn(p, " \t"); + if (!len) + break; + + snprintf(evname, len + 1, "%s", p); + + match = 0; + evlist__for_each_entry(session->evlist, pos) { + if (evsel__name_is(pos, evname)) { + match = 1; + break; + } + } + + if (!match) { + fclose(fp); + return -1; + } + } + } + + fclose(fp); + return 0; +} + +/* + * Return -1 if none is found, otherwise the actual scripts number. + * + * Currently the only user of this function is the script browser, which + * will list all statically runnable scripts, select one, execute it and + * show the output in a perf browser. + */ +static int find_scripts(char **scripts_array, char **scripts_path_array, int num, + int pathlen) +{ + struct dirent *script_dirent, *lang_dirent; + int scripts_dir_fd, lang_dir_fd; + DIR *scripts_dir, *lang_dir; + struct perf_session *session; + struct perf_data data = { + .path = input_name, + .mode = PERF_DATA_MODE_READ, + }; + char *temp; + int i = 0; + const char *exec_path = get_argv_exec_path(); + + session = perf_session__new(&data, NULL); + if (IS_ERR(session)) + return PTR_ERR(session); + + { + char scripts_path[PATH_MAX]; + + snprintf(scripts_path, sizeof(scripts_path), "%s/scripts", exec_path); + scripts_dir_fd = open(scripts_path, O_DIRECTORY); + pr_err("Failed to open directory '%s'", scripts_path); + if (scripts_dir_fd == -1) { + perf_session__delete(session); + return -1; + } + } + scripts_dir = fdopendir(scripts_dir_fd); + if (!scripts_dir) { + close(scripts_dir_fd); + perf_session__delete(session); + return -1; + } + + while ((lang_dirent = readdir(scripts_dir)) != NULL) { + if (lang_dirent->d_type != DT_DIR && + (lang_dirent->d_type == DT_UNKNOWN && + !is_directory_at(scripts_dir_fd, lang_dirent->d_name))) + continue; + if (!strcmp(lang_dirent->d_name, ".") || !strcmp(lang_dirent->d_name, "..")) + continue; + +#ifndef HAVE_LIBPERL_SUPPORT + if (strstr(lang_dirent->d_name, "perl")) + continue; +#endif +#ifndef HAVE_LIBPYTHON_SUPPORT + if (strstr(lang_dirent->d_name, "python")) + continue; +#endif + + lang_dir_fd = openat(scripts_dir_fd, lang_dirent->d_name, O_DIRECTORY); + if (lang_dir_fd == -1) + continue; + lang_dir = fdopendir(lang_dir_fd); + if (!lang_dir) { + close(lang_dir_fd); + continue; + } + while ((script_dirent = readdir(lang_dir)) != NULL) { + if (script_dirent->d_type == DT_DIR) + continue; + if (script_dirent->d_type == DT_UNKNOWN && + is_directory_at(lang_dir_fd, script_dirent->d_name)) + continue; + /* Skip those real time scripts: xxxtop.p[yl] */ + if (strstr(script_dirent->d_name, "top.")) + continue; + if (i >= num) + break; + scnprintf(scripts_path_array[i], pathlen, "%s/scripts/%s/%s", + exec_path, + lang_dirent->d_name, + script_dirent->d_name); + temp = strchr(script_dirent->d_name, '.'); + snprintf(scripts_array[i], + (temp - script_dirent->d_name) + 1, + "%s", script_dirent->d_name); + + if (check_ev_match(lang_dir_fd, scripts_array[i], session)) + continue; + + i++; + } + closedir(lang_dir); + } + + closedir(scripts_dir); + perf_session__delete(session); + return i; +} + /* * When success, will copy the full path of the selected script * into the buffer pointed by script_name, and return 0. diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index f8b291143884..4593c937febb 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -1307,12 +1307,6 @@ error: /* The following are stubs to avoid dragging in builtin-* objects. */ /* TODO: move the code out of the builtin-* file into util. */ -int find_scripts(char **scripts_array __maybe_unused, char **scripts_path_array __maybe_unused, - int num __maybe_unused, int pathlen __maybe_unused) -{ - return -1; -} - void perf_stat__set_no_csv_summary(int set __maybe_unused) { } -- cgit v1.2.3 From 9557d1562a8f49e8803265b4b30045f690b6d041 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Mon, 18 Nov 2024 17:16:30 -0800 Subject: perf stat: Move stat_config into config.c stat_config is accessed by config.c via helper functions, but declared in builtin-stat. Move to util/config.c so that stub functions aren't needed in python.c which doesn't link against the builtin files. To avoid name conflicts change builtin-script to use the same stat_config as builtin-stat. Rename local variables in tests to avoid shadow declaration warnings. Signed-off-by: Ian Rogers Tested-by: Arnaldo Carvalho de Melo Acked-by: Arnaldo Carvalho de Melo Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Andi Kleen Cc: Athira Rajeev Cc: Colin Ian King Cc: Dapeng Mi Cc: Howard Chu Cc: Ilya Leoshkevich Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Josh Poimboeuf Cc: Kan Liang Cc: Mark Rutland Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Thomas Richter Cc: Veronika Molnarova Cc: Weilin Wang Link: https://lore.kernel.org/r/20241119011644.971342-9-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-script.c | 1 - tools/perf/builtin-stat.c | 27 --------------------------- tools/perf/tests/stat.c | 16 +++++++++------- tools/perf/util/config.c | 27 +++++++++++++++++++++++++++ tools/perf/util/python.c | 10 ---------- tools/perf/util/stat.h | 3 ++- 6 files changed, 38 insertions(+), 46 deletions(-) (limited to 'tools/perf/builtin-script.c') diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 25c25058121a..7d21a52ad94e 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -85,7 +85,6 @@ static bool system_wide; static bool print_flags; static const char *cpu_list; static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); -static struct perf_stat_config stat_config; static int max_blocks; static bool native_arch; static struct dlfilter *dlfilter; diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index fdf5172646a5..77e327d4a9a7 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -112,8 +112,6 @@ static struct target target = { .uid = UINT_MAX, }; -#define METRIC_ONLY_LEN 20 - static volatile sig_atomic_t child_pid = -1; static int detailed_run = 0; static bool transaction_run; @@ -151,21 +149,6 @@ static struct perf_stat perf_stat; static volatile sig_atomic_t done = 0; -static struct perf_stat_config stat_config = { - .aggr_mode = AGGR_GLOBAL, - .aggr_level = MAX_CACHE_LVL + 1, - .scale = true, - .unit_width = 4, /* strlen("unit") */ - .run_count = 1, - .metric_only_len = METRIC_ONLY_LEN, - .walltime_nsecs_stats = &walltime_nsecs_stats, - .ru_stats = &ru_stats, - .big_num = true, - .ctl_fd = -1, - .ctl_fd_ack = -1, - .iostat_run = false, -}; - /* Options set from the command line. */ struct opt_aggr_mode { bool node, socket, die, cluster, cache, core, thread, no_aggr; @@ -1071,16 +1054,6 @@ static void sig_atexit(void) kill(getpid(), signr); } -void perf_stat__set_big_num(int set) -{ - stat_config.big_num = (set != 0); -} - -void perf_stat__set_no_csv_summary(int set) -{ - stat_config.no_csv_summary = (set != 0); -} - static int stat__set_big_num(const struct option *opt __maybe_unused, const char *s __maybe_unused, int unset) { diff --git a/tools/perf/tests/stat.c b/tools/perf/tests/stat.c index 6468cc0d0204..d60983657bad 100644 --- a/tools/perf/tests/stat.c +++ b/tools/perf/tests/stat.c @@ -27,7 +27,7 @@ static int process_stat_config_event(const struct perf_tool *tool __maybe_unused struct machine *machine __maybe_unused) { struct perf_record_stat_config *config = &event->stat_config; - struct perf_stat_config stat_config = {}; + struct perf_stat_config test_stat_config = {}; #define HAS(term, val) \ has_term(config, PERF_STAT_CONFIG_TERM__##term, val) @@ -39,25 +39,27 @@ static int process_stat_config_event(const struct perf_tool *tool __maybe_unused #undef HAS - perf_event__read_stat_config(&stat_config, config); + perf_event__read_stat_config(&test_stat_config, config); - TEST_ASSERT_VAL("wrong aggr_mode", stat_config.aggr_mode == AGGR_CORE); - TEST_ASSERT_VAL("wrong scale", stat_config.scale == 1); - TEST_ASSERT_VAL("wrong interval", stat_config.interval == 1); + TEST_ASSERT_VAL("wrong aggr_mode", test_stat_config.aggr_mode == AGGR_CORE); + TEST_ASSERT_VAL("wrong scale", test_stat_config.scale == 1); + TEST_ASSERT_VAL("wrong interval", test_stat_config.interval == 1); return 0; } static int test__synthesize_stat_config(struct test_suite *test __maybe_unused, int subtest __maybe_unused) { - struct perf_stat_config stat_config = { + struct perf_stat_config test_stat_config = { .aggr_mode = AGGR_CORE, .scale = 1, .interval = 1, }; TEST_ASSERT_VAL("failed to synthesize stat_config", - !perf_event__synthesize_stat_config(NULL, &stat_config, process_stat_config_event, NULL)); + !perf_event__synthesize_stat_config(NULL, &test_stat_config, + process_stat_config_event, + NULL)); return 0; } diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c index 68f9407ca74b..2d07c9257a1a 100644 --- a/tools/perf/util/config.c +++ b/tools/perf/util/config.c @@ -13,6 +13,7 @@ #include #include "cache.h" #include "callchain.h" +#include "header.h" #include #include "util/event.h" /* proc_map_timeout */ #include "util/hist.h" /* perf_hist_config */ @@ -34,6 +35,22 @@ #define DEBUG_CACHE_DIR ".debug" +#define METRIC_ONLY_LEN 20 + +struct perf_stat_config stat_config = { + .aggr_mode = AGGR_GLOBAL, + .aggr_level = MAX_CACHE_LVL + 1, + .scale = true, + .unit_width = 4, /* strlen("unit") */ + .run_count = 1, + .metric_only_len = METRIC_ONLY_LEN, + .walltime_nsecs_stats = &walltime_nsecs_stats, + .ru_stats = &ru_stats, + .big_num = true, + .ctl_fd = -1, + .ctl_fd_ack = -1, + .iostat_run = false, +}; char buildid_dir[MAXPATHLEN]; /* root dir for buildid, binary cache */ @@ -455,6 +472,16 @@ static int perf_ui_config(const char *var, const char *value) return 0; } +void perf_stat__set_big_num(int set) +{ + stat_config.big_num = (set != 0); +} + +static void perf_stat__set_no_csv_summary(int set) +{ + stat_config.no_csv_summary = (set != 0); +} + static int perf_stat_config(const char *var, const char *value) { if (!strcmp(var, "stat.big-num")) diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index 4593c937febb..7fc3ec5684c3 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -17,8 +17,6 @@ #include "trace-event.h" #include "mmap.h" #include "util/env.h" -#include "util/kvm-stat.h" -#include "util/stat.h" #include "util/kwork.h" #include "util/sample.h" #include "util/lock-contention.h" @@ -1307,14 +1305,6 @@ error: /* The following are stubs to avoid dragging in builtin-* objects. */ /* TODO: move the code out of the builtin-* file into util. */ -void perf_stat__set_no_csv_summary(int set __maybe_unused) -{ -} - -void perf_stat__set_big_num(int set __maybe_unused) -{ -} - int script_spec_register(const char *spec __maybe_unused, struct scripting_ops *ops __maybe_unused) { return -1; diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h index 6f8cff3cd39a..2fda9acd7374 100644 --- a/tools/perf/util/stat.h +++ b/tools/perf/util/stat.h @@ -117,8 +117,9 @@ struct perf_stat_config { unsigned int topdown_level; }; +extern struct perf_stat_config stat_config; + void perf_stat__set_big_num(int set); -void perf_stat__set_no_csv_summary(int set); void update_stats(struct stats *stats, u64 val); double avg_stats(struct stats *stats); -- cgit v1.2.3 From 04051b4a9330bd84fd3d42bee0eb3d0fd65546ee Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Mon, 18 Nov 2024 17:16:31 -0800 Subject: perf script: Move script_spec code to trace-event-scripting.c The script_spec code is referenced in util/trace-event-scripting but the list was in builtin-script, accessed via a function that required a stub function in python.c. Move all the logic to trace-event-scripting, with lookup and foreach functions exposed for builtin-script's benefit. Signed-off-by: Ian Rogers Tested-by: Arnaldo Carvalho de Melo Acked-by: Arnaldo Carvalho de Melo Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Andi Kleen Cc: Athira Rajeev Cc: Colin Ian King Cc: Dapeng Mi Cc: Howard Chu Cc: Ilya Leoshkevich Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Josh Poimboeuf Cc: Kan Liang Cc: Mark Rutland Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Thomas Richter Cc: Veronika Molnarova Cc: Weilin Wang Link: https://lore.kernel.org/r/20241119011644.971342-10-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-script.c | 67 ++--------------------------- tools/perf/util/python.c | 5 --- tools/perf/util/trace-event-scripting.c | 75 +++++++++++++++++++++++++++++++++ tools/perf/util/trace-event.h | 3 +- 4 files changed, 80 insertions(+), 70 deletions(-) (limited to 'tools/perf/builtin-script.c') diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 7d21a52ad94e..7158669239da 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -2961,79 +2961,18 @@ static int __cmd_script(struct perf_script *script) return ret; } -struct script_spec { - struct list_head node; - struct scripting_ops *ops; - char spec[]; -}; - -static LIST_HEAD(script_specs); - -static struct script_spec *script_spec__new(const char *spec, - struct scripting_ops *ops) +static int list_available_languages_cb(struct scripting_ops *ops, const char *spec) { - struct script_spec *s = malloc(sizeof(*s) + strlen(spec) + 1); - - if (s != NULL) { - strcpy(s->spec, spec); - s->ops = ops; - } - - return s; -} - -static void script_spec__add(struct script_spec *s) -{ - list_add_tail(&s->node, &script_specs); -} - -static struct script_spec *script_spec__find(const char *spec) -{ - struct script_spec *s; - - list_for_each_entry(s, &script_specs, node) - if (strcasecmp(s->spec, spec) == 0) - return s; - return NULL; -} - -int script_spec_register(const char *spec, struct scripting_ops *ops) -{ - struct script_spec *s; - - s = script_spec__find(spec); - if (s) - return -1; - - s = script_spec__new(spec, ops); - if (!s) - return -1; - else - script_spec__add(s); - + fprintf(stderr, " %-42s [%s]\n", spec, ops->name); return 0; } -static struct scripting_ops *script_spec__lookup(const char *spec) -{ - struct script_spec *s = script_spec__find(spec); - if (!s) - return NULL; - - return s->ops; -} - static void list_available_languages(void) { - struct script_spec *s; - fprintf(stderr, "\n"); fprintf(stderr, "Scripting language extensions (used in " "perf script -s [spec:]script.[spec]):\n\n"); - - list_for_each_entry(s, &script_specs, node) - fprintf(stderr, " %-42s [%s]\n", s->spec, s->ops->name); - + script_spec__for_each(&list_available_languages_cb); fprintf(stderr, "\n"); } diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index 7fc3ec5684c3..d157aaa4bb53 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -1305,11 +1305,6 @@ error: /* The following are stubs to avoid dragging in builtin-* objects. */ /* TODO: move the code out of the builtin-* file into util. */ -int script_spec_register(const char *spec __maybe_unused, struct scripting_ops *ops __maybe_unused) -{ - return -1; -} - arch_syscalls__strerrno_t *arch_syscalls__strerrno_function(const char *arch __maybe_unused) { return NULL; diff --git a/tools/perf/util/trace-event-scripting.c b/tools/perf/util/trace-event-scripting.c index a7f0a14c05b6..d8f4b5bce4ad 100644 --- a/tools/perf/util/trace-event-scripting.c +++ b/tools/perf/util/trace-event-scripting.c @@ -24,6 +24,81 @@ unsigned int scripting_max_stack = PERF_MAX_STACK_DEPTH; struct scripting_context *scripting_context; +struct script_spec { + struct list_head node; + struct scripting_ops *ops; + char spec[]; +}; + +static LIST_HEAD(script_specs); + +static struct script_spec *script_spec__new(const char *spec, + struct scripting_ops *ops) +{ + struct script_spec *s = malloc(sizeof(*s) + strlen(spec) + 1); + + if (s != NULL) { + strcpy(s->spec, spec); + s->ops = ops; + } + + return s; +} + +static void script_spec__add(struct script_spec *s) +{ + list_add_tail(&s->node, &script_specs); +} + +static struct script_spec *script_spec__find(const char *spec) +{ + struct script_spec *s; + + list_for_each_entry(s, &script_specs, node) + if (strcasecmp(s->spec, spec) == 0) + return s; + return NULL; +} + +static int script_spec_register(const char *spec, struct scripting_ops *ops) +{ + struct script_spec *s; + + s = script_spec__find(spec); + if (s) + return -1; + + s = script_spec__new(spec, ops); + if (!s) + return -1; + + script_spec__add(s); + return 0; +} + +struct scripting_ops *script_spec__lookup(const char *spec) +{ + struct script_spec *s = script_spec__find(spec); + + if (!s) + return NULL; + + return s->ops; +} + +int script_spec__for_each(int (*cb)(struct scripting_ops *ops, const char *spec)) +{ + struct script_spec *s; + int ret = 0; + + list_for_each_entry(s, &script_specs, node) { + ret = cb(s->ops, s->spec); + if (ret) + break; + } + return ret; +} + void scripting_context__update(struct scripting_context *c, union perf_event *event, struct perf_sample *sample, diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h index 2543bf969fdd..4eacf802c655 100644 --- a/tools/perf/util/trace-event.h +++ b/tools/perf/util/trace-event.h @@ -113,7 +113,8 @@ struct scripting_ops { extern unsigned int scripting_max_stack; -int script_spec_register(const char *spec, struct scripting_ops *ops); +struct scripting_ops *script_spec__lookup(const char *spec); +int script_spec__for_each(int (*cb)(struct scripting_ops *ops, const char *spec)); void script_fetch_insn(struct perf_sample *sample, struct thread *thread, struct machine *machine); -- cgit v1.2.3 From 1ff2ca39b39f2ff5718a74bc4c92183b8eb9763f Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Mon, 18 Nov 2024 17:16:32 -0800 Subject: perf script: Move script_fetch_insn to trace-event-scripting.c Add native_arch as a parameter to script_fetch_insn rather than relying on the builtin-script value that won't be initialized for the dlfilter and python Context use cases. Assume both of those cases are running natively. Signed-off-by: Ian Rogers Tested-by: Arnaldo Carvalho de Melo Acked-by: Arnaldo Carvalho de Melo Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Andi Kleen Cc: Athira Rajeev Cc: Colin Ian King Cc: Dapeng Mi Cc: Howard Chu Cc: Ilya Leoshkevich Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Josh Poimboeuf Cc: Kan Liang Cc: Mark Rutland Cc: Michael Petlan Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Thomas Richter Cc: Veronika Molnarova Cc: Weilin Wang Link: https://lore.kernel.org/r/20241119011644.971342-11-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-script.c | 15 +-------------- tools/perf/scripts/python/Perf-Trace-Util/Context.c | 2 +- tools/perf/util/dlfilter.c | 3 ++- tools/perf/util/python.c | 6 ------ tools/perf/util/trace-event-scripting.c | 14 ++++++++++++++ tools/perf/util/trace-event.h | 2 +- 6 files changed, 19 insertions(+), 23 deletions(-) (limited to 'tools/perf/builtin-script.c') diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 7158669239da..098c5ac6a6f5 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -1586,19 +1586,6 @@ static int perf_sample__fprintf_callindent(struct perf_sample *sample, return len + dlen; } -__weak void arch_fetch_insn(struct perf_sample *sample __maybe_unused, - struct thread *thread __maybe_unused, - struct machine *machine __maybe_unused) -{ -} - -void script_fetch_insn(struct perf_sample *sample, struct thread *thread, - struct machine *machine) -{ - if (sample->insn_len == 0 && native_arch) - arch_fetch_insn(sample, thread, machine); -} - static int perf_sample__fprintf_insn(struct perf_sample *sample, struct evsel *evsel, struct perf_event_attr *attr, @@ -1608,7 +1595,7 @@ static int perf_sample__fprintf_insn(struct perf_sample *sample, { int printed = 0; - script_fetch_insn(sample, thread, machine); + script_fetch_insn(sample, thread, machine, native_arch); if (PRINT_FIELD(INSNLEN)) printed += fprintf(fp, " ilen: %d", sample->insn_len); diff --git a/tools/perf/scripts/python/Perf-Trace-Util/Context.c b/tools/perf/scripts/python/Perf-Trace-Util/Context.c index d742daaa5d5a..60dcfe56d4d9 100644 --- a/tools/perf/scripts/python/Perf-Trace-Util/Context.c +++ b/tools/perf/scripts/python/Perf-Trace-Util/Context.c @@ -93,7 +93,7 @@ static PyObject *perf_sample_insn(PyObject *obj, PyObject *args) if (c->sample->ip && !c->sample->insn_len && thread__maps(c->al->thread)) { struct machine *machine = maps__machine(thread__maps(c->al->thread)); - script_fetch_insn(c->sample, c->al->thread, machine); + script_fetch_insn(c->sample, c->al->thread, machine, /*native_arch=*/true); } if (!c->sample->insn_len) Py_RETURN_NONE; /* N.B. This is a return statement */ diff --git a/tools/perf/util/dlfilter.c b/tools/perf/util/dlfilter.c index 7d180bdaedbc..ddacef881af2 100644 --- a/tools/perf/util/dlfilter.c +++ b/tools/perf/util/dlfilter.c @@ -234,7 +234,8 @@ static const __u8 *dlfilter__insn(void *ctx, __u32 *len) struct machine *machine = maps__machine(thread__maps(al->thread)); if (machine) - script_fetch_insn(d->sample, al->thread, machine); + script_fetch_insn(d->sample, al->thread, machine, + /*native_arch=*/true); } } diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index d157aaa4bb53..3ade7b05def2 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -1317,12 +1317,6 @@ struct kwork_work *perf_kwork_add_work(struct perf_kwork *kwork __maybe_unused, return NULL; } -void script_fetch_insn(struct perf_sample *sample __maybe_unused, - struct thread *thread __maybe_unused, - struct machine *machine __maybe_unused) -{ -} - int perf_sample__sprintf_flags(u32 flags __maybe_unused, char *str __maybe_unused, size_t sz __maybe_unused) { diff --git a/tools/perf/util/trace-event-scripting.c b/tools/perf/util/trace-event-scripting.c index d8f4b5bce4ad..62ba1af79936 100644 --- a/tools/perf/util/trace-event-scripting.c +++ b/tools/perf/util/trace-event-scripting.c @@ -13,6 +13,7 @@ #include #endif +#include "archinsn.h" #include "debug.h" #include "trace-event.h" #include "evsel.h" @@ -271,3 +272,16 @@ void setup_perl_scripting(void) } #endif #endif + +__weak void arch_fetch_insn(struct perf_sample *sample __maybe_unused, + struct thread *thread __maybe_unused, + struct machine *machine __maybe_unused) +{ +} + +void script_fetch_insn(struct perf_sample *sample, struct thread *thread, + struct machine *machine, bool native_arch) +{ + if (sample->insn_len == 0 && native_arch) + arch_fetch_insn(sample, thread, machine); +} diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h index 4eacf802c655..ac9fde2f980c 100644 --- a/tools/perf/util/trace-event.h +++ b/tools/perf/util/trace-event.h @@ -117,7 +117,7 @@ struct scripting_ops *script_spec__lookup(const char *spec); int script_spec__for_each(int (*cb)(struct scripting_ops *ops, const char *spec)); void script_fetch_insn(struct perf_sample *sample, struct thread *thread, - struct machine *machine); + struct machine *machine, bool native_arch); void setup_perl_scripting(void); void setup_python_scripting(void); -- cgit v1.2.3 From dc7be5e4c08feb5310ecbf6a2e7db56b3855c631 Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Mon, 18 Nov 2024 17:16:33 -0800 Subject: perf script: Move perf_sample__sprintf_flags to trace-event-scripting.c perf_sample__sprintf_flags is used in the python C code and so needs to be in the util library rather than a builtin. Signed-off-by: Ian Rogers Link: https://lore.kernel.org/r/20241119011644.971342-12-irogers@google.com Cc: Mark Rutland Cc: Colin Ian King Cc: Howard Chu Cc: Peter Zijlstra Cc: Adrian Hunter Cc: Weilin Wang Cc: Arnaldo Carvalho de Melo Cc: Jiri Olsa Cc: Namhyung Kim Cc: James Clark Cc: Ilya Leoshkevich Cc: Thomas Richter Cc: Andi Kleen Cc: Alexander Shishkin Cc: Dapeng Mi Cc: Kan Liang Cc: Athira Jajeev Cc: Josh Poimboeuf Cc: Ingo Molnar Cc: Michael Petlan Cc: Veronika Molnarova Cc: linux-kernel@vger.kernel.org Cc: linux-perf-users@vger.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-script.c | 81 -------------------------------- tools/perf/util/python.c | 6 --- tools/perf/util/trace-event-scripting.c | 83 +++++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+), 87 deletions(-) (limited to 'tools/perf/builtin-script.c') diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 098c5ac6a6f5..6d5773539cfd 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -1693,87 +1693,6 @@ static int perf_sample__fprintf_bts(struct perf_sample *sample, return printed; } -static struct { - u32 flags; - const char *name; -} sample_flags[] = { - {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL, "call"}, - {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN, "return"}, - {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CONDITIONAL, "jcc"}, - {PERF_IP_FLAG_BRANCH, "jmp"}, - {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_INTERRUPT, "int"}, - {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN | PERF_IP_FLAG_INTERRUPT, "iret"}, - {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_SYSCALLRET, "syscall"}, - {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN | PERF_IP_FLAG_SYSCALLRET, "sysret"}, - {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_ASYNC, "async"}, - {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_ASYNC | PERF_IP_FLAG_INTERRUPT, "hw int"}, - {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TX_ABORT, "tx abrt"}, - {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TRACE_BEGIN, "tr strt"}, - {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TRACE_END, "tr end"}, - {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_VMENTRY, "vmentry"}, - {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_VMEXIT, "vmexit"}, - {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_BRANCH_MISS, "br miss"}, - {0, NULL} -}; - -static const char *sample_flags_to_name(u32 flags) -{ - int i; - - for (i = 0; sample_flags[i].name ; i++) { - if (sample_flags[i].flags == flags) - return sample_flags[i].name; - } - - return NULL; -} - -int perf_sample__sprintf_flags(u32 flags, char *str, size_t sz) -{ - u32 xf = PERF_IP_FLAG_IN_TX | PERF_IP_FLAG_INTR_DISABLE | - PERF_IP_FLAG_INTR_TOGGLE; - const char *chars = PERF_IP_FLAG_CHARS; - const size_t n = strlen(PERF_IP_FLAG_CHARS); - const char *name = NULL; - size_t i, pos = 0; - char xs[16] = {0}; - - if (flags & xf) - snprintf(xs, sizeof(xs), "(%s%s%s)", - flags & PERF_IP_FLAG_IN_TX ? "x" : "", - flags & PERF_IP_FLAG_INTR_DISABLE ? "D" : "", - flags & PERF_IP_FLAG_INTR_TOGGLE ? "t" : ""); - - name = sample_flags_to_name(flags & ~xf); - if (name) - return snprintf(str, sz, "%-15s%6s", name, xs); - - if (flags & PERF_IP_FLAG_TRACE_BEGIN) { - name = sample_flags_to_name(flags & ~(xf | PERF_IP_FLAG_TRACE_BEGIN)); - if (name) - return snprintf(str, sz, "tr strt %-7s%6s", name, xs); - } - - if (flags & PERF_IP_FLAG_TRACE_END) { - name = sample_flags_to_name(flags & ~(xf | PERF_IP_FLAG_TRACE_END)); - if (name) - return snprintf(str, sz, "tr end %-7s%6s", name, xs); - } - - for (i = 0; i < n; i++, flags >>= 1) { - if ((flags & 1) && pos < sz) - str[pos++] = chars[i]; - } - for (; i < 32; i++, flags >>= 1) { - if ((flags & 1) && pos < sz) - str[pos++] = '?'; - } - if (pos < sz) - str[pos] = 0; - - return pos; -} - static int perf_sample__fprintf_flags(u32 flags, FILE *fp) { char str[SAMPLE_FLAGS_BUF_SIZE]; diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index 3ade7b05def2..fa3ab954662c 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -1317,12 +1317,6 @@ struct kwork_work *perf_kwork_add_work(struct perf_kwork *kwork __maybe_unused, return NULL; } -int perf_sample__sprintf_flags(u32 flags __maybe_unused, char *str __maybe_unused, - size_t sz __maybe_unused) -{ - return -1; -} - bool match_callstack_filter(struct machine *machine __maybe_unused, u64 *callstack __maybe_unused) { return false; diff --git a/tools/perf/util/trace-event-scripting.c b/tools/perf/util/trace-event-scripting.c index 62ba1af79936..04e3c9e29f95 100644 --- a/tools/perf/util/trace-event-scripting.c +++ b/tools/perf/util/trace-event-scripting.c @@ -15,6 +15,7 @@ #include "archinsn.h" #include "debug.h" +#include "event.h" #include "trace-event.h" #include "evsel.h" #include @@ -285,3 +286,85 @@ void script_fetch_insn(struct perf_sample *sample, struct thread *thread, if (sample->insn_len == 0 && native_arch) arch_fetch_insn(sample, thread, machine); } + +static const struct { + u32 flags; + const char *name; +} sample_flags[] = { + {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL, "call"}, + {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN, "return"}, + {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CONDITIONAL, "jcc"}, + {PERF_IP_FLAG_BRANCH, "jmp"}, + {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_INTERRUPT, "int"}, + {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN | PERF_IP_FLAG_INTERRUPT, "iret"}, + {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_SYSCALLRET, "syscall"}, + {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN | PERF_IP_FLAG_SYSCALLRET, "sysret"}, + {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_ASYNC, "async"}, + {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_ASYNC | PERF_IP_FLAG_INTERRUPT, + "hw int"}, + {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TX_ABORT, "tx abrt"}, + {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TRACE_BEGIN, "tr strt"}, + {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TRACE_END, "tr end"}, + {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_VMENTRY, "vmentry"}, + {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_VMEXIT, "vmexit"}, + {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_BRANCH_MISS, "br miss"}, + {0, NULL} +}; + +static const char *sample_flags_to_name(u32 flags) +{ + int i; + + for (i = 0; sample_flags[i].name ; i++) { + if (sample_flags[i].flags == flags) + return sample_flags[i].name; + } + + return NULL; +} + +int perf_sample__sprintf_flags(u32 flags, char *str, size_t sz) +{ + u32 xf = PERF_IP_FLAG_IN_TX | PERF_IP_FLAG_INTR_DISABLE | + PERF_IP_FLAG_INTR_TOGGLE; + const char *chars = PERF_IP_FLAG_CHARS; + const size_t n = strlen(PERF_IP_FLAG_CHARS); + const char *name = NULL; + size_t i, pos = 0; + char xs[16] = {0}; + + if (flags & xf) + snprintf(xs, sizeof(xs), "(%s%s%s)", + flags & PERF_IP_FLAG_IN_TX ? "x" : "", + flags & PERF_IP_FLAG_INTR_DISABLE ? "D" : "", + flags & PERF_IP_FLAG_INTR_TOGGLE ? "t" : ""); + + name = sample_flags_to_name(flags & ~xf); + if (name) + return snprintf(str, sz, "%-15s%6s", name, xs); + + if (flags & PERF_IP_FLAG_TRACE_BEGIN) { + name = sample_flags_to_name(flags & ~(xf | PERF_IP_FLAG_TRACE_BEGIN)); + if (name) + return snprintf(str, sz, "tr strt %-7s%6s", name, xs); + } + + if (flags & PERF_IP_FLAG_TRACE_END) { + name = sample_flags_to_name(flags & ~(xf | PERF_IP_FLAG_TRACE_END)); + if (name) + return snprintf(str, sz, "tr end %-7s%6s", name, xs); + } + + for (i = 0; i < n; i++, flags >>= 1) { + if ((flags & 1) && pos < sz) + str[pos++] = chars[i]; + } + for (; i < 32; i++, flags >>= 1) { + if ((flags & 1) && pos < sz) + str[pos++] = '?'; + } + if (pos < sz) + str[pos] = 0; + + return pos; +} -- cgit v1.2.3 From efff5add204fd30c4f1707a87369e00704721315 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 20 Dec 2024 16:10:28 -0300 Subject: perf script: Cache the output type Right now every time we need to figure out the type of an evsel for output purposes we do a quick sequence of ifs, but there are new cases where there is a need to do more complex iterations over multiple data structures, sso allow for caching this operation on a hole of 'struct evsel'. This should really be done on the evsel->priv area that 'perf script' sets up, but more work is needed to make sure that it is allocated when we need it, right now it is only used for conditionally, add some comments so that we move this to that 'perf script' specific area when the conditions are in place for that. Acked-by: Thomas Falcon Cc: Adrian Hunter Cc: Alexander Shishkin Cc: Ian Rogers Cc: Ingo Molnar Cc: James Clark Cc: Jiri Olsa Cc: Kan Liang Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Ravi Bangoria Link: https://lore.kernel.org/lkml/Z2XCi3PgstSrV0SE@x1 Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-script.c | 91 ++++++++++++++++++++++++--------------------- tools/perf/util/evsel.c | 1 + tools/perf/util/evsel.h | 1 + 3 files changed, 51 insertions(+), 42 deletions(-) (limited to 'tools/perf/builtin-script.c') diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 6d5773539cfd..33667b534634 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -221,6 +221,10 @@ enum { OUTPUT_TYPE_MAX }; +// We need to refactor the evsel->priv use in in 'perf script' to allow for +// using that area, that is being used only in some cases. +#define OUTPUT_TYPE_UNSET -1 + /* default set to maintain compatibility with current format */ static struct { bool user_set; @@ -394,6 +398,14 @@ static inline int output_type(unsigned int type) return OUTPUT_TYPE_OTHER; } +static inline int evsel__output_type(struct evsel *evsel) +{ + if (evsel->script_output_type == OUTPUT_TYPE_UNSET) + evsel->script_output_type = output_type(evsel->core.attr.type); + + return evsel->script_output_type; +} + static bool output_set_by_user(void) { int j; @@ -418,13 +430,13 @@ static const char *output_field2str(enum perf_output_field field) return str; } -#define PRINT_FIELD(x) (output[output_type(attr->type)].fields & PERF_OUTPUT_##x) +#define PRINT_FIELD(x) (output[evsel__output_type(evsel)].fields & PERF_OUTPUT_##x) static int evsel__do_check_stype(struct evsel *evsel, u64 sample_type, const char *sample_msg, enum perf_output_field field, bool allow_user_set) { struct perf_event_attr *attr = &evsel->core.attr; - int type = output_type(attr->type); + int type = evsel__output_type(evsel); const char *evname; if (attr->sample_type & sample_type) @@ -458,7 +470,6 @@ static int evsel__check_stype(struct evsel *evsel, u64 sample_type, const char * static int evsel__check_attr(struct evsel *evsel, struct perf_session *session) { - struct perf_event_attr *attr = &evsel->core.attr; bool allow_user_set; if (evsel__is_dummy_event(evsel)) @@ -575,9 +586,9 @@ static int evsel__check_attr(struct evsel *evsel, struct perf_session *session) return 0; } -static void set_print_ip_opts(struct perf_event_attr *attr) +static void evsel__set_print_ip_opts(struct evsel *evsel) { - unsigned int type = output_type(attr->type); + unsigned int type = evsel__output_type(evsel); output[type].print_ip_opts = 0; if (PRINT_FIELD(IP)) @@ -607,7 +618,7 @@ static struct evsel *find_first_output_type(struct evlist *evlist, evlist__for_each_entry(evlist, evsel) { if (evsel__is_dummy_event(evsel)) continue; - if (output_type(evsel->core.attr.type) == (int)type) + if (evsel__output_type(evsel) == (int)type) return evsel; } return NULL; @@ -649,7 +660,7 @@ static int perf_session__check_output_opt(struct perf_session *session) if (output[j].fields & PERF_OUTPUT_DSOFF) output[j].fields |= PERF_OUTPUT_DSO; - set_print_ip_opts(&evsel->core.attr); + evsel__set_print_ip_opts(evsel); tod |= output[j].fields & PERF_OUTPUT_TOD; } @@ -685,7 +696,7 @@ static int perf_session__check_output_opt(struct perf_session *session) output[j].fields |= PERF_OUTPUT_SYM; output[j].fields |= PERF_OUTPUT_SYMOFFSET; output[j].fields |= PERF_OUTPUT_DSO; - set_print_ip_opts(&evsel->core.attr); + evsel__set_print_ip_opts(evsel); goto out; } } @@ -789,7 +800,6 @@ static int perf_sample__fprintf_start(struct perf_script *script, struct evsel *evsel, u32 type, FILE *fp) { - struct perf_event_attr *attr = &evsel->core.attr; unsigned long secs; unsigned long long nsecs; int printed = 0; @@ -941,7 +951,7 @@ static int print_bstack_flags(FILE *fp, struct branch_entry *br) static int perf_sample__fprintf_brstack(struct perf_sample *sample, struct thread *thread, - struct perf_event_attr *attr, FILE *fp) + struct evsel *evsel, FILE *fp) { struct branch_stack *br = sample->branch_stack; struct branch_entry *entries = perf_sample__branch_entries(sample); @@ -980,7 +990,7 @@ static int perf_sample__fprintf_brstack(struct perf_sample *sample, static int perf_sample__fprintf_brstacksym(struct perf_sample *sample, struct thread *thread, - struct perf_event_attr *attr, FILE *fp) + struct evsel *evsel, FILE *fp) { struct branch_stack *br = sample->branch_stack; struct branch_entry *entries = perf_sample__branch_entries(sample); @@ -1018,7 +1028,7 @@ static int perf_sample__fprintf_brstacksym(struct perf_sample *sample, static int perf_sample__fprintf_brstackoff(struct perf_sample *sample, struct thread *thread, - struct perf_event_attr *attr, FILE *fp) + struct evsel *evsel, FILE *fp) { struct branch_stack *br = sample->branch_stack; struct branch_entry *entries = perf_sample__branch_entries(sample); @@ -1185,7 +1195,7 @@ out: return ret; } -static int any_dump_insn(struct perf_event_attr *attr __maybe_unused, +static int any_dump_insn(struct evsel *evsel __maybe_unused, struct perf_insn *x, uint64_t ip, u8 *inbuf, int inlen, int *lenp, FILE *fp) @@ -1213,15 +1223,14 @@ static int add_padding(FILE *fp, int printed, int padding) static int ip__fprintf_jump(uint64_t ip, struct branch_entry *en, struct perf_insn *x, u8 *inbuf, int len, int insn, FILE *fp, int *total_cycles, - struct perf_event_attr *attr, - struct thread *thread, struct evsel *evsel, + struct thread *thread, u64 br_cntr) { int ilen = 0; int printed = fprintf(fp, "\t%016" PRIx64 "\t", ip); - printed += add_padding(fp, any_dump_insn(attr, x, ip, inbuf, len, &ilen, fp), 30); + printed += add_padding(fp, any_dump_insn(evsel, x, ip, inbuf, len, &ilen, fp), 30); printed += fprintf(fp, "\t"); if (PRINT_FIELD(BRSTACKINSNLEN)) @@ -1277,7 +1286,7 @@ static int ip__fprintf_jump(uint64_t ip, struct branch_entry *en, static int ip__fprintf_sym(uint64_t addr, struct thread *thread, u8 cpumode, int cpu, struct symbol **lastsym, - struct perf_event_attr *attr, FILE *fp) + struct evsel *evsel, FILE *fp) { struct addr_location al; int off, printed = 0, ret = 0; @@ -1353,10 +1362,10 @@ static int perf_sample__fprintf_brstackinsn(struct perf_sample *sample, machine, thread, &x.is64bit, &x.cpumode, false); if (len > 0) { printed += ip__fprintf_sym(entries[nr - 1].from, thread, - x.cpumode, x.cpu, &lastsym, attr, fp); + x.cpumode, x.cpu, &lastsym, evsel, fp); printed += ip__fprintf_jump(entries[nr - 1].from, &entries[nr - 1], &x, buffer, len, 0, fp, &total_cycles, - attr, thread, evsel, br_cntr); + evsel, thread, br_cntr); if (PRINT_FIELD(SRCCODE)) printed += print_srccode(thread, x.cpumode, entries[nr - 1].from); } @@ -1384,19 +1393,19 @@ static int perf_sample__fprintf_brstackinsn(struct perf_sample *sample, for (off = 0; off < (unsigned)len; off += ilen) { uint64_t ip = start + off; - printed += ip__fprintf_sym(ip, thread, x.cpumode, x.cpu, &lastsym, attr, fp); + printed += ip__fprintf_sym(ip, thread, x.cpumode, x.cpu, &lastsym, evsel, fp); if (ip == end) { if (PRINT_FIELD(BRCNTR) && sample->branch_stack_cntr) br_cntr = sample->branch_stack_cntr[i]; printed += ip__fprintf_jump(ip, &entries[i], &x, buffer + off, len - off, ++insn, fp, - &total_cycles, attr, thread, evsel, br_cntr); + &total_cycles, evsel, thread, br_cntr); if (PRINT_FIELD(SRCCODE)) printed += print_srccode(thread, x.cpumode, ip); break; } else { ilen = 0; printed += fprintf(fp, "\t%016" PRIx64 "\t", ip); - printed += any_dump_insn(attr, &x, ip, buffer + off, len - off, &ilen, fp); + printed += any_dump_insn(evsel, &x, ip, buffer + off, len - off, &ilen, fp); if (PRINT_FIELD(BRSTACKINSNLEN)) printed += fprintf(fp, "\tilen: %d", ilen); printed += fprintf(fp, "\n"); @@ -1435,7 +1444,7 @@ static int perf_sample__fprintf_brstackinsn(struct perf_sample *sample, end = start + 128; } len = grab_bb(buffer, start, end, machine, thread, &x.is64bit, &x.cpumode, true); - printed += ip__fprintf_sym(start, thread, x.cpumode, x.cpu, &lastsym, attr, fp); + printed += ip__fprintf_sym(start, thread, x.cpumode, x.cpu, &lastsym, evsel, fp); if (len <= 0) { /* Print at least last IP if basic block did not work */ len = grab_bb(buffer, sample->ip, sample->ip, @@ -1444,7 +1453,7 @@ static int perf_sample__fprintf_brstackinsn(struct perf_sample *sample, goto out; ilen = 0; printed += fprintf(fp, "\t%016" PRIx64 "\t", sample->ip); - printed += any_dump_insn(attr, &x, sample->ip, buffer, len, &ilen, fp); + printed += any_dump_insn(evsel, &x, sample->ip, buffer, len, &ilen, fp); if (PRINT_FIELD(BRSTACKINSNLEN)) printed += fprintf(fp, "\tilen: %d", ilen); printed += fprintf(fp, "\n"); @@ -1455,7 +1464,7 @@ static int perf_sample__fprintf_brstackinsn(struct perf_sample *sample, for (off = 0; off <= end - start; off += ilen) { ilen = 0; printed += fprintf(fp, "\t%016" PRIx64 "\t", start + off); - printed += any_dump_insn(attr, &x, start + off, buffer + off, len - off, &ilen, fp); + printed += any_dump_insn(evsel, &x, start + off, buffer + off, len - off, &ilen, fp); if (PRINT_FIELD(BRSTACKINSNLEN)) printed += fprintf(fp, "\tilen: %d", ilen); printed += fprintf(fp, "\n"); @@ -1479,13 +1488,13 @@ out: static int perf_sample__fprintf_addr(struct perf_sample *sample, struct thread *thread, - struct perf_event_attr *attr, FILE *fp) + struct evsel *evsel, FILE *fp) { struct addr_location al; int printed = fprintf(fp, "%16" PRIx64, sample->addr); addr_location__init(&al); - if (!sample_addr_correlates_sym(attr)) + if (!sample_addr_correlates_sym(&evsel->core.attr)) goto out; thread__resolve(thread, &al, sample); @@ -1512,11 +1521,10 @@ static const char *resolve_branch_sym(struct perf_sample *sample, struct addr_location *addr_al, u64 *ip) { - struct perf_event_attr *attr = &evsel->core.attr; const char *name = NULL; if (sample->flags & (PERF_IP_FLAG_CALL | PERF_IP_FLAG_TRACE_BEGIN)) { - if (sample_addr_correlates_sym(attr)) { + if (sample_addr_correlates_sym(&evsel->core.attr)) { if (!addr_al->thread) thread__resolve(thread, addr_al, sample); if (addr_al->sym) @@ -1542,7 +1550,6 @@ static int perf_sample__fprintf_callindent(struct perf_sample *sample, struct addr_location *addr_al, FILE *fp) { - struct perf_event_attr *attr = &evsel->core.attr; size_t depth = thread_stack__depth(thread, sample->cpu); const char *name = NULL; static int spacing; @@ -1614,7 +1621,7 @@ static int perf_sample__fprintf_insn(struct perf_sample *sample, } static int perf_sample__fprintf_ipc(struct perf_sample *sample, - struct perf_event_attr *attr, FILE *fp) + struct evsel *evsel, FILE *fp) { unsigned int ipc; @@ -1635,7 +1642,7 @@ static int perf_sample__fprintf_bts(struct perf_sample *sample, struct machine *machine, FILE *fp) { struct perf_event_attr *attr = &evsel->core.attr; - unsigned int type = output_type(attr->type); + unsigned int type = evsel__output_type(evsel); bool print_srcline_last = false; int printed = 0; @@ -1672,10 +1679,10 @@ static int perf_sample__fprintf_bts(struct perf_sample *sample, ((evsel->core.attr.sample_type & PERF_SAMPLE_ADDR) && !output[type].user_set)) { printed += fprintf(fp, " => "); - printed += perf_sample__fprintf_addr(sample, thread, attr, fp); + printed += perf_sample__fprintf_addr(sample, thread, evsel, fp); } - printed += perf_sample__fprintf_ipc(sample, attr, fp); + printed += perf_sample__fprintf_ipc(sample, evsel, fp); if (print_srcline_last) printed += map__fprintf_srcline(al->map, al->addr, "\n ", fp); @@ -2157,7 +2164,7 @@ static void process_event(struct perf_script *script, { struct thread *thread = al->thread; struct perf_event_attr *attr = &evsel->core.attr; - unsigned int type = output_type(attr->type); + unsigned int type = evsel__output_type(evsel); struct evsel_script *es = evsel->priv; FILE *fp = es->fp; char str[PAGE_SIZE_NAME_LEN]; @@ -2205,7 +2212,7 @@ static void process_event(struct perf_script *script, perf_sample__fprintf_synth(sample, evsel, fp); if (PRINT_FIELD(ADDR)) - perf_sample__fprintf_addr(sample, thread, attr, fp); + perf_sample__fprintf_addr(sample, thread, evsel, fp); if (PRINT_FIELD(DATA_SRC)) data_src__fprintf(sample->data_src, fp); @@ -2255,11 +2262,11 @@ static void process_event(struct perf_script *script, perf_sample__fprintf_uregs(sample, attr, arch, fp); if (PRINT_FIELD(BRSTACK)) - perf_sample__fprintf_brstack(sample, thread, attr, fp); + perf_sample__fprintf_brstack(sample, thread, evsel, fp); else if (PRINT_FIELD(BRSTACKSYM)) - perf_sample__fprintf_brstacksym(sample, thread, attr, fp); + perf_sample__fprintf_brstacksym(sample, thread, evsel, fp); else if (PRINT_FIELD(BRSTACKOFF)) - perf_sample__fprintf_brstackoff(sample, thread, attr, fp); + perf_sample__fprintf_brstackoff(sample, thread, evsel, fp); if (evsel__is_bpf_output(evsel) && PRINT_FIELD(BPF_OUTPUT)) perf_sample__fprintf_bpf_output(sample, fp); @@ -2274,7 +2281,7 @@ static void process_event(struct perf_script *script, if (PRINT_FIELD(CODE_PAGE_SIZE)) fprintf(fp, " %s", get_page_size_name(sample->code_page_size, str)); - perf_sample__fprintf_ipc(sample, attr, fp); + perf_sample__fprintf_ipc(sample, evsel, fp); fprintf(fp, "\n"); @@ -2507,14 +2514,14 @@ static int process_attr(const struct perf_tool *tool, union perf_event *event, sample_type & PERF_SAMPLE_BRANCH_STACK || (sample_type & PERF_SAMPLE_REGS_USER && sample_type & PERF_SAMPLE_STACK_USER))) { - int type = output_type(evsel->core.attr.type); + int type = evsel__output_type(evsel); if (!(output[type].user_unset_fields & PERF_OUTPUT_IP)) output[type].fields |= PERF_OUTPUT_IP; if (!(output[type].user_unset_fields & PERF_OUTPUT_SYM)) output[type].fields |= PERF_OUTPUT_SYM; } - set_print_ip_opts(&evsel->core.attr); + evsel__set_print_ip_opts(evsel); return 0; } diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 6ae5d110994a..697428efa644 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -395,6 +395,7 @@ void evsel__init(struct evsel *evsel, evsel->group_pmu_name = NULL; evsel->skippable = false; evsel->alternate_hw_config = PERF_COUNT_HW_MAX; + evsel->script_output_type = -1; // FIXME: OUTPUT_TYPE_UNSET, see builtin-script.c } struct evsel *evsel__new_idx(struct perf_event_attr *attr, int idx) diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 5ad352c94d00..5e789fa80590 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -121,6 +121,7 @@ struct evsel { bool default_metricgroup; /* A member of the Default metricgroup */ struct hashmap *per_pkg_mask; int err; + int script_output_type; struct { evsel__sb_cb_t *cb; void *data; -- cgit v1.2.3