]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
perf env: Refactor perf_env__arch_strerrno
authorIan Rogers <irogers@google.com>
Tue, 2 Jun 2026 15:25:11 +0000 (08:25 -0700)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Wed, 3 Jun 2026 19:50:45 +0000 (16:50 -0300)
The previous approach maps an architecture string to a function
pointer to a function that takes an int errno value and returns a
string. The new approach takes an e_machine and an errno value and
returns a string.

As the only call site is in builtin-trace.c, the e_machine is already
present and potentially more specific than the perf_env arch string
that is a single global value.

Since the errno-to-name mapping is now generated statically and no
longer depends on libtraceevent, we can remove the HAVE_LIBTRACEEVENT
guards entirely, making perf_env__arch_strerrno unconditionally
available.

The major complication in this approach is having the shell script
that generates the C code map a linux directory name to the matching
ELF machine constants. To ensure compatibility with older hosts that
have older glibc versions, output fallback definitions for newer ELF
machine constants (EM_AARCH64, EM_CSKY, EM_LOONGARCH) if they are not
defined in the system <elf.h>.

Signed-off-by: Ian Rogers <irogers@google.com>
Acked-by: Namhyung Kim <namhyung@kernel.org>
Cc: Alexander Gordeev <agordeev@linux.ibm.com>
Cc: Heiko Carstens <hca@linux.ibm.com>
Cc: Honglei Wang <jameshongleiwang@126.com>
Cc: Jan Polensky <japo@linux.ibm.com>
Cc: Sumanth Korikkar <sumanthk@linux.ibm.com>
Cc: Thomas Richter <tmricht@linux.ibm.com>
Cc: Vasily Gorbik <gor@linux.ibm.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/builtin-trace.c
tools/perf/trace/beauty/Build
tools/perf/trace/beauty/arch_errno_names.sh
tools/perf/util/env.c
tools/perf/util/env.h

index 2530b4035e4f57e162020ef0f44487e2d357159d..377f0a18b00e3aa874b4691f2be2cd0b88397d29 100644 (file)
@@ -3032,9 +3032,8 @@ signed_print:
        } else if (ret < 0) {
 errno_print: {
                char bf[STRERR_BUFSIZE];
-               struct perf_env *env = evsel__env(evsel) ?: &trace->host_env;
                const char *emsg = str_error_r(-ret, bf, sizeof(bf));
-               const char *e = perf_env__arch_strerrno(env, err);
+               const char *e = perf_env__arch_strerrno(e_machine, err);
 
                fprintf(trace->output, "-1 %s (%s)", e, emsg);
        }
@@ -4921,7 +4920,9 @@ static size_t syscall__dump_stats(struct trace *trace, int e_machine, FILE *fp,
 
                                for (e = 0; e < stats->max_errno; ++e) {
                                        if (stats->errnos[e] != 0)
-                                               fprintf(fp, "\t\t\t\t%s: %d\n", perf_env__arch_strerrno(trace->host->env, e + 1), stats->errnos[e]);
+                                               fprintf(fp, "\t\t\t\t%s: %d\n",
+                                                       perf_env__arch_strerrno(e_machine, e + 1),
+                                                       stats->errnos[e]);
                                }
                        }
                        lines++;
index 996e63cdf765b617004d783c90b5d0a7bc996b41..bf9553f683f80d8aec060d1adad6c22576546989 100644 (file)
@@ -36,6 +36,7 @@ perf-y += signum.o
 perf-y += socket_type.o
 perf-y += waitid_options.o
 perf-util-y += arch_errno_names.o
+
 perf-y += tracepoints/
 
 ifdef SHELLCHECK
index d48d8561a7bb419d9419b5da2b1e16e7311b6408..8751bfa4a2b23477233f6654a33f17602a7aee57 100755 (executable)
@@ -52,21 +52,50 @@ process_arch()
                |IFS=, create_errno_lookup_func "$arch"
 }
 
+arch_to_e_machine()
+{
+       case "$1" in
+       alpha)      printf '\tcase EM_ALPHA:\n' ;;
+       arc)        printf '\tcase EM_ARC:\n' ;;
+       arm)        printf '\tcase EM_ARM:\n' ;;
+       arm64)      printf '\tcase EM_AARCH64:\n' ;;
+       csky)       printf '\tcase EM_CSKY:\n' ;;
+       hexagon)    printf '\tcase EM_HEXAGON:\n' ;;
+       loongarch)  printf '\tcase EM_LOONGARCH:\n' ;;
+       microblaze) printf '\tcase EM_MICROBLAZE:\n' ;;
+       mips)       printf '\tcase EM_MIPS:\n' ;;
+       parisc)     printf '\tcase EM_PARISC:\n' ;;
+       powerpc)    printf '\tcase EM_PPC:\n\tcase EM_PPC64:\n' ;;
+       riscv)      printf '\tcase EM_RISCV:\n' ;;
+       s390)       printf '\tcase EM_S390:\n' ;;
+       sh)         printf '\tcase EM_SH:\n' ;;
+       sparc)      printf '\tcase EM_SPARC:\n\tcase EM_SPARCV9:\n' ;;
+       x86)        printf '\tcase EM_386:\n\tcase EM_X86_64:\n' ;;
+       xtensa)     printf '\tcase EM_XTENSA:\n' ;;
+       esac
+}
+
 create_arch_errno_table_func()
 {
        archlist="$1"
        default="$2"
 
-       printf 'arch_syscalls__strerrno_t *\n'
-       printf 'arch_syscalls__strerrno_function(const char *arch)\n'
+       printf 'const char *arch_syscalls__strerrno(uint16_t e_machine, int err);\n\n'
+       printf '__attribute__((unused)) const char *\n'
+       printf 'arch_syscalls__strerrno(uint16_t e_machine, int err)\n'
        printf '{\n'
+       printf '\tswitch (e_machine) {\n'
        for arch in $archlist; do
                arch_str=$(arch_string "$arch")
-               printf '\tif (!strcmp(arch, "%s"))\n' "$arch_str"
-               printf '\t\treturn errno_to_name__%s;\n' "$arch_str"
+               ems=$(arch_to_e_machine "$arch_str")
+               if [ -n "$ems" ]; then
+                       printf '%s\n' "$ems"
+                       printf '\t\treturn errno_to_name__%s(err);\n' "$arch_str"
+               fi
        done
        arch_str=$(arch_string "$default")
-       printf '\treturn errno_to_name__%s;\n' "$arch_str"
+       printf '\tdefault:\n\t\treturn errno_to_name__%s(err);\n' "$arch_str"
+       printf '\t}\n'
        printf '}\n'
 }
 
@@ -74,6 +103,20 @@ cat <<EoHEADER
 /* SPDX-License-Identifier: GPL-2.0 */
 
 #include <string.h>
+#include <stdint.h>
+#include <elf.h>
+
+#ifndef EM_AARCH64
+#define EM_AARCH64     183
+#endif
+
+#ifndef EM_CSKY
+#define EM_CSKY                252
+#endif
+
+#ifndef EM_LOONGARCH
+#define EM_LOONGARCH   258
+#endif
 
 EoHEADER
 
index fae70b07ba8dea90df5b7a7c7513559f3d6a1dc5..b41562fb06c632e61306f5e4ed2a033896c05892 100644 (file)
@@ -851,16 +851,11 @@ const char *perf_env__arch(struct perf_env *env)
        return arch;
 }
 
-const char *perf_env__arch_strerrno(struct perf_env *env __maybe_unused, int err __maybe_unused)
-{
-#if defined(HAVE_LIBTRACEEVENT)
-       if (env->arch_strerrno == NULL)
-               env->arch_strerrno = arch_syscalls__strerrno_function(perf_env__arch(env));
+const char *arch_syscalls__strerrno(uint16_t e_machine, int err);
 
-       return env->arch_strerrno ? env->arch_strerrno(err) : "no arch specific strerrno function";
-#else
-       return "!HAVE_LIBTRACEEVENT";
-#endif
+const char *perf_env__arch_strerrno(uint16_t e_machine, int err)
+{
+       return arch_syscalls__strerrno(e_machine, err);
 }
 
 const char *perf_env__cpuid(struct perf_env *env)
index dd9907dbc3450a0e85808c578a4232a5a13ce874..5a917271ca0d8abc085db2f698b3c889b7498b75 100644 (file)
@@ -67,8 +67,6 @@ struct cpu_domain_map {
        struct domain_info      **domains;
 };
 
-typedef const char *(arch_syscalls__strerrno_t)(int err);
-
 struct perf_env {
        char                    *hostname;
        char                    *os_release;
@@ -158,7 +156,6 @@ struct perf_env {
                 */
                bool    enabled;
        } clock;
-       arch_syscalls__strerrno_t *arch_strerrno;
 };
 
 enum perf_compress_type {
@@ -191,8 +188,7 @@ void cpu_cache_level__free(struct cpu_cache_level *cache);
 uint16_t perf_env__e_machine_nocache(struct perf_env *env, uint32_t *e_flags);
 uint16_t perf_env__e_machine(struct perf_env *env, uint32_t *e_flags);
 const char *perf_env__arch(struct perf_env *env);
-const char *perf_env__arch_strerrno(struct perf_env *env, int err);
-arch_syscalls__strerrno_t *arch_syscalls__strerrno_function(const char *arch);
+const char *perf_env__arch_strerrno(uint16_t e_machine, int err);
 const char *perf_env__cpuid(struct perf_env *env);
 const char *perf_env__raw_arch(struct perf_env *env);
 int perf_env__nr_cpus_avail(struct perf_env *env);