perf trace: Use heuristic when deciding if a syscall tracepoint "const char *" field is really a string

'perf trace' tries to find BPF progs associated with a syscall that have
a signature that is similar to syscalls without one to try and reuse,
so, for instance, the 'open' signature can be reused with many other
syscalls that have as its first arg a string.

It uses the tracefs events format file for finding a signature that can
be reused, but then comes the "write" syscall with its second argument
as a "const char *":

  # cat /sys/kernel/debug/tracing/events/syscalls/sys_enter_write/format
  name: sys_enter_write
  ID: 746
  format:
  	field:unsigned short common_type;	offset:0;	size:2;	signed:0;
  	field:unsigned char common_flags;	offset:2;	size:1;	signed:0;
  	field:unsigned char common_preempt_count;	offset:3;	size:1;	signed:0;
  	field:int common_pid;	offset:4;	size:4;	signed:1;

  	field:int __syscall_nr;	offset:8;	size:4;	signed:1;
  	field:unsigned int fd;	offset:16;	size:8;	signed:0;
  	field:const char * buf;	offset:24;	size:8;	signed:0;
  	field:size_t count;	offset:32;	size:8;	signed:0;

  print fmt: "fd: 0x%08lx, buf: 0x%08lx, count: 0x%08lx", ((unsigned long)(REC->fd)), ((unsigned long)(REC->buf)), ((unsigned long)(REC->count))
  #

Which isn't a string (the man page for glibc has buf as "void *"), so we
have to use the name of the argument as an heuristic, to consider a
string just args that are "const char *" and that have in its name  the
"path", "file", etc substrings.

With that now it reuses:

  [root@quaco ~]# perf trace -v --max-events=1 |& grep Reus
  Reusing "open" BPF sys_enter augmenter for "stat"
  Reusing "open" BPF sys_enter augmenter for "lstat"
  Reusing "open" BPF sys_enter augmenter for "access"
  Reusing "connect" BPF sys_enter augmenter for "accept"
  Reusing "sendto" BPF sys_enter augmenter for "recvfrom"
  Reusing "connect" BPF sys_enter augmenter for "bind"
  Reusing "connect" BPF sys_enter augmenter for "getsockname"
  Reusing "connect" BPF sys_enter augmenter for "getpeername"
  Reusing "open" BPF sys_enter augmenter for "execve"
  Reusing "open" BPF sys_enter augmenter for "truncate"
  Reusing "open" BPF sys_enter augmenter for "chdir"
  Reusing "open" BPF sys_enter augmenter for "mkdir"
  Reusing "open" BPF sys_enter augmenter for "rmdir"
  Reusing "open" BPF sys_enter augmenter for "creat"
  Reusing "open" BPF sys_enter augmenter for "link"
  Reusing "open" BPF sys_enter augmenter for "unlink"
  Reusing "open" BPF sys_enter augmenter for "symlink"
  Reusing "open" BPF sys_enter augmenter for "readlink"
  Reusing "open" BPF sys_enter augmenter for "chmod"
  Reusing "open" BPF sys_enter augmenter for "chown"
  Reusing "open" BPF sys_enter augmenter for "lchown"
  Reusing "open" BPF sys_enter augmenter for "mknod"
  Reusing "open" BPF sys_enter augmenter for "statfs"
  Reusing "open" BPF sys_enter augmenter for "pivot_root"
  Reusing "open" BPF sys_enter augmenter for "chroot"
  Reusing "open" BPF sys_enter augmenter for "acct"
  Reusing "open" BPF sys_enter augmenter for "swapon"
  Reusing "open" BPF sys_enter augmenter for "swapoff"
  Reusing "open" BPF sys_enter augmenter for "delete_module"
  Reusing "open" BPF sys_enter augmenter for "setxattr"
  Reusing "open" BPF sys_enter augmenter for "lsetxattr"
  Reusing "openat" BPF sys_enter augmenter for "fsetxattr"
  Reusing "open" BPF sys_enter augmenter for "getxattr"
  Reusing "open" BPF sys_enter augmenter for "lgetxattr"
  Reusing "openat" BPF sys_enter augmenter for "fgetxattr"
  Reusing "open" BPF sys_enter augmenter for "listxattr"
  Reusing "open" BPF sys_enter augmenter for "llistxattr"
  Reusing "open" BPF sys_enter augmenter for "removexattr"
  Reusing "open" BPF sys_enter augmenter for "lremovexattr"
  Reusing "fsetxattr" BPF sys_enter augmenter for "fremovexattr"
  Reusing "open" BPF sys_enter augmenter for "mq_open"
  Reusing "open" BPF sys_enter augmenter for "mq_unlink"
  Reusing "fsetxattr" BPF sys_enter augmenter for "add_key"
  Reusing "fremovexattr" BPF sys_enter augmenter for "request_key"
  Reusing "fremovexattr" BPF sys_enter augmenter for "inotify_add_watch"
  Reusing "fremovexattr" BPF sys_enter augmenter for "mkdirat"
  Reusing "fremovexattr" BPF sys_enter augmenter for "mknodat"
  Reusing "fremovexattr" BPF sys_enter augmenter for "fchownat"
  Reusing "fremovexattr" BPF sys_enter augmenter for "futimesat"
  Reusing "fremovexattr" BPF sys_enter augmenter for "newfstatat"
  Reusing "fremovexattr" BPF sys_enter augmenter for "unlinkat"
  Reusing "fremovexattr" BPF sys_enter augmenter for "linkat"
  Reusing "open" BPF sys_enter augmenter for "symlinkat"
  Reusing "fremovexattr" BPF sys_enter augmenter for "readlinkat"
  Reusing "fremovexattr" BPF sys_enter augmenter for "fchmodat"
  Reusing "fremovexattr" BPF sys_enter augmenter for "faccessat"
  Reusing "fremovexattr" BPF sys_enter augmenter for "utimensat"
  Reusing "connect" BPF sys_enter augmenter for "accept4"
  Reusing "fremovexattr" BPF sys_enter augmenter for "name_to_handle_at"
  Reusing "fremovexattr" BPF sys_enter augmenter for "renameat2"
  Reusing "open" BPF sys_enter augmenter for "memfd_create"
  Reusing "fremovexattr" BPF sys_enter augmenter for "execveat"
  Reusing "fremovexattr" BPF sys_enter augmenter for "statx"
  [root@quaco ~]#

Reviewed-by: Ian Rogers <irogers@google.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alan Maguire <alan.maguire@oracle.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Link: https://lore.kernel.org/lkml/ZN5lrdeEdSMCn7hk@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
Arnaldo Carvalho de Melo 2023-08-17 15:14:21 -03:00
parent 83a0943b18
commit 64917f4df0

View File

@ -3398,6 +3398,19 @@ static struct bpf_program *trace__find_usable_bpf_prog_entry(struct trace *trace
if (strcmp(field->type, candidate_field->type))
goto next_candidate;
/*
* This is limited in the BPF program but sys_write
* uses "const char *" for its "buf" arg so we need to
* use some heuristic that is kinda future proof...
*/
if (strcmp(field->type, "const char *") == 0 &&
!(strstr(field->name, "name") ||
strstr(field->name, "path") ||
strstr(field->name, "file") ||
strstr(field->name, "root") ||
strstr(field->name, "description")))
goto next_candidate;
is_candidate = true;
}