builtin-trace.c (ae6ba10d5090fc7e9095eaef3dcf06ba016725a6) builtin-trace.c (ff7a4f98d52cd3f13b1f4f6f22208498b0c113f7)
1/*
2 * builtin-trace.c
3 *
4 * Builtin 'trace' command:
5 *
6 * Display a continuously updated trace of any workload, CPU, specific PID,
7 * system wide, etc. Default format is loosely strace like, but any other
8 * event may be specified using --event.

--- 5 unchanged lines hidden (view full) ---

14 * http://lwn.net/Articles/415728/ ("Announcing a new utility: 'trace'")
15 *
16 * Released under the GPL v2. (and only v2, not any later version)
17 */
18
19#include <traceevent/event-parse.h>
20#include <api/fs/tracing_path.h>
21#include <bpf/bpf.h>
1/*
2 * builtin-trace.c
3 *
4 * Builtin 'trace' command:
5 *
6 * Display a continuously updated trace of any workload, CPU, specific PID,
7 * system wide, etc. Default format is loosely strace like, but any other
8 * event may be specified using --event.

--- 5 unchanged lines hidden (view full) ---

14 * http://lwn.net/Articles/415728/ ("Announcing a new utility: 'trace'")
15 *
16 * Released under the GPL v2. (and only v2, not any later version)
17 */
18
19#include <traceevent/event-parse.h>
20#include <api/fs/tracing_path.h>
21#include <bpf/bpf.h>
22#include "util/bpf_map.h"
22#include "builtin.h"
23#include "util/cgroup.h"
24#include "util/color.h"
25#include "util/config.h"
26#include "util/debug.h"
27#include "util/env.h"
28#include "util/event.h"
29#include "util/evlist.h"
30#include <subcmd/exec-cmd.h>
31#include "util/machine.h"
23#include "builtin.h"
24#include "util/cgroup.h"
25#include "util/color.h"
26#include "util/config.h"
27#include "util/debug.h"
28#include "util/env.h"
29#include "util/event.h"
30#include "util/evlist.h"
31#include <subcmd/exec-cmd.h>
32#include "util/machine.h"
33#include "util/map.h"
34#include "util/symbol.h"
32#include "util/path.h"
33#include "util/session.h"
34#include "util/thread.h"
35#include <subcmd/parse-options.h>
36#include "util/strlist.h"
37#include "util/intlist.h"
38#include "util/thread_map.h"
39#include "util/stat.h"

--- 40 unchanged lines hidden (view full) ---

80 struct syscall *table;
81 struct bpf_map *map;
82 struct {
83 struct perf_evsel *sys_enter,
84 *sys_exit,
85 *augmented;
86 } events;
87 } syscalls;
35#include "util/path.h"
36#include "util/session.h"
37#include "util/thread.h"
38#include <subcmd/parse-options.h>
39#include "util/strlist.h"
40#include "util/intlist.h"
41#include "util/thread_map.h"
42#include "util/stat.h"

--- 40 unchanged lines hidden (view full) ---

83 struct syscall *table;
84 struct bpf_map *map;
85 struct {
86 struct perf_evsel *sys_enter,
87 *sys_exit,
88 *augmented;
89 } events;
90 } syscalls;
91 struct {
92 struct bpf_map *map;
93 } dump;
88 struct record_opts opts;
89 struct perf_evlist *evlist;
90 struct machine *host;
91 struct thread *current;
92 struct cgroup *cgroup;
93 u64 base_time;
94 FILE *output;
95 unsigned long nr_events;

--- 938 unchanged lines hidden (view full) ---

1034
1035#define TRACE_PFMAJ (1 << 0)
1036#define TRACE_PFMIN (1 << 1)
1037
1038static const size_t trace__entry_str_size = 2048;
1039
1040static struct file *thread_trace__files_entry(struct thread_trace *ttrace, int fd)
1041{
94 struct record_opts opts;
95 struct perf_evlist *evlist;
96 struct machine *host;
97 struct thread *current;
98 struct cgroup *cgroup;
99 u64 base_time;
100 FILE *output;
101 unsigned long nr_events;

--- 938 unchanged lines hidden (view full) ---

1040
1041#define TRACE_PFMAJ (1 << 0)
1042#define TRACE_PFMIN (1 << 1)
1043
1044static const size_t trace__entry_str_size = 2048;
1045
1046static struct file *thread_trace__files_entry(struct thread_trace *ttrace, int fd)
1047{
1048 if (fd < 0)
1049 return NULL;
1050
1042 if (fd > ttrace->files.max) {
1043 struct file *nfiles = realloc(ttrace->files.table, (fd + 1) * sizeof(struct file));
1044
1045 if (nfiles == NULL)
1046 return NULL;
1047
1048 if (ttrace->files.max != -1) {
1049 memset(nfiles + ttrace->files.max + 1, 0,

--- 1711 unchanged lines hidden (view full) ---

2761 struct thread *thread = machine__find_thread(trace->host, pids[0], pids[0]);
2762
2763 while (thread && nr < ARRAY_SIZE(pids)) {
2764 struct thread *parent = machine__find_thread(trace->host, thread->ppid, thread->ppid);
2765
2766 if (parent == NULL)
2767 break;
2768
1051 if (fd > ttrace->files.max) {
1052 struct file *nfiles = realloc(ttrace->files.table, (fd + 1) * sizeof(struct file));
1053
1054 if (nfiles == NULL)
1055 return NULL;
1056
1057 if (ttrace->files.max != -1) {
1058 memset(nfiles + ttrace->files.max + 1, 0,

--- 1711 unchanged lines hidden (view full) ---

2770 struct thread *thread = machine__find_thread(trace->host, pids[0], pids[0]);
2771
2772 while (thread && nr < ARRAY_SIZE(pids)) {
2773 struct thread *parent = machine__find_thread(trace->host, thread->ppid, thread->ppid);
2774
2775 if (parent == NULL)
2776 break;
2777
2769 if (!strcmp(thread__comm_str(parent), "sshd")) {
2778 if (!strcmp(thread__comm_str(parent), "sshd") ||
2779 strstarts(thread__comm_str(parent), "gnome-terminal")) {
2770 pids[nr++] = parent->tid;
2771 break;
2772 }
2773 thread = parent;
2774 }
2775
2776 err = perf_evlist__set_tp_filter_pids(trace->evlist, nr, pids);
2777 if (!err && trace->filter_pids.map)

--- 208 unchanged lines hidden (view full) ---

2986 trace->syscalls.events.sys_exit->filter);
2987 }
2988 }
2989
2990 err = perf_evlist__apply_filters(evlist, &evsel);
2991 if (err < 0)
2992 goto out_error_apply_filters;
2993
2780 pids[nr++] = parent->tid;
2781 break;
2782 }
2783 thread = parent;
2784 }
2785
2786 err = perf_evlist__set_tp_filter_pids(trace->evlist, nr, pids);
2787 if (!err && trace->filter_pids.map)

--- 208 unchanged lines hidden (view full) ---

2996 trace->syscalls.events.sys_exit->filter);
2997 }
2998 }
2999
3000 err = perf_evlist__apply_filters(evlist, &evsel);
3001 if (err < 0)
3002 goto out_error_apply_filters;
3003
3004 if (trace->dump.map)
3005 bpf_map__fprintf(trace->dump.map, trace->output);
3006
2994 err = perf_evlist__mmap(evlist, trace->opts.mmap_pages);
2995 if (err < 0)
2996 goto out_error_mmap;
2997
2998 if (!target__none(&trace->opts.target) && !trace->opts.initial_delay)
2999 perf_evlist__enable(evlist);
3000
3001 if (forks)

--- 673 unchanged lines hidden (view full) ---

3675 .show_duration = true,
3676 .show_arg_names = true,
3677 .args_alignment = 70,
3678 .trace_syscalls = false,
3679 .kernel_syscallchains = false,
3680 .max_stack = UINT_MAX,
3681 .max_events = ULONG_MAX,
3682 };
3007 err = perf_evlist__mmap(evlist, trace->opts.mmap_pages);
3008 if (err < 0)
3009 goto out_error_mmap;
3010
3011 if (!target__none(&trace->opts.target) && !trace->opts.initial_delay)
3012 perf_evlist__enable(evlist);
3013
3014 if (forks)

--- 673 unchanged lines hidden (view full) ---

3688 .show_duration = true,
3689 .show_arg_names = true,
3690 .args_alignment = 70,
3691 .trace_syscalls = false,
3692 .kernel_syscallchains = false,
3693 .max_stack = UINT_MAX,
3694 .max_events = ULONG_MAX,
3695 };
3696 const char *map_dump_str = NULL;
3683 const char *output_name = NULL;
3684 const struct option trace_options[] = {
3685 OPT_CALLBACK('e', "event", &trace, "event",
3686 "event/syscall selector. use 'perf list' to list available events",
3687 trace__parse_events_option),
3688 OPT_BOOLEAN(0, "comm", &trace.show_comm,
3689 "show the thread COMM next to its id"),
3690 OPT_BOOLEAN(0, "tool_stats", &trace.show_tool_stats, "show tool stats"),

--- 16 unchanged lines hidden (view full) ---

3707 OPT_CALLBACK('m', "mmap-pages", &trace.opts.mmap_pages, "pages",
3708 "number of mmap data pages",
3709 perf_evlist__parse_mmap_pages),
3710 OPT_STRING('u', "uid", &trace.opts.target.uid_str, "user",
3711 "user to profile"),
3712 OPT_CALLBACK(0, "duration", &trace, "float",
3713 "show only events with duration > N.M ms",
3714 trace__set_duration),
3697 const char *output_name = NULL;
3698 const struct option trace_options[] = {
3699 OPT_CALLBACK('e', "event", &trace, "event",
3700 "event/syscall selector. use 'perf list' to list available events",
3701 trace__parse_events_option),
3702 OPT_BOOLEAN(0, "comm", &trace.show_comm,
3703 "show the thread COMM next to its id"),
3704 OPT_BOOLEAN(0, "tool_stats", &trace.show_tool_stats, "show tool stats"),

--- 16 unchanged lines hidden (view full) ---

3721 OPT_CALLBACK('m', "mmap-pages", &trace.opts.mmap_pages, "pages",
3722 "number of mmap data pages",
3723 perf_evlist__parse_mmap_pages),
3724 OPT_STRING('u', "uid", &trace.opts.target.uid_str, "user",
3725 "user to profile"),
3726 OPT_CALLBACK(0, "duration", &trace, "float",
3727 "show only events with duration > N.M ms",
3728 trace__set_duration),
3729#ifdef HAVE_LIBBPF_SUPPORT
3730 OPT_STRING(0, "map-dump", &map_dump_str, "BPF map", "BPF map to periodically dump"),
3731#endif
3715 OPT_BOOLEAN(0, "sched", &trace.sched, "show blocking scheduler events"),
3716 OPT_INCR('v', "verbose", &verbose, "be more verbose"),
3717 OPT_BOOLEAN('T', "time", &trace.full_time,
3718 "Show full timestamp, not time relative to first start"),
3719 OPT_BOOLEAN(0, "failure", &trace.failure_only,
3720 "Show only syscalls that failed"),
3721 OPT_BOOLEAN('s', "summary", &trace.summary_only,
3722 "Show only syscall summary with statistics"),

--- 78 unchanged lines hidden (view full) ---

3801 if (err) {
3802 bpf__strerror_setup_stdout(trace.evlist, err, bf, sizeof(bf));
3803 pr_err("ERROR: Setup BPF stdout failed: %s\n", bf);
3804 goto out;
3805 }
3806
3807 err = -1;
3808
3732 OPT_BOOLEAN(0, "sched", &trace.sched, "show blocking scheduler events"),
3733 OPT_INCR('v', "verbose", &verbose, "be more verbose"),
3734 OPT_BOOLEAN('T', "time", &trace.full_time,
3735 "Show full timestamp, not time relative to first start"),
3736 OPT_BOOLEAN(0, "failure", &trace.failure_only,
3737 "Show only syscalls that failed"),
3738 OPT_BOOLEAN('s', "summary", &trace.summary_only,
3739 "Show only syscall summary with statistics"),

--- 78 unchanged lines hidden (view full) ---

3818 if (err) {
3819 bpf__strerror_setup_stdout(trace.evlist, err, bf, sizeof(bf));
3820 pr_err("ERROR: Setup BPF stdout failed: %s\n", bf);
3821 goto out;
3822 }
3823
3824 err = -1;
3825
3826 if (map_dump_str) {
3827 trace.dump.map = bpf__find_map_by_name(map_dump_str);
3828 if (trace.dump.map == NULL) {
3829 pr_err("ERROR: BPF map \"%s\" not found\n", map_dump_str);
3830 goto out;
3831 }
3832 }
3833
3809 if (trace.trace_pgfaults) {
3810 trace.opts.sample_address = true;
3811 trace.opts.sample_time = true;
3812 }
3813
3814 if (trace.opts.mmap_pages == UINT_MAX)
3815 mmap_pages_user_set = false;
3816

--- 43 unchanged lines hidden (view full) ---

3860 evlist__for_each_entry(trace.evlist, evsel) {
3861 bool raw_syscalls_sys_exit = strcmp(perf_evsel__name(evsel), "raw_syscalls:sys_exit") == 0;
3862
3863 if (raw_syscalls_sys_exit) {
3864 trace.raw_augmented_syscalls = true;
3865 goto init_augmented_syscall_tp;
3866 }
3867
3834 if (trace.trace_pgfaults) {
3835 trace.opts.sample_address = true;
3836 trace.opts.sample_time = true;
3837 }
3838
3839 if (trace.opts.mmap_pages == UINT_MAX)
3840 mmap_pages_user_set = false;
3841

--- 43 unchanged lines hidden (view full) ---

3885 evlist__for_each_entry(trace.evlist, evsel) {
3886 bool raw_syscalls_sys_exit = strcmp(perf_evsel__name(evsel), "raw_syscalls:sys_exit") == 0;
3887
3888 if (raw_syscalls_sys_exit) {
3889 trace.raw_augmented_syscalls = true;
3890 goto init_augmented_syscall_tp;
3891 }
3892
3868 if (strcmp(perf_evsel__name(evsel), "raw_syscalls:sys_enter") == 0) {
3893 if (trace.syscalls.events.augmented->priv == NULL &&
3894 strstr(perf_evsel__name(evsel), "syscalls:sys_enter")) {
3869 struct perf_evsel *augmented = trace.syscalls.events.augmented;
3870 if (perf_evsel__init_augmented_syscall_tp(augmented, evsel) ||
3871 perf_evsel__init_augmented_syscall_tp_args(augmented))
3872 goto out;
3873 augmented->handler = trace__sys_enter;
3874 }
3875
3876 if (strstarts(perf_evsel__name(evsel), "syscalls:sys_exit_")) {

--- 80 unchanged lines hidden ---
3895 struct perf_evsel *augmented = trace.syscalls.events.augmented;
3896 if (perf_evsel__init_augmented_syscall_tp(augmented, evsel) ||
3897 perf_evsel__init_augmented_syscall_tp_args(augmented))
3898 goto out;
3899 augmented->handler = trace__sys_enter;
3900 }
3901
3902 if (strstarts(perf_evsel__name(evsel), "syscalls:sys_exit_")) {

--- 80 unchanged lines hidden ---