diff options
Diffstat (limited to 'tools/perf/builtin-script.c')
| -rw-r--r-- | tools/perf/builtin-script.c | 173 |
1 files changed, 96 insertions, 77 deletions
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index c8ac9f01a36b..ad8ca08ceb5f 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -1,74 +1,78 @@ // SPDX-License-Identifier: GPL-2.0 -#include "builtin.h" +#include <errno.h> +#include <inttypes.h> +#include <signal.h> +#include <stdio.h> +#include <dirent.h> +#include <fcntl.h> +#include <linux/bitmap.h> +#include <linux/compiler.h> +#include <linux/ctype.h> +#include <linux/err.h> +#include <linux/kernel.h> +#include <linux/stringify.h> +#include <linux/time64.h> +#include <linux/unaligned.h> +#include <linux/zalloc.h> +#include <sys/param.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/utsname.h> +#include <unistd.h> + +#include <perf/evlist.h> +#include <subcmd/exec-cmd.h> +#include <subcmd/pager.h> +#include <subcmd/parse-options.h> + +#include "asm/bug.h" +#include "builtin.h" +#include "perf.h" +#include "print_binary.h" +#include "print_insn.h" +#include "ui/ui.h" +#include "util/annotate.h" +#include "util/auxtrace.h" +#include "util/cgroup.h" +#include "util/color.h" #include "util/counts.h" +#include "util/cpumap.h" +#include "util/data.h" #include "util/debug.h" +#include "util/dlfilter.h" #include "util/dso.h" -#include <subcmd/exec-cmd.h> -#include "util/header.h" -#include <subcmd/parse-options.h> -#include "util/perf_regs.h" -#include "util/session.h" -#include "util/tool.h" -#include "util/map.h" -#include "util/srcline.h" -#include "util/symbol.h" -#include "util/thread.h" -#include "util/trace-event.h" +#include "util/dump-insn.h" #include "util/env.h" +#include "util/event.h" #include "util/evlist.h" #include "util/evsel.h" #include "util/evsel_fprintf.h" #include "util/evswitch.h" +#include "util/header.h" +#include "util/map.h" +#include "util/mem-events.h" +#include "util/mem-info.h" +#include "util/metricgroup.h" +#include "util/path.h" +#include "util/perf_regs.h" +#include "util/pmu.h" +#include "util/record.h" +#include "util/session.h" #include "util/sort.h" -#include "util/data.h" -#include "util/auxtrace.h" -#include "util/cpumap.h" -#include "util/thread_map.h" +#include "util/srcline.h" #include "util/stat.h" -#include "util/color.h" #include "util/string2.h" +#include "util/symbol.h" #include "util/thread-stack.h" +#include "util/thread.h" +#include "util/thread_map.h" #include "util/time-utils.h" -#include "util/path.h" -#include "util/event.h" -#include "util/mem-info.h" -#include "util/metricgroup.h" -#include "ui/ui.h" -#include "print_binary.h" -#include "print_insn.h" -#include <linux/bitmap.h> -#include <linux/compiler.h> -#include <linux/kernel.h> -#include <linux/stringify.h> -#include <linux/time64.h> -#include <linux/zalloc.h> -#include <linux/unaligned.h> -#include <sys/utsname.h> -#include "asm/bug.h" -#include "util/mem-events.h" -#include "util/dump-insn.h" -#include <dirent.h> -#include <errno.h> -#include <inttypes.h> -#include <signal.h> -#include <stdio.h> -#include <sys/param.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <unistd.h> -#include <subcmd/pager.h> -#include <perf/evlist.h> -#include <linux/err.h> -#include "util/dlfilter.h" -#include "util/record.h" +#include "util/tool.h" +#include "util/trace-event.h" +#include "util/unwind.h" #include "util/util.h" -#include "util/cgroup.h" -#include "util/annotate.h" -#include "perf.h" -#include <linux/ctype.h> #ifdef HAVE_LIBTRACEEVENT #include <event-parse.h> #endif @@ -1287,8 +1291,12 @@ static int ip__fprintf_jump(uint64_t ip, struct branch_entry *en, if (!verbose) { for (j = 0; j < num; j++) printed += fprintf(fp, "%s", pos->abbr_name); - } else - printed += fprintf(fp, "%s %d ", pos->name, num); + if (mask && (num == mask)) + printed += fprintf(fp, "+"); + } else { + printed += fprintf(fp, "%s %d%s", pos->name, + num, mask && (num == mask) ? "+ " : " "); + } } if (numprinted == 0 && !verbose) printed += fprintf(fp, "-"); @@ -1683,7 +1691,7 @@ static int perf_sample__fprintf_bts(struct perf_sample *sample, if (symbol_conf.use_callchain && sample->callchain) { cursor = get_tls_callchain_cursor(); - if (thread__resolve_callchain(al->thread, cursor, evsel, + if (thread__resolve_callchain(al->thread, cursor, sample, NULL, NULL, scripting_max_stack)) cursor = NULL; @@ -2166,6 +2174,7 @@ static int script_find_metrics(const struct pmu_metric *pm, struct evsel *metric_evsel; int ret = metricgroup__parse_groups(metric_evlist, /*pmu=*/"all", + /*cputype_filter=*/false, pm->metric_name, /*metric_no_group=*/false, /*metric_no_merge=*/false, @@ -2221,9 +2230,10 @@ static int script_find_metrics(const struct pmu_metric *pm, evlist__for_each_entry(metric_evlist, metric_evsel) { struct evsel *script_evsel = map_metric_evsel_to_script_evsel(script_evlist, metric_evsel); - struct metric_event *metric_me = metricgroup__lookup(&metric_evlist->metric_events, - metric_evsel, - /*create=*/false); + struct metric_event *metric_me = + metricgroup__lookup(evlist__metric_events(metric_evlist), + metric_evsel, + /*create=*/false); if (script_evsel->metric_id == NULL) { script_evsel->metric_id = metric_evsel->metric_id; @@ -2243,7 +2253,7 @@ static int script_find_metrics(const struct pmu_metric *pm, if (metric_me) { struct metric_expr *expr; struct metric_event *script_me = - metricgroup__lookup(&script_evlist->metric_events, + metricgroup__lookup(evlist__metric_events(script_evlist), script_evsel, /*create=*/true); @@ -2266,8 +2276,8 @@ static int script_find_metrics(const struct pmu_metric *pm, } pr_debug("Found metric '%s' whose evsels match those of in the perf data\n", pm->metric_name); - evlist__delete(metric_evlist); out: + evlist__put(metric_evlist); return 0; } @@ -2313,7 +2323,7 @@ static void perf_sample__fprint_metric(struct thread *thread, assert(stat_config.aggr_mode == AGGR_GLOBAL); stat_config.aggr_get_id = script_aggr_cpu_id_get; stat_config.aggr_map = - cpu_aggr_map__new(evsel->evlist->core.user_requested_cpus, + cpu_aggr_map__new(evlist__core(evsel->evlist)->user_requested_cpus, aggr_cpu_id__global, /*data=*/NULL, /*needs_sort=*/false); } @@ -2418,12 +2428,13 @@ static bool show_event(struct perf_sample *sample, } static void process_event(struct perf_script *script, - struct perf_sample *sample, struct evsel *evsel, + struct perf_sample *sample, struct addr_location *al, struct addr_location *addr_al, struct machine *machine) { struct thread *thread = al->thread; + struct evsel *evsel = sample->evsel; struct perf_event_attr *attr = &evsel->core.attr; unsigned int type = evsel__output_type(evsel); struct evsel_script *es = evsel->priv; @@ -2506,7 +2517,7 @@ static void process_event(struct perf_script *script, if (symbol_conf.use_callchain && sample->callchain) { cursor = get_tls_callchain_cursor(); - if (thread__resolve_callchain(al->thread, cursor, evsel, + if (thread__resolve_callchain(al->thread, cursor, sample, NULL, NULL, scripting_max_stack)) cursor = NULL; @@ -2637,7 +2648,7 @@ static int cleanup_scripting(void) static bool filter_cpu(struct perf_sample *sample) { - if (cpu_list && sample->cpu != (u32)-1) + if (cpu_list && sample->cpu != (u32)-1 && sample->cpu < MAX_NR_CPUS) return !test_bit(sample->cpu, cpu_bitmap); return false; } @@ -2645,10 +2656,10 @@ static bool filter_cpu(struct perf_sample *sample) static int process_sample_event(const struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, - struct evsel *evsel, struct machine *machine) { struct perf_script *scr = container_of(tool, struct perf_script, tool); + struct evsel *evsel = sample->evsel; struct addr_location al; struct addr_location addr_al; int ret = 0; @@ -2684,8 +2695,9 @@ static int process_sample_event(const struct perf_tool *tool, goto out_put; if (!al.thread && machine__resolve(machine, &al, sample) < 0) { - pr_err("problem processing %d event, skipping it.\n", - event->header.type); + pr_err("problem processing %s (%u) event at offset %#" PRIx64 ", skipping it.\n", + perf_event__name(event->header.type), event->header.type, + sample->file_offset); ret = -1; goto out_put; } @@ -2715,9 +2727,9 @@ static int process_sample_event(const struct perf_tool *tool, thread__resolve(al.thread, &addr_al, sample); addr_al_ptr = &addr_al; } - scripting_ops->process_event(event, sample, evsel, &al, addr_al_ptr); + scripting_ops->process_event(event, sample, &al, addr_al_ptr); } else { - process_event(scr, sample, evsel, &al, &addr_al, machine); + process_event(scr, sample, &al, &addr_al, machine); } out_put: @@ -2729,10 +2741,10 @@ out_put: static int process_deferred_sample_event(const struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, - struct evsel *evsel, struct machine *machine) { struct perf_script *scr = container_of(tool, struct perf_script, tool); + struct evsel *evsel = sample->evsel; struct perf_event_attr *attr = &evsel->core.attr; struct evsel_script *es = evsel->priv; unsigned int type = output_type(attr->type); @@ -2766,8 +2778,9 @@ static int process_deferred_sample_event(const struct perf_tool *tool, goto out_put; if (machine__resolve(machine, &al, sample) < 0) { - pr_err("problem processing %d event, skipping it.\n", - event->header.type); + pr_err("problem processing %s (%u) event at offset %#" PRIx64 ", skipping it.\n", + perf_event__name(event->header.type), event->header.type, + sample->file_offset); ret = -1; goto out_put; } @@ -2791,7 +2804,7 @@ static int process_deferred_sample_event(const struct perf_tool *tool, if (symbol_conf.use_callchain && sample->callchain) { cursor = get_tls_callchain_cursor(); - if (thread__resolve_callchain(al.thread, cursor, evsel, + if (thread__resolve_callchain(al.thread, cursor, sample, NULL, NULL, scripting_max_stack)) { pr_info("cannot resolve deferred callchains\n"); @@ -2893,9 +2906,12 @@ static int print_event_with_time(const struct perf_tool *tool, { struct perf_script *script = container_of(tool, struct perf_script, tool); struct perf_session *session = script->session; - struct evsel *evsel = evlist__id2evsel(session->evlist, sample->id); + struct evsel *evsel = sample->evsel; struct thread *thread = NULL; + if (!evsel) + evsel = evlist__id2evsel(session->evlist, sample->id); + if (evsel && !evsel->core.attr.sample_id_all) { sample->cpu = 0; sample->time = timestamp; @@ -3895,7 +3911,7 @@ static int set_maps(struct perf_script *script) if (WARN_ONCE(script->allocated, "stats double allocation\n")) return -EINVAL; - perf_evlist__set_maps(&evlist->core, script->cpus, script->threads); + perf_evlist__set_maps(evlist__core(evlist), script->cpus, script->threads); if (evlist__alloc_stats(&stat_config, evlist, /*alloc_raw=*/true)) return -ENOMEM; @@ -4159,6 +4175,9 @@ int cmd_script(int argc, const char **argv) "Enable symbol demangling"), OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel, "Enable kernel symbol demangling"), + OPT_CALLBACK(0, "unwind-style", NULL, "unwind style", + "unwind styles (libdw,libunwind)", + unwind__option), OPT_STRING(0, "addr2line", &symbol_conf.addr2line_path, "path", "addr2line binary to use for line numbers"), OPT_STRING(0, "time", &script.time_str, "str", |
