Merge remote-tracking branch 'torvalds/master' into perf/core
[linux-2.6-microblaze.git] / tools / perf / builtin-script.c
index 1280cbf..57488d6 100644 (file)
@@ -1417,6 +1417,13 @@ __weak void arch_fetch_insn(struct perf_sample *sample __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 perf_event_attr *attr,
                                     struct thread *thread,
@@ -1424,8 +1431,7 @@ static int perf_sample__fprintf_insn(struct perf_sample *sample,
 {
        int printed = 0;
 
-       if (sample->insn_len == 0 && native_arch)
-               arch_fetch_insn(sample, thread, machine);
+       script_fetch_insn(sample, thread, machine);
 
        if (PRINT_FIELD(INSNLEN))
                printed += fprintf(fp, " ilen: %d", sample->insn_len);
@@ -1553,41 +1559,49 @@ static const char *sample_flags_to_name(u32 flags)
        return NULL;
 }
 
-static int perf_sample__fprintf_flags(u32 flags, FILE *fp)
+int perf_sample__sprintf_flags(u32 flags, char *str, size_t sz)
 {
        const char *chars = PERF_IP_FLAG_CHARS;
-       const int n = strlen(PERF_IP_FLAG_CHARS);
+       const size_t n = strlen(PERF_IP_FLAG_CHARS);
        bool in_tx = flags & PERF_IP_FLAG_IN_TX;
        const char *name = NULL;
-       char str[33];
-       int i, pos = 0;
+       size_t i, pos = 0;
 
        name = sample_flags_to_name(flags & ~PERF_IP_FLAG_IN_TX);
        if (name)
-               return fprintf(fp, "  %-15s%4s ", name, in_tx ? "(x)" : "");
+               return snprintf(str, sz, "%-15s%4s", name, in_tx ? "(x)" : "");
 
        if (flags & PERF_IP_FLAG_TRACE_BEGIN) {
                name = sample_flags_to_name(flags & ~(PERF_IP_FLAG_IN_TX | PERF_IP_FLAG_TRACE_BEGIN));
                if (name)
-                       return fprintf(fp, "  tr strt %-7s%4s ", name, in_tx ? "(x)" : "");
+                       return snprintf(str, sz, "tr strt %-7s%4s", name, in_tx ? "(x)" : "");
        }
 
        if (flags & PERF_IP_FLAG_TRACE_END) {
                name = sample_flags_to_name(flags & ~(PERF_IP_FLAG_IN_TX | PERF_IP_FLAG_TRACE_END));
                if (name)
-                       return fprintf(fp, "  tr end  %-7s%4s ", name, in_tx ? "(x)" : "");
+                       return snprintf(str, sz, "tr end  %-7s%4s", name, in_tx ? "(x)" : "");
        }
 
        for (i = 0; i < n; i++, flags >>= 1) {
-               if (flags & 1)
+               if ((flags & 1) && pos < sz)
                        str[pos++] = chars[i];
        }
        for (; i < 32; i++, flags >>= 1) {
-               if (flags & 1)
+               if ((flags & 1) && pos < sz)
                        str[pos++] = '?';
        }
-       str[pos] = 0;
+       if (pos < sz)
+               str[pos] = 0;
+
+       return pos;
+}
 
+static int perf_sample__fprintf_flags(u32 flags, FILE *fp)
+{
+       char str[SAMPLE_FLAGS_BUF_SIZE];
+
+       perf_sample__sprintf_flags(flags, str, sizeof(str));
        return fprintf(fp, "  %-19s ", str);
 }
 
@@ -2189,10 +2203,19 @@ static int process_sample_event(struct perf_tool *tool,
        if (filter_cpu(sample))
                goto out_put;
 
-       if (scripting_ops)
-               scripting_ops->process_event(event, sample, evsel, &al);
-       else
+       if (scripting_ops) {
+               struct addr_location *addr_al_ptr = NULL;
+               struct addr_location addr_al;
+
+               if ((evsel->core.attr.sample_type & PERF_SAMPLE_ADDR) &&
+                   sample_addr_correlates_sym(&evsel->core.attr)) {
+                       thread__resolve(al.thread, &addr_al, sample);
+                       addr_al_ptr = &addr_al;
+               }
+               scripting_ops->process_event(event, sample, evsel, &al, addr_al_ptr);
+       } else {
                process_event(scr, sample, evsel, &al, machine);
+       }
 
 out_put:
        addr_location__put(&al);
@@ -2415,6 +2438,17 @@ static int process_switch_event(struct perf_tool *tool,
                           sample->tid);
 }
 
+static int process_auxtrace_error(struct perf_session *session,
+                                 union perf_event *event)
+{
+       if (scripting_ops && scripting_ops->process_auxtrace_error) {
+               scripting_ops->process_auxtrace_error(session, event);
+               return 0;
+       }
+
+       return perf_event__process_auxtrace_error(session, event);
+}
+
 static int
 process_lost_event(struct perf_tool *tool,
                   union perf_event *event,
@@ -2554,6 +2588,8 @@ static int __cmd_script(struct perf_script *script)
        }
        if (script->show_switch_events || (scripting_ops && scripting_ops->process_switch))
                script->tool.context_switch = process_switch_event;
+       if (scripting_ops && scripting_ops->process_auxtrace_error)
+               script->tool.auxtrace_error = process_auxtrace_error;
        if (script->show_namespace_events)
                script->tool.namespaces = process_namespaces_event;
        if (script->show_cgroup_events)
@@ -2665,6 +2701,37 @@ static void list_available_languages(void)
        fprintf(stderr, "\n");
 }
 
+/* Find script file relative to current directory or exec path */
+static char *find_script(const char *script)
+{
+       char path[PATH_MAX];
+
+       if (!scripting_ops) {
+               const char *ext = strrchr(script, '.');
+
+               if (!ext)
+                       return NULL;
+
+               scripting_ops = script_spec__lookup(++ext);
+               if (!scripting_ops)
+                       return NULL;
+       }
+
+       if (access(script, R_OK)) {
+               char *exec_path = get_argv_exec_path();
+
+               if (!exec_path)
+                       return NULL;
+               snprintf(path, sizeof(path), "%s/scripts/%s/%s",
+                        exec_path, scripting_ops->dirname, script);
+               free(exec_path);
+               script = path;
+               if (access(script, R_OK))
+                       return NULL;
+       }
+       return strdup(script);
+}
+
 static int parse_scriptname(const struct option *opt __maybe_unused,
                            const char *str, int unset __maybe_unused)
 {
@@ -2706,7 +2773,9 @@ static int parse_scriptname(const struct option *opt __maybe_unused,
                }
        }
 
-       script_name = strdup(script);
+       script_name = find_script(script);
+       if (!script_name)
+               script_name = strdup(script);
 
        return 0;
 }
@@ -3718,6 +3787,12 @@ int cmd_script(int argc, const char **argv)
                rep_script_path = get_script_path(argv[0], REPORT_SUFFIX);
 
                if (!rec_script_path && !rep_script_path) {
+                       script_name = find_script(argv[0]);
+                       if (script_name) {
+                               argc -= 1;
+                               argv += 1;
+                               goto script_found;
+                       }
                        usage_with_options_msg(script_usage, options,
                                "Couldn't find script `%s'\n\n See perf"
                                " script -l for available scripts.\n", argv[0]);
@@ -3810,7 +3885,7 @@ int cmd_script(int argc, const char **argv)
                free(__argv);
                exit(-1);
        }
-
+script_found:
        if (rec_script_path)
                script_path = rec_script_path;
        if (rep_script_path)
@@ -3948,7 +4023,7 @@ int cmd_script(int argc, const char **argv)
        }
 
        if (script_name) {
-               err = scripting_ops->start_script(script_name, argc, argv);
+               err = scripting_ops->start_script(script_name, argc, argv, session);
                if (err)
                        goto out_delete;
                pr_debug("perf script started with script %s\n\n", script_name);