aboutsummaryrefslogtreecommitdiffstats
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.c134
1 files changed, 82 insertions, 52 deletions
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 8f113dab8bf1..dec8ced61fb0 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -114,10 +114,85 @@ static size_t syscall__fprintf_args(struct syscall *sc, unsigned long *args, FIL
114 return printed; 114 return printed;
115} 115}
116 116
117typedef int (*tracepoint_handler)(struct trace *trace, struct perf_evsel *evsel,
118 struct perf_sample *sample);
119
120static struct syscall *trace__syscall_info(struct trace *trace,
121 struct perf_evsel *evsel,
122 struct perf_sample *sample)
123{
124 int id = perf_evsel__intval(evsel, sample, "id");
125
126 if (id < 0) {
127 printf("Invalid syscall %d id, skipping...\n", id);
128 return NULL;
129 }
130
131 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL) &&
132 trace__read_syscall_info(trace, id))
133 goto out_cant_read;
134
135 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL))
136 goto out_cant_read;
137
138 return &trace->syscalls.table[id];
139
140out_cant_read:
141 printf("Problems reading syscall %d information\n", id);
142 return NULL;
143}
144
145static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
146 struct perf_sample *sample)
147{
148 void *args;
149 struct syscall *sc = trace__syscall_info(trace, evsel, sample);
150
151 if (sc == NULL)
152 return -1;
153
154 args = perf_evsel__rawptr(evsel, sample, "args");
155 if (args == NULL) {
156 printf("Problems reading syscall arguments\n");
157 return -1;
158 }
159
160 printf("%s(", sc->name);
161 syscall__fprintf_args(sc, args, stdout);
162
163 return 0;
164}
165
166static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
167 struct perf_sample *sample)
168{
169 int ret;
170 struct syscall *sc = trace__syscall_info(trace, evsel, sample);
171
172 if (sc == NULL)
173 return -1;
174
175 ret = perf_evsel__intval(evsel, sample, "ret");
176
177 if (ret < 0 && sc->fmt && sc->fmt->errmsg) {
178 char bf[256];
179 const char *emsg = strerror_r(-ret, bf, sizeof(bf)),
180 *e = audit_errno_to_name(-ret);
181
182 printf(") = -1 %s %s", e, emsg);
183 } else if (ret == 0 && sc->fmt && sc->fmt->timeout)
184 printf(") = 0 Timeout");
185 else
186 printf(") = %d", ret);
187
188 putchar('\n');
189 return 0;
190}
191
117static int trace__run(struct trace *trace) 192static int trace__run(struct trace *trace)
118{ 193{
119 struct perf_evlist *evlist = perf_evlist__new(NULL, NULL); 194 struct perf_evlist *evlist = perf_evlist__new(NULL, NULL);
120 struct perf_evsel *evsel, *evsel_enter, *evsel_exit; 195 struct perf_evsel *evsel;
121 int err = -1, i, nr_events = 0, before; 196 int err = -1, i, nr_events = 0, before;
122 197
123 if (evlist == NULL) { 198 if (evlist == NULL) {
@@ -125,22 +200,12 @@ static int trace__run(struct trace *trace)
125 goto out; 200 goto out;
126 } 201 }
127 202
128 evsel_enter = perf_evsel__newtp("raw_syscalls", "sys_enter", 0); 203 if (perf_evlist__add_newtp(evlist, "raw_syscalls", "sys_enter", trace__sys_enter) ||
129 if (evsel_enter == NULL) { 204 perf_evlist__add_newtp(evlist, "raw_syscalls", "sys_exit", trace__sys_exit)) {
130 printf("Couldn't read the raw_syscalls:sys_enter tracepoint information!\n"); 205 printf("Couldn't read the raw_syscalls tracepoints information!\n");
131 goto out_delete_evlist;
132 }
133
134 perf_evlist__add(evlist, evsel_enter);
135
136 evsel_exit = perf_evsel__newtp("raw_syscalls", "sys_exit", 1);
137 if (evsel_exit == NULL) {
138 printf("Couldn't read the raw_syscalls:sys_exit tracepoint information!\n");
139 goto out_delete_evlist; 206 goto out_delete_evlist;
140 } 207 }
141 208
142 perf_evlist__add(evlist, evsel_exit);
143
144 err = perf_evlist__create_maps(evlist, &trace->opts.target); 209 err = perf_evlist__create_maps(evlist, &trace->opts.target);
145 if (err < 0) { 210 if (err < 0) {
146 printf("Problems parsing the target to trace, check your options!\n"); 211 printf("Problems parsing the target to trace, check your options!\n");
@@ -170,9 +235,8 @@ again:
170 235
171 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) { 236 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
172 const u32 type = event->header.type; 237 const u32 type = event->header.type;
173 struct syscall *sc; 238 tracepoint_handler handler;
174 struct perf_sample sample; 239 struct perf_sample sample;
175 int id;
176 240
177 ++nr_events; 241 ++nr_events;
178 242
@@ -200,45 +264,11 @@ again:
200 continue; 264 continue;
201 } 265 }
202 266
203 id = perf_evsel__intval(evsel, &sample, "id");
204 if (id < 0) {
205 printf("Invalid syscall %d id, skipping...\n", id);
206 continue;
207 }
208
209 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL) &&
210 trace__read_syscall_info(trace, id))
211 continue;
212
213 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL))
214 continue;
215
216 sc = &trace->syscalls.table[id];
217
218 if (evlist->threads->map[0] == -1 || evlist->threads->nr > 1) 267 if (evlist->threads->map[0] == -1 || evlist->threads->nr > 1)
219 printf("%d ", sample.tid); 268 printf("%d ", sample.tid);
220 269
221 if (evsel == evsel_enter) { 270 handler = evsel->handler.func;
222 void *args = perf_evsel__rawptr(evsel, &sample, "args"); 271 handler(trace, evsel, &sample);
223
224 printf("%s(", sc->name);
225 syscall__fprintf_args(sc, args, stdout);
226 } else if (evsel == evsel_exit) {
227 int ret = perf_evsel__intval(evsel, &sample, "ret");
228
229 if (ret < 0 && sc->fmt && sc->fmt->errmsg) {
230 char bf[256];
231 const char *emsg = strerror_r(-ret, bf, sizeof(bf)),
232 *e = audit_errno_to_name(-ret);
233
234 printf(") = -1 %s %s", e, emsg);
235 } else if (ret == 0 && sc->fmt && sc->fmt->timeout)
236 printf(") = 0 Timeout");
237 else
238 printf(") = %d", ret);
239
240 putchar('\n');
241 }
242 } 272 }
243 } 273 }
244 274