diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/perf/builtin-trace.c | 132 |
1 files changed, 87 insertions, 45 deletions
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 8f113dab8bf1..76b1202c03c8 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 return printed; } +typedef int (*tracepoint_handler)(struct trace *trace, struct perf_evsel *evsel, + struct perf_sample *sample); + +static struct syscall *trace__syscall_info(struct trace *trace, + struct perf_evsel *evsel, + struct perf_sample *sample) +{ + int id = perf_evsel__intval(evsel, sample, "id"); + + if (id < 0) { + printf("Invalid syscall %d id, skipping...\n", id); + return NULL; + } + + if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL) && + trace__read_syscall_info(trace, id)) + goto out_cant_read; + + if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL)) + goto out_cant_read; + + return &trace->syscalls.table[id]; + +out_cant_read: + printf("Problems reading syscall %d information\n", id); + return NULL; +} + +static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel, + struct perf_sample *sample) +{ + void *args; + struct syscall *sc = trace__syscall_info(trace, evsel, sample); + + if (sc == NULL) + return -1; + + args = perf_evsel__rawptr(evsel, sample, "args"); + if (args == NULL) { + printf("Problems reading syscall arguments\n"); + return -1; + } + + printf("%s(", sc->name); + syscall__fprintf_args(sc, args, stdout); + + return 0; +} + +static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel, + struct perf_sample *sample) +{ + int ret; + struct syscall *sc = trace__syscall_info(trace, evsel, sample); + + if (sc == NULL) + return -1; + + ret = perf_evsel__intval(evsel, sample, "ret"); + + if (ret < 0 && sc->fmt && sc->fmt->errmsg) { + char bf[256]; + const char *emsg = strerror_r(-ret, bf, sizeof(bf)), + *e = audit_errno_to_name(-ret); + + printf(") = -1 %s %s", e, emsg); + } else if (ret == 0 && sc->fmt && sc->fmt->timeout) + printf(") = 0 Timeout"); + else + printf(") = %d", ret); + + putchar('\n'); + return 0; +} + static int trace__run(struct trace *trace) { struct perf_evlist *evlist = perf_evlist__new(NULL, NULL); - struct perf_evsel *evsel, *evsel_enter, *evsel_exit; + struct perf_evsel *evsel; int err = -1, i, nr_events = 0, before; if (evlist == NULL) { @@ -125,21 +200,23 @@ static int trace__run(struct trace *trace) goto out; } - evsel_enter = perf_evsel__newtp("raw_syscalls", "sys_enter", 0); - if (evsel_enter == NULL) { + evsel = perf_evsel__newtp("raw_syscalls", "sys_enter", 0); + if (evsel == NULL) { printf("Couldn't read the raw_syscalls:sys_enter tracepoint information!\n"); goto out_delete_evlist; } - perf_evlist__add(evlist, evsel_enter); + evsel->handler.func = trace__sys_enter; + perf_evlist__add(evlist, evsel); - evsel_exit = perf_evsel__newtp("raw_syscalls", "sys_exit", 1); - if (evsel_exit == NULL) { + evsel = perf_evsel__newtp("raw_syscalls", "sys_exit", 1); + if (evsel == NULL) { printf("Couldn't read the raw_syscalls:sys_exit tracepoint information!\n"); goto out_delete_evlist; } - perf_evlist__add(evlist, evsel_exit); + evsel->handler.func = trace__sys_exit; + perf_evlist__add(evlist, evsel); err = perf_evlist__create_maps(evlist, &trace->opts.target); if (err < 0) { @@ -170,9 +247,8 @@ again: while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) { const u32 type = event->header.type; - struct syscall *sc; + tracepoint_handler handler; struct perf_sample sample; - int id; ++nr_events; @@ -200,45 +276,11 @@ again: continue; } - id = perf_evsel__intval(evsel, &sample, "id"); - if (id < 0) { - printf("Invalid syscall %d id, skipping...\n", id); - continue; - } - - if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL) && - trace__read_syscall_info(trace, id)) - continue; - - if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL)) - continue; - - sc = &trace->syscalls.table[id]; - if (evlist->threads->map[0] == -1 || evlist->threads->nr > 1) printf("%d ", sample.tid); - if (evsel == evsel_enter) { - void *args = perf_evsel__rawptr(evsel, &sample, "args"); - - printf("%s(", sc->name); - syscall__fprintf_args(sc, args, stdout); - } else if (evsel == evsel_exit) { - int ret = perf_evsel__intval(evsel, &sample, "ret"); - - if (ret < 0 && sc->fmt && sc->fmt->errmsg) { - char bf[256]; - const char *emsg = strerror_r(-ret, bf, sizeof(bf)), - *e = audit_errno_to_name(-ret); - - printf(") = -1 %s %s", e, emsg); - } else if (ret == 0 && sc->fmt && sc->fmt->timeout) - printf(") = 0 Timeout"); - else - printf(") = %d", ret); - - putchar('\n'); - } + handler = evsel->handler.func; + handler(trace, evsel, &sample); } } |