about summary refs log tree commit diff
path: root/sysdeps/unix/sysv/linux/x86
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/unix/sysv/linux/x86')
-rw-r--r--sysdeps/unix/sysv/linux/x86/elf-read-prop.h60
-rw-r--r--sysdeps/unix/sysv/linux/x86/readelflib.c23
2 files changed, 72 insertions, 11 deletions
diff --git a/sysdeps/unix/sysv/linux/x86/elf-read-prop.h b/sysdeps/unix/sysv/linux/x86/elf-read-prop.h
new file mode 100644
index 0000000000..85affa2864
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/x86/elf-read-prop.h
@@ -0,0 +1,60 @@
+/* Support for GNU properties in ldconfig.  x86 version.
+   Copyright (C) 2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#ifndef _ELF_READ_PROP_H
+#define _ELF_READ_PROP_H
+
+#include <dl-cache.h>
+
+/* Called for each property in the NT_GNU_PROPERTY_TYPE_0 note of SEGMENT.
+   Return value:
+     false: Continue processing the properties.
+     true : Stop processing the properties.
+ */
+static inline bool __attribute__ ((always_inline))
+read_gnu_property (unsigned int *isal_level, uint32_t type,
+		   uint32_t datasz, void *data)
+{
+  /* Property type must be in ascending order.  */
+  if (type > GNU_PROPERTY_X86_ISA_1_NEEDED)
+    return true;
+
+  if (type == GNU_PROPERTY_X86_ISA_1_NEEDED)
+    {
+      if (datasz == 4)
+	{
+	  /* The size of GNU_PROPERTY_X86_ISA_1_NEEDED must be 4 bytes.
+	     There is no point to continue if this type is ill-formed.  */
+	  unsigned int isa_1_needed = *(unsigned int *) data;
+	  _Static_assert (((sizeof (isa_1_needed) * 8)
+			   <= (1 << DL_CACHE_HWCAP_ISA_LEVEL_COUNT)),
+			  "DL_CACHE_HWCAP_ISA_LEVEL_COUNT is too small");
+	  if (isa_1_needed != 0)
+	    {
+	      unsigned int level;
+	      asm ("bsr %1, %0" : "=r" (level) : "g" (isa_1_needed));
+	      *isal_level = level;
+	    }
+	}
+      return true;
+    }
+
+  return false;
+}
+
+#endif
diff --git a/sysdeps/unix/sysv/linux/x86/readelflib.c b/sysdeps/unix/sysv/linux/x86/readelflib.c
index a4df70e7e6..4a9bcc82cb 100644
--- a/sysdeps/unix/sysv/linux/x86/readelflib.c
+++ b/sysdeps/unix/sysv/linux/x86/readelflib.c
@@ -17,19 +17,20 @@
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
-
-int process_elf32_file (const char *file_name, const char *lib, int *flag,
-			unsigned int *osversion, char **soname,
+int process_elf32_file (const char *file_name, const char *lib,
+			int *flag, unsigned int *osversion,
+			unsigned int *isa_level, char **soname,
 			void *file_contents, size_t file_length);
-int process_elf64_file (const char *file_name, const char *lib, int *flag,
-			unsigned int *osversion, char **soname,
+int process_elf64_file (const char *file_name, const char *lib,
+			int *flag, unsigned int *osversion,
+			unsigned int *isa_level, char **soname,
 			void *file_contents, size_t file_length);
 
 /* Returns 0 if everything is ok, != 0 in case of error.  */
 int
 process_elf_file (const char *file_name, const char *lib, int *flag,
-		  unsigned int *osversion, char **soname, void *file_contents,
-		  size_t file_length)
+		  unsigned int *osversion, unsigned int *isa_level,
+		  char **soname, void *file_contents, size_t file_length)
 {
   ElfW(Ehdr) *elf_header = (ElfW(Ehdr) *) file_contents;
   int ret, file_flag = 0;
@@ -68,11 +69,11 @@ failed:
     }
 
   if (elf_header->e_ident[EI_CLASS] == ELFCLASS32)
-    ret = process_elf32_file (file_name, lib, flag, osversion, soname,
-			      file_contents, file_length);
+    ret = process_elf32_file (file_name, lib, flag, osversion, isa_level,
+			      soname, file_contents, file_length);
   else
-    ret = process_elf64_file (file_name, lib, flag, osversion, soname,
-			      file_contents, file_length);
+    ret = process_elf64_file (file_name, lib, flag, osversion, isa_level,
+			      soname, file_contents, file_length);
 
   if (!ret && file_flag)
     *flag = file_flag;