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

Message ID ZN5lrdeEdSMCn7hk@kernel.org
State New
Headers
Series [1/1] perf trace: Use heuristic when deciding if a syscall tracepoint "const char *" field is really a string |

Commit Message

Arnaldo Carvalho de Melo Aug. 17, 2023, 6:23 p.m. UTC
  '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 ~]#

Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alan Maguire <alan.maguire@oracle.com>
Cc: Ian Rogers <irogers@google.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Link: https://lore.kernel.org/lkml/
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-trace.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)
  

Patch

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 3964cf44cdbcb3e8..e541d0e2777ab935 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -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;
 		}