diff options
Diffstat (limited to 'sysdeps/unix/sysv/linux')
-rw-r--r-- | sysdeps/unix/sysv/linux/arm/readelflib.c | 22 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/ia64/readelflib.c | 22 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/mips/readelflib.c | 22 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/powerpc/readelflib.c | 22 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/riscv/readelflib.c | 22 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/s390/readelflib.c | 22 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/sparc/readelflib.c | 22 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/x86/elf-read-prop.h | 60 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/x86/readelflib.c | 23 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/x86_64/Makefile | 51 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/x86_64/tst-glibc-hwcaps-2.c | 84 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/x86_64/x86-64-isa-level-VALUE.c | 4 |
12 files changed, 295 insertions, 81 deletions
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/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; diff --git a/sysdeps/unix/sysv/linux/x86_64/Makefile b/sysdeps/unix/sysv/linux/x86_64/Makefile index 9b82155393..5e19202ebf 100644 --- a/sysdeps/unix/sysv/linux/x86_64/Makefile +++ b/sysdeps/unix/sysv/linux/x86_64/Makefile @@ -13,3 +13,54 @@ endif ifeq ($(subdir),misc) gen-as-const-headers += sigaltstack-offsets.sym endif + +ifeq ($(subdir),elf) +ifeq (yes,$(enable-x86-isa-level)) +tests += \ + tst-glibc-hwcaps-2 +ifeq (no,$(build-hardcoded-path-in-tests)) +# This is an ld.so.cache test, and RPATH/RUNPATH in the executable +# interferes with its test objectives. +tests-container += \ + tst-glibc-hwcaps-2-cache +endif +modules-names += \ + libx86-64-isa-level-1 \ + libx86-64-isa-level-2 \ + libx86-64-isa-level-3 \ + libx86-64-isa-level-4 + +$(objpfx)tst-glibc-hwcaps-2: $(objpfx)libx86-64-isa-level.so + +$(objpfx)tst-glibc-hwcaps-2.out: \ + $(objpfx)glibc-hwcaps/x86-64-v2/libx86-64-isa-level.so \ + $(objpfx)glibc-hwcaps/x86-64-v4/libx86-64-isa-level.so \ + $(objpfx)glibc-hwcaps/x86-64-v3/libx86-64-isa-level.so +$(objpfx)glibc-hwcaps/x86-64-v2/libx86-64-isa-level.so: \ + $(objpfx)libx86-64-isa-level-2.so + $(make-target-directory) + cp $< $@ +$(objpfx)glibc-hwcaps/x86-64-v3/libx86-64-isa-level.so: \ + $(objpfx)libx86-64-isa-level-3.so + $(make-target-directory) + cp $< $@ +$(objpfx)glibc-hwcaps/x86-64-v4/libx86-64-isa-level.so: \ + $(objpfx)libx86-64-isa-level-4.so + $(make-target-directory) + cp $< $@ + +CFLAGS-libx86-64-isa-level-1.os += -march=x86-64 +CFLAGS-libx86-64-isa-level-2.os += -march=x86-64 +CFLAGS-libx86-64-isa-level-3.os += -march=x86-64 +CFLAGS-libx86-64-isa-level-4.os += -march=x86-64 + +# The test modules are parameterized by preprocessor macros. +LDFLAGS-libx86-64-isa-level-1.so += -Wl,-soname,libx86-64-isa-level.so +LDFLAGS-libx86-64-isa-level-4.so += -Wl,-soname,libx86-64-isa-level.so +$(objpfx)libx86-64-isa-level%.os: $(..)/sysdeps/unix/sysv/linux/x86_64/x86-64-isa-level-VALUE.c + $(compile-command.c) -DVALUE=$(lastword $(subst -, ,$*)) \ + -DISA_LEVEL="(1 << ($(lastword $(subst -, ,$*)) - 1))" +$(objpfx)libx86-64-isa-level.so: $(objpfx)libx86-64-isa-level-1.so + cp $< $@ +endif +endif # $(subdir) == elf diff --git a/sysdeps/unix/sysv/linux/x86_64/tst-glibc-hwcaps-2.c b/sysdeps/unix/sysv/linux/x86_64/tst-glibc-hwcaps-2.c new file mode 100644 index 0000000000..fe91bfd224 --- /dev/null +++ b/sysdeps/unix/sysv/linux/x86_64/tst-glibc-hwcaps-2.c @@ -0,0 +1,84 @@ +/* Check ISA level on shared object in glibc-hwcaps subdirectories. + 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/>. */ + +#include <stdbool.h> +#include <stdlib.h> +#include <stdio.h> +#include <elf.h> +#include <get-isa-level.h> +#include <support/check.h> +#include <support/test-driver.h> + +extern int dso_isa_level (void); + +static int +do_test (void) +{ + const struct cpu_features *cpu_features + = __x86_get_cpu_features (COMMON_CPUID_INDEX_MAX); + unsigned int isa_level = get_isa_level (cpu_features); + bool has_isa_baseline = ((isa_level & GNU_PROPERTY_X86_ISA_1_BASELINE) + == GNU_PROPERTY_X86_ISA_1_BASELINE); + bool has_isa_v2 = ((isa_level & GNU_PROPERTY_X86_ISA_1_V2) + == GNU_PROPERTY_X86_ISA_1_V2); + bool has_isa_v3 = ((isa_level & GNU_PROPERTY_X86_ISA_1_V3) + == GNU_PROPERTY_X86_ISA_1_V3); + bool has_isa_v4 = ((isa_level & GNU_PROPERTY_X86_ISA_1_V4) + == GNU_PROPERTY_X86_ISA_1_V4); + + if (!has_isa_baseline) + return EXIT_FAILURE; + + int level = dso_isa_level (); + int ret; + switch (level) + { + case 1: + case 2: + /* The default libx86-64-isa-level.so is used. */ + printf ("The default shared library is used.\n"); + if (has_isa_v3 || has_isa_v4 || !has_isa_v2) + ret = EXIT_FAILURE; + else + ret = EXIT_SUCCESS; + break; + case 3: + /* libx86-64-isa-level.so marked as x86-64 ISA level 3 needed in + x86-64-v2 should be ignored on lesser CPU. */ + printf ("x86-64 ISA level 3 shared library is used.\n"); + if (has_isa_v4 || !has_isa_v3) + ret = EXIT_FAILURE; + else + ret = EXIT_SUCCESS; + break; + case 4: + /* libx86-64-isa-level.so marked as x86-64 ISA level 4 needed in + x86-64-v3 should be ignored on lesser CPU. */ + printf ("x86-64 ISA level 4 shared library is used.\n"); + if (has_isa_v4) + ret = EXIT_SUCCESS; + else + ret = EXIT_FAILURE; + break; + default: + abort (); + } + return ret; +} + +#include <support/test-driver.c> diff --git a/sysdeps/unix/sysv/linux/x86_64/x86-64-isa-level-VALUE.c b/sysdeps/unix/sysv/linux/x86_64/x86-64-isa-level-VALUE.c new file mode 100644 index 0000000000..2813d627cc --- /dev/null +++ b/sysdeps/unix/sysv/linux/x86_64/x86-64-isa-level-VALUE.c @@ -0,0 +1,4 @@ +#define INCLUDE_X86_ISA_LEVEL +#define MARKER dso_isa_level +#include <isa-level.c> +#include <markermodMARKER-VALUE.c> |