]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
tests/check_ppc64_auxv_cap: replace LD_SHOW_AUXV-grep shell script with C program...
authorAbhay Kandpal via Valgrind-developers <valgrind-developers@lists.sourceforge.net>
Thu, 18 Jun 2026 18:08:26 +0000 (13:08 -0500)
committerMark Wielaard <mark@klomp.org>
Thu, 18 Jun 2026 21:46:47 +0000 (23:46 +0200)
glibc 2.42 removed sysdeps/powerpc/dl-procinfo.h, which contained
the PowerPC-specific _dl_procinfo() hook that printed human-readable
capability strings in LD_SHOW_AUXV output.  After the change,
LD_SHOW_AUXV emits raw hex for AT_HWCAP / AT_HWCAP2 instead of
capability names like 'altivec' or 'vsx'.

tests/check_ppc64_auxv_cap was a shell script that grep'd
LD_SHOW_AUXV output for capability words, used as a .vgtest 'prereq:'
across many PowerPC tests under none/tests/ppc{32,64}/ and
memcheck/tests/ppc{32,64}/.  On glibc 2.42 it always returns
non-zero, so vg_regtest.in silently skips every test that depends
on it (rc 256, "skipping, prereq failed").  Effectively the entire
PowerPC instruction-level regression suite was disabled.

Replace the shell script with a small C program using getauxval(),
which reads AT_HWCAP / AT_HWCAP2 directly and is unaffected by the
glibc change.  Calling convention and exit codes match the original
script exactly, so none of the .vgtest files need modification:

    check_ppc64_auxv_cap <capability>
      exit 0 - capability is present
      exit 1 - capability is absent, unknown, or usage error

tests/Makefile.am: move check_ppc64_auxv_cap from dist_noinst_SCRIPTS
to check_PROGRAMS so automake builds the binary from the C source.

For portability, configure.ac is extended with AC_CHECK_FUNCS([getauxval])
to detect whether the platform provides getauxval().  On glibc Linux it
is always present (since 2.16, 2012).  On other platforms (FreeBSD,
Solaris, macOS) the function may be absent; on those, the program is
compiled with a stub main() that returns 1 for every query.  None of
those platforms currently use Valgrind's PowerPC port, but the build
must still succeed there.

Signed-off-by: Abhay Kandpal <abhay@linux.ibm.com>
configure.ac
tests/Makefile.am
tests/check_ppc64_auxv_cap [deleted file]
tests/check_ppc64_auxv_cap.c [new file with mode: 0644]

index f8e7fb89f9f7a272265218ac6362270969e02b0b..0737441441c648baf5cfe7bf31255a5fbad5b1a3 100644 (file)
@@ -5372,7 +5372,8 @@ AC_CHECK_FUNCS([     \
         timer_delete \
         fchroot      \
         setcred      \
-        exterrctl
+        exterrctl    \
+        getauxval
         ])
 
 if test "$VGCONF_OS" = "solaris" ; then
index efe3546ac7f3091398a05030b1656dbe114fafc3..7063bd82fba3c5de8284bfe3198482931bd89072 100644 (file)
@@ -24,7 +24,6 @@ min_power_isa_FLAGS = $(ISA_2_05_FLAG)  $(ISA_2_06_FLAG) $(ISA_2_07_FLAG)
 dist_noinst_SCRIPTS = \
        check_headers_and_includes \
        check_makefile_consistency \
-       check_ppc64_auxv_cap \
        filter_addresses \
        filter_libc \
        filter_numbers \
@@ -52,6 +51,7 @@ check_PROGRAMS = \
        x86_amd64_features \
        s390x_features \
        mips_features \
+       check_ppc64_auxv_cap \
        power_insn_available \
        is_ppc64_BE \
        min_power_isa \
diff --git a/tests/check_ppc64_auxv_cap b/tests/check_ppc64_auxv_cap
deleted file mode 100755 (executable)
index caceef5..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-#!/bin/sh
-
-# Check if the passed in (CAPABILITY_WORD) matches a value found in the
-# current hwcap aux vector.
-
-# return '0' to indicate the capability was found.
-# return '1' for not found, or any other error condition.
-
-CAPABILITY_WORD=$1
-
-# SANITY CHECK Begin:
-# These are potential hwcap values as found in the glibc dl-procinfo.c
-# sources as of July 2015.
-P_HWCAP_1=" vsx arch_2_06 power6x dfp pa6t arch_2_05 ic_snoop smt booke"
-P_HWCAP_2=" cellbe power5+ power5 power4 notb efpdouble efpsingle spe"
-P_HWCAP_3=" ucache 4xxmac mmu fpu altivec ppc601 ppc64 ppc32 "
-P_HWCAP2_1=" tar isel ebb dscr htm arch_2_07 arch_3_00 "
-# Additional entries as of ... future
-P_HWCAP2_2=" arch_3_1 mma "
-CAPABILITY_FOUND="no"
-for POTENTIAL_CAP in $P_HWCAP_1 $P_HWCAP_2 $P_HWCAP_3 $P_HWCAP2_1 $P_HWCAP2_2 ; do
-       if [ "x$CAPABILITY_WORD" = "x$POTENTIAL_CAP" ]; then
-               CAPABILITY_FOUND="yes"
-               break
-       fi
-done
-if [ x$CAPABILITY_FOUND = "xno" ]; then
-       echo "Warning: did not find $CAPABILITY_WORD in the potential capabilities list."
-       echo "         LD_SHOW_AUXV=1 /bin/true | grep ^AT_HWCAP "
-       echo "         Double-check that the input value [$CAPABILITY_WORD] is valid."
-fi
-# SANITY CHECK End
-
-# Capability Check Begin:
-LD_SHOW_AUXV=1 /bin/true | grep ^AT_HWCAP | grep -w $CAPABILITY_WORD 2>&1 > /dev/null
-if [ "$?" -eq "0" ]; then
-       #echo "found the capability"
-       exit 0
-elif [ "$?" -eq "2" ]; then
-       # echo "grep failure"
-       exit 1
-else
-       #echo "did not find the capability"
-       exit 1
-fi
-
diff --git a/tests/check_ppc64_auxv_cap.c b/tests/check_ppc64_auxv_cap.c
new file mode 100644 (file)
index 0000000..43e5657
--- /dev/null
@@ -0,0 +1,136 @@
+/* ---------------------------------------------------------------------
+   This file is part of Valgrind, a dynamic binary instrumentation
+   framework.
+
+   Copyright (C) 2026  Abhay Kandpal <abhay@linux.ibm.com>
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 3 of the
+   License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+   The GNU General Public License is contained in the file COPYING.
+   ------------------------------------------------------------------ */
+
+/* check_ppc64_auxv_cap.c
+
+   Replacement for the historical 'tests/check_ppc64_auxv_cap' shell
+   script.  Used as a .vgtest 'prereq:' helper by ~51 tests under
+   none/tests/ppc{32,64}/ and memcheck/tests/ppc{32,64}/ to decide,
+   at test-run time, whether the host machine supports a given
+   PowerPC capability (altivec, vsx, dfp, arch_2_05, arch_2_06,
+   arch_2_07, arch_3_00, arch_3_1, htm, mma).
+
+   The original shell script parsed the textual output of
+       LD_SHOW_AUXV=1 /bin/true | grep ^AT_HWCAP
+   for human-readable capability words such as 'altivec'.  glibc 2.42
+   removed the PowerPC-specific _dl_procinfo() hook (formerly in
+   sysdeps/powerpc/dl-procinfo.h, commits 6cb703b / 1d60b9d), so
+   LD_SHOW_AUXV now prints raw hex for AT_HWCAP / AT_HWCAP2 and the
+   'grep -w altivec' pattern in the script never matches.  The
+   resulting non-zero exit caused vg_regtest.in to skip every test
+   that depends on this prereq, silently disabling essentially the
+   whole PowerPC instruction-level regression suite.
+
+   This C version uses getauxval() to read AT_HWCAP / AT_HWCAP2
+   directly.  That is the documented, stable interface to the auxv,
+   and it is unaffected by the glibc change.
+
+   Calling convention (preserved from the old script so the existing
+   .vgtest files need no modification):
+       check_ppc64_auxv_cap <capability>
+       exit code 0  - capability is present
+       exit code 1  - capability is absent, unknown, or usage error
+*/
+
+#include "config.h"
+#include <stdio.h>
+#include <string.h>
+
+#ifdef HAVE_GETAUXVAL
+
+#include <sys/auxv.h>
+
+/* Capability bit table.  Values are taken from
+   /usr/include/bits/hwcap.h on a glibc-2.41-or-earlier system, and
+   cross-checked against arch/powerpc/include/uapi/asm/cputable.h in
+   the Linux kernel.  AT_HWCAP / AT_HWCAP2 bit assignments are part of
+   the kernel ABI and are stable, so it is safe to hardcode them here
+   rather than depend on the PowerPC-specific bits/hwcap.h header
+   being installed at build time. */
+
+typedef
+   struct {
+      const char*   name;
+      unsigned long type;   /* AT_HWCAP or AT_HWCAP2 */
+      unsigned long bit;
+   }
+   CapEntry;
+
+static const CapEntry cap_table[] = {
+   /* AT_HWCAP  */
+   { "altivec",   AT_HWCAP,  0x10000000UL },
+   { "vsx",       AT_HWCAP,  0x00000080UL },
+   { "dfp",       AT_HWCAP,  0x00000400UL },
+   { "arch_2_05", AT_HWCAP,  0x00001000UL },
+   { "arch_2_06", AT_HWCAP,  0x00000100UL },
+   /* AT_HWCAP2 */
+   { "arch_2_07", AT_HWCAP2, 0x80000000UL },
+   { "arch_3_00", AT_HWCAP2, 0x00800000UL },
+   { "arch_3_1",  AT_HWCAP2, 0x00040000UL },
+   { "htm",       AT_HWCAP2, 0x40000000UL },
+   { "mma",       AT_HWCAP2, 0x00020000UL },
+};
+
+#define N_CAP_TABLE  (sizeof cap_table / sizeof cap_table[0])
+
+int main(int argc, char** argv)
+{
+   unsigned int  i;
+   unsigned long hwcap;
+   const char*   progname
+      = (argc > 0 && argv[0] != NULL) ? argv[0] : "check_ppc64_auxv_cap";
+
+   if (argc != 2) {
+      fprintf(stderr, "usage: %s <capability>\n", progname);
+      return 1;
+   }
+
+   for (i = 0; i < N_CAP_TABLE; i++) {
+      if (strcmp(argv[1], cap_table[i].name) == 0) {
+         hwcap = getauxval(cap_table[i].type);
+         return (hwcap & cap_table[i].bit) ? 0 : 1;
+      }
+   }
+
+   /* Unknown capability name.  Report 'not found', matching the
+      behaviour of the original grep-based script when the requested
+      capability word did not appear in the LD_SHOW_AUXV output. */
+   fprintf(stderr, "%s: unknown capability '%s'\n", progname, argv[1]);
+   return 1;
+}
+
+#else /* !HAVE_GETAUXVAL */
+
+/* getauxval() is not available on this platform (e.g. FreeBSD, Solaris,
+   macOS).  None of those platforms currently use Valgrind's PowerPC
+   port, but the program must still build and link there.  Return 1 for
+   every query - equivalent to "capability not detected" - which causes
+   the .vgtest harness to skip any test using this as a prereq. */
+
+int main(int argc, char** argv)
+{
+   (void)argc;
+   (void)argv;
+   return 1;
+}
+
+#endif /* HAVE_GETAUXVAL */