All of lore.kernel.org
 help / color / mirror / Atom feed
From: Charlie Jenkins <charlie@rivosinc.com>
To: Ian Rogers <irogers@google.com>
Cc: "Peter Zijlstra" <peterz@infradead.org>,
	"Ingo Molnar" <mingo@redhat.com>,
	"Arnaldo Carvalho de Melo" <acme@kernel.org>,
	"Namhyung Kim" <namhyung@kernel.org>,
	"Mark Rutland" <mark.rutland@arm.com>,
	"Alexander Shishkin" <alexander.shishkin@linux.intel.com>,
	"Jiri Olsa" <jolsa@kernel.org>,
	"Adrian Hunter" <adrian.hunter@intel.com>,
	"Kan Liang" <kan.liang@linux.intel.com>,
	"John Garry" <john.g.garry@oracle.com>,
	"Will Deacon" <will@kernel.org>,
	"James Clark" <james.clark@linaro.org>,
	"Mike Leach" <mike.leach@linaro.org>,
	"Leo Yan" <leo.yan@linux.dev>, "Guo Ren" <guoren@kernel.org>,
	"Paul Walmsley" <paul.walmsley@sifive.com>,
	"Palmer Dabbelt" <palmer@dabbelt.com>,
	"Albert Ou" <aou@eecs.berkeley.edu>,
	"Bibo Mao" <maobibo@loongson.cn>, "Arnd Bergmann" <arnd@arndb.de>,
	"Huacai Chen" <chenhuacai@kernel.org>,
	"Catalin Marinas" <catalin.marinas@arm.com>,
	"Jiri Slaby" <jirislaby@kernel.org>,
	"Björn Töpel" <bjorn@rivosinc.com>,
	"Howard Chu" <howardchu95@gmail.com>,
	linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org, linux-csky@vger.kernel.org,
	linux-riscv@lists.infradead.org
Subject: Re: [PATCH v2 2/7] perf trace: Reorganize syscalls
Date: Mon, 10 Feb 2025 16:17:57 -0800	[thread overview]
Message-ID: <Z6qXNcjQE2RaoDUZ@ghost> (raw)
In-Reply-To: <20250210165108.95894-3-irogers@google.com>

On Mon, Feb 10, 2025 at 08:51:03AM -0800, Ian Rogers wrote:
> Identify struct syscall information in the syscalls table by a machine
> type and syscall number, not just system call number. Having the
> machine type means that 32-bit system calls can be differentiated from
> 64-bit ones on a machine capable of both. Having a table for all
> machine types and all system call numbers would be too large, so
> maintain a sorted array of system calls as they are encountered.

Reviewed-by: Charlie Jenkins <charlie@rivosinc.com>
Tested-by: Charlie Jenkins <charlie@rivosinc.com>

> 
> Signed-off-by: Ian Rogers <irogers@google.com>
> Reviewed-by: Howard Chu <howardchu95@gmail.com>
> ---
>  tools/perf/builtin-trace.c | 178 +++++++++++++++++++++++++------------
>  1 file changed, 119 insertions(+), 59 deletions(-)
> 
> diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
> index 06356217adeb..916a51df236b 100644
> --- a/tools/perf/builtin-trace.c
> +++ b/tools/perf/builtin-trace.c
> @@ -66,6 +66,7 @@
>  #include "rb_resort.h"
>  #include "../perf.h"
>  #include "trace_augment.h"
> +#include "dwarf-regs.h"
>  
>  #include <errno.h>
>  #include <inttypes.h>
> @@ -86,6 +87,7 @@
>  
>  #include <linux/ctype.h>
>  #include <perf/mmap.h>
> +#include <tools/libc_compat.h>
>  
>  #ifdef HAVE_LIBTRACEEVENT
>  #include <event-parse.h>
> @@ -143,7 +145,10 @@ struct trace {
>  	struct perf_tool	tool;
>  	struct syscalltbl	*sctbl;
>  	struct {
> +		/** Sorted sycall numbers used by the trace. */
>  		struct syscall  *table;
> +		/** Size of table. */
> +		size_t		table_size;
>  		struct {
>  			struct evsel *sys_enter,
>  				*sys_exit,
> @@ -1445,22 +1450,37 @@ static const struct syscall_fmt *syscall_fmt__find_by_alias(const char *alias)
>  	return __syscall_fmt__find_by_alias(syscall_fmts, nmemb, alias);
>  }
>  
> -/*
> - * is_exit: is this "exit" or "exit_group"?
> - * is_open: is this "open" or "openat"? To associate the fd returned in sys_exit with the pathname in sys_enter.
> - * args_size: sum of the sizes of the syscall arguments, anything after that is augmented stuff: pathname for openat, etc.
> - * nonexistent: Just a hole in the syscall table, syscall id not allocated
> +/**
> + * struct syscall
>   */
>  struct syscall {
> +	/** @e_machine: The ELF machine associated with the entry. */
> +	int e_machine;
> +	/** @id: id value from the tracepoint, the system call number. */
> +	int id;
>  	struct tep_event    *tp_format;
>  	int		    nr_args;
> +	/**
> +	 * @args_size: sum of the sizes of the syscall arguments, anything
> +	 * after that is augmented stuff: pathname for openat, etc.
> +	 */
> +
>  	int		    args_size;
>  	struct {
>  		struct bpf_program *sys_enter,
>  				   *sys_exit;
>  	}		    bpf_prog;
> +	/** @is_exit: is this "exit" or "exit_group"? */
>  	bool		    is_exit;
> +	/**
> +	 * @is_open: is this "open" or "openat"? To associate the fd returned in
> +	 * sys_exit with the pathname in sys_enter.
> +	 */
>  	bool		    is_open;
> +	/**
> +	 * @nonexistent: Name lookup failed. Just a hole in the syscall table,
> +	 * syscall id not allocated.
> +	 */
>  	bool		    nonexistent;
>  	bool		    use_btf;
>  	struct tep_format_field *args;
> @@ -2066,22 +2086,21 @@ static int syscall__set_arg_fmts(struct syscall *sc)
>  	return 0;
>  }
>  
> -static int trace__read_syscall_info(struct trace *trace, int id)
> +static int syscall__read_info(struct syscall *sc, struct trace *trace)
>  {
>  	char tp_name[128];
> -	struct syscall *sc;
> -	const char *name = syscalltbl__name(trace->sctbl, id);
> +	const char *name;
>  	int err;
>  
> -	if (trace->syscalls.table == NULL) {
> -		trace->syscalls.table = calloc(trace->sctbl->syscalls.max_id + 1, sizeof(*sc));
> -		if (trace->syscalls.table == NULL)
> -			return -ENOMEM;
> -	}
> -	sc = trace->syscalls.table + id;
>  	if (sc->nonexistent)
>  		return -EEXIST;
>  
> +	if (sc->name) {
> +		/* Info already read. */
> +		return 0;
> +	}
> +
> +	name = syscalltbl__name(trace->sctbl, sc->id);
>  	if (name == NULL) {
>  		sc->nonexistent = true;
>  		return -EEXIST;
> @@ -2104,15 +2123,16 @@ static int trace__read_syscall_info(struct trace *trace, int id)
>  	 */
>  	if (IS_ERR(sc->tp_format)) {
>  		sc->nonexistent = true;
> -		return PTR_ERR(sc->tp_format);
> +		err = PTR_ERR(sc->tp_format);
> +		sc->tp_format = NULL;
> +		return err;
>  	}
>  
>  	/*
>  	 * The tracepoint format contains __syscall_nr field, so it's one more
>  	 * than the actual number of syscall arguments.
>  	 */
> -	if (syscall__alloc_arg_fmts(sc, IS_ERR(sc->tp_format) ?
> -					RAW_SYSCALL_ARGS_NUM : sc->tp_format->format.nr_fields - 1))
> +	if (syscall__alloc_arg_fmts(sc, sc->tp_format->format.nr_fields - 1))
>  		return -ENOMEM;
>  
>  	sc->args = sc->tp_format->format.fields;
> @@ -2401,13 +2421,67 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
>  	return printed;
>  }
>  
> +static void syscall__init(struct syscall *sc, int e_machine, int id)
> +{
> +	memset(sc, 0, sizeof(*sc));
> +	sc->e_machine = e_machine;
> +	sc->id = id;
> +}
> +
> +static void syscall__exit(struct syscall *sc)
> +{
> +	if (!sc)
> +		return;
> +
> +	zfree(&sc->arg_fmt);
> +}
> +
> +static int syscall__cmp(const void *va, const void *vb)
> +{
> +	const struct syscall *a = va, *b = vb;
> +
> +	if (a->e_machine != b->e_machine)
> +		return a->e_machine - b->e_machine;
> +
> +	return a->id - b->id;
> +}
> +
> +static struct syscall *trace__find_syscall(struct trace *trace, int e_machine, int id)
> +{
> +	struct syscall key = {
> +		.e_machine = e_machine,
> +		.id = id,
> +	};
> +	struct syscall *sc, *tmp;
> +
> +	sc = bsearch(&key, trace->syscalls.table, trace->syscalls.table_size,
> +		     sizeof(struct syscall), syscall__cmp);
> +	if (sc)
> +		return sc;
> +
> +	tmp = reallocarray(trace->syscalls.table, trace->syscalls.table_size + 1,
> +			   sizeof(struct syscall));
> +	if (!tmp)
> +		return NULL;
> +
> +	trace->syscalls.table = tmp;
> +	sc = &trace->syscalls.table[trace->syscalls.table_size++];
> +	syscall__init(sc, e_machine, id);
> +	qsort(trace->syscalls.table, trace->syscalls.table_size, sizeof(struct syscall),
> +	      syscall__cmp);
> +	sc = bsearch(&key, trace->syscalls.table, trace->syscalls.table_size,
> +		     sizeof(struct syscall), syscall__cmp);
> +	return sc;
> +}
> +
>  typedef int (*tracepoint_handler)(struct trace *trace, struct evsel *evsel,
>  				  union perf_event *event,
>  				  struct perf_sample *sample);
>  
> -static struct syscall *trace__syscall_info(struct trace *trace,
> -					   struct evsel *evsel, int id)
> +static struct syscall *trace__syscall_info(struct trace *trace, struct evsel *evsel,
> +					   int e_machine, int id)
>  {
> +	struct syscall *sc;
>  	int err = 0;
>  
>  	if (id < 0) {
> @@ -2432,28 +2506,20 @@ static struct syscall *trace__syscall_info(struct trace *trace,
>  
>  	err = -EINVAL;
>  
> -	if (id > trace->sctbl->syscalls.max_id) {
> -		goto out_cant_read;
> -	}
> -
> -	if ((trace->syscalls.table == NULL || trace->syscalls.table[id].name == NULL) &&
> -	    (err = trace__read_syscall_info(trace, id)) != 0)
> -		goto out_cant_read;
> +	sc = trace__find_syscall(trace, e_machine, id);
> +	if (sc)
> +		err = syscall__read_info(sc, trace);
>  
> -	if (trace->syscalls.table && trace->syscalls.table[id].nonexistent)
> -		goto out_cant_read;
> -
> -	return &trace->syscalls.table[id];
> -
> -out_cant_read:
> -	if (verbose > 0) {
> +	if (err && verbose > 0) {
>  		char sbuf[STRERR_BUFSIZE];
> -		fprintf(trace->output, "Problems reading syscall %d: %d (%s)", id, -err, str_error_r(-err, sbuf, sizeof(sbuf)));
> -		if (id <= trace->sctbl->syscalls.max_id && trace->syscalls.table[id].name != NULL)
> -			fprintf(trace->output, "(%s)", trace->syscalls.table[id].name);
> +
> +		fprintf(trace->output, "Problems reading syscall %d: %d (%s)", id, -err,
> +			str_error_r(-err, sbuf, sizeof(sbuf)));
> +		if (sc && sc->name)
> +			fprintf(trace->output, "(%s)", sc->name);
>  		fputs(" information\n", trace->output);
>  	}
> -	return NULL;
> +	return err ? NULL : sc;
>  }
>  
>  struct syscall_stats {
> @@ -2600,14 +2666,6 @@ static void *syscall__augmented_args(struct syscall *sc, struct perf_sample *sam
>  	return NULL;
>  }
>  
> -static void syscall__exit(struct syscall *sc)
> -{
> -	if (!sc)
> -		return;
> -
> -	zfree(&sc->arg_fmt);
> -}
> -
>  static int trace__sys_enter(struct trace *trace, struct evsel *evsel,
>  			    union perf_event *event __maybe_unused,
>  			    struct perf_sample *sample)
> @@ -2619,7 +2677,7 @@ static int trace__sys_enter(struct trace *trace, struct evsel *evsel,
>  	int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
>  	int augmented_args_size = 0;
>  	void *augmented_args = NULL;
> -	struct syscall *sc = trace__syscall_info(trace, evsel, id);
> +	struct syscall *sc = trace__syscall_info(trace, evsel, EM_HOST, id);
>  	struct thread_trace *ttrace;
>  
>  	if (sc == NULL)
> @@ -2693,7 +2751,7 @@ static int trace__fprintf_sys_enter(struct trace *trace, struct evsel *evsel,
>  	struct thread_trace *ttrace;
>  	struct thread *thread;
>  	int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
> -	struct syscall *sc = trace__syscall_info(trace, evsel, id);
> +	struct syscall *sc = trace__syscall_info(trace, evsel, EM_HOST, id);
>  	char msg[1024];
>  	void *args, *augmented_args = NULL;
>  	int augmented_args_size;
> @@ -2768,7 +2826,7 @@ static int trace__sys_exit(struct trace *trace, struct evsel *evsel,
>  	struct thread *thread;
>  	int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1, callchain_ret = 0, printed = 0;
>  	int alignment = trace->args_alignment;
> -	struct syscall *sc = trace__syscall_info(trace, evsel, id);
> +	struct syscall *sc = trace__syscall_info(trace, evsel, EM_HOST, id);
>  	struct thread_trace *ttrace;
>  
>  	if (sc == NULL)
> @@ -3121,7 +3179,7 @@ static int trace__event_handler(struct trace *trace, struct evsel *evsel,
>  
>  	if (evsel == trace->syscalls.events.bpf_output) {
>  		int id = perf_evsel__sc_tp_uint(evsel, id, sample);
> -		struct syscall *sc = trace__syscall_info(trace, evsel, id);
> +		struct syscall *sc = trace__syscall_info(trace, evsel, EM_HOST, id);
>  
>  		if (sc) {
>  			fprintf(trace->output, "%s(", sc->name);
> @@ -3626,7 +3684,7 @@ static struct bpf_program *trace__find_syscall_bpf_prog(struct trace *trace, str
>  
>  static void trace__init_syscall_bpf_progs(struct trace *trace, int id)
>  {
> -	struct syscall *sc = trace__syscall_info(trace, NULL, id);
> +	struct syscall *sc = trace__syscall_info(trace, NULL, EM_HOST, id);
>  
>  	if (sc == NULL)
>  		return;
> @@ -3637,20 +3695,20 @@ static void trace__init_syscall_bpf_progs(struct trace *trace, int id)
>  
>  static int trace__bpf_prog_sys_enter_fd(struct trace *trace, int id)
>  {
> -	struct syscall *sc = trace__syscall_info(trace, NULL, id);
> +	struct syscall *sc = trace__syscall_info(trace, NULL, EM_HOST, id);
>  	return sc ? bpf_program__fd(sc->bpf_prog.sys_enter) : bpf_program__fd(trace->skel->progs.syscall_unaugmented);
>  }
>  
>  static int trace__bpf_prog_sys_exit_fd(struct trace *trace, int id)
>  {
> -	struct syscall *sc = trace__syscall_info(trace, NULL, id);
> +	struct syscall *sc = trace__syscall_info(trace, NULL, EM_HOST, id);
>  	return sc ? bpf_program__fd(sc->bpf_prog.sys_exit) : bpf_program__fd(trace->skel->progs.syscall_unaugmented);
>  }
>  
>  static int trace__bpf_sys_enter_beauty_map(struct trace *trace, int key, unsigned int *beauty_array)
>  {
>  	struct tep_format_field *field;
> -	struct syscall *sc = trace__syscall_info(trace, NULL, key);
> +	struct syscall *sc = trace__syscall_info(trace, NULL, EM_HOST, key);
>  	const struct btf_type *bt;
>  	char *struct_offset, *tmp, name[32];
>  	bool can_augment = false;
> @@ -3748,7 +3806,7 @@ static struct bpf_program *trace__find_usable_bpf_prog_entry(struct trace *trace
>  try_to_find_pair:
>  	for (int i = 0; i < trace->sctbl->syscalls.nr_entries; ++i) {
>  		int id = syscalltbl__id_at_idx(trace->sctbl, i);
> -		struct syscall *pair = trace__syscall_info(trace, NULL, id);
> +		struct syscall *pair = trace__syscall_info(trace, NULL, EM_HOST, id);
>  		struct bpf_program *pair_prog;
>  		bool is_candidate = false;
>  
> @@ -3898,7 +3956,7 @@ static int trace__init_syscalls_bpf_prog_array_maps(struct trace *trace)
>  	 */
>  	for (int i = 0; i < trace->sctbl->syscalls.nr_entries; ++i) {
>  		int key = syscalltbl__id_at_idx(trace->sctbl, i);
> -		struct syscall *sc = trace__syscall_info(trace, NULL, key);
> +		struct syscall *sc = trace__syscall_info(trace, NULL, EM_HOST, key);
>  		struct bpf_program *pair_prog;
>  		int prog_fd;
>  
> @@ -4663,7 +4721,11 @@ static size_t thread__dump_stats(struct thread_trace *ttrace,
>  			pct = avg ? 100.0 * stddev_stats(&stats->stats) / avg : 0.0;
>  			avg /= NSEC_PER_MSEC;
>  
> -			sc = &trace->syscalls.table[syscall_stats_entry->syscall];
> +			sc = trace__syscall_info(trace, /*evsel=*/NULL, EM_HOST,
> +						 syscall_stats_entry->syscall);
> +			if (!sc)
> +				continue;
> +
>  			printed += fprintf(fp, "   %-15s", sc->name);
>  			printed += fprintf(fp, " %8" PRIu64 " %6" PRIu64 " %9.3f %9.3f %9.3f",
>  					   n, stats->nr_failures, syscall_stats_entry->msecs, min, avg);
> @@ -5071,12 +5133,10 @@ static int trace__config(const char *var, const char *value, void *arg)
>  
>  static void trace__exit(struct trace *trace)
>  {
> -	int i;
> -
>  	strlist__delete(trace->ev_qualifier);
>  	zfree(&trace->ev_qualifier_ids.entries);
>  	if (trace->syscalls.table) {
> -		for (i = 0; i <= trace->sctbl->syscalls.max_id; i++)
> +		for (size_t i = 0; i < trace->syscalls.table_size; i++)
>  			syscall__exit(&trace->syscalls.table[i]);
>  		zfree(&trace->syscalls.table);
>  	}
> -- 
> 2.48.1.502.g6dc24dfdaf-goog
> 


WARNING: multiple messages have this Message-ID (diff)
From: Charlie Jenkins <charlie@rivosinc.com>
To: Ian Rogers <irogers@google.com>
Cc: "Peter Zijlstra" <peterz@infradead.org>,
	"Ingo Molnar" <mingo@redhat.com>,
	"Arnaldo Carvalho de Melo" <acme@kernel.org>,
	"Namhyung Kim" <namhyung@kernel.org>,
	"Mark Rutland" <mark.rutland@arm.com>,
	"Alexander Shishkin" <alexander.shishkin@linux.intel.com>,
	"Jiri Olsa" <jolsa@kernel.org>,
	"Adrian Hunter" <adrian.hunter@intel.com>,
	"Kan Liang" <kan.liang@linux.intel.com>,
	"John Garry" <john.g.garry@oracle.com>,
	"Will Deacon" <will@kernel.org>,
	"James Clark" <james.clark@linaro.org>,
	"Mike Leach" <mike.leach@linaro.org>,
	"Leo Yan" <leo.yan@linux.dev>, "Guo Ren" <guoren@kernel.org>,
	"Paul Walmsley" <paul.walmsley@sifive.com>,
	"Palmer Dabbelt" <palmer@dabbelt.com>,
	"Albert Ou" <aou@eecs.berkeley.edu>,
	"Bibo Mao" <maobibo@loongson.cn>, "Arnd Bergmann" <arnd@arndb.de>,
	"Huacai Chen" <chenhuacai@kernel.org>,
	"Catalin Marinas" <catalin.marinas@arm.com>,
	"Jiri Slaby" <jirislaby@kernel.org>,
	"Björn Töpel" <bjorn@rivosinc.com>,
	"Howard Chu" <howardchu95@gmail.com>,
	linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org, linux-csky@vger.kernel.org,
	linux-riscv@lists.infradead.org
Subject: Re: [PATCH v2 2/7] perf trace: Reorganize syscalls
Date: Mon, 10 Feb 2025 16:17:57 -0800	[thread overview]
Message-ID: <Z6qXNcjQE2RaoDUZ@ghost> (raw)
In-Reply-To: <20250210165108.95894-3-irogers@google.com>

On Mon, Feb 10, 2025 at 08:51:03AM -0800, Ian Rogers wrote:
> Identify struct syscall information in the syscalls table by a machine
> type and syscall number, not just system call number. Having the
> machine type means that 32-bit system calls can be differentiated from
> 64-bit ones on a machine capable of both. Having a table for all
> machine types and all system call numbers would be too large, so
> maintain a sorted array of system calls as they are encountered.

Reviewed-by: Charlie Jenkins <charlie@rivosinc.com>
Tested-by: Charlie Jenkins <charlie@rivosinc.com>

> 
> Signed-off-by: Ian Rogers <irogers@google.com>
> Reviewed-by: Howard Chu <howardchu95@gmail.com>
> ---
>  tools/perf/builtin-trace.c | 178 +++++++++++++++++++++++++------------
>  1 file changed, 119 insertions(+), 59 deletions(-)
> 
> diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
> index 06356217adeb..916a51df236b 100644
> --- a/tools/perf/builtin-trace.c
> +++ b/tools/perf/builtin-trace.c
> @@ -66,6 +66,7 @@
>  #include "rb_resort.h"
>  #include "../perf.h"
>  #include "trace_augment.h"
> +#include "dwarf-regs.h"
>  
>  #include <errno.h>
>  #include <inttypes.h>
> @@ -86,6 +87,7 @@
>  
>  #include <linux/ctype.h>
>  #include <perf/mmap.h>
> +#include <tools/libc_compat.h>
>  
>  #ifdef HAVE_LIBTRACEEVENT
>  #include <event-parse.h>
> @@ -143,7 +145,10 @@ struct trace {
>  	struct perf_tool	tool;
>  	struct syscalltbl	*sctbl;
>  	struct {
> +		/** Sorted sycall numbers used by the trace. */
>  		struct syscall  *table;
> +		/** Size of table. */
> +		size_t		table_size;
>  		struct {
>  			struct evsel *sys_enter,
>  				*sys_exit,
> @@ -1445,22 +1450,37 @@ static const struct syscall_fmt *syscall_fmt__find_by_alias(const char *alias)
>  	return __syscall_fmt__find_by_alias(syscall_fmts, nmemb, alias);
>  }
>  
> -/*
> - * is_exit: is this "exit" or "exit_group"?
> - * is_open: is this "open" or "openat"? To associate the fd returned in sys_exit with the pathname in sys_enter.
> - * args_size: sum of the sizes of the syscall arguments, anything after that is augmented stuff: pathname for openat, etc.
> - * nonexistent: Just a hole in the syscall table, syscall id not allocated
> +/**
> + * struct syscall
>   */
>  struct syscall {
> +	/** @e_machine: The ELF machine associated with the entry. */
> +	int e_machine;
> +	/** @id: id value from the tracepoint, the system call number. */
> +	int id;
>  	struct tep_event    *tp_format;
>  	int		    nr_args;
> +	/**
> +	 * @args_size: sum of the sizes of the syscall arguments, anything
> +	 * after that is augmented stuff: pathname for openat, etc.
> +	 */
> +
>  	int		    args_size;
>  	struct {
>  		struct bpf_program *sys_enter,
>  				   *sys_exit;
>  	}		    bpf_prog;
> +	/** @is_exit: is this "exit" or "exit_group"? */
>  	bool		    is_exit;
> +	/**
> +	 * @is_open: is this "open" or "openat"? To associate the fd returned in
> +	 * sys_exit with the pathname in sys_enter.
> +	 */
>  	bool		    is_open;
> +	/**
> +	 * @nonexistent: Name lookup failed. Just a hole in the syscall table,
> +	 * syscall id not allocated.
> +	 */
>  	bool		    nonexistent;
>  	bool		    use_btf;
>  	struct tep_format_field *args;
> @@ -2066,22 +2086,21 @@ static int syscall__set_arg_fmts(struct syscall *sc)
>  	return 0;
>  }
>  
> -static int trace__read_syscall_info(struct trace *trace, int id)
> +static int syscall__read_info(struct syscall *sc, struct trace *trace)
>  {
>  	char tp_name[128];
> -	struct syscall *sc;
> -	const char *name = syscalltbl__name(trace->sctbl, id);
> +	const char *name;
>  	int err;
>  
> -	if (trace->syscalls.table == NULL) {
> -		trace->syscalls.table = calloc(trace->sctbl->syscalls.max_id + 1, sizeof(*sc));
> -		if (trace->syscalls.table == NULL)
> -			return -ENOMEM;
> -	}
> -	sc = trace->syscalls.table + id;
>  	if (sc->nonexistent)
>  		return -EEXIST;
>  
> +	if (sc->name) {
> +		/* Info already read. */
> +		return 0;
> +	}
> +
> +	name = syscalltbl__name(trace->sctbl, sc->id);
>  	if (name == NULL) {
>  		sc->nonexistent = true;
>  		return -EEXIST;
> @@ -2104,15 +2123,16 @@ static int trace__read_syscall_info(struct trace *trace, int id)
>  	 */
>  	if (IS_ERR(sc->tp_format)) {
>  		sc->nonexistent = true;
> -		return PTR_ERR(sc->tp_format);
> +		err = PTR_ERR(sc->tp_format);
> +		sc->tp_format = NULL;
> +		return err;
>  	}
>  
>  	/*
>  	 * The tracepoint format contains __syscall_nr field, so it's one more
>  	 * than the actual number of syscall arguments.
>  	 */
> -	if (syscall__alloc_arg_fmts(sc, IS_ERR(sc->tp_format) ?
> -					RAW_SYSCALL_ARGS_NUM : sc->tp_format->format.nr_fields - 1))
> +	if (syscall__alloc_arg_fmts(sc, sc->tp_format->format.nr_fields - 1))
>  		return -ENOMEM;
>  
>  	sc->args = sc->tp_format->format.fields;
> @@ -2401,13 +2421,67 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
>  	return printed;
>  }
>  
> +static void syscall__init(struct syscall *sc, int e_machine, int id)
> +{
> +	memset(sc, 0, sizeof(*sc));
> +	sc->e_machine = e_machine;
> +	sc->id = id;
> +}
> +
> +static void syscall__exit(struct syscall *sc)
> +{
> +	if (!sc)
> +		return;
> +
> +	zfree(&sc->arg_fmt);
> +}
> +
> +static int syscall__cmp(const void *va, const void *vb)
> +{
> +	const struct syscall *a = va, *b = vb;
> +
> +	if (a->e_machine != b->e_machine)
> +		return a->e_machine - b->e_machine;
> +
> +	return a->id - b->id;
> +}
> +
> +static struct syscall *trace__find_syscall(struct trace *trace, int e_machine, int id)
> +{
> +	struct syscall key = {
> +		.e_machine = e_machine,
> +		.id = id,
> +	};
> +	struct syscall *sc, *tmp;
> +
> +	sc = bsearch(&key, trace->syscalls.table, trace->syscalls.table_size,
> +		     sizeof(struct syscall), syscall__cmp);
> +	if (sc)
> +		return sc;
> +
> +	tmp = reallocarray(trace->syscalls.table, trace->syscalls.table_size + 1,
> +			   sizeof(struct syscall));
> +	if (!tmp)
> +		return NULL;
> +
> +	trace->syscalls.table = tmp;
> +	sc = &trace->syscalls.table[trace->syscalls.table_size++];
> +	syscall__init(sc, e_machine, id);
> +	qsort(trace->syscalls.table, trace->syscalls.table_size, sizeof(struct syscall),
> +	      syscall__cmp);
> +	sc = bsearch(&key, trace->syscalls.table, trace->syscalls.table_size,
> +		     sizeof(struct syscall), syscall__cmp);
> +	return sc;
> +}
> +
>  typedef int (*tracepoint_handler)(struct trace *trace, struct evsel *evsel,
>  				  union perf_event *event,
>  				  struct perf_sample *sample);
>  
> -static struct syscall *trace__syscall_info(struct trace *trace,
> -					   struct evsel *evsel, int id)
> +static struct syscall *trace__syscall_info(struct trace *trace, struct evsel *evsel,
> +					   int e_machine, int id)
>  {
> +	struct syscall *sc;
>  	int err = 0;
>  
>  	if (id < 0) {
> @@ -2432,28 +2506,20 @@ static struct syscall *trace__syscall_info(struct trace *trace,
>  
>  	err = -EINVAL;
>  
> -	if (id > trace->sctbl->syscalls.max_id) {
> -		goto out_cant_read;
> -	}
> -
> -	if ((trace->syscalls.table == NULL || trace->syscalls.table[id].name == NULL) &&
> -	    (err = trace__read_syscall_info(trace, id)) != 0)
> -		goto out_cant_read;
> +	sc = trace__find_syscall(trace, e_machine, id);
> +	if (sc)
> +		err = syscall__read_info(sc, trace);
>  
> -	if (trace->syscalls.table && trace->syscalls.table[id].nonexistent)
> -		goto out_cant_read;
> -
> -	return &trace->syscalls.table[id];
> -
> -out_cant_read:
> -	if (verbose > 0) {
> +	if (err && verbose > 0) {
>  		char sbuf[STRERR_BUFSIZE];
> -		fprintf(trace->output, "Problems reading syscall %d: %d (%s)", id, -err, str_error_r(-err, sbuf, sizeof(sbuf)));
> -		if (id <= trace->sctbl->syscalls.max_id && trace->syscalls.table[id].name != NULL)
> -			fprintf(trace->output, "(%s)", trace->syscalls.table[id].name);
> +
> +		fprintf(trace->output, "Problems reading syscall %d: %d (%s)", id, -err,
> +			str_error_r(-err, sbuf, sizeof(sbuf)));
> +		if (sc && sc->name)
> +			fprintf(trace->output, "(%s)", sc->name);
>  		fputs(" information\n", trace->output);
>  	}
> -	return NULL;
> +	return err ? NULL : sc;
>  }
>  
>  struct syscall_stats {
> @@ -2600,14 +2666,6 @@ static void *syscall__augmented_args(struct syscall *sc, struct perf_sample *sam
>  	return NULL;
>  }
>  
> -static void syscall__exit(struct syscall *sc)
> -{
> -	if (!sc)
> -		return;
> -
> -	zfree(&sc->arg_fmt);
> -}
> -
>  static int trace__sys_enter(struct trace *trace, struct evsel *evsel,
>  			    union perf_event *event __maybe_unused,
>  			    struct perf_sample *sample)
> @@ -2619,7 +2677,7 @@ static int trace__sys_enter(struct trace *trace, struct evsel *evsel,
>  	int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
>  	int augmented_args_size = 0;
>  	void *augmented_args = NULL;
> -	struct syscall *sc = trace__syscall_info(trace, evsel, id);
> +	struct syscall *sc = trace__syscall_info(trace, evsel, EM_HOST, id);
>  	struct thread_trace *ttrace;
>  
>  	if (sc == NULL)
> @@ -2693,7 +2751,7 @@ static int trace__fprintf_sys_enter(struct trace *trace, struct evsel *evsel,
>  	struct thread_trace *ttrace;
>  	struct thread *thread;
>  	int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;
> -	struct syscall *sc = trace__syscall_info(trace, evsel, id);
> +	struct syscall *sc = trace__syscall_info(trace, evsel, EM_HOST, id);
>  	char msg[1024];
>  	void *args, *augmented_args = NULL;
>  	int augmented_args_size;
> @@ -2768,7 +2826,7 @@ static int trace__sys_exit(struct trace *trace, struct evsel *evsel,
>  	struct thread *thread;
>  	int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1, callchain_ret = 0, printed = 0;
>  	int alignment = trace->args_alignment;
> -	struct syscall *sc = trace__syscall_info(trace, evsel, id);
> +	struct syscall *sc = trace__syscall_info(trace, evsel, EM_HOST, id);
>  	struct thread_trace *ttrace;
>  
>  	if (sc == NULL)
> @@ -3121,7 +3179,7 @@ static int trace__event_handler(struct trace *trace, struct evsel *evsel,
>  
>  	if (evsel == trace->syscalls.events.bpf_output) {
>  		int id = perf_evsel__sc_tp_uint(evsel, id, sample);
> -		struct syscall *sc = trace__syscall_info(trace, evsel, id);
> +		struct syscall *sc = trace__syscall_info(trace, evsel, EM_HOST, id);
>  
>  		if (sc) {
>  			fprintf(trace->output, "%s(", sc->name);
> @@ -3626,7 +3684,7 @@ static struct bpf_program *trace__find_syscall_bpf_prog(struct trace *trace, str
>  
>  static void trace__init_syscall_bpf_progs(struct trace *trace, int id)
>  {
> -	struct syscall *sc = trace__syscall_info(trace, NULL, id);
> +	struct syscall *sc = trace__syscall_info(trace, NULL, EM_HOST, id);
>  
>  	if (sc == NULL)
>  		return;
> @@ -3637,20 +3695,20 @@ static void trace__init_syscall_bpf_progs(struct trace *trace, int id)
>  
>  static int trace__bpf_prog_sys_enter_fd(struct trace *trace, int id)
>  {
> -	struct syscall *sc = trace__syscall_info(trace, NULL, id);
> +	struct syscall *sc = trace__syscall_info(trace, NULL, EM_HOST, id);
>  	return sc ? bpf_program__fd(sc->bpf_prog.sys_enter) : bpf_program__fd(trace->skel->progs.syscall_unaugmented);
>  }
>  
>  static int trace__bpf_prog_sys_exit_fd(struct trace *trace, int id)
>  {
> -	struct syscall *sc = trace__syscall_info(trace, NULL, id);
> +	struct syscall *sc = trace__syscall_info(trace, NULL, EM_HOST, id);
>  	return sc ? bpf_program__fd(sc->bpf_prog.sys_exit) : bpf_program__fd(trace->skel->progs.syscall_unaugmented);
>  }
>  
>  static int trace__bpf_sys_enter_beauty_map(struct trace *trace, int key, unsigned int *beauty_array)
>  {
>  	struct tep_format_field *field;
> -	struct syscall *sc = trace__syscall_info(trace, NULL, key);
> +	struct syscall *sc = trace__syscall_info(trace, NULL, EM_HOST, key);
>  	const struct btf_type *bt;
>  	char *struct_offset, *tmp, name[32];
>  	bool can_augment = false;
> @@ -3748,7 +3806,7 @@ static struct bpf_program *trace__find_usable_bpf_prog_entry(struct trace *trace
>  try_to_find_pair:
>  	for (int i = 0; i < trace->sctbl->syscalls.nr_entries; ++i) {
>  		int id = syscalltbl__id_at_idx(trace->sctbl, i);
> -		struct syscall *pair = trace__syscall_info(trace, NULL, id);
> +		struct syscall *pair = trace__syscall_info(trace, NULL, EM_HOST, id);
>  		struct bpf_program *pair_prog;
>  		bool is_candidate = false;
>  
> @@ -3898,7 +3956,7 @@ static int trace__init_syscalls_bpf_prog_array_maps(struct trace *trace)
>  	 */
>  	for (int i = 0; i < trace->sctbl->syscalls.nr_entries; ++i) {
>  		int key = syscalltbl__id_at_idx(trace->sctbl, i);
> -		struct syscall *sc = trace__syscall_info(trace, NULL, key);
> +		struct syscall *sc = trace__syscall_info(trace, NULL, EM_HOST, key);
>  		struct bpf_program *pair_prog;
>  		int prog_fd;
>  
> @@ -4663,7 +4721,11 @@ static size_t thread__dump_stats(struct thread_trace *ttrace,
>  			pct = avg ? 100.0 * stddev_stats(&stats->stats) / avg : 0.0;
>  			avg /= NSEC_PER_MSEC;
>  
> -			sc = &trace->syscalls.table[syscall_stats_entry->syscall];
> +			sc = trace__syscall_info(trace, /*evsel=*/NULL, EM_HOST,
> +						 syscall_stats_entry->syscall);
> +			if (!sc)
> +				continue;
> +
>  			printed += fprintf(fp, "   %-15s", sc->name);
>  			printed += fprintf(fp, " %8" PRIu64 " %6" PRIu64 " %9.3f %9.3f %9.3f",
>  					   n, stats->nr_failures, syscall_stats_entry->msecs, min, avg);
> @@ -5071,12 +5133,10 @@ static int trace__config(const char *var, const char *value, void *arg)
>  
>  static void trace__exit(struct trace *trace)
>  {
> -	int i;
> -
>  	strlist__delete(trace->ev_qualifier);
>  	zfree(&trace->ev_qualifier_ids.entries);
>  	if (trace->syscalls.table) {
> -		for (i = 0; i <= trace->sctbl->syscalls.max_id; i++)
> +		for (size_t i = 0; i < trace->syscalls.table_size; i++)
>  			syscall__exit(&trace->syscalls.table[i]);
>  		zfree(&trace->syscalls.table);
>  	}
> -- 
> 2.48.1.502.g6dc24dfdaf-goog
> 

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

  reply	other threads:[~2025-02-11  2:41 UTC|newest]

Thread overview: 52+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-02-10 16:51 [PATCH v2 0/7] perf: Support multiple system call tables in the build Ian Rogers
2025-02-10 16:51 ` Ian Rogers
2025-02-10 16:51 ` [PATCH v2 1/7] perf syscalltble: Remove syscall_table.h Ian Rogers
2025-02-10 16:51   ` Ian Rogers
2025-02-10 23:48   ` Charlie Jenkins
2025-02-10 23:48     ` Charlie Jenkins
2025-02-10 16:51 ` [PATCH v2 2/7] perf trace: Reorganize syscalls Ian Rogers
2025-02-10 16:51   ` Ian Rogers
2025-02-11  0:17   ` Charlie Jenkins [this message]
2025-02-11  0:17     ` Charlie Jenkins
2025-02-10 16:51 ` [PATCH v2 3/7] perf syscalltbl: Remove struct syscalltbl Ian Rogers
2025-02-10 16:51   ` Ian Rogers
2025-02-11  0:19   ` Charlie Jenkins
2025-02-11  0:19     ` Charlie Jenkins
2025-02-11  7:48   ` Arnd Bergmann
2025-02-11  7:48     ` Arnd Bergmann
2025-02-11 16:18     ` Ian Rogers
2025-02-11 16:18       ` Ian Rogers
2025-02-11 16:34       ` Arnd Bergmann
2025-02-11 16:34         ` Arnd Bergmann
2025-02-11 17:32         ` Ian Rogers
2025-02-11 17:32           ` Ian Rogers
2025-02-10 16:51 ` [PATCH v2 4/7] perf thread: Add support for reading the e_machine type for a thread Ian Rogers
2025-02-10 16:51   ` Ian Rogers
2025-02-11  0:20   ` Charlie Jenkins
2025-02-11  0:20     ` Charlie Jenkins
2025-02-10 16:51 ` [PATCH v2 5/7] perf trace beauty: Add syscalltbl.sh generating all system call tables Ian Rogers
2025-02-10 16:51   ` Ian Rogers
2025-02-11  0:22   ` Charlie Jenkins
2025-02-11  0:22     ` Charlie Jenkins
2025-02-11  5:08     ` Ian Rogers
2025-02-11  5:08       ` Ian Rogers
2025-02-11  8:08   ` Arnd Bergmann
2025-02-11  8:08     ` Arnd Bergmann
2025-02-11 17:24     ` Ian Rogers
2025-02-11 17:24       ` Ian Rogers
2025-02-11 17:53       ` Arnd Bergmann
2025-02-11 17:53         ` Arnd Bergmann
2025-02-11 18:45         ` Ian Rogers
2025-02-11 18:45           ` Ian Rogers
2025-02-12 13:59         ` David Laight
2025-02-12 13:59           ` David Laight
2025-02-10 16:51 ` [PATCH v2 6/7] perf syscalltbl: Use lookup table containing multiple architectures Ian Rogers
2025-02-10 16:51   ` Ian Rogers
2025-02-10 23:39   ` Charlie Jenkins
2025-02-10 23:39     ` Charlie Jenkins
2025-02-11  5:15     ` Ian Rogers
2025-02-11  5:15       ` Ian Rogers
2025-02-11  0:23   ` Charlie Jenkins
2025-02-11  0:23     ` Charlie Jenkins
2025-02-10 16:51 ` [PATCH v2 7/7] perf build: Remove Makefile.syscalls Ian Rogers
2025-02-10 16:51   ` Ian Rogers

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=Z6qXNcjQE2RaoDUZ@ghost \
    --to=charlie@rivosinc.com \
    --cc=acme@kernel.org \
    --cc=adrian.hunter@intel.com \
    --cc=alexander.shishkin@linux.intel.com \
    --cc=aou@eecs.berkeley.edu \
    --cc=arnd@arndb.de \
    --cc=bjorn@rivosinc.com \
    --cc=catalin.marinas@arm.com \
    --cc=chenhuacai@kernel.org \
    --cc=guoren@kernel.org \
    --cc=howardchu95@gmail.com \
    --cc=irogers@google.com \
    --cc=james.clark@linaro.org \
    --cc=jirislaby@kernel.org \
    --cc=john.g.garry@oracle.com \
    --cc=jolsa@kernel.org \
    --cc=kan.liang@linux.intel.com \
    --cc=leo.yan@linux.dev \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-csky@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-perf-users@vger.kernel.org \
    --cc=linux-riscv@lists.infradead.org \
    --cc=maobibo@loongson.cn \
    --cc=mark.rutland@arm.com \
    --cc=mike.leach@linaro.org \
    --cc=mingo@redhat.com \
    --cc=namhyung@kernel.org \
    --cc=palmer@dabbelt.com \
    --cc=paul.walmsley@sifive.com \
    --cc=peterz@infradead.org \
    --cc=will@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.