aboutsummaryrefslogtreecommitdiff
path: root/sysdeps
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps')
-rw-r--r--sysdeps/generic/dl-cache.h16
-rw-r--r--sysdeps/generic/dl-isa-level.h25
-rw-r--r--sysdeps/generic/elf-read-prop.h34
-rw-r--r--sysdeps/generic/ldconfig.h22
-rw-r--r--sysdeps/unix/sysv/linux/arm/readelflib.c22
-rw-r--r--sysdeps/unix/sysv/linux/ia64/readelflib.c22
-rw-r--r--sysdeps/unix/sysv/linux/mips/readelflib.c22
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/readelflib.c22
-rw-r--r--sysdeps/unix/sysv/linux/riscv/readelflib.c22
-rw-r--r--sysdeps/unix/sysv/linux/s390/readelflib.c22
-rw-r--r--sysdeps/unix/sysv/linux/sparc/readelflib.c22
-rw-r--r--sysdeps/unix/sysv/linux/x86/elf-read-prop.h60
-rw-r--r--sysdeps/unix/sysv/linux/x86/readelflib.c23
-rw-r--r--sysdeps/unix/sysv/linux/x86_64/Makefile51
-rw-r--r--sysdeps/unix/sysv/linux/x86_64/tst-glibc-hwcaps-2.c84
-rw-r--r--sysdeps/unix/sysv/linux/x86_64/x86-64-isa-level-VALUE.c4
-rw-r--r--sysdeps/x86/dl-isa-level.h31
17 files changed, 412 insertions, 92 deletions
diff --git a/sysdeps/generic/dl-cache.h b/sysdeps/generic/dl-cache.h
index c7eca70d0c..964d50a486 100644
--- a/sysdeps/generic/dl-cache.h
+++ b/sysdeps/generic/dl-cache.h
@@ -106,14 +106,24 @@ struct file_entry_new
entries. */
#define DL_CACHE_HWCAP_EXTENSION (1ULL << 62)
+/* The number of the ISA level bits in the upper 32 bits of the hwcap
+ field. */
+#define DL_CACHE_HWCAP_ISA_LEVEL_COUNT 10
+
+/* The mask of the ISA level bits in the hwcap field. */
+#define DL_CACHE_HWCAP_ISA_LEVEL_MASK \
+ ((1 << DL_CACHE_HWCAP_ISA_LEVEL_COUNT) -1)
+
/* Return true if the ENTRY->hwcap value indicates that
DL_CACHE_HWCAP_EXTENSION is used. */
static inline bool
dl_cache_hwcap_extension (struct file_entry_new *entry)
{
- /* If DL_CACHE_HWCAP_EXTENSION is set, but other bits as well, this
- is a different kind of extension. */
- return (entry->hwcap >> 32) == (DL_CACHE_HWCAP_EXTENSION >> 32);
+ /* This is an hwcap extension if only the DL_CACHE_HWCAP_EXTENSION bit
+ is set, ignoring the lower 32 bits as well as the ISA level bits in
+ the upper 32 bits. */
+ return (((entry->hwcap >> 32) & ~DL_CACHE_HWCAP_ISA_LEVEL_MASK)
+ == (DL_CACHE_HWCAP_EXTENSION >> 32));
}
/* See flags member of struct cache_file_new below. */
diff --git a/sysdeps/generic/dl-isa-level.h b/sysdeps/generic/dl-isa-level.h
new file mode 100644
index 0000000000..6fcd319c49
--- /dev/null
+++ b/sysdeps/generic/dl-isa-level.h
@@ -0,0 +1,25 @@
+/* Support for reading ISA level in /etc/ld.so.cache files written by
+ Linux ldconfig. Generic 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/>. */
+
+/* Return true if the ISA level in ENTRY is compatible with CPU. */
+static inline bool
+dl_cache_hwcap_isa_level_compatible (struct file_entry_new *entry)
+{
+ return true;
+}
diff --git a/sysdeps/generic/elf-read-prop.h b/sysdeps/generic/elf-read-prop.h
new file mode 100644
index 0000000000..98c3d2acb5
--- /dev/null
+++ b/sysdeps/generic/elf-read-prop.h
@@ -0,0 +1,34 @@
+/* Support for GNU properties in ldconfig. Generic 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
+
+/* 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)
+{
+ return true;
+}
+
+#endif
diff --git a/sysdeps/generic/ldconfig.h b/sysdeps/generic/ldconfig.h
index eb070fd259..3ab757077d 100644
--- a/sysdeps/generic/ldconfig.h
+++ b/sysdeps/generic/ldconfig.h
@@ -70,8 +70,9 @@ const char *glibc_hwcaps_subdirectory_name
(const struct glibc_hwcaps_subdirectory *);
extern void add_to_cache (const char *path, const char *filename,
- const char *soname,
- int flags, unsigned int osversion, uint64_t hwcap,
+ const char *soname, int flags,
+ unsigned int osversion, unsigned int isa_level,
+ uint64_t hwcap,
struct glibc_hwcaps_subdirectory *);
extern void init_aux_cache (void);
@@ -79,23 +80,28 @@ extern void init_aux_cache (void);
extern void load_aux_cache (const char *aux_cache_name);
extern int search_aux_cache (struct stat64 *stat_buf, int *flags,
- unsigned int *osversion, char **soname);
+ unsigned int *osversion,
+ unsigned int *isa_level, char **soname);
extern void add_to_aux_cache (struct stat64 *stat_buf, int flags,
- unsigned int osversion, const char *soname);
+ unsigned int osversion,
+ unsigned int isa_level, const char *soname);
extern void save_aux_cache (const char *aux_cache_name);
/* Declared in readlib.c. */
extern int process_file (const char *real_file_name, const char *file_name,
- const char *lib, int *flag, unsigned int *osversion,
- char **soname, int is_link, struct stat64 *stat_buf);
+ const char *lib, int *flag,
+ unsigned int *osversion, unsigned int *isa_level,
+ char **soname, int is_link,
+ struct stat64 *stat_buf);
extern char *implicit_soname (const char *lib, int flag);
/* Declared in readelflib.c. */
-extern int process_elf_file (const char *file_name, const char *lib, int *flag,
- unsigned int *osversion, char **soname,
+extern int process_elf_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);
/* Declared in chroot_canon.c. */
diff --git a/sysdeps/unix/sysv/linux/arm/readelflib.c b/sysdeps/unix/sysv/linux/arm/readelflib.c
index 2d3ecb1eef..ade2f49aeb 100644
--- a/sysdeps/unix/sysv/linux/arm/readelflib.c
+++ b/sysdeps/unix/sysv/linux/arm/readelflib.c
@@ -18,18 +18,20 @@
<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;
@@ -38,8 +40,8 @@ process_elf_file (const char *file_name, const char *lib, int *flag,
{
Elf32_Ehdr *elf32_header = (Elf32_Ehdr *) elf_header;
- 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);
if (!ret && EF_ARM_EABI_VERSION (elf32_header->e_flags) == EF_ARM_EABI_VER5)
{
@@ -57,8 +59,8 @@ process_elf_file (const char *file_name, const char *lib, int *flag,
}
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);
/* AArch64 libraries are always libc.so.6+. */
if (!ret)
*flag = FLAG_AARCH64_LIB64|FLAG_ELF_LIBC6;
diff --git a/sysdeps/unix/sysv/linux/ia64/readelflib.c b/sysdeps/unix/sysv/linux/ia64/readelflib.c
index 7fb3ace359..2aa32666aa 100644
--- a/sysdeps/unix/sysv/linux/ia64/readelflib.c
+++ b/sysdeps/unix/sysv/linux/ia64/readelflib.c
@@ -16,29 +16,31 @@
<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;
if (elf_header->e_ident [EI_CLASS] == ELFCLASS32)
- return process_elf32_file (file_name, lib, flag, osversion, soname,
- file_contents, file_length);
+ return 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);
/* Intel 64bit libraries are always libc.so.6+. */
if (!ret)
*flag = FLAG_IA64_LIB64|FLAG_ELF_LIBC6;
diff --git a/sysdeps/unix/sysv/linux/mips/readelflib.c b/sysdeps/unix/sysv/linux/mips/readelflib.c
index e50bc3ce23..d0e809d893 100644
--- a/sysdeps/unix/sysv/linux/mips/readelflib.c
+++ b/sysdeps/unix/sysv/linux/mips/readelflib.c
@@ -20,18 +20,20 @@
<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)
{
union
{
@@ -45,8 +47,8 @@ process_elf_file (const char *file_name, const char *lib, int *flag,
elf_header.eh = file_contents;
if (elf_header.eh->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);
if (!ret)
{
Elf32_Word flags = elf_header.eh32->e_flags;
@@ -62,8 +64,8 @@ process_elf_file (const char *file_name, const char *lib, int *flag,
}
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);
/* n64 libraries are always libc.so.6+. */
if (!ret)
{
diff --git a/sysdeps/unix/sysv/linux/powerpc/readelflib.c b/sysdeps/unix/sysv/linux/powerpc/readelflib.c
index 4f9a9be254..51f8a9496a 100644
--- a/sysdeps/unix/sysv/linux/powerpc/readelflib.c
+++ b/sysdeps/unix/sysv/linux/powerpc/readelflib.c
@@ -17,29 +17,31 @@
<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;
if (elf_header->e_ident [EI_CLASS] == ELFCLASS32)
- return process_elf32_file (file_name, lib, flag, osversion, soname,
- file_contents, file_length);
+ return 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);
/* PowerPC 64bit libraries are always libc.so.6+. */
if (!ret)
*flag = FLAG_POWERPC_LIB64|FLAG_ELF_LIBC6;
diff --git a/sysdeps/unix/sysv/linux/riscv/readelflib.c b/sysdeps/unix/sysv/linux/riscv/readelflib.c
index 2aca6670a8..3822d63a05 100644
--- a/sysdeps/unix/sysv/linux/riscv/readelflib.c
+++ b/sysdeps/unix/sysv/linux/riscv/readelflib.c
@@ -17,11 +17,13 @@
<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);
/* The ELF flags supported by our current glibc port:
@@ -38,8 +40,8 @@ int process_elf64_file (const char *file_name, const char *lib, int *flag,
/* 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;
Elf32_Ehdr *elf32_header = (Elf32_Ehdr *) elf_header;
@@ -52,14 +54,14 @@ process_elf_file (const char *file_name, const char *lib, int *flag,
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);
flags = elf32_header->e_flags;
}
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);
flags = elf64_header->e_flags;
}
diff --git a/sysdeps/unix/sysv/linux/s390/readelflib.c b/sysdeps/unix/sysv/linux/s390/readelflib.c
index fc21af34d8..e190109e3d 100644
--- a/sysdeps/unix/sysv/linux/s390/readelflib.c
+++ b/sysdeps/unix/sysv/linux/s390/readelflib.c
@@ -16,29 +16,31 @@
<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;
if (elf_header->e_ident [EI_CLASS] == ELFCLASS32)
- return process_elf32_file (file_name, lib, flag, osversion, soname,
- file_contents, file_length);
+ return 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);
/* S/390 64bit libraries are always libc.so.6+. */
if (!ret)
*flag = FLAG_S390_LIB64|FLAG_ELF_LIBC6;
diff --git a/sysdeps/unix/sysv/linux/sparc/readelflib.c b/sysdeps/unix/sysv/linux/sparc/readelflib.c
index d54b8dfd28..bbfc81337a 100644
--- a/sysdeps/unix/sysv/linux/sparc/readelflib.c
+++ b/sysdeps/unix/sysv/linux/sparc/readelflib.c
@@ -18,29 +18,31 @@
<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;
if (elf_header->e_ident [EI_CLASS] == ELFCLASS32)
- return process_elf32_file (file_name, lib, flag, osversion, soname,
- file_contents, file_length);
+ return 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);
/* Sparc 64bit libraries are always libc.so.6+. */
if (!ret)
*flag = FLAG_SPARC_LIB64|FLAG_ELF_LIBC6;
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/