Merge branch 'next/drivers' into HEAD
[deliverable/linux.git] / tools / perf / builtin-script.c
index 1e60ab70b2b14789b17a2a7199f5a8d175709242..1be843aa1546ed1df603119e3cec193d04cf0673 100644 (file)
@@ -14,6 +14,7 @@
 #include "util/util.h"
 #include "util/evlist.h"
 #include "util/evsel.h"
+#include "util/sort.h"
 #include <linux/bitmap.h>
 
 static char const              *script_name;
@@ -28,11 +29,6 @@ static bool                  system_wide;
 static const char              *cpu_list;
 static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
 
-struct perf_script {
-       struct perf_tool    tool;
-       struct perf_session *session;
-};
-
 enum perf_output_field {
        PERF_OUTPUT_COMM            = 1U << 0,
        PERF_OUTPUT_TID             = 1U << 1,
@@ -262,14 +258,11 @@ static int perf_session__check_output_opt(struct perf_session *session)
        return 0;
 }
 
-static void print_sample_start(struct pevent *pevent,
-                              struct perf_sample *sample,
+static void print_sample_start(struct perf_sample *sample,
                               struct thread *thread,
                               struct perf_evsel *evsel)
 {
-       int type;
        struct perf_event_attr *attr = &evsel->attr;
-       struct event_format *event;
        const char *evname = NULL;
        unsigned long secs;
        unsigned long usecs;
@@ -307,20 +300,7 @@ static void print_sample_start(struct pevent *pevent,
        }
 
        if (PRINT_FIELD(EVNAME)) {
-               if (attr->type == PERF_TYPE_TRACEPOINT) {
-                       /*
-                        * XXX Do we really need this here?
-                        * perf_evlist__set_tracepoint_names should have done
-                        * this already
-                        */
-                       type = trace_parse_common_type(pevent,
-                                                      sample->raw_data);
-                       event = pevent_find_event(pevent, type);
-                       if (event)
-                               evname = event->name;
-               } else
-                       evname = perf_evsel__name(evsel);
-
+               evname = perf_evsel__name(evsel);
                printf("%s: ", evname ? evname : "[unknown]");
        }
 }
@@ -401,7 +381,7 @@ static void print_sample_bts(union perf_event *event,
                        printf(" ");
                else
                        printf("\n");
-               perf_event__print_ip(event, sample, machine,
+               perf_evsel__print_ip(evsel, event, sample, machine,
                                     PRINT_FIELD(SYM), PRINT_FIELD(DSO),
                                     PRINT_FIELD(SYMOFFSET));
        }
@@ -415,19 +395,17 @@ static void print_sample_bts(union perf_event *event,
        printf("\n");
 }
 
-static void process_event(union perf_event *event __unused,
-                         struct pevent *pevent,
-                         struct perf_sample *sample,
-                         struct perf_evsel *evsel,
-                         struct machine *machine,
-                         struct thread *thread)
+static void process_event(union perf_event *event, struct perf_sample *sample,
+                         struct perf_evsel *evsel, struct machine *machine,
+                         struct addr_location *al)
 {
        struct perf_event_attr *attr = &evsel->attr;
+       struct thread *thread = al->thread;
 
        if (output[attr->type].fields == 0)
                return;
 
-       print_sample_start(pevent, sample, thread, evsel);
+       print_sample_start(sample, thread, evsel);
 
        if (is_bts_event(attr)) {
                print_sample_bts(event, sample, evsel, machine, thread);
@@ -435,9 +413,8 @@ static void process_event(union perf_event *event __unused,
        }
 
        if (PRINT_FIELD(TRACE))
-               print_trace_event(pevent, sample->cpu, sample->raw_data,
-                                 sample->raw_size);
-
+               event_format__print(evsel->tp_format, sample->cpu,
+                                   sample->raw_data, sample->raw_size);
        if (PRINT_FIELD(ADDR))
                print_sample_addr(event, sample, machine, thread, attr);
 
@@ -446,7 +423,7 @@ static void process_event(union perf_event *event __unused,
                        printf(" ");
                else
                        printf("\n");
-               perf_event__print_ip(event, sample, machine,
+               perf_evsel__print_ip(evsel, event, sample, machine,
                                     PRINT_FIELD(SYM), PRINT_FIELD(DSO),
                                     PRINT_FIELD(SYMOFFSET));
        }
@@ -454,9 +431,9 @@ static void process_event(union perf_event *event __unused,
        printf("\n");
 }
 
-static int default_start_script(const char *script __unused,
-                               int argc __unused,
-                               const char **argv __unused)
+static int default_start_script(const char *script __maybe_unused,
+                               int argc __maybe_unused,
+                               const char **argv __maybe_unused)
 {
        return 0;
 }
@@ -466,8 +443,8 @@ static int default_stop_script(void)
        return 0;
 }
 
-static int default_generate_script(struct pevent *pevent __unused,
-                                  const char *outfile __unused)
+static int default_generate_script(struct pevent *pevent __maybe_unused,
+                                  const char *outfile __maybe_unused)
 {
        return 0;
 }
@@ -498,14 +475,13 @@ static int cleanup_scripting(void)
 
 static const char *input_name;
 
-static int process_sample_event(struct perf_tool *tool __used,
+static int process_sample_event(struct perf_tool *tool __maybe_unused,
                                union perf_event *event,
                                struct perf_sample *sample,
                                struct perf_evsel *evsel,
                                struct machine *machine)
 {
        struct addr_location al;
-       struct perf_script *scr = container_of(tool, struct perf_script, tool);
        struct thread *thread = machine__findnew_thread(machine, event->ip.tid);
 
        if (thread == NULL) {
@@ -537,32 +513,29 @@ static int process_sample_event(struct perf_tool *tool __used,
        if (cpu_list && !test_bit(sample->cpu, cpu_bitmap))
                return 0;
 
-       scripting_ops->process_event(event, scr->session->pevent,
-                                    sample, evsel, machine, thread);
+       scripting_ops->process_event(event, sample, evsel, machine, &al);
 
        evsel->hists.stats.total_period += sample->period;
        return 0;
 }
 
-static struct perf_script perf_script = {
-       .tool = {
-               .sample          = process_sample_event,
-               .mmap            = perf_event__process_mmap,
-               .comm            = perf_event__process_comm,
-               .exit            = perf_event__process_task,
-               .fork            = perf_event__process_task,
-               .attr            = perf_event__process_attr,
-               .event_type      = perf_event__process_event_type,
-               .tracing_data    = perf_event__process_tracing_data,
-               .build_id        = perf_event__process_build_id,
-               .ordered_samples = true,
-               .ordering_requires_timestamps = true,
-       },
+static struct perf_tool perf_script = {
+       .sample          = process_sample_event,
+       .mmap            = perf_event__process_mmap,
+       .comm            = perf_event__process_comm,
+       .exit            = perf_event__process_task,
+       .fork            = perf_event__process_task,
+       .attr            = perf_event__process_attr,
+       .event_type      = perf_event__process_event_type,
+       .tracing_data    = perf_event__process_tracing_data,
+       .build_id        = perf_event__process_build_id,
+       .ordered_samples = true,
+       .ordering_requires_timestamps = true,
 };
 
 extern volatile int session_done;
 
-static void sig_handler(int sig __unused)
+static void sig_handler(int sig __maybe_unused)
 {
        session_done = 1;
 }
@@ -573,7 +546,7 @@ static int __cmd_script(struct perf_session *session)
 
        signal(SIGINT, sig_handler);
 
-       ret = perf_session__process_events(session, &perf_script.tool);
+       ret = perf_session__process_events(session, &perf_script);
 
        if (debug_mode)
                pr_err("Misordered timestamps: %" PRIu64 "\n", nr_unordered);
@@ -672,8 +645,8 @@ static void list_available_languages(void)
        fprintf(stderr, "\n");
 }
 
-static int parse_scriptname(const struct option *opt __used,
-                           const char *str, int unset __used)
+static int parse_scriptname(const struct option *opt __maybe_unused,
+                           const char *str, int unset __maybe_unused)
 {
        char spec[PATH_MAX];
        const char *script, *ext;
@@ -718,8 +691,8 @@ static int parse_scriptname(const struct option *opt __used,
        return 0;
 }
 
-static int parse_output_fields(const struct option *opt __used,
-                           const char *arg, int unset __used)
+static int parse_output_fields(const struct option *opt __maybe_unused,
+                           const char *arg, int unset __maybe_unused)
 {
        char *tok;
        int i, imax = sizeof(all_output_options) / sizeof(struct output_option);
@@ -1010,8 +983,9 @@ static char *get_script_root(struct dirent *script_dirent, const char *suffix)
        return script_root;
 }
 
-static int list_available_scripts(const struct option *opt __used,
-                                 const char *s __used, int unset __used)
+static int list_available_scripts(const struct option *opt __maybe_unused,
+                                 const char *s __maybe_unused,
+                                 int unset __maybe_unused)
 {
        struct dirent *script_next, *lang_next, script_dirent, lang_dirent;
        char scripts_path[MAXPATHLEN];
@@ -1058,6 +1032,61 @@ static int list_available_scripts(const struct option *opt __used,
        exit(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)
+{
+       struct dirent *script_next, *lang_next, script_dirent, lang_dirent;
+       char scripts_path[MAXPATHLEN];
+       DIR *scripts_dir, *lang_dir;
+       char lang_path[MAXPATHLEN];
+       char *temp;
+       int i = 0;
+
+       snprintf(scripts_path, MAXPATHLEN, "%s/scripts", perf_exec_path());
+
+       scripts_dir = opendir(scripts_path);
+       if (!scripts_dir)
+               return -1;
+
+       for_each_lang(scripts_path, scripts_dir, lang_dirent, lang_next) {
+               snprintf(lang_path, MAXPATHLEN, "%s/%s", scripts_path,
+                        lang_dirent.d_name);
+#ifdef NO_LIBPERL
+               if (strstr(lang_path, "perl"))
+                       continue;
+#endif
+#ifdef NO_LIBPYTHON
+               if (strstr(lang_path, "python"))
+                       continue;
+#endif
+
+               lang_dir = opendir(lang_path);
+               if (!lang_dir)
+                       continue;
+
+               for_each_script(lang_path, lang_dir, script_dirent, script_next) {
+                       /* Skip those real time scripts: xxxtop.p[yl] */
+                       if (strstr(script_dirent.d_name, "top."))
+                               continue;
+                       sprintf(scripts_path_array[i], "%s/%s", lang_path,
+                               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);
+                       i++;
+               }
+       }
+
+       return i;
+}
+
 static char *get_script_path(const char *script_root, const char *suffix)
 {
        struct dirent *script_next, *lang_next, script_dirent, lang_dirent;
@@ -1170,6 +1199,8 @@ static const struct option options[] = {
                     parse_output_fields),
        OPT_BOOLEAN('a', "all-cpus", &system_wide,
                     "system-wide collection from all CPUs"),
+       OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
+                  "only consider these symbols"),
        OPT_STRING('C', "cpu", &cpu_list, "cpu", "list of cpus to profile"),
        OPT_STRING('c', "comms", &symbol_conf.comm_list_str, "comm[,comm...]",
                   "only display events for these comms"),
@@ -1181,21 +1212,26 @@ static const struct option options[] = {
        OPT_END()
 };
 
-static bool have_cmd(int argc, const char **argv)
+static int have_cmd(int argc, const char **argv)
 {
        char **__argv = malloc(sizeof(const char *) * argc);
 
-       if (!__argv)
-               die("malloc");
+       if (!__argv) {
+               pr_err("malloc failed\n");
+               return -1;
+       }
+
        memcpy(__argv, argv, sizeof(const char *) * argc);
        argc = parse_options(argc, (const char **)__argv, record_options,
                             NULL, PARSE_OPT_STOP_AT_NON_OPTION);
        free(__argv);
 
-       return argc != 0;
+       system_wide = (argc == 0);
+
+       return 0;
 }
 
-int cmd_script(int argc, const char **argv, const char *prefix __used)
+int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
 {
        char *rec_script_path = NULL;
        char *rep_script_path = NULL;
@@ -1259,13 +1295,13 @@ int cmd_script(int argc, const char **argv, const char *prefix __used)
 
                if (pipe(live_pipe) < 0) {
                        perror("failed to create pipe");
-                       exit(-1);
+                       return -1;
                }
 
                pid = fork();
                if (pid < 0) {
                        perror("failed to fork");
-                       exit(-1);
+                       return -1;
                }
 
                if (!pid) {
@@ -1277,13 +1313,18 @@ int cmd_script(int argc, const char **argv, const char *prefix __used)
                        if (is_top_script(argv[0])) {
                                system_wide = true;
                        } else if (!system_wide) {
-                               system_wide = !have_cmd(argc - rep_args,
-                                                       &argv[rep_args]);
+                               if (have_cmd(argc - rep_args, &argv[rep_args]) != 0) {
+                                       err = -1;
+                                       goto out;
+                               }
                        }
 
                        __argv = malloc((argc + 6) * sizeof(const char *));
-                       if (!__argv)
-                               die("malloc");
+                       if (!__argv) {
+                               pr_err("malloc failed\n");
+                               err = -ENOMEM;
+                               goto out;
+                       }
 
                        __argv[j++] = "/bin/sh";
                        __argv[j++] = rec_script_path;
@@ -1305,8 +1346,12 @@ int cmd_script(int argc, const char **argv, const char *prefix __used)
                close(live_pipe[1]);
 
                __argv = malloc((argc + 4) * sizeof(const char *));
-               if (!__argv)
-                       die("malloc");
+               if (!__argv) {
+                       pr_err("malloc failed\n");
+                       err = -ENOMEM;
+                       goto out;
+               }
+
                j = 0;
                __argv[j++] = "/bin/sh";
                __argv[j++] = rep_script_path;
@@ -1331,12 +1376,20 @@ int cmd_script(int argc, const char **argv, const char *prefix __used)
 
                if (!rec_script_path)
                        system_wide = false;
-               else if (!system_wide)
-                       system_wide = !have_cmd(argc - 1, &argv[1]);
+               else if (!system_wide) {
+                       if (have_cmd(argc - 1, &argv[1]) != 0) {
+                               err = -1;
+                               goto out;
+                       }
+               }
 
                __argv = malloc((argc + 2) * sizeof(const char *));
-               if (!__argv)
-                       die("malloc");
+               if (!__argv) {
+                       pr_err("malloc failed\n");
+                       err = -ENOMEM;
+                       goto out;
+               }
+
                __argv[j++] = "/bin/sh";
                __argv[j++] = script_path;
                if (system_wide)
@@ -1356,12 +1409,10 @@ int cmd_script(int argc, const char **argv, const char *prefix __used)
                setup_pager();
 
        session = perf_session__new(input_name, O_RDONLY, 0, false,
-                                   &perf_script.tool);
+                                   &perf_script);
        if (session == NULL)
                return -ENOMEM;
 
-       perf_script.session = session;
-
        if (cpu_list) {
                if (perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap))
                        return -1;
@@ -1387,18 +1438,18 @@ int cmd_script(int argc, const char **argv, const char *prefix __used)
                input = open(session->filename, O_RDONLY);      /* input_name */
                if (input < 0) {
                        perror("failed to open file");
-                       exit(-1);
+                       return -1;
                }
 
                err = fstat(input, &perf_stat);
                if (err < 0) {
                        perror("failed to stat file");
-                       exit(-1);
+                       return -1;
                }
 
                if (!perf_stat.st_size) {
                        fprintf(stderr, "zero-sized file, nothing to do!\n");
-                       exit(0);
+                       return 0;
                }
 
                scripting_ops = script_spec__lookup(generate_script_lang);
This page took 0.045106 seconds and 5 git commands to generate.