446cf2
commit 31563b68410ff8e9490c5aafca31ec71b38f87a5
446cf2
Author: Florian Weimer <fweimer@redhat.com>
446cf2
Date:   Thu May 28 10:21:17 2020 +0200
446cf2
446cf2
    elf: Remove extra hwcap mechanism from ldconfig
446cf2
    
446cf2
    Historically, this mechanism was used to process "nosegneg"
446cf2
    subdirectories, and it is still used to include the "tls"
446cf2
    subdirectories.  With nosegneg support gone from ld.so, this is part
446cf2
    no longer useful.
446cf2
    
446cf2
    The entire mechanism is not well-designed because it causes the
446cf2
    meaning of hwcap bits in ld.so.cache to depend on the kernel version
446cf2
    that was used to generate the cache, which makes it difficult to use
446cf2
    this mechanism for anything else in the future.
446cf2
    
446cf2
    Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
446cf2
446cf2
diff --git a/elf/ldconfig.c b/elf/ldconfig.c
446cf2
index f31e10817dd5d665..7c8fd29387463a8a 100644
446cf2
--- a/elf/ldconfig.c
446cf2
+++ b/elf/ldconfig.c
446cf2
@@ -44,11 +44,15 @@
446cf2
 
446cf2
 #include <dl-procinfo.h>
446cf2
 
446cf2
-#ifdef _DL_FIRST_PLATFORM
446cf2
-# define _DL_FIRST_EXTRA (_DL_FIRST_PLATFORM + _DL_PLATFORMS_COUNT)
446cf2
-#else
446cf2
-# define _DL_FIRST_EXTRA _DL_HWCAP_COUNT
446cf2
-#endif
446cf2
+/* This subpath in search path entries is always supported and
446cf2
+   included in the cache for backwards compatibility.  */
446cf2
+#define TLS_SUBPATH "tls"
446cf2
+
446cf2
+/* The MSB of the hwcap field is set for objects in TLS_SUBPATH
446cf2
+   directories.  There is always TLS support in glibc, so the dynamic
446cf2
+   loader does not check the bit directly.  But more hwcap bits make a
446cf2
+   an object more preferred, so the bit still has meaning.  */
446cf2
+#define TLS_HWCAP_BIT 63
446cf2
 
446cf2
 #ifndef LD_SO_CONF
446cf2
 # define LD_SO_CONF SYSCONFDIR "/ld.so.conf"
446cf2
@@ -127,9 +131,6 @@ static const char *config_file;
446cf2
 /* Mask to use for important hardware capabilities.  */
446cf2
 static unsigned long int hwcap_mask = HWCAP_IMPORTANT;
446cf2
 
446cf2
-/* Configuration-defined capabilities defined in kernel vDSOs.  */
446cf2
-static const char *hwcap_extra[64 - _DL_FIRST_EXTRA];
446cf2
-
446cf2
 /* Name and version of program.  */
446cf2
 static void print_version (FILE *stream, struct argp_state *state);
446cf2
 void (*argp_program_version_hook) (FILE *, struct argp_state *)
446cf2
@@ -186,12 +187,9 @@ is_hwcap_platform (const char *name)
446cf2
   if (hwcap_idx != -1)
446cf2
     return 1;
446cf2
 
446cf2
-  /* Is this one of the extra pseudo-hwcaps that we map beyond
446cf2
-     _DL_FIRST_EXTRA like "tls", or "nosegneg?"  */
446cf2
-  for (hwcap_idx = _DL_FIRST_EXTRA; hwcap_idx < 64; ++hwcap_idx)
446cf2
-    if (hwcap_extra[hwcap_idx - _DL_FIRST_EXTRA] != NULL
446cf2
-	&& !strcmp (name, hwcap_extra[hwcap_idx - _DL_FIRST_EXTRA]))
446cf2
-      return 1;
446cf2
+  /* Backwards-compatibility for the "tls" subdirectory.  */
446cf2
+  if (strcmp (name, TLS_SUBPATH) == 0)
446cf2
+    return 1;
446cf2
 
446cf2
   return 0;
446cf2
 }
446cf2
@@ -226,11 +224,9 @@ path_hwcap (const char *path)
446cf2
 	  h = _dl_string_platform (ptr + 1);
446cf2
 	  if (h == (uint64_t) -1)
446cf2
 	    {
446cf2
-	      for (h = _DL_FIRST_EXTRA; h < 64; ++h)
446cf2
-		if (hwcap_extra[h - _DL_FIRST_EXTRA] != NULL
446cf2
-		    && !strcmp (ptr + 1, hwcap_extra[h - _DL_FIRST_EXTRA]))
446cf2
-		  break;
446cf2
-	      if (h == 64)
446cf2
+	      if (strcmp (ptr + 1, TLS_SUBPATH) == 0)
446cf2
+		h = TLS_HWCAP_BIT;
446cf2
+	      else
446cf2
 		break;
446cf2
 	    }
446cf2
 	}
446cf2
@@ -1145,52 +1141,7 @@ Warning: ignoring configuration file that cannot be opened: %s"),
446cf2
 	      parse_conf_include (filename, lineno, do_chroot, dir);
446cf2
 	}
446cf2
       else if (!strncasecmp (cp, "hwcap", 5) && isblank (cp[5]))
446cf2
-	{
446cf2
-	  cp += 6;
446cf2
-	  char *p, *name = NULL;
446cf2
-	  unsigned long int n = strtoul (cp, &cp, 0);
446cf2
-	  if (cp != NULL && isblank (*cp))
446cf2
-	    while ((p = strsep (&cp, " \t")) != NULL)
446cf2
-	      if (p[0] != '\0')
446cf2
-		{
446cf2
-		  if (name == NULL)
446cf2
-		    name = p;
446cf2
-		  else
446cf2
-		    {
446cf2
-		      name = NULL;
446cf2
-		      break;
446cf2
-		    }
446cf2
-		}
446cf2
-	  if (name == NULL)
446cf2
-	    {
446cf2
-	      error (EXIT_FAILURE, 0, _("%s:%u: bad syntax in hwcap line"),
446cf2
-		     filename, lineno);
446cf2
-	      break;
446cf2
-	    }
446cf2
-	  if (n >= (64 - _DL_FIRST_EXTRA))
446cf2
-	    error (EXIT_FAILURE, 0,
446cf2
-		   _("%s:%u: hwcap index %lu above maximum %u"),
446cf2
-		   filename, lineno, n, 64 - _DL_FIRST_EXTRA - 1);
446cf2
-	  if (hwcap_extra[n] == NULL)
446cf2
-	    {
446cf2
-	      for (unsigned long int h = 0; h < (64 - _DL_FIRST_EXTRA); ++h)
446cf2
-		if (hwcap_extra[h] != NULL && !strcmp (name, hwcap_extra[h]))
446cf2
-		  error (EXIT_FAILURE, 0,
446cf2
-			 _("%s:%u: hwcap index %lu already defined as %s"),
446cf2
-			 filename, lineno, h, name);
446cf2
-	      hwcap_extra[n] = xstrdup (name);
446cf2
-	    }
446cf2
-	  else
446cf2
-	    {
446cf2
-	      if (strcmp (name, hwcap_extra[n]))
446cf2
-		error (EXIT_FAILURE, 0,
446cf2
-		       _("%s:%u: hwcap index %lu already defined as %s"),
446cf2
-		       filename, lineno, n, hwcap_extra[n]);
446cf2
-	      if (opt_verbose)
446cf2
-		error (0, 0, _("%s:%u: duplicate hwcap %lu %s"),
446cf2
-		       filename, lineno, n, name);
446cf2
-	    }
446cf2
-	}
446cf2
+	error (0, 0, _("%s:%u: hwcap directive ignored"), filename, lineno);
446cf2
       else
446cf2
 	add_dir_1 (cp, filename, lineno);
446cf2
     }
446cf2
@@ -1303,12 +1254,6 @@ main (int argc, char **argv)
446cf2
 	  add_dir_1 (argv[i], "<cmdline>", 0);
446cf2
     }
446cf2
 
446cf2
-  /* The last entry in hwcap_extra is reserved for the "tls" pseudo-hwcap which
446cf2
-     indicates support for TLS.  This pseudo-hwcap is only used by old versions
446cf2
-     under which TLS support was optional.  The entry is no longer needed, but
446cf2
-     must remain for compatibility.  */
446cf2
-  hwcap_extra[63 - _DL_FIRST_EXTRA] = "tls";
446cf2
-
446cf2
   set_hwcap ();
446cf2
 
446cf2
   if (opt_chroot)