Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf trace: Move syscall table id <-> name routines to separate class

We're using libaudit for doing name to id and id to syscall name
translations, but that makes 'perf trace' to have to wait for newer
libaudit versions supporting recently added syscalls, such as
"userfaultfd" at the time of this changeset.

We have all the information right there, in the kernel sources, so move
this code to a separate place, wrapped behind functions that will
progressively use the kernel source files to extract the syscall table
for use in 'perf trace'.

Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Wang Nan <wangnan0@huawei.com>
Link: http://lkml.kernel.org/n/tip-i38opd09ow25mmyrvfwnbvkj@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

+71 -13
+11 -13
tools/perf/builtin-trace.c
··· 34 34 #include "trace-event.h" 35 35 #include "util/parse-events.h" 36 36 #include "util/bpf-loader.h" 37 + #include "syscalltbl.h" 37 38 38 - #include <libaudit.h> 39 + #include <libaudit.h> /* FIXME: Still needed for audit_errno_to_name */ 39 40 #include <stdlib.h> 40 41 #include <sys/mman.h> 41 42 #include <linux/futex.h> ··· 115 114 116 115 struct trace { 117 116 struct perf_tool tool; 118 - struct { 119 - int machine; 120 - int open_id; 121 - } audit; 117 + struct syscalltbl *sctbl; 122 118 struct { 123 119 int max; 124 120 struct syscall *table; ··· 161 163 bool force; 162 164 bool vfs_getname; 163 165 int trace_pgfaults; 166 + int open_id; 164 167 }; 165 168 166 169 struct tp_field { ··· 1779 1780 { 1780 1781 char tp_name[128]; 1781 1782 struct syscall *sc; 1782 - const char *name = audit_syscall_to_name(id, trace->audit.machine); 1783 + const char *name = syscalltbl__name(trace->sctbl, id); 1783 1784 1784 1785 if (name == NULL) 1785 1786 return -1; ··· 1854 1855 1855 1856 strlist__for_each(pos, trace->ev_qualifier) { 1856 1857 const char *sc = pos->s; 1857 - int id = audit_name_to_syscall(sc, trace->audit.machine); 1858 + int id = syscalltbl__id(trace->sctbl, sc); 1858 1859 1859 1860 if (id < 0) { 1860 1861 if (err == 0) { ··· 2136 2137 2137 2138 ret = perf_evsel__sc_tp_uint(evsel, ret, sample); 2138 2139 2139 - if (id == trace->audit.open_id && ret >= 0 && ttrace->filename.pending_open) { 2140 + if (id == trace->open_id && ret >= 0 && ttrace->filename.pending_open) { 2140 2141 trace__set_fd_pathname(thread, ret, ttrace->filename.name); 2141 2142 ttrace->filename.pending_open = false; 2142 2143 ++trace->stats.vfs_getname; ··· 3188 3189 NULL 3189 3190 }; 3190 3191 struct trace trace = { 3191 - .audit = { 3192 - .machine = audit_detect_machine(), 3193 - .open_id = audit_name_to_syscall("open", trace.audit.machine), 3194 - }, 3195 3192 .syscalls = { 3196 3193 . max = -1, 3197 3194 }, ··· 3262 3267 signal(SIGFPE, sighandler_dump_stack); 3263 3268 3264 3269 trace.evlist = perf_evlist__new(); 3270 + trace.sctbl = syscalltbl__new(); 3265 3271 3266 - if (trace.evlist == NULL) { 3272 + if (trace.evlist == NULL || trace.sctbl == NULL) { 3267 3273 pr_err("Not enough memory to run!\n"); 3268 3274 err = -ENOMEM; 3269 3275 goto out; ··· 3301 3305 goto out; 3302 3306 } 3303 3307 } 3308 + 3309 + trace.open_id = syscalltbl__id(trace.sctbl, "open"); 3304 3310 3305 3311 if (ev_qualifier_str != NULL) { 3306 3312 const char *s = ev_qualifier_str;
+1
tools/perf/util/Build
··· 38 38 libperf-y += map.o 39 39 libperf-y += pstack.o 40 40 libperf-y += session.o 41 + libperf-$(CONFIG_AUDIT) += syscalltbl.o 41 42 libperf-y += ordered-events.o 42 43 libperf-y += comm.o 43 44 libperf-y += thread.o
+43
tools/perf/util/syscalltbl.c
··· 1 + /* 2 + * System call table mapper 3 + * 4 + * (C) 2016 Arnaldo Carvalho de Melo <acme@redhat.com> 5 + * 6 + * This program is free software; you can redistribute it and/or modify it 7 + * under the terms and conditions of the GNU General Public License, 8 + * version 2, as published by the Free Software Foundation. 9 + * 10 + * This program is distributed in the hope it will be useful, but WITHOUT 11 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 + * more details. 14 + */ 15 + 16 + #include "syscalltbl.h" 17 + #include <string.h> 18 + #include <libaudit.h> 19 + 20 + 21 + struct syscalltbl *syscalltbl__new(void) 22 + { 23 + struct syscalltbl *tbl = malloc(sizeof(*tbl)); 24 + if (tbl) { 25 + tbl->audit_machine = audit_detect_machine(); 26 + } 27 + return tbl; 28 + } 29 + 30 + void syscalltbl__delete(struct syscalltbl *tbl) 31 + { 32 + free(tbl); 33 + } 34 + 35 + const char *syscalltbl__name(const struct syscalltbl *tbl, int id) 36 + { 37 + return audit_syscall_to_name(id, tbl->audit_machine); 38 + } 39 + 40 + int syscalltbl__id(struct syscalltbl *tbl, const char *name) 41 + { 42 + return audit_name_to_syscall(name, tbl->audit_machine); 43 + }
+16
tools/perf/util/syscalltbl.h
··· 1 + #ifndef __PERF_SYSCALLTBL_H 2 + #define __PERF_SYSCALLTBL_H 3 + 4 + struct syscalltbl { 5 + union { 6 + int audit_machine; 7 + }; 8 + }; 9 + 10 + struct syscalltbl *syscalltbl__new(void); 11 + void syscalltbl__delete(struct syscalltbl *tbl); 12 + 13 + const char *syscalltbl__name(const struct syscalltbl *tbl, int id); 14 + int syscalltbl__id(struct syscalltbl *tbl, const char *name); 15 + 16 + #endif /* __PERF_SYSCALLTBL_H */