summaryrefslogtreecommitdiff
path: root/tools/perf/builtin-trace.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/builtin-trace.c')
-rw-r--r--tools/perf/builtin-trace.c268
1 files changed, 95 insertions, 173 deletions
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 2ab1b8e05ad3..fe737b3ac6e6 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -20,9 +20,6 @@
#include <bpf/bpf.h>
#include <bpf/libbpf.h>
#include <bpf/btf.h>
-#ifdef HAVE_BPF_SKEL
-#include "bpf_skel/augmented_raw_syscalls.skel.h"
-#endif
#endif
#include "util/bpf_map.h"
#include "util/rlimit.h"
@@ -143,6 +140,7 @@ struct syscall_fmt {
};
struct trace {
+ struct perf_env host_env;
struct perf_tool tool;
struct {
/** Sorted sycall numbers used by the trace. */
@@ -155,9 +153,6 @@ struct trace {
*bpf_output;
} events;
} syscalls;
-#ifdef HAVE_BPF_SKEL
- struct augmented_raw_syscalls_bpf *skel;
-#endif
#ifdef HAVE_LIBBPF_SUPPORT
struct btf *btf;
#endif
@@ -236,6 +231,7 @@ struct trace {
struct ordered_events data;
u64 last;
} oe;
+ const char *uid_str;
};
static void trace__load_vmlinux_btf(struct trace *trace __maybe_unused)
@@ -1123,12 +1119,14 @@ static bool syscall_arg__strtoul_btf_type(char *bf __maybe_unused, size_t size _
#define STRARRAY(name, array) \
{ .scnprintf = SCA_STRARRAY, \
.strtoul = STUL_STRARRAY, \
- .parm = &strarray__##array, }
+ .parm = &strarray__##array, \
+ .show_zero = true, }
#define STRARRAY_FLAGS(name, array) \
{ .scnprintf = SCA_STRARRAY_FLAGS, \
.strtoul = STUL_STRARRAY_FLAGS, \
- .parm = &strarray__##array, }
+ .parm = &strarray__##array, \
+ .show_zero = true, }
#include "trace/beauty/eventfd.c"
#include "trace/beauty/futex_op.c"
@@ -1980,17 +1978,24 @@ static char *trace__machine__resolve_kernel_addr(void *vmachine, unsigned long l
return machine__resolve_kernel_addr(vmachine, addrp, modp);
}
-static int trace__symbols_init(struct trace *trace, struct evlist *evlist)
+static int trace__symbols_init(struct trace *trace, int argc, const char **argv,
+ struct evlist *evlist)
{
int err = symbol__init(NULL);
if (err)
return err;
- trace->host = machine__new_host();
- if (trace->host == NULL)
- return -ENOMEM;
+ perf_env__init(&trace->host_env);
+ err = perf_env__set_cmdline(&trace->host_env, argc, argv);
+ if (err)
+ goto out;
+ trace->host = machine__new_host(&trace->host_env);
+ if (trace->host == NULL) {
+ err = -ENOMEM;
+ goto out;
+ }
thread__set_priv_destructor(thread_trace__delete);
err = trace_event__register_resolver(trace->host, trace__machine__resolve_kernel_addr);
@@ -2001,9 +2006,10 @@ static int trace__symbols_init(struct trace *trace, struct evlist *evlist)
evlist->core.threads, trace__tool_process,
true, false, 1);
out:
- if (err)
+ if (err) {
+ perf_env__exit(&trace->host_env);
symbol__exit();
-
+ }
return err;
}
@@ -2012,6 +2018,7 @@ static void trace__symbols__exit(struct trace *trace)
machine__exit(trace->host);
trace->host = NULL;
+ perf_env__exit(&trace->host_env);
symbol__exit();
}
@@ -2891,13 +2898,6 @@ static int trace__fprintf_callchain(struct trace *trace, struct perf_sample *sam
return sample__fprintf_callchain(sample, 38, print_opts, get_tls_callchain_cursor(), symbol_conf.bt_stop_list, trace->output);
}
-static const char *errno_to_name(struct evsel *evsel, int err)
-{
- struct perf_env *env = evsel__env(evsel);
-
- return perf_env__arch_strerrno(env, err);
-}
-
static int trace__sys_exit(struct trace *trace, struct evsel *evsel,
union perf_event *event __maybe_unused,
struct perf_sample *sample)
@@ -2983,8 +2983,9 @@ signed_print:
} else if (ret < 0) {
errno_print: {
char bf[STRERR_BUFSIZE];
- const char *emsg = str_error_r(-ret, bf, sizeof(bf)),
- *e = errno_to_name(evsel, -ret);
+ struct perf_env *env = evsel__env(evsel) ?: &trace->host_env;
+ const char *emsg = str_error_r(-ret, bf, sizeof(bf));
+ const char *e = perf_env__arch_strerrno(env, err);
fprintf(trace->output, "-1 %s (%s)", e, emsg);
}
@@ -3700,7 +3701,10 @@ out_enomem:
goto out;
}
-#ifdef HAVE_BPF_SKEL
+#ifdef HAVE_LIBBPF_SUPPORT
+
+static struct bpf_program *unaugmented_prog;
+
static int syscall_arg_fmt__cache_btf_struct(struct syscall_arg_fmt *arg_fmt, struct btf *btf, char *type)
{
int id;
@@ -3718,26 +3722,8 @@ static int syscall_arg_fmt__cache_btf_struct(struct syscall_arg_fmt *arg_fmt, st
return 0;
}
-static struct bpf_program *trace__find_bpf_program_by_title(struct trace *trace, const char *name)
-{
- struct bpf_program *pos, *prog = NULL;
- const char *sec_name;
-
- if (trace->skel->obj == NULL)
- return NULL;
-
- bpf_object__for_each_program(pos, trace->skel->obj) {
- sec_name = bpf_program__section_name(pos);
- if (sec_name && !strcmp(sec_name, name)) {
- prog = pos;
- break;
- }
- }
-
- return prog;
-}
-
-static struct bpf_program *trace__find_syscall_bpf_prog(struct trace *trace, struct syscall *sc,
+static struct bpf_program *trace__find_syscall_bpf_prog(struct trace *trace __maybe_unused,
+ struct syscall *sc,
const char *prog_name, const char *type)
{
struct bpf_program *prog;
@@ -3745,19 +3731,19 @@ static struct bpf_program *trace__find_syscall_bpf_prog(struct trace *trace, str
if (prog_name == NULL) {
char default_prog_name[256];
scnprintf(default_prog_name, sizeof(default_prog_name), "tp/syscalls/sys_%s_%s", type, sc->name);
- prog = trace__find_bpf_program_by_title(trace, default_prog_name);
+ prog = augmented_syscalls__find_by_title(default_prog_name);
if (prog != NULL)
goto out_found;
if (sc->fmt && sc->fmt->alias) {
scnprintf(default_prog_name, sizeof(default_prog_name), "tp/syscalls/sys_%s_%s", type, sc->fmt->alias);
- prog = trace__find_bpf_program_by_title(trace, default_prog_name);
+ prog = augmented_syscalls__find_by_title(default_prog_name);
if (prog != NULL)
goto out_found;
}
goto out_unaugmented;
}
- prog = trace__find_bpf_program_by_title(trace, prog_name);
+ prog = augmented_syscalls__find_by_title(prog_name);
if (prog != NULL) {
out_found:
@@ -3767,7 +3753,7 @@ out_found:
pr_debug("Couldn't find BPF prog \"%s\" to associate with syscalls:sys_%s_%s, not augmenting it\n",
prog_name, type, sc->name);
out_unaugmented:
- return trace->skel->progs.syscall_unaugmented;
+ return unaugmented_prog;
}
static void trace__init_syscall_bpf_progs(struct trace *trace, int e_machine, int id)
@@ -3784,13 +3770,13 @@ static void trace__init_syscall_bpf_progs(struct trace *trace, int e_machine, in
static int trace__bpf_prog_sys_enter_fd(struct trace *trace, int e_machine, int id)
{
struct syscall *sc = trace__syscall_info(trace, NULL, e_machine, id);
- return sc ? bpf_program__fd(sc->bpf_prog.sys_enter) : bpf_program__fd(trace->skel->progs.syscall_unaugmented);
+ return sc ? bpf_program__fd(sc->bpf_prog.sys_enter) : bpf_program__fd(unaugmented_prog);
}
static int trace__bpf_prog_sys_exit_fd(struct trace *trace, int e_machine, int id)
{
struct syscall *sc = trace__syscall_info(trace, NULL, e_machine, id);
- return sc ? bpf_program__fd(sc->bpf_prog.sys_exit) : bpf_program__fd(trace->skel->progs.syscall_unaugmented);
+ return sc ? bpf_program__fd(sc->bpf_prog.sys_exit) : bpf_program__fd(unaugmented_prog);
}
static int trace__bpf_sys_enter_beauty_map(struct trace *trace, int e_machine, int key, unsigned int *beauty_array)
@@ -3900,7 +3886,7 @@ try_to_find_pair:
bool is_candidate = false;
if (pair == NULL || pair->id == sc->id ||
- pair->bpf_prog.sys_enter == trace->skel->progs.syscall_unaugmented)
+ pair->bpf_prog.sys_enter == unaugmented_prog)
continue;
for (field = sc->args, candidate_field = pair->args;
@@ -3966,7 +3952,7 @@ try_to_find_pair:
*/
if (pair_prog == NULL) {
pair_prog = trace__find_syscall_bpf_prog(trace, pair, pair->fmt ? pair->fmt->bpf_prog_name.sys_enter : NULL, "enter");
- if (pair_prog == trace->skel->progs.syscall_unaugmented)
+ if (pair_prog == unaugmented_prog)
goto next_candidate;
}
@@ -3982,12 +3968,17 @@ try_to_find_pair:
static int trace__init_syscalls_bpf_prog_array_maps(struct trace *trace, int e_machine)
{
- int map_enter_fd = bpf_map__fd(trace->skel->maps.syscalls_sys_enter);
- int map_exit_fd = bpf_map__fd(trace->skel->maps.syscalls_sys_exit);
- int beauty_map_fd = bpf_map__fd(trace->skel->maps.beauty_map_enter);
+ int map_enter_fd;
+ int map_exit_fd;
+ int beauty_map_fd;
int err = 0;
unsigned int beauty_array[6];
+ if (augmented_syscalls__get_map_fds(&map_enter_fd, &map_exit_fd, &beauty_map_fd) < 0)
+ return -1;
+
+ unaugmented_prog = augmented_syscalls__unaugmented();
+
for (int i = 0, num_idx = syscalltbl__num_idx(e_machine); i < num_idx; ++i) {
int prog_fd, key = syscalltbl__id_at_idx(e_machine, i);
@@ -4057,7 +4048,7 @@ static int trace__init_syscalls_bpf_prog_array_maps(struct trace *trace, int e_m
* For now we're just reusing the sys_enter prog, and if it
* already has an augmenter, we don't need to find one.
*/
- if (sc->bpf_prog.sys_enter != trace->skel->progs.syscall_unaugmented)
+ if (sc->bpf_prog.sys_enter != unaugmented_prog)
continue;
/*
@@ -4082,7 +4073,13 @@ static int trace__init_syscalls_bpf_prog_array_maps(struct trace *trace, int e_m
return err;
}
-#endif // HAVE_BPF_SKEL
+#else // !HAVE_LIBBPF_SUPPORT
+static int trace__init_syscalls_bpf_prog_array_maps(struct trace *trace __maybe_unused,
+ int e_machine __maybe_unused)
+{
+ return -1;
+}
+#endif // HAVE_LIBBPF_SUPPORT
static int trace__set_ev_qualifier_filter(struct trace *trace)
{
@@ -4091,24 +4088,6 @@ static int trace__set_ev_qualifier_filter(struct trace *trace)
return 0;
}
-static int bpf_map__set_filter_pids(struct bpf_map *map __maybe_unused,
- size_t npids __maybe_unused, pid_t *pids __maybe_unused)
-{
- int err = 0;
-#ifdef HAVE_LIBBPF_SUPPORT
- bool value = true;
- int map_fd = bpf_map__fd(map);
- size_t i;
-
- for (i = 0; i < npids; ++i) {
- err = bpf_map_update_elem(map_fd, &pids[i], &value, BPF_ANY);
- if (err)
- break;
- }
-#endif
- return err;
-}
-
static int trace__set_filter_loop_pids(struct trace *trace)
{
unsigned int nr = 1, err;
@@ -4137,8 +4116,8 @@ static int trace__set_filter_loop_pids(struct trace *trace)
thread__put(thread);
err = evlist__append_tp_filter_pids(trace->evlist, nr, pids);
- if (!err && trace->filter_pids.map)
- err = bpf_map__set_filter_pids(trace->filter_pids.map, nr, pids);
+ if (!err)
+ err = augmented_syscalls__set_filter_pids(nr, pids);
return err;
}
@@ -4155,8 +4134,8 @@ static int trace__set_filter_pids(struct trace *trace)
if (trace->filter_pids.nr > 0) {
err = evlist__append_tp_filter_pids(trace->evlist, trace->filter_pids.nr,
trace->filter_pids.entries);
- if (!err && trace->filter_pids.map) {
- err = bpf_map__set_filter_pids(trace->filter_pids.map, trace->filter_pids.nr,
+ if (!err) {
+ err = augmented_syscalls__set_filter_pids(trace->filter_pids.nr,
trace->filter_pids.entries);
}
} else if (perf_thread_map__pid(trace->evlist->core.threads, 0) == -1) {
@@ -4412,8 +4391,8 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
evlist__add(evlist, pgfault_min);
}
- /* Enable ignoring missing threads when -u/-p option is defined. */
- trace->opts.ignore_missing_thread = trace->opts.target.uid != UINT_MAX || trace->opts.target.pid;
+ /* Enable ignoring missing threads when -p option is defined. */
+ trace->opts.ignore_missing_thread = trace->opts.target.pid;
if (trace->sched &&
evlist__add_newtp(evlist, "sched", "sched_stat_runtime", trace__sched_stat_runtime))
@@ -4453,7 +4432,7 @@ create_maps:
goto out_delete_evlist;
}
- err = trace__symbols_init(trace, evlist);
+ err = trace__symbols_init(trace, argc, argv, evlist);
if (err < 0) {
fprintf(trace->output, "Problems initializing symbol libraries!\n");
goto out_delete_evlist;
@@ -4479,41 +4458,18 @@ create_maps:
err = evlist__open(evlist);
if (err < 0)
goto out_error_open;
-#ifdef HAVE_BPF_SKEL
- if (trace->syscalls.events.bpf_output) {
- struct perf_cpu cpu;
- /*
- * Set up the __augmented_syscalls__ BPF map to hold for each
- * CPU the bpf-output event's file descriptor.
- */
- perf_cpu_map__for_each_cpu(cpu, i, trace->syscalls.events.bpf_output->core.cpus) {
- int mycpu = cpu.cpu;
-
- bpf_map__update_elem(trace->skel->maps.__augmented_syscalls__,
- &mycpu, sizeof(mycpu),
- xyarray__entry(trace->syscalls.events.bpf_output->core.fd,
- mycpu, 0),
- sizeof(__u32), BPF_ANY);
- }
- }
+ augmented_syscalls__setup_bpf_output();
- if (trace->skel)
- trace->filter_pids.map = trace->skel->maps.pids_filtered;
-#endif
err = trace__set_filter_pids(trace);
if (err < 0)
goto out_error_mem;
-#ifdef HAVE_BPF_SKEL
- if (trace->skel && trace->skel->progs.sys_enter) {
- /*
- * TODO: Initialize for all host binary machine types, not just
- * those matching the perf binary.
- */
- trace__init_syscalls_bpf_prog_array_maps(trace, EM_HOST);
- }
-#endif
+ /*
+ * TODO: Initialize for all host binary machine types, not just
+ * those matching the perf binary.
+ */
+ trace__init_syscalls_bpf_prog_array_maps(trace, EM_HOST);
if (trace->ev_qualifier_ids.nr > 0) {
err = trace__set_ev_qualifier_filter(trace);
@@ -4749,7 +4705,7 @@ static int trace__replay(struct trace *trace)
if (trace->opts.target.tid)
symbol_conf.tid_list_str = strdup(trace->opts.target.tid);
- if (symbol__init(&session->header.env) < 0)
+ if (symbol__init(perf_session__env(session)) < 0)
goto out;
trace->host = &session->machines.host;
@@ -5358,6 +5314,7 @@ out:
static void trace__exit(struct trace *trace)
{
+ thread__zput(trace->current);
strlist__delete(trace->ev_qualifier);
zfree(&trace->ev_qualifier_ids.entries);
if (trace->syscalls.table) {
@@ -5368,24 +5325,13 @@ static void trace__exit(struct trace *trace)
zfree(&trace->perfconfig_events);
evlist__delete(trace->evlist);
trace->evlist = NULL;
+ ordered_events__free(&trace->oe.data);
#ifdef HAVE_LIBBPF_SUPPORT
btf__free(trace->btf);
trace->btf = NULL;
#endif
}
-#ifdef HAVE_BPF_SKEL
-static int bpf__setup_bpf_output(struct evlist *evlist)
-{
- int err = parse_event(evlist, "bpf-output/no-inherit=1,name=__augmented_syscalls__/");
-
- if (err)
- pr_debug("ERROR: failed to create the \"__augmented_syscalls__\" bpf-output event\n");
-
- return err;
-}
-#endif
-
int cmd_trace(int argc, const char **argv)
{
const char *trace_usage[] = {
@@ -5398,7 +5344,6 @@ int cmd_trace(int argc, const char **argv)
struct trace trace = {
.opts = {
.target = {
- .uid = UINT_MAX,
.uses_mmap = true,
},
.user_freq = UINT_MAX,
@@ -5445,8 +5390,7 @@ int cmd_trace(int argc, const char **argv)
"child tasks do not inherit counters"),
OPT_CALLBACK('m', "mmap-pages", &trace.opts.mmap_pages, "pages",
"number of mmap data pages", evlist__parse_mmap_pages),
- OPT_STRING('u', "uid", &trace.opts.target.uid_str, "user",
- "user to profile"),
+ OPT_STRING('u', "uid", &trace.uid_str, "user", "user to profile"),
OPT_CALLBACK(0, "duration", &trace, "float",
"show only events with duration > N.M ms",
trace__set_duration),
@@ -5519,6 +5463,9 @@ int cmd_trace(int argc, const char **argv)
sigchld_act.sa_sigaction = sighandler_chld;
sigaction(SIGCHLD, &sigchld_act, NULL);
+ ordered_events__init(&trace.oe.data, ordered_events__deliver_event, &trace);
+ ordered_events__set_copy_on_queue(&trace.oe.data, true);
+
trace.evlist = evlist__new();
if (trace.evlist == NULL) {
@@ -5581,7 +5528,6 @@ int cmd_trace(int argc, const char **argv)
"cgroup monitoring only available in system-wide mode");
}
-#ifdef HAVE_BPF_SKEL
if (!trace.trace_syscalls)
goto skip_augmentation;
@@ -5600,42 +5546,17 @@ int cmd_trace(int argc, const char **argv)
goto skip_augmentation;
}
- trace.skel = augmented_raw_syscalls_bpf__open();
- if (!trace.skel) {
- pr_debug("Failed to open augmented syscalls BPF skeleton");
- } else {
- /*
- * Disable attaching the BPF programs except for sys_enter and
- * sys_exit that tail call into this as necessary.
- */
- struct bpf_program *prog;
-
- bpf_object__for_each_program(prog, trace.skel->obj) {
- if (prog != trace.skel->progs.sys_enter && prog != trace.skel->progs.sys_exit)
- bpf_program__set_autoattach(prog, /*autoattach=*/false);
- }
+ err = augmented_syscalls__prepare();
+ if (err < 0)
+ goto skip_augmentation;
- err = augmented_raw_syscalls_bpf__load(trace.skel);
+ trace__add_syscall_newtp(&trace);
- if (err < 0) {
- libbpf_strerror(err, bf, sizeof(bf));
- pr_debug("Failed to load augmented syscalls BPF skeleton: %s\n", bf);
- } else {
- augmented_raw_syscalls_bpf__attach(trace.skel);
- trace__add_syscall_newtp(&trace);
- }
- }
+ err = augmented_syscalls__create_bpf_output(trace.evlist);
+ if (err == 0)
+ trace.syscalls.events.bpf_output = evlist__last(trace.evlist);
- err = bpf__setup_bpf_output(trace.evlist);
- if (err) {
- libbpf_strerror(err, bf, sizeof(bf));
- pr_err("ERROR: Setup BPF output event failed: %s\n", bf);
- goto out;
- }
- trace.syscalls.events.bpf_output = evlist__last(trace.evlist);
- assert(evsel__name_is(trace.syscalls.events.bpf_output, "__augmented_syscalls__"));
skip_augmentation:
-#endif
err = -1;
if (trace.trace_pgfaults) {
@@ -5677,11 +5598,6 @@ skip_augmentation:
trace__load_vmlinux_btf(&trace);
}
- if (trace.sort_events) {
- ordered_events__init(&trace.oe.data, ordered_events__deliver_event, &trace);
- ordered_events__set_copy_on_queue(&trace.oe.data, true);
- }
-
/*
* If we are augmenting syscalls, then combine what we put in the
* __augmented_syscalls__ BPF map with what is in the
@@ -5804,11 +5720,19 @@ init_augmented_syscall_tp:
goto out_close;
}
- err = target__parse_uid(&trace.opts.target);
- if (err) {
- target__strerror(&trace.opts.target, err, bf, sizeof(bf));
- fprintf(trace.output, "%s", bf);
- goto out_close;
+ if (trace.uid_str) {
+ uid_t uid = parse_uid(trace.uid_str);
+
+ if (uid == UINT_MAX) {
+ ui__error("Invalid User: %s", trace.uid_str);
+ err = -EINVAL;
+ goto out_close;
+ }
+ err = parse_uid_filter(trace.evlist, uid);
+ if (err)
+ goto out_close;
+
+ trace.opts.target.system_wide = true;
}
if (!argc && target__none(&trace.opts.target))
@@ -5824,8 +5748,6 @@ out_close:
fclose(trace.output);
out:
trace__exit(&trace);
-#ifdef HAVE_BPF_SKEL
- augmented_raw_syscalls_bpf__destroy(trace.skel);
-#endif
+ augmented_syscalls__cleanup();
return err;
}