diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2025-08-01 16:55:47 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2025-08-01 16:55:47 -0700 |
commit | f4f346c3465949ebba80c6cc52cd8d2eeaa545fd (patch) | |
tree | c4da4e549bd6a050c00ad902486dab70847ee41d /tools/perf/builtin-trace.c | |
parent | 0905809b38bda1fa0b206986c44d846e46f13c1d (diff) | |
parent | 6235ce77749f45cac27f630337e2fdf04e8a6c73 (diff) |
Merge tag 'perf-tools-for-v6.17-2025-08-01' of git://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools
Pull perf tools updates from Namhyung Kim:
"Build-ID processing goodies:
Build-IDs are content based hashes to link regions of memory to ELF
files in post processing. They have been available in distros for
quite a while:
$ file /bin/bash
/bin/bash: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV),
dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2,
BuildID[sha1]=707a1c670cd72f8e55ffedfbe94ea98901b7ce3a,
for GNU/Linux 3.2.0, stripped
It is possible to ask the kernel to get it from mmap executable
backing storage at time they are being put in place and send it as
metadata at that moment to have in perf.data.
Prefer that across the board to speed up 'record' time - it post
processes the samples to find binaries touched by any samples and
to save them with build-ID. It can skip reading build-ID in
userspace if it comes from the kernel.
perf record:
* Make --buildid-mmap default. The kernel can generate MMAP2 events
with a build-ID from ELF header. Use that by default instead of using
inode and device ID to identify binaries. It also can be disabled
with --no-buildid-mmap.
* Use BPF for -u/--uid option to sample processes belong to a user.
BPF can track user processes more accurately and the existing logic
often fails to get the list of processes due to race with reading the
/proc filesystem.
* Generate PERF_RECORD_BPF_METADATA when it profiles BPF programs and
they have variables starting with "bpf_metadata_". This will help to
identify BPF objects used in the profile. This has been supported in
bpftool for some time and allows the recording of metadata such as
commit hashes, versions, etc, that now gets recorded in perf.data as
well.
* Collect list of DSOs touched in the sample callchains as well as in
the sample itself. This would increase the processing time at the end
of record, but can improve the data quality.
perf stat:
* Add a new 'drm' pseudo-PMU support like in 'hwmon'. It can collect
DRM usage stats using fdinfo in /proc.
On my Intel laptop, it shows like below:
$ perf list drm
...
drm:
drm-active-stolen-system0
[Total memory active in one or more engines. Unit: drm_i915]
drm-active-system0
[Total memory active in one or more engines. Unit: drm_i915]
drm-engine-capacity-video
[Engine capacity. Unit: drm_i915]
drm-engine-copy
[Utilization in ns. Unit: drm_i915]
drm-engine-render
[Utilization in ns. Unit: drm_i915]
drm-engine-video
[Utilization in ns. Unit: drm_i915]
...
$ sudo perf stat -a -e drm-engine-render,drm-engine-video,drm-engine-capacity-video sleep 1
Performance counter stats for 'system wide':
48,137,316,988,873 ns drm-engine-render
34,452,696,746 ns drm-engine-video
20 capacity drm-engine-capacity-video
1.002086194 seconds time elapsed
perf list
* Add description for software events. The description is in JSON format
and the event parser now can handle the software events like others
(for example, it's case-insensitive and subject to wildcard matching).
$ perf list software
List of pre-defined events (to be used in -e or -M):
software:
alignment-faults
[Number of kernel handled memory alignment faults. Unit: software]
bpf-output
[An event used by BPF programs to write to the perf ring buffer. Unit: software]
cgroup-switches
[Number of context switches to a task in a different cgroup. Unit: software]
context-switches
[Number of context switches [This event is an alias of cs]. Unit: software]
cpu-clock
[Per-CPU high-resolution timer based event. Unit: software]
cpu-migrations
[Number of times a process has migrated to a new CPU [This event is an alias of migrations]. Unit: software]
cs
[Number of context switches [This event is an alias of context-switches]. Unit: software]
dummy
[A placeholder event that doesn't count anything. Unit: software]
emulation-faults
[Number of kernel handled unimplemented instruction faults handled through emulation. Unit: software]
faults
[Number of page faults [This event is an alias of page-faults]. Unit: software]
major-faults
[Number of major page faults. Major faults require I/O to handle. Unit: software]
migrations
[Number of times a process has migrated to a new CPU [This event is an alias of cpu-migrations]. Unit: software]
minor-faults
[Number of minor page faults. Minor faults don't require I/O to handle. Unit: software]
page-faults
[Number of page faults [This event is an alias of faults]. Unit: software]
task-clock
[Per-task high-resolution timer based event. Unit: software]
perf ftrace:
* Add -e/--events option to perf ftrace latency to measure latency
between the two events instead of a function.
$ sudo perf ftrace latency -ab -e i915_request_wait_begin,i915_request_wait_end --hide-empty -- sleep 1
# DURATION | COUNT | GRAPH |
256 - 512 us | 4 | ###### |
2 - 4 ms | 2 | ### |
4 - 8 ms | 12 | ################### |
8 - 16 ms | 10 | ################ |
# statistics (in usec)
total time: 194915
avg time: 6961
max time: 12855
min time: 373
count: 28
* Add new function graph tracer options (--graph-opts) to display more
info like arguments and return value. They will be passed to the
kernel ftrace directly.
$ sudo perf ftrace -G vfs_write --graph-opts retval,retaddr
# tracer: function_graph
#
# CPU DURATION FUNCTION CALLS
# | | | | | | |
...
5) | mutex_unlock() { /* <-rb_simple_write+0xda/0x150 */
5) 0.188 us | local_clock(); /* <-lock_release+0x2ad/0x440 ret=0x3bf2a3cf90e */
5) | rt_mutex_slowunlock() { /* <-rb_simple_write+0xda/0x150 */
5) | _raw_spin_lock_irqsave() { /* <-rt_mutex_slowunlock+0x4f/0x200 */
5) 0.123 us | preempt_count_add(); /* <-_raw_spin_lock_irqsave+0x23/0x90 ret=0x0 */
5) 0.128 us | local_clock(); /* <-__lock_acquire.isra.0+0x17a/0x740 ret=0x3bf2a3cfc8b */
5) 0.086 us | do_raw_spin_trylock(); /* <-_raw_spin_lock_irqsave+0x4a/0x90 ret=0x1 */
5) 0.845 us | } /* _raw_spin_lock_irqsave ret=0x292 */
...
Misc:
* Add perf archive --exclude-buildids <FILE> option to skip some binaries.
The format of the FILE should be same as an output of perf buildid-list.
* Get rid of dependency of libcrypto. It was just to get SHA-1 hash so
implement it directly like in the kernel. A side effect is that it
needs -fno-strict-aliasing compiler option (again, like in the kernel).
* Convert all shell script tests to use bash"
* tag 'perf-tools-for-v6.17-2025-08-01' of git://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools: (179 commits)
perf record: Cache build-ID of hit DSOs only
perf test: Ensure lock contention using pipe mode
perf python: Stop using deprecated PyUnicode_AsString()
perf list: Skip ABI PMUs when printing pmu values
perf list: Remove tracepoint printing code
perf tp_pmu: Add event APIs
perf tp_pmu: Factor existing tracepoint logic to new file
perf parse-events: Remove non-json software events
perf jevents: Add common software event json
perf tools: Remove libtraceevent in .gitignore
perf test: Fix comment ordering
perf sort: Use perf_env to set arch sort keys and header
perf test: Move PERF_SAMPLE_WEIGHT_STRUCT parsing to common test
perf sample: Remove arch notion of sample parsing
perf env: Remove global perf_env
perf trace: Avoid global perf_env with evsel__env
perf auxtrace: Pass perf_env from session through to mmap read
perf machine: Explicitly pass in host perf_env
perf bench synthesize: Avoid use of global perf_env
perf top: Make perf_env locally scoped
...
Diffstat (limited to 'tools/perf/builtin-trace.c')
-rw-r--r-- | tools/perf/builtin-trace.c | 268 |
1 files changed, 95 insertions, 173 deletions
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 2ab1b8e05ad31..fe737b3ac6e67 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; } |