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>
This commit is contained in:
parent
a9e8c1f856
commit
d21cb73a90
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user