summaryrefslogtreecommitdiff
path: root/tools/perf/builtin-script.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/builtin-script.c')
-rw-r--r--tools/perf/builtin-script.c173
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",