1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
4 *
5 */
6 #include <stdlib.h>
7 #include <getopt.h>
8 #include <errno.h>
9
10 #include "tracefs.h"
11 #include "trace-local.h"
12
13 enum {
14 OPT_cpumask = 240,
15 OPT_graph_notrace,
16 OPT_graph_function,
17 OPT_ftrace_pid,
18 OPT_ftrace_notrace,
19 OPT_ftrace_filter,
20 OPT_buffer_subbuf_size_kb,
21 OPT_buffer_total_size_kb,
22 OPT_buffer_size_kb,
23 OPT_buffer_percent,
24 OPT_current_tracer,
25 OPT_tracing_on,
26 OPT_hist,
27 OPT_trigger,
28 };
29
trace_show(int argc,char ** argv)30 void trace_show(int argc, char **argv)
31 {
32 const char *buffer = NULL;
33 const char *file = "trace";
34 const char *cpu = NULL;
35 struct buffer_instance *instance = &top_instance;
36 char *hist = NULL;
37 char *trigger = NULL;
38 char cpu_path[128];
39 char *path;
40 int snap = 0;
41 int pipe = 0;
42 int show_name = 0;
43 int option_index = 0;
44 int stop = 0;
45 int c;
46 static struct option long_options[] = {
47 {"hist", required_argument, NULL, OPT_hist},
48 {"trigger", required_argument, NULL, OPT_trigger},
49 {"tracing_on", no_argument, NULL, OPT_tracing_on},
50 {"current_tracer", no_argument, NULL, OPT_current_tracer},
51 {"buffer_size", no_argument, NULL, OPT_buffer_size_kb},
52 {"buffer_total_size", no_argument, NULL, OPT_buffer_total_size_kb},
53 {"buffer_subbuf_size", no_argument, NULL, OPT_buffer_subbuf_size_kb},
54 {"buffer_percent", no_argument, NULL, OPT_buffer_percent},
55 {"ftrace_filter", no_argument, NULL, OPT_ftrace_filter},
56 {"ftrace_notrace", no_argument, NULL, OPT_ftrace_notrace},
57 {"ftrace_pid", no_argument, NULL, OPT_ftrace_pid},
58 {"graph_function", no_argument, NULL, OPT_graph_function},
59 {"graph_notrace", no_argument, NULL, OPT_graph_notrace},
60 {"cpumask", no_argument, NULL, OPT_cpumask},
61 {"help", no_argument, NULL, '?'},
62 {NULL, 0, NULL, 0}
63 };
64
65 init_top_instance();
66
67 while ((c = getopt_long(argc-1, argv+1, "B:c:fsp",
68 long_options, &option_index)) >= 0) {
69 switch (c) {
70 case 'h':
71 usage(argv);
72 break;
73 case 'B':
74 if (buffer)
75 die("Can only show one buffer at a time");
76 buffer = optarg;
77 instance = allocate_instance(optarg);
78 if (!instance)
79 die("Failed to create instance");
80 break;
81 case 'c':
82 if (cpu)
83 die("Can only show one CPU at a time");
84 cpu = optarg;
85 break;
86 case 'f':
87 show_name = 1;
88 break;
89 case 's':
90 snap = 1;
91 if (pipe)
92 die("Can not have -s and -p together");
93 break;
94 case 'p':
95 pipe = 1;
96 if (snap)
97 die("Can not have -s and -p together");
98 break;
99 case OPT_hist:
100 hist = optarg;
101 break;
102 case OPT_trigger:
103 trigger = optarg;
104 break;
105
106 case OPT_tracing_on:
107 show_instance_file(instance, "tracing_on");
108 stop = 1;
109 break;
110 case OPT_current_tracer:
111 show_instance_file(instance, "current_tracer");
112 stop = 1;
113 break;
114 case OPT_buffer_size_kb:
115 show_instance_file(instance, "buffer_size_kb");
116 stop = 1;
117 break;
118 case OPT_buffer_total_size_kb:
119 show_instance_file(instance, "buffer_total_size_kb");
120 stop = 1;
121 break;
122 case OPT_buffer_subbuf_size_kb:
123 show_instance_file(instance, "buffer_subbuf_size_kb");
124 stop = 1;
125 break;
126 case OPT_buffer_percent:
127 show_instance_file(instance, "buffer_percent");
128 stop = 1;
129 break;
130 case OPT_ftrace_filter:
131 show_instance_file(instance, "set_ftrace_filter");
132 stop = 1;
133 break;
134 case OPT_ftrace_notrace:
135 show_instance_file(instance, "set_ftrace_notrace");
136 stop = 1;
137 break;
138 case OPT_ftrace_pid:
139 show_instance_file(instance, "set_ftrace_pid");
140 stop = 1;
141 break;
142 case OPT_graph_function:
143 show_instance_file(instance, "set_graph_function");
144 stop = 1;
145 break;
146 case OPT_graph_notrace:
147 show_instance_file(instance, "set_graph_notrace");
148 stop = 1;
149 break;
150 case OPT_cpumask:
151 show_instance_file(instance, "tracing_cpumask");
152 stop = 1;
153 break;
154 default:
155 usage(argv);
156 }
157 }
158 if (stop)
159 exit(0);
160 if (pipe)
161 file = "trace_pipe";
162 else if (snap)
163 file = "snapshot";
164
165 if (hist || trigger) {
166 char **systems = NULL;
167 char *system = NULL;
168 char *event = hist ? hist : trigger;
169 char *file = hist ? "hist" : "trigger";
170 char *p;
171
172 if ((p = strstr(event, ":"))) {
173 system = event;
174 event = p + 1;
175 *p = '\0';
176 }
177
178 if (!system) {
179 systems = tracefs_event_systems(NULL);
180
181 for (int i = 0; systems && systems[i]; i++) {
182 system = systems[i];
183 if (tracefs_event_file_exists(instance->tracefs,
184 system, event, file))
185 break;
186 }
187 if (!system)
188 die("Could not find system of event %s",
189 event);
190 }
191
192 path = tracefs_event_file_read(instance->tracefs,
193 system, event, file, NULL);
194 tracefs_list_free(systems);
195 if (!path)
196 die("Could not find hist for %s%s%s",
197 system ? system : "", system ? ":":"", event);
198 printf("%s\n", path);
199 free(path);
200 exit(0);
201 }
202
203 if (cpu) {
204 char *endptr;
205 long val;
206
207 errno = 0;
208 val = strtol(cpu, &endptr, 0);
209 if (errno || cpu == endptr)
210 die("Invalid CPU index '%s'", cpu);
211 snprintf(cpu_path, 128, "per_cpu/cpu%ld/%s", val, file);
212 file = cpu_path;
213 }
214
215 if (buffer) {
216 int ret;
217
218 ret = asprintf(&path, "instances/%s/%s", buffer, file);
219 if (ret < 0)
220 die("Failed to allocate instance path %s", file);
221 file = path;
222 }
223
224 if (show_name) {
225 char *name;
226 name = tracefs_get_tracing_file(file);
227 printf("%s\n", name);
228 tracefs_put_tracing_file(name);
229 }
230 show_file(file);
231 if (buffer)
232 free(path);
233
234 return;
235 }
236