Commit 13d4ff3eb36474728be2acfa773b31ff39f3ea4d
1 parent
adaa18bf5d
Exists in
master
and in
20 other branches
perf trace: Introduce syscall arg formatters
Starting with one for printing pointers in hexadecimal, using the information in the syscall tracepoint format. Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: David Ahern <dsahern@gmail.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Link: http://lkml.kernel.org/n/tip-c4y4jy7qqkn8wsd8q6j1g7zh@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Showing 1 changed file with 36 additions and 3 deletions Side-by-side Diff
tools/perf/builtin-trace.c
... | ... | @@ -12,6 +12,11 @@ |
12 | 12 | #include <libaudit.h> |
13 | 13 | #include <stdlib.h> |
14 | 14 | |
15 | +static size_t syscall_arg__scnprintf_hex(char *bf, size_t size, unsigned long arg) | |
16 | +{ | |
17 | + return scnprintf(bf, size, "%#lx", arg); | |
18 | +} | |
19 | + | |
15 | 20 | static struct syscall_fmt { |
16 | 21 | const char *name; |
17 | 22 | const char *alias; |
... | ... | @@ -51,6 +56,7 @@ |
51 | 56 | const char *name; |
52 | 57 | bool filtered; |
53 | 58 | struct syscall_fmt *fmt; |
59 | + size_t (**arg_scnprintf)(char *bf, size_t size, unsigned long arg); | |
54 | 60 | }; |
55 | 61 | |
56 | 62 | static size_t fprintf_duration(unsigned long t, FILE *fp) |
... | ... | @@ -207,6 +213,24 @@ |
207 | 213 | return err; |
208 | 214 | } |
209 | 215 | |
216 | +static int syscall__set_arg_fmts(struct syscall *sc) | |
217 | +{ | |
218 | + struct format_field *field; | |
219 | + int idx = 0; | |
220 | + | |
221 | + sc->arg_scnprintf = calloc(sc->tp_format->format.nr_fields - 1, sizeof(void *)); | |
222 | + if (sc->arg_scnprintf == NULL) | |
223 | + return -1; | |
224 | + | |
225 | + for (field = sc->tp_format->format.fields->next; field; field = field->next) { | |
226 | + if (field->flags & FIELD_IS_POINTER) | |
227 | + sc->arg_scnprintf[idx] = syscall_arg__scnprintf_hex; | |
228 | + ++idx; | |
229 | + } | |
230 | + | |
231 | + return 0; | |
232 | +} | |
233 | + | |
210 | 234 | static int trace__read_syscall_info(struct trace *trace, int id) |
211 | 235 | { |
212 | 236 | char tp_name[128]; |
... | ... | @@ -259,7 +283,10 @@ |
259 | 283 | sc->tp_format = event_format__new("syscalls", tp_name); |
260 | 284 | } |
261 | 285 | |
262 | - return sc->tp_format != NULL ? 0 : -1; | |
286 | + if (sc->tp_format == NULL) | |
287 | + return -1; | |
288 | + | |
289 | + return syscall__set_arg_fmts(sc); | |
263 | 290 | } |
264 | 291 | |
265 | 292 | static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size, |
... | ... | @@ -273,8 +300,14 @@ |
273 | 300 | |
274 | 301 | for (field = sc->tp_format->format.fields->next; field; field = field->next) { |
275 | 302 | printed += scnprintf(bf + printed, size - printed, |
276 | - "%s%s: %ld", printed ? ", " : "", | |
277 | - field->name, args[i++]); | |
303 | + "%s%s: ", printed ? ", " : "", field->name); | |
304 | + | |
305 | + if (sc->arg_scnprintf && sc->arg_scnprintf[i]) | |
306 | + printed += sc->arg_scnprintf[i](bf + printed, size - printed, args[i]); | |
307 | + else | |
308 | + printed += scnprintf(bf + printed, size - printed, | |
309 | + "%ld", args[i]); | |
310 | + ++i; | |
278 | 311 | } |
279 | 312 | } else { |
280 | 313 | while (i < 6) { |