diff options
author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2020-05-28 23:21:29 +0300 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2020-05-29 22:51:11 +0300 |
commit | d21cb73a9025ffa9ef4f5a0d4051780c264fa02e (patch) | |
tree | efcae80ab733a9e9bb64518f33b2b0be262ecfc8 /tools/perf | |
parent | a9e8c1f85696057e35fc316af3ae7aa00ddb7522 (diff) | |
download | linux-d21cb73a9025ffa9ef4f5a0d4051780c264fa02e.tar.xz |
perf trace: Grow the syscall table as needed when using libaudit
The audit-libs API doesn't provide a way to figure out what is the
syscall with the greatest number/id, take that into account when using
that method to go on growing the syscall table as we the syscalls go on
appearing on the radar.
With this the libaudit based method is back working, i.e. when building
with:
$ make NO_SYSCALL_TABLE=1 O=/tmp/build/perf -C tools/perf install-bin
<SNIP>
Auto-detecting system features:
<SNIP>
... libaudit: [ on ]
... libbfd: [ on ]
... libcap: [ on ]
<SNIP>
$ ldd ~/bin/perf | grep audit
libaudit.so.1 => /lib64/libaudit.so.1 (0x00007faef22df000)
$
perf trace is back working, which makes it functional in arches other
than x86_64, powerpc, arm64 and s390, that provides these generators:
$ find tools/perf/arch/ -name "*syscalltbl*"
tools/perf/arch/x86/entry/syscalls/syscalltbl.sh
tools/perf/arch/arm64/entry/syscalls/mksyscalltbl
tools/perf/arch/s390/entry/syscalls/mksyscalltbl
tools/perf/arch/powerpc/entry/syscalls/mksyscalltbl
$
Example output forcing the libaudit method on x86_64:
# perf trace -e file,nanosleep sleep 0.001
? ( ): sleep/859090 ... [continued]: execve()) = 0
0.045 ( 0.005 ms): sleep/859090 access(filename: 0x8733e850, mode: R) = -1 ENOENT (No such file or directory)
0.055 ( 0.005 ms): sleep/859090 openat(dfd: CWD, filename: 0x8733ba29, flags: RDONLY|CLOEXEC) = 3
0.079 ( 0.005 ms): sleep/859090 openat(dfd: CWD, filename: 0x87345d20, flags: RDONLY|CLOEXEC) = 3
0.085 ( 0.002 ms): sleep/859090 read(fd: 3, buf: 0x7ffd9d483f58, count: 832) = 832
0.090 ( 0.002 ms): sleep/859090 read(fd: 3, buf: 0x7ffd9d483b50, count: 784) = 784
0.094 ( 0.002 ms): sleep/859090 read(fd: 3, buf: 0x7ffd9d483b20, count: 32) = 32
0.098 ( 0.002 ms): sleep/859090 read(fd: 3, buf: 0x7ffd9d483ad0, count: 68) = 68
0.109 ( 0.002 ms): sleep/859090 read(fd: 3, buf: 0x7ffd9d483a50, count: 784) = 784
0.113 ( 0.002 ms): sleep/859090 read(fd: 3, buf: 0x7ffd9d483730, count: 32) = 32
0.117 ( 0.002 ms): sleep/859090 read(fd: 3, buf: 0x7ffd9d483710, count: 68) = 68
0.320 ( 0.008 ms): sleep/859090 openat(dfd: CWD, filename: 0x872c3660, flags: RDONLY|CLOEXEC) = 3
0.372 ( 1.057 ms): sleep/859090 nanosleep(rqtp: 0x7ffd9d484ac0) = 0
#
There are still some limitations when using the libaudit method, that
will be fixed at some point, i.e., this works with the mksyscalltbl
method but not with libaudit's:
# perf trace -e file,*sleep sleep 0.001
event syntax error: '*sleep'
\___ parser error
Run 'perf list' for a list of valid events
Usage: perf trace [<options>] [<command>]
or: perf trace [<options>] -- <command> [<options>]
or: perf trace record [<options>] [<command>]
or: perf trace record [<options>] -- <command> [<options>]
-e, --event <event> event/syscall selector. use 'perf list' to list available events
#
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf')
-rw-r--r-- | tools/perf/builtin-trace.c | 28 |
1 files changed, 27 insertions, 1 deletions
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 61bafca1018a..4cbb64edc998 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -1748,12 +1748,26 @@ static int trace__read_syscall_info(struct trace *trace, int id) struct syscall *sc; const char *name = syscalltbl__name(trace->sctbl, id); +#ifdef HAVE_SYSCALL_TABLE_SUPPORT if (trace->syscalls.table == NULL) { trace->syscalls.table = calloc(trace->sctbl->syscalls.max_id + 1, sizeof(*sc)); if (trace->syscalls.table == NULL) return -ENOMEM; } +#else + if (id > trace->sctbl->syscalls.max_id || (id == 0 && trace->syscalls.table == NULL)) { + // When using libaudit we don't know beforehand what is the max syscall id + struct syscall *table = realloc(trace->syscalls.table, (id + 1) * sizeof(*sc)); + + if (table == NULL) + return -ENOMEM; + memset(table + trace->sctbl->syscalls.max_id, 0, (id - trace->sctbl->syscalls.max_id) * sizeof(*sc)); + + trace->syscalls.table = table; + trace->sctbl->syscalls.max_id = id; + } +#endif sc = trace->syscalls.table + id; if (sc->nonexistent) return 0; @@ -2077,8 +2091,20 @@ static struct syscall *trace__syscall_info(struct trace *trace, err = -EINVAL; - if (id > trace->sctbl->syscalls.max_id) +#ifdef HAVE_SYSCALL_TABLE_SUPPORT + if (id > trace->sctbl->syscalls.max_id) { +#else + if (id >= trace->sctbl->syscalls.max_id) { + /* + * With libaudit we don't know beforehand what is the max_id, + * so we let trace__read_syscall_info() figure that out as we + * go on reading syscalls. + */ + err = trace__read_syscall_info(trace, id); + if (err) +#endif goto out_cant_read; + } if ((trace->syscalls.table == NULL || trace->syscalls.table[id].name == NULL) && (err = trace__read_syscall_info(trace, id)) != 0) |