From nobody Mon Feb 9 05:59:21 2026 Received: from mail-yw1-f202.google.com (mail-yw1-f202.google.com [209.85.128.202]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AFBD554670 for ; Sat, 8 Mar 2025 00:32:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741393944; cv=none; b=Y/Eg8xl0j5ORxKy6iaHhvjiUkw+77KJWTRQSBx1PZhRgAzKhxIAVlJdaYUq3LZ48LAKDtS9cf6sx2XvtewlnrjCpieR0JtUBn2gg1cp80QjABsDZwY5bTS7HIpChY1dzuPvwqiv3sBVmbsU7vn4uzyKdCv8BDqCir+PqzcWiWJQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1741393944; c=relaxed/simple; bh=51j0JQwCKLfIqtjUdJi2Z47ymuGZPSnIEL4ZrnqgUQo=; h=Date:In-Reply-To:Message-Id:Mime-Version:References:Subject:From: To:Content-Type; b=ZFMMdMc3lgWspdAlda4hsafMuCqcwZGAGQWfb8S/4R+olb6PtFvgxkkqxhcMRRPmaNIaAGlUD2UtkYxo3GQt8GcN6gzQSHjNlqVXP5T6fID8vkaFY1PPFwWE/Hy6hB3pT0k7bXYyrvYk2L4T70iAgyoEe+JcK+D8pqwhH9OaePw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=aHp+r7t+; arc=none smtp.client-ip=209.85.128.202 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="aHp+r7t+" Received: by mail-yw1-f202.google.com with SMTP id 00721157ae682-6f2737d115eso33512917b3.2 for ; Fri, 07 Mar 2025 16:32:22 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1741393941; x=1741998741; darn=vger.kernel.org; h=to:from:subject:references:mime-version:message-id:in-reply-to:date :from:to:cc:subject:date:message-id:reply-to; bh=TAhKsnqf/Wp2f2WfbkipSd7nOjZwLTYVF9Ek4E/oE+c=; b=aHp+r7t+f+ChDad0pcCA7zluO8/zsG1+C+zDyAx5O1Lrl/lizQiskQUYjd997poRFT Paoxpi2qwDK8tvBnVoxuLyLBb9zVeJDl8l/Jnxo5iqROCELenduuK+O6ltVBgGFWnd/E Dgf5dZIYQtgeSHg8zC7OUTBDd/xWgT8KZrgOivt1KXoUWkMCio82BtTZIvJqeeqZSo91 BHgoJ1MMyDHDoVMAHv5VQyhtNn34McW/W3bL3B0j+wNL5jT2qr0tsjwAy36AgUgs1Oml 1Y46QnzAWo3KwxtQOJOMk9zFbBMBIaSHyA924/DWPlxbjKCqgYhmwPNGiSaJtC7MUzbj cgFw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1741393941; x=1741998741; h=to:from:subject:references:mime-version:message-id:in-reply-to:date :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=TAhKsnqf/Wp2f2WfbkipSd7nOjZwLTYVF9Ek4E/oE+c=; b=AytBNaMibb8oAIAlhbWPG5QFGYoz/QkdE94wKxA9p2nUTenH5vfBDBVw20u3bLmDpG nM2SXFkKubwRlsXRJDFi0cmo7INVeZp8WeYP96+gLosgWVAUlnhF92F/sXZaucVfG6Qv NmAjTYfAyd1qSvpheA9e2xnQYww2cAI1TkGIbEFug2QVc4prNIRKq53lTJwuIll2u2yu W2NXquuPvgQC7BzaiCXyJJV+J87RDSDKCn2ez7Wo0kLLB2qAVnWpwHt2ca2+qPVckBES ad2lXzUg8POa0ot4ctIeNAdRlZ5Ts8l4D6l8cn2V5RFycsYXlq477PtQQ2D/zUFo2wpd Fjtw== X-Forwarded-Encrypted: i=1; AJvYcCWknc/FzMdqL2ssHtemZw68tjeM8UpxbtYtxj9HptgUqhR2D6rgSDGOYZ4acdfV6YYlkVAx+Q0oVNczz1k=@vger.kernel.org X-Gm-Message-State: AOJu0YwGH05ODwhpSd+3rsN/cE6G0AZUhd90MLhkPpkUNGWUSI6qWGtT Nq55Rbu/39K57cai1P5oteW/riZyfVTS2wYf+7aJWN7eIdNQ5x2Cr00NpfPLWBa8R1PD0m1/fgi GtU4jVQ== X-Google-Smtp-Source: AGHT+IHvMBwSpjV05SawdQeDnvO1NysXWTjbmEJ0nWK7el3XmxDMXs7tHdQwLWAKqgCphUNf5PaqFDEdB38d X-Received: from irogers.svl.corp.google.com ([2620:15c:2c5:11:1541:e490:aa80:5766]) (user=irogers job=sendgmr) by 2002:a25:310b:0:b0:e60:92c9:1b63 with SMTP id 3f1490d57ef6-e635bf15b12mr36961276.0.1741393941601; Fri, 07 Mar 2025 16:32:21 -0800 (PST) Date: Fri, 7 Mar 2025 16:32:02 -0800 In-Reply-To: <20250308003209.234114-1-irogers@google.com> Message-Id: <20250308003209.234114-5-irogers@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250308003209.234114-1-irogers@google.com> X-Mailer: git-send-email 2.49.0.rc0.332.g42c0ae87b1-goog Subject: [PATCH v5 04/11] perf trace: Reorganize syscalls From: Ian Rogers To: Ian Rogers , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Alexander Shishkin , Jiri Olsa , Adrian Hunter , Kan Liang , John Garry , Will Deacon , James Clark , Mike Leach , Leo Yan , guoren , Paul Walmsley , Palmer Dabbelt , Albert Ou , Charlie Jenkins , Bibo Mao , Huacai Chen , Catalin Marinas , Jiri Slaby , "=?UTF-8?q?Bj=C3=B6rn=20T=C3=B6pel?=" , Howard Chu , 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, Arnd Bergmann Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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. Signed-off-by: Ian Rogers Reviewed-by: Howard Chu Reviewed-by: Charlie Jenkins --- tools/perf/builtin-trace.c | 177 ++++++++++++++++++++++++------------- 1 file changed, 118 insertions(+), 59 deletions(-) diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 092c5f6404ba..f7d035dc0e00 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -66,6 +66,7 @@ #include "syscalltbl.h" #include "../perf.h" #include "trace_augment.h" +#include "dwarf-regs.h" =20 #include #include @@ -86,6 +87,7 @@ =20 #include #include +#include =20 #ifdef HAVE_LIBTRACEEVENT #include @@ -149,7 +151,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, @@ -1454,22 +1459,37 @@ static const struct syscall_fmt *syscall_fmt__find_= by_alias(const char *alias) return __syscall_fmt__find_by_alias(syscall_fmts, nmemb, alias); } =20 -/* - * is_exit: is this "exit" or "exit_group"? - * is_open: is this "open" or "openat"? To associate the fd returned in sy= s_exit with the pathname in sys_enter. - * args_size: sum of the sizes of the syscall arguments, anything after th= at 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; @@ -2107,22 +2127,21 @@ static int syscall__set_arg_fmts(struct syscall *sc) return 0; } =20 -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 =3D syscalltbl__name(trace->sctbl, id); + const char *name; int err; =20 - if (trace->syscalls.table =3D=3D NULL) { - trace->syscalls.table =3D calloc(trace->sctbl->syscalls.max_id + 1, size= of(*sc)); - if (trace->syscalls.table =3D=3D NULL) - return -ENOMEM; - } - sc =3D trace->syscalls.table + id; if (sc->nonexistent) return -EEXIST; =20 + if (sc->name) { + /* Info already read. */ + return 0; + } + + name =3D syscalltbl__name(trace->sctbl, sc->id); if (name =3D=3D NULL) { sc->nonexistent =3D true; return -EEXIST; @@ -2145,15 +2164,16 @@ static int trace__read_syscall_info(struct trace *t= race, int id) */ if (IS_ERR(sc->tp_format)) { sc->nonexistent =3D true; - return PTR_ERR(sc->tp_format); + err =3D PTR_ERR(sc->tp_format); + sc->tp_format =3D NULL; + return err; } =20 /* * 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; =20 sc->args =3D sc->tp_format->format.fields; @@ -2442,13 +2462,67 @@ static size_t syscall__scnprintf_args(struct syscal= l *sc, char *bf, size_t size, return printed; } =20 +static void syscall__init(struct syscall *sc, int e_machine, int id) +{ + memset(sc, 0, sizeof(*sc)); + sc->e_machine =3D e_machine; + sc->id =3D 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 =3D va, *b =3D vb; + + if (a->e_machine !=3D 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_mach= ine, int id) +{ + struct syscall key =3D { + .e_machine =3D e_machine, + .id =3D id, + }; + struct syscall *sc, *tmp; + + sc =3D bsearch(&key, trace->syscalls.table, trace->syscalls.table_size, + sizeof(struct syscall), syscall__cmp); + if (sc) + return sc; + + tmp =3D reallocarray(trace->syscalls.table, trace->syscalls.table_size + = 1, + sizeof(struct syscall)); + if (!tmp) + return NULL; + + trace->syscalls.table =3D tmp; + sc =3D &trace->syscalls.table[trace->syscalls.table_size++]; + syscall__init(sc, e_machine, id); + qsort(trace->syscalls.table, trace->syscalls.table_size, sizeof(struct sy= scall), + syscall__cmp); + sc =3D 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); =20 -static struct syscall *trace__syscall_info(struct trace *trace, - struct evsel *evsel, int id) +static struct syscall *trace__syscall_info(struct trace *trace, struct evs= el *evsel, + int e_machine, int id) { + struct syscall *sc; int err =3D 0; =20 if (id < 0) { @@ -2473,28 +2547,20 @@ static struct syscall *trace__syscall_info(struct t= race *trace, =20 err =3D -EINVAL; =20 - if (id > trace->sctbl->syscalls.max_id) { - goto out_cant_read; - } - - if ((trace->syscalls.table =3D=3D NULL || trace->syscalls.table[id].name = =3D=3D NULL) && - (err =3D trace__read_syscall_info(trace, id)) !=3D 0) - goto out_cant_read; + sc =3D trace__find_syscall(trace, e_machine, id); + if (sc) + err =3D syscall__read_info(sc, trace); =20 - 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 <=3D trace->sctbl->syscalls.max_id && trace->syscalls.table[id].n= ame !=3D 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; } =20 struct syscall_stats { @@ -2643,14 +2709,6 @@ static void *syscall__augmented_args(struct syscall = *sc, struct perf_sample *sam return NULL; } =20 -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) @@ -2662,7 +2720,7 @@ static int trace__sys_enter(struct trace *trace, stru= ct evsel *evsel, int id =3D perf_evsel__sc_tp_uint(evsel, id, sample), err =3D -1; int augmented_args_size =3D 0; void *augmented_args =3D NULL; - struct syscall *sc =3D trace__syscall_info(trace, evsel, id); + struct syscall *sc =3D trace__syscall_info(trace, evsel, EM_HOST, id); struct thread_trace *ttrace; =20 if (sc =3D=3D NULL) @@ -2736,7 +2794,7 @@ static int trace__fprintf_sys_enter(struct trace *tra= ce, struct evsel *evsel, struct thread_trace *ttrace; struct thread *thread; int id =3D perf_evsel__sc_tp_uint(evsel, id, sample), err =3D -1; - struct syscall *sc =3D trace__syscall_info(trace, evsel, id); + struct syscall *sc =3D trace__syscall_info(trace, evsel, EM_HOST, id); char msg[1024]; void *args, *augmented_args =3D NULL; int augmented_args_size; @@ -2811,7 +2869,7 @@ static int trace__sys_exit(struct trace *trace, struc= t evsel *evsel, struct thread *thread; int id =3D perf_evsel__sc_tp_uint(evsel, id, sample), err =3D -1, callcha= in_ret =3D 0, printed =3D 0; int alignment =3D trace->args_alignment; - struct syscall *sc =3D trace__syscall_info(trace, evsel, id); + struct syscall *sc =3D trace__syscall_info(trace, evsel, EM_HOST, id); struct thread_trace *ttrace; =20 if (sc =3D=3D NULL) @@ -3164,7 +3222,7 @@ static int trace__event_handler(struct trace *trace, = struct evsel *evsel, =20 if (evsel =3D=3D trace->syscalls.events.bpf_output) { int id =3D perf_evsel__sc_tp_uint(evsel, id, sample); - struct syscall *sc =3D trace__syscall_info(trace, evsel, id); + struct syscall *sc =3D trace__syscall_info(trace, evsel, EM_HOST, id); =20 if (sc) { fprintf(trace->output, "%s(", sc->name); @@ -3673,7 +3731,7 @@ static struct bpf_program *trace__find_syscall_bpf_pr= og(struct trace *trace, str =20 static void trace__init_syscall_bpf_progs(struct trace *trace, int id) { - struct syscall *sc =3D trace__syscall_info(trace, NULL, id); + struct syscall *sc =3D trace__syscall_info(trace, NULL, EM_HOST, id); =20 if (sc =3D=3D NULL) return; @@ -3684,20 +3742,20 @@ static void trace__init_syscall_bpf_progs(struct tr= ace *trace, int id) =20 static int trace__bpf_prog_sys_enter_fd(struct trace *trace, int id) { - struct syscall *sc =3D trace__syscall_info(trace, NULL, id); + struct syscall *sc =3D trace__syscall_info(trace, NULL, EM_HOST, id); return sc ? bpf_program__fd(sc->bpf_prog.sys_enter) : bpf_program__fd(tra= ce->skel->progs.syscall_unaugmented); } =20 static int trace__bpf_prog_sys_exit_fd(struct trace *trace, int id) { - struct syscall *sc =3D trace__syscall_info(trace, NULL, id); + struct syscall *sc =3D trace__syscall_info(trace, NULL, EM_HOST, id); return sc ? bpf_program__fd(sc->bpf_prog.sys_exit) : bpf_program__fd(trac= e->skel->progs.syscall_unaugmented); } =20 static int trace__bpf_sys_enter_beauty_map(struct trace *trace, int key, u= nsigned int *beauty_array) { struct tep_format_field *field; - struct syscall *sc =3D trace__syscall_info(trace, NULL, key); + struct syscall *sc =3D trace__syscall_info(trace, NULL, EM_HOST, key); const struct btf_type *bt; char *struct_offset, *tmp, name[32]; bool can_augment =3D false; @@ -3795,7 +3853,7 @@ static struct bpf_program *trace__find_usable_bpf_pro= g_entry(struct trace *trace try_to_find_pair: for (int i =3D 0; i < trace->sctbl->syscalls.nr_entries; ++i) { int id =3D syscalltbl__id_at_idx(trace->sctbl, i); - struct syscall *pair =3D trace__syscall_info(trace, NULL, id); + struct syscall *pair =3D trace__syscall_info(trace, NULL, EM_HOST, id); struct bpf_program *pair_prog; bool is_candidate =3D false; =20 @@ -3945,7 +4003,7 @@ static int trace__init_syscalls_bpf_prog_array_maps(s= truct trace *trace) */ for (int i =3D 0; i < trace->sctbl->syscalls.nr_entries; ++i) { int key =3D syscalltbl__id_at_idx(trace->sctbl, i); - struct syscall *sc =3D trace__syscall_info(trace, NULL, key); + struct syscall *sc =3D trace__syscall_info(trace, NULL, EM_HOST, key); struct bpf_program *pair_prog; int prog_fd; =20 @@ -4761,7 +4819,10 @@ static size_t syscall__dump_stats(struct trace *trac= e, FILE *fp, pct =3D avg ? 100.0 * stddev_stats(&stats->stats) / avg : 0.0; avg /=3D NSEC_PER_MSEC; =20 - sc =3D &trace->syscalls.table[entry->syscall]; + sc =3D trace__syscall_info(trace, /*evsel=3D*/NULL, EM_HOST, entry->sys= call); + if (!sc) + continue; + printed +=3D fprintf(fp, " %-15s", sc->name); printed +=3D fprintf(fp, " %8" PRIu64 " %6" PRIu64 " %9.3f %9.3f %9.3f", n, stats->nr_failures, entry->msecs, min, avg); @@ -5218,12 +5279,10 @@ static int trace__config(const char *var, const cha= r *value, void *arg) =20 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 =3D 0; i <=3D trace->sctbl->syscalls.max_id; i++) + for (size_t i =3D 0; i < trace->syscalls.table_size; i++) syscall__exit(&trace->syscalls.table[i]); zfree(&trace->syscalls.table); } --=20 2.49.0.rc0.332.g42c0ae87b1-goog