On Tue, Jan 12, 2021 at 8:25 AM Adhemerval Zanella wrote: > > > > On 09/12/2020 00:27, H.J. Lu via Libc-alpha wrote: > > On Tue, Dec 8, 2020 at 7:31 AM H.J. Lu wrote: > >> > >> On Tue, Dec 8, 2020 at 7:16 AM Florian Weimer wrote: > >>> > >>> * H. J. Lu: > >>> > >>>>>> For each file entry for a shared object, the hwcap field has been used by > >>>>>> DL_CACHE_HWCAP_EXTENSION for glibc-hwcaps. Are you suggesting > >>>>>> to add another file entry for the same shared object to store ISA level > >>>>>> requirement? > >>>>> > >>>>> It's a 64-bit field. We do this: > >>>>> > >>>>> /* This bit in the hwcap field of struct file_entry_new indicates that > >>>>> the lower 32 bits contain an index into the > >>>>> cache_extension_tag_glibc_hwcaps section. Older glibc versions do > >>>>> not know about this HWCAP bit, so they will ignore these > >>>>> entries. */ > >>>>> #define DL_CACHE_HWCAP_EXTENSION (1ULL << 62) > >>>>> > >>>>> /* 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); > >>>>> } > >>>>> > >>>>> So we can use a different bit pattern involving DL_CACHE_HWCAP_EXTENSION > >>>>> to express something else. In particular, only the lower 32 bits are > >>>>> currently used as an index. > >>>> > >>>> So bits 33-47 can be used for ISA level requirement. This should support > >>>> 65536 ISA levels. > >>> > >>> The question is whether the ISA levels and the glibc-hwcaps name are > >>> used in parallel. If not, we can use (1ULL << 62) | (1ULL << 32) as > >>> the marker bits and a 32-bit index in the lower half. > >>> > >>> (I do not think this is necessarily relevant for levels, but it could be > >>> used for locating objects according to other criteria.) > >>> > >> > >> I think ISA level and glibc-hwcaps should go together. > >> > > > > Here is the patch to store ISA level in the portion of the unused > > upper 32 bits of the hwcaps field in cache and the unused pad > > field in aux cache. > > > > > > From f5053fabd1e8a5567b487ef4054793e043a7b817 Mon Sep 17 00:00:00 2001 > > From: "H.J. Lu" > > Date: Sat, 5 Dec 2020 07:01:58 -0800 > > Subject: [PATCH] ldconfig/x86: Store ISA level in cache and aux cache > > > > Store ISA level in the portion of the unused upper 32 bits of the hwcaps > > field in cache and the unused pad field in aux cache. ISA level is stored > > and checked only for shared objects in glibc-hwcaps subdirectories. The > > shared objects in the default directories aren't checked since there are > > no fallbacks for these shared objects. > > Some comments below, most minor changes and code organization. The main > change I would like is to improve test coverage, as for the first patch. > > > --- > > elf/cache.c | 34 +++++--- > > elf/dl-cache.c | 4 + > > elf/ldconfig.c | 18 +++-- > > elf/readelflib.c | 81 ++++++++++++++++++- > > elf/readlib.c | 7 +- > > elf/tst-glibc-hwcaps-2-cache.c | 45 +++++++++++ > > .../etc/ld.so.conf | 2 + > > .../postclean.req | 0 > > elf/tst-glibc-hwcaps-2-cache.script | 6 ++ > > sysdeps/generic/dl-cache.h | 15 +++- > > sysdeps/generic/dl-isa-level.h | 26 ++++++ > > sysdeps/generic/ldconfig.h | 22 +++-- > > sysdeps/generic/read-prop.h | 35 ++++++++ > > sysdeps/unix/sysv/linux/arm/readelflib.c | 22 ++--- > > sysdeps/unix/sysv/linux/ia64/readelflib.c | 22 ++--- > > sysdeps/unix/sysv/linux/mips/readelflib.c | 22 ++--- > > sysdeps/unix/sysv/linux/powerpc/readelflib.c | 22 ++--- > > sysdeps/unix/sysv/linux/riscv/readelflib.c | 22 ++--- > > sysdeps/unix/sysv/linux/s390/readelflib.c | 22 ++--- > > sysdeps/unix/sysv/linux/sparc/readelflib.c | 22 ++--- > > sysdeps/unix/sysv/linux/x86/read-prop.h | 61 ++++++++++++++ > > sysdeps/unix/sysv/linux/x86/readelflib.c | 23 +++--- > > sysdeps/unix/sysv/linux/x86_64/Makefile | 31 +++++++ > > .../sysv/linux/x86_64/tst-glibc-hwcaps-2.c | 61 ++++++++++++++ > > .../linux/x86_64/x86-64-isa-level-VALUE.c | 4 + > > sysdeps/x86/dl-isa-level.h | 32 ++++++++ > > 26 files changed, 550 insertions(+), 111 deletions(-) > > create mode 100644 elf/tst-glibc-hwcaps-2-cache.c > > create mode 100644 elf/tst-glibc-hwcaps-2-cache.root/etc/ld.so.conf > > create mode 100644 elf/tst-glibc-hwcaps-2-cache.root/postclean.req > > create mode 100644 elf/tst-glibc-hwcaps-2-cache.script > > create mode 100644 sysdeps/generic/dl-isa-level.h > > create mode 100644 sysdeps/generic/read-prop.h > > create mode 100644 sysdeps/unix/sysv/linux/x86/read-prop.h > > create mode 100644 sysdeps/unix/sysv/linux/x86_64/tst-glibc-hwcaps-2.c > > create mode 100644 sysdeps/unix/sysv/linux/x86_64/x86-64-isa-level-VALUE.c > > create mode 100644 sysdeps/x86/dl-isa-level.h > > > > diff --git a/elf/cache.c b/elf/cache.c > > index b03c5319f8..91a72381ae 100644 > > --- a/elf/cache.c > > +++ b/elf/cache.c > > @@ -145,6 +145,7 @@ struct cache_entry > > struct stringtable_entry *path; /* Path to find library. */ > > int flags; /* Flags to indicate kind of library. */ > > unsigned int osversion; /* Required OS version. */ > > + unsigned int isa_level; /* Required ISAL level. */ > > Maybe a typo here 'ISAL'? Fixed. > > uint64_t hwcap; /* Important hardware capabilities. */ > > int bits_hwcap; /* Number of bits set in hwcap. */ > > > > @@ -660,8 +661,14 @@ save_cache (const char *cache_name) > > if (entry->hwcaps == NULL) > > file_entries_new->libs[idx_new].hwcap = entry->hwcap; > > else > > - file_entries_new->libs[idx_new].hwcap > > - = DL_CACHE_HWCAP_EXTENSION | entry->hwcaps->section_index; > > + { > > + if (entry->isa_level > (1 << DL_CACHE_HWCAP_ISA_LEVEL_COUNT)) > > Maybe wrap this on a macro at dl-cache.h? It already does it for > DL_CACHE_HWCAP_ISA_LEVEL_MASK. > > + abort (); > > Maybe use 'error (...)' to print a proper error message? I changed it to + if (entry->isa_level > DL_CACHE_HWCAP_ISA_LEVEL_MASK) + error (EXIT_FAILURE, 0, _("%s: ISA level is too high (%d > %d)"), + entry->path->string, entry->isa_level, + DL_CACHE_HWCAP_ISA_LEVEL_MASK); since DL_CACHE_HWCAP_ISA_LEVEL_MASK is the maximum ISA level. > > + file_entries_new->libs[idx_new].hwcap > > + = (DL_CACHE_HWCAP_EXTENSION > > + | (((uint64_t) entry->isa_level) << 32) > > + | entry->hwcaps->section_index); > > + } > > Would be better to wrap this on a inline function at dl-cache.h? > > static inline unsigned int dl_cache_hwcap_isa_level (struct file_entry_new *entry) > { > return DL_CACHE_HWCAP_EXTENSION > | ((uint64_t) entry->isa_level << 32) > | entry->hwcaps->sections_index; > } This function takes "struct cache_entry *entry" which is private to cache.c I added compute_hwcap_value to cache.c instead. > > file_entries_new->libs[idx_new].key > > = str_offset + entry->lib->offset; > > file_entries_new->libs[idx_new].value > > @@ -776,7 +783,8 @@ save_cache (const char *cache_name) > > /* Add one library to the cache. */ > > void > > add_to_cache (const char *path, const char *filename, const char *soname, > > - int flags, unsigned int osversion, uint64_t hwcap, > > + int flags, unsigned int osversion, > > + unsigned int isa_level, uint64_t hwcap, > > struct glibc_hwcaps_subdirectory *hwcaps) > > { > > struct cache_entry *new_entry = xmalloc (sizeof (*new_entry)); > > @@ -794,6 +802,7 @@ add_to_cache (const char *path, const char *filename, const char *soname, > > new_entry->path = path_interned; > > new_entry->flags = flags; > > new_entry->osversion = osversion; > > + new_entry->isa_level = isa_level; > > new_entry->hwcap = hwcap; > > new_entry->hwcaps = hwcaps; > > new_entry->bits_hwcap = 0; > > Ok. > > > @@ -850,6 +859,7 @@ struct aux_cache_entry > > struct aux_cache_entry_id id; > > int flags; > > unsigned int osversion; > > + unsigned int isa_level; > > int used; > > char *soname; > > struct aux_cache_entry *next; > > @@ -863,7 +873,7 @@ struct aux_cache_file_entry > > int32_t flags; /* This is 1 for an ELF library. */ > > uint32_t soname; /* String table indice. */ > > uint32_t osversion; /* Required OS version. */ > > - int32_t pad; > > + uint32_t isa_level; /* Required ISA level. */ > > }; > > > > I think it would be good to have a _Static_assert with the > expected aux_cache_entry size. What would that be? aux_cache_entry_id size is increased by 4 bytes with my patch. > > /* ldconfig maintains an auxiliary cache file that allows > > @@ -914,7 +924,8 @@ init_aux_cache (void) > > > > int > > search_aux_cache (struct stat64 *stat_buf, int *flags, > > - unsigned int *osversion, char **soname) > > + unsigned int *osversion, unsigned int *isa_level, > > + char **soname) > > { > > struct aux_cache_entry_id id; > > id.ino = (uint64_t) stat_buf->st_ino; > > @@ -932,6 +943,7 @@ search_aux_cache (struct stat64 *stat_buf, int *flags, > > { > > *flags = entry->flags; > > *osversion = entry->osversion; > > + *isa_level = entry->isa_level; > > if (entry->soname != NULL) > > *soname = xstrdup (entry->soname); > > else > > Ok. > > > @@ -945,7 +957,8 @@ search_aux_cache (struct stat64 *stat_buf, int *flags, > > > > static void > > insert_to_aux_cache (struct aux_cache_entry_id *id, int flags, > > - unsigned int osversion, const char *soname, int used) > > + unsigned int osversion, unsigned int isa_level, > > + const char *soname, int used) > > { > > size_t hash = aux_cache_entry_id_hash (id) % aux_hash_size; > > struct aux_cache_entry *entry; > > @@ -961,6 +974,7 @@ insert_to_aux_cache (struct aux_cache_entry_id *id, int flags, > > entry->id = *id; > > entry->flags = flags; > > entry->osversion = osversion; > > + entry->isa_level = isa_level; > > entry->used = used; > > if (soname != NULL) > > entry->soname = memcpy ((char *) (entry + 1), soname, len); > > Ok. > > > @@ -972,14 +986,15 @@ insert_to_aux_cache (struct aux_cache_entry_id *id, int flags, > > > > 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) > > { > > struct aux_cache_entry_id id; > > id.ino = (uint64_t) stat_buf->st_ino; > > id.ctime = (uint64_t) stat_buf->st_ctime; > > id.size = (uint64_t) stat_buf->st_size; > > id.dev = (uint64_t) stat_buf->st_dev; > > - insert_to_aux_cache (&id, flags, osversion, soname, 1); > > + insert_to_aux_cache (&id, flags, osversion, isa_level, soname, 1); > > } > > > > /* Load auxiliary cache to search for unchanged entries. */ > > @@ -1025,6 +1040,7 @@ load_aux_cache (const char *aux_cache_name) > > insert_to_aux_cache (&aux_cache->libs[i].id, > > aux_cache->libs[i].flags, > > aux_cache->libs[i].osversion, > > + aux_cache->libs[i].isa_level, > > aux_cache->libs[i].soname == 0 > > ? NULL : aux_cache_data + aux_cache->libs[i].soname, > > 0); > > @@ -1093,7 +1109,7 @@ save_aux_cache (const char *aux_cache_name) > > str_offset += len; > > } > > file_entries->libs[idx].osversion = entry->osversion; > > - file_entries->libs[idx++].pad = 0; > > + file_entries->libs[idx++].isa_level = entry->isa_level; > > } > > > > /* Write out auxiliary cache file. */ > > Ok. > > > diff --git a/elf/dl-cache.c b/elf/dl-cache.c > > index 97093bb700..edeff7ccc1 100644 > > --- a/elf/dl-cache.c > > +++ b/elf/dl-cache.c > > @@ -25,6 +25,7 @@ > > #include > > #include <_itoa.h> > > #include > > +#include > > > > #ifndef _DL_PLATFORMS_COUNT > > # define _DL_PLATFORMS_COUNT 0 > > @@ -284,6 +285,9 @@ search_cache (const char *string_table, uint32_t string_table_size, > > > > #ifdef SHARED > > named_hwcap = dl_cache_hwcap_extension (libnew); > > + if (named_hwcap > > + && !dl_cache_hwcap_isa_level_compatible (libnew)) > > + continue; > > #endif > > > > /* The entries with named/extension hwcaps > > Ok, so it skips non compatible ISA shared libraries. > > > diff --git a/elf/ldconfig.c b/elf/ldconfig.c > > index 10927a8c7f..9dceac38aa 100644 > > --- a/elf/ldconfig.c > > +++ b/elf/ldconfig.c > > @@ -655,6 +655,7 @@ manual_link (char *library) > > struct stat64 stat_buf; > > int flag; > > unsigned int osversion; > > + unsigned int isa_level; > > > > /* Prepare arguments for create_links call. Split library name in > > directory and filename first. Since path is allocated, we've got > > @@ -721,7 +722,7 @@ manual_link (char *library) > > } > > > > if (process_file (real_library, library, libname, &flag, &osversion, > > - &soname, 0, &stat_buf)) > > + &isa_level, &soname, 0, &stat_buf)) > > { > > error (0, 0, _("No link created since soname could not be found for %s"), > > library); > > @@ -768,6 +769,7 @@ struct dlib_entry > > int flag; > > int is_link; > > unsigned int osversion; > > + unsigned int isa_level; > > struct dlib_entry *next; > > }; > > > > Ok. > > > @@ -980,17 +982,21 @@ search_dir (const struct dir_entry *entry) > > library already and it's not changed. */ > > char *soname; > > unsigned int osversion; > > - if (!search_aux_cache (&lstat_buf, &flag, &osversion, &soname)) > > + unsigned int isa_level; > > + if (!search_aux_cache (&lstat_buf, &flag, &osversion, &isa_level, > > + &soname)) > > { > > if (process_file (real_name, file_name, direntry->d_name, &flag, > > - &osversion, &soname, is_link, &lstat_buf)) > > + &osversion, &isa_level, &soname, is_link, > > + &lstat_buf)) > > { > > if (real_name != real_file_name) > > free (real_name); > > continue; > > } > > else if (opt_build_cache) > > - add_to_aux_cache (&lstat_buf, flag, osversion, soname); > > + add_to_aux_cache (&lstat_buf, flag, osversion, isa_level, > > + soname); > > } > > > > if (soname == NULL) > > Ok. > > > @@ -1096,6 +1102,7 @@ search_dir (const struct dir_entry *entry) > > dlib_ptr->name = xstrdup (direntry->d_name); > > dlib_ptr->is_link = is_link; > > dlib_ptr->osversion = osversion; > > + dlib_ptr->isa_level = isa_level; > > } > > /* Don't add this library, abort loop. */ > > /* Also free soname, since it's dynamically allocated. */ > > @@ -1112,6 +1119,7 @@ search_dir (const struct dir_entry *entry) > > dlib_ptr->flag = flag; > > dlib_ptr->is_link = is_link; > > dlib_ptr->osversion = osversion; > > + dlib_ptr->isa_level = isa_level; > > /* Add at head of list. */ > > dlib_ptr->next = dlibs; > > dlibs = dlib_ptr; > > @@ -1149,7 +1157,7 @@ search_dir (const struct dir_entry *entry) > > if (opt_build_cache) > > add_to_cache (entry->path, filename, dlib_ptr->soname, > > dlib_ptr->flag, dlib_ptr->osversion, > > - hwcap, entry->hwcaps); > > + dlib_ptr->isa_level, hwcap, entry->hwcaps); > > } > > > > /* Free all resources. */ > > Ok. > > > diff --git a/elf/readelflib.c b/elf/readelflib.c > > index 5905f6d344..abb1ac61fa 100644 > > --- a/elf/readelflib.c > > +++ b/elf/readelflib.c > > @@ -17,6 +17,8 @@ > > License along with the GNU C Library; if not, see > > . */ > > > > +#include > > + > > /* This code is a heavily simplified version of the readelf program > > that's part of the current binutils development version. For architectures > > which need to handle both 32bit and 64bit ELF libraries, this file is > > @@ -40,8 +42,8 @@ do \ > > /* 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) > > { > > int i; > > unsigned int j; > > @@ -86,6 +88,9 @@ process_elf_file (const char *file_name, const char *lib, int *flag, > > libc5/libc6. */ > > *flag = FLAG_ELF; > > > > + /* The default ISA level is 0. */ > > + *isa_level = 0; > > + > > dynamic_addr = 0; > > dynamic_size = 0; > > program_interpreter = NULL; > > @@ -164,6 +169,78 @@ process_elf_file (const char *file_name, const char *lib, int *flag, > > } > > break; > > > > + case PT_GNU_PROPERTY: > > + /* The NT_GNU_PROPERTY_TYPE_0 note must be aligned to 4 bytes > > + in 32-bit objects and to 8 bytes in 64-bit objects. Skip > > + notes with incorrect alignment. */ > > + if (segment->p_align == (__ELF_NATIVE_CLASS / 8)) > > + { > > + const ElfW(Nhdr) *note = (const void *) (file_contents > > + + segment->p_offset); > > + const ElfW(Addr) size = segment->p_filesz; > > + const ElfW(Addr) align = segment->p_align; > > + > > + const ElfW(Addr) start = (ElfW(Addr)) (uintptr_t) note; > > + unsigned int last_type = 0; > > + > > + while ((ElfW(Addr)) (uintptr_t) (note + 1) - start < size) > > + { > > + /* Find the NT_GNU_PROPERTY_TYPE_0 note. */ > > + if (note->n_namesz == 4 > > + && note->n_type == NT_GNU_PROPERTY_TYPE_0 > > + && memcmp (note + 1, "GNU", 4) == 0) > > + { > > + /* Check for invalid property. */ > > + if (note->n_descsz < 8 > > + || (note->n_descsz % sizeof (ElfW(Addr))) != 0) > > + goto done; > > + > > + /* Start and end of property array. */ > > + unsigned char *ptr = (unsigned char *) (note + 1) + 4; > > + unsigned char *ptr_end = ptr + note->n_descsz; > > + > > + do > > + { > > + unsigned int type = *(unsigned int *) ptr; > > + unsigned int datasz = *(unsigned int *) (ptr + 4); > > + > > + /* Property type must be in ascending order. */ > > + if (type < last_type) > > + goto done; > > + > > + ptr += 8; > > + if ((ptr + datasz) > ptr_end) > > + goto done; > > + > > + last_type = type; > > + > > + /* Target specific property processing. > > + Return value: > > + false: Continue processing the properties. > > + true : Stop processing the properties. > > + */ > > + if (read_gnu_property (isa_level, type, > > + datasz, ptr)) > > + goto done; > > + > > + /* Check the next property item. */ > > + ptr += ALIGN_UP (datasz, sizeof (ElfW(Addr))); > > + } > > + while ((ptr_end - ptr) >= 8); > > + > > + /* Only handle one NT_GNU_PROPERTY_TYPE_0. */ > > + goto done; > > + } > > + > > + note = ((const void *) note > > + + ELF_NOTE_NEXT_OFFSET (note->n_namesz, > > + note->n_descsz, > > + align)); > > + } > > + } > > +done: > > + break; > > + > > default: > > break; > > } > > Ok, although this is quite similar to the _dl_process_pt_gnu_property > (maybe a future work to try refactor both to use a common code). That is a future possibility. > > diff --git a/elf/readlib.c b/elf/readlib.c > > index 994a4426a1..def0eafbeb 100644 > > --- a/elf/readlib.c > > +++ b/elf/readlib.c > > @@ -75,7 +75,8 @@ is_gdb_python_file (const char *name) > > 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) > > + unsigned int *isa_level, char **soname, int is_link, > > + struct stat64 *stat_buf) > > { > > FILE *file; > > struct stat64 statbuf; > > @@ -173,8 +174,8 @@ process_file (const char *real_file_name, const char *file_name, > > /* Libraries have to be shared object files. */ > > else if (elf_header->e_type != ET_DYN) > > ret = 1; > > - else if (process_elf_file (file_name, lib, flag, osversion, soname, > > - file_contents, statbuf.st_size)) > > + else if (process_elf_file (file_name, lib, flag, osversion, isa_level, > > + soname, file_contents, statbuf.st_size)) > > ret = 1; > > > > done: > > Ok. > > > diff --git a/elf/tst-glibc-hwcaps-2-cache.c b/elf/tst-glibc-hwcaps-2-cache.c > > new file mode 100644 > > index 0000000000..2c30a2c911 > > --- /dev/null > > +++ b/elf/tst-glibc-hwcaps-2-cache.c > > @@ -0,0 +1,45 @@ > > +/* Wrapper to invoke tst-glibc-hwcaps-2 in a container to test ldconfig. > > + Copyright (C) 2020 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 > > + . */ > > + > > +/* This program is just a wrapper that runs ldconfig followed by > > + tst-glibc-hwcaps-2. The actual test is provided via an > > + implementation in a sysdeps subdirectory. */ > > + > > +#include > > +#include > > +#include > > +#include > > + > > +int > > +main (int argc, char **argv) > > +{ > > + /* Run ldconfig to populate the cache. */ > > + { > > + char *command = xasprintf ("%s/ldconfig", support_install_rootsbindir); > > + if (system (command) != 0) > > + return 1; > > + free (command); > > + } > > Maybe use support_capture_subprogram here? > > char *command = xasprintf ("%s/ldconfig", support_install_rootsbindir); > struct support_capture_subprocess result = > support_capture_subprogram (command, &((char *) { NULL })); > support_capture_subprocess_check (&result, "ldconfig", 0, sc_allow_none); > free (command); Fixed. > > + > > + /* Reuse tst-glibc-hwcaps. Since this code is running in a > > + container, we can launch it directly. */ > > + char *path = xasprintf ("%s/elf/tst-glibc-hwcaps-2", support_objdir_root); > > + execv (path, argv); > > + printf ("error: execv of %s failed: %m\n", path); > > + return 1; > > +} > > Ok. > > > diff --git a/elf/tst-glibc-hwcaps-2-cache.root/etc/ld.so.conf b/elf/tst-glibc-hwcaps-2-cache.root/etc/ld.so.conf > > new file mode 100644 > > index 0000000000..e1e74dbda2 > > --- /dev/null > > +++ b/elf/tst-glibc-hwcaps-2-cache.root/etc/ld.so.conf > > @@ -0,0 +1,2 @@ > > +# This file was created to suppress a warning from ldconfig: > > +# /sbin/ldconfig: Warning: ignoring configuration file that cannot be opened: /etc/ld.so.conf: No such file or directory > > diff --git a/elf/tst-glibc-hwcaps-2-cache.root/postclean.req b/elf/tst-glibc-hwcaps-2-cache.root/postclean.req > > new file mode 100644 > > index 0000000000..e69de29bb2 > > Ok. > > > diff --git a/elf/tst-glibc-hwcaps-2-cache.script b/elf/tst-glibc-hwcaps-2-cache.script > > new file mode 100644 > > index 0000000000..29ccfc3b49 > > --- /dev/null > > +++ b/elf/tst-glibc-hwcaps-2-cache.script > > @@ -0,0 +1,6 @@ > > +# test-container does not support scripts in sysdeps directories, so > > +# collect everything in one file. > > + > > +mkdirp 0770 $L/glibc-hwcaps/x86-64-v2 > > Ok. > > > +cp $B/elf/libx86-64-isa-level-1.so $L/libx86-64-isa-level.so > > +cp $B/elf/libx86-64-isa-level-4.so $L/glibc-hwcaps/x86-64-v2/libx86-64-isa-level.so > > diff --git a/sysdeps/generic/dl-cache.h b/sysdeps/generic/dl-cache.h > > index 72a66b45ee..1138228e5c 100644 > > --- a/sysdeps/generic/dl-cache.h > > +++ b/sysdeps/generic/dl-cache.h > > @@ -106,14 +106,23 @@ 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) > > + > > Space after '-'. Fixed. > > /* 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); > > + /* If DL_CACHE_HWCAP_EXTENSION is set, but other bits, except for the > > + ISA level bits, as well, this is a different kind of extension. */ > > + return (((entry->hwcap >> 32) & ~DL_CACHE_HWCAP_ISA_LEVEL_MASK) > > + == (DL_CACHE_HWCAP_EXTENSION >> 32)); > > } > > > > /* See flags member of struct cache_file_new below. */ > > The comment sounds confusing. I changed it to /* 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. */ > > diff --git a/sysdeps/generic/dl-isa-level.h b/sysdeps/generic/dl-isa-level.h > > new file mode 100644 > > index 0000000000..77735775b9 > > --- /dev/null > > +++ b/sysdeps/generic/dl-isa-level.h > > @@ -0,0 +1,26 @@ > > +/* Support for reading ISA level in /etc/ld.so.cache files written by > > + Linux ldconfig. Generic version. > > + Copyright (C) 2020 Free Software Foundation, Inc. > > s/2020/2021 Fixed. > > + 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 > > + . */ > > + > > +/* Return true if the ISA level in ENTRY is compatible with CPU. */ > > + > > My understanding is for function comment there is no need to add an > extra newline. Fixed. > > +static inline bool > > +dl_cache_hwcap_isa_level_compatible (struct file_entry_new *entry) > > +{ > > + return true; > > +} > > Ok. > > > diff --git a/sysdeps/generic/ldconfig.h b/sysdeps/generic/ldconfig.h > > index 1ad1528890..a5ed350237 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. */ > > > Ok. > > > diff --git a/sysdeps/generic/read-prop.h b/sysdeps/generic/read-prop.h > > new file mode 100644 > > index 0000000000..091bd2f6c1 > > --- /dev/null > > +++ b/sysdeps/generic/read-prop.h > > Maybe elf-read-prop.h to add more information on exactly this > file intends to? Renamed to elf-read-prop.h. > > @@ -0,0 +1,35 @@ > > +/* Support for GNU properties in ldconfig. Generic version. > > + Copyright (C) 2020 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 > > + . */ > > + > > +#ifndef _READ_PROP_H > > +#define _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 > > Ok. > > > diff --git a/sysdeps/unix/sysv/linux/arm/readelflib.c b/sysdeps/unix/sysv/linux/arm/readelflib.c > > index 9d03fa6405..7f444add14 100644 > > --- a/sysdeps/unix/sysv/linux/arm/readelflib.c > > +++ b/sysdeps/unix/sysv/linux/arm/readelflib.c > > @@ -18,18 +18,20 @@ > > . */ > > > > > > -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; > > Ok. > > > diff --git a/sysdeps/unix/sysv/linux/ia64/readelflib.c b/sysdeps/unix/sysv/linux/ia64/readelflib.c > > index d24a934351..19d37b438e 100644 > > --- a/sysdeps/unix/sysv/linux/ia64/readelflib.c > > +++ b/sysdeps/unix/sysv/linux/ia64/readelflib.c > > @@ -16,29 +16,31 @@ > > . */ > > > > > > -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; > > Ok. > > > diff --git a/sysdeps/unix/sysv/linux/mips/readelflib.c b/sysdeps/unix/sysv/linux/mips/readelflib.c > > index 8363b8afcc..a3399961c9 100644 > > --- a/sysdeps/unix/sysv/linux/mips/readelflib.c > > +++ b/sysdeps/unix/sysv/linux/mips/readelflib.c > > @@ -20,18 +20,20 @@ > > . */ > > > > > > -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) > > { > > Ok. > > > diff --git a/sysdeps/unix/sysv/linux/powerpc/readelflib.c b/sysdeps/unix/sysv/linux/powerpc/readelflib.c > > index eb20680418..ce01658fb3 100644 > > --- a/sysdeps/unix/sysv/linux/powerpc/readelflib.c > > +++ b/sysdeps/unix/sysv/linux/powerpc/readelflib.c > > @@ -17,29 +17,31 @@ > > . */ > > > > > > -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; > > Ok. > > > diff --git a/sysdeps/unix/sysv/linux/riscv/readelflib.c b/sysdeps/unix/sysv/linux/riscv/readelflib.c > > index 1e70735cc0..98ae3c0b2b 100644 > > --- a/sysdeps/unix/sysv/linux/riscv/readelflib.c > > +++ b/sysdeps/unix/sysv/linux/riscv/readelflib.c > > @@ -17,11 +17,13 @@ > > . */ > > > > > > -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; > > } > > > > Ok. > > > diff --git a/sysdeps/unix/sysv/linux/s390/readelflib.c b/sysdeps/unix/sysv/linux/s390/readelflib.c > > index 1718efc9f9..6d19e351ba 100644 > > --- a/sysdeps/unix/sysv/linux/s390/readelflib.c > > +++ b/sysdeps/unix/sysv/linux/s390/readelflib.c > > @@ -16,29 +16,31 @@ > > . */ > > > > > > -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; > > Ok. > > > diff --git a/sysdeps/unix/sysv/linux/sparc/readelflib.c b/sysdeps/unix/sysv/linux/sparc/readelflib.c > > index e027a11a37..3768003925 100644 > > --- a/sysdeps/unix/sysv/linux/sparc/readelflib.c > > +++ b/sysdeps/unix/sysv/linux/sparc/readelflib.c > > @@ -18,29 +18,31 @@ > > . */ > > > > > > -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; > > Ok. > > > diff --git a/sysdeps/unix/sysv/linux/x86/read-prop.h b/sysdeps/unix/sysv/linux/x86/read-prop.h > > new file mode 100644 > > index 0000000000..ac37fbc449 > > --- /dev/null > > +++ b/sysdeps/unix/sysv/linux/x86/read-prop.h > > @@ -0,0 +1,61 @@ > > +/* Support for GNU properties in ldconfig. x86 version. > > + Copyright (C) 2020 Free Software Foundation, Inc. > > s/2020/2021. Fixed, > > + 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 > > + . */ > > + > > +#ifndef _READ_PROP_H > > +#define _READ_PROP_H > > + > > +#include > > + > > +/* 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) > > Implicit check. Fixed. > > + { > > + unsigned int level; > > + asm ("bsr %1, %0" : "=r" (level) : "g" (isa_1_needed)); > > + *isal_level = level; > > + } > > + } > > + return true; > > + } > > + > > + return false; > > +} > > + > > +#endif > > Ok. > > > diff --git a/sysdeps/unix/sysv/linux/x86/readelflib.c b/sysdeps/unix/sysv/linux/x86/readelflib.c > > index 3e83419f5b..716629bf10 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 > > . */ > > > > - > > -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; > > Ok. > > > diff --git a/sysdeps/unix/sysv/linux/x86_64/Makefile b/sysdeps/unix/sysv/linux/x86_64/Makefile > > index 9b82155393..9a7b3cd8e5 100644 > > --- a/sysdeps/unix/sysv/linux/x86_64/Makefile > > +++ b/sysdeps/unix/sysv/linux/x86_64/Makefile > > @@ -13,3 +13,34 @@ endif > > ifeq ($(subdir),misc) > > gen-as-const-headers += sigaltstack-offsets.sym > > endif > > + > > +ifeq ($(subdir),elf) > > +ifeq (yesyes,$(enable-x86-isa-level)$(config-cflags-skylake-avx512)) > > As for first patch, I think we should extend the test coverage to check not > only for config-cflags-skylake-avx512. It means to build at least one > shared object with different ISA levels and run the ldconfig and check the > output against the system supported ISA level. I removed $(config-cflags-skylake-avx512) and added more tests. > > +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-4 > > + > > +$(objpfx)tst-glibc-hwcaps-2: $(objpfx)libx86-64-isa-level.so > > + > > +$(objpfx)tst-glibc-hwcaps-2.out: \ > > + $(objpfx)glibc-hwcaps/x86-64-v4/libx86-64-isa-level.so > > +$(objpfx)glibc-hwcaps/x86-64-v4/libx86-64-isa-level.so: \ > > + $(objpfx)libx86-64-isa-level-4.so > > + cp $< $@ > > + > > +CFLAGS-libx86-64-isa-level-1.os += -march=x86-64 > > +CFLAGS-libx86-64-isa-level-4.os += -march=skylake-avx512 > > + > > +# 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 -, ,$*)) > > +$(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..8d6b17d658 > > --- /dev/null > > +++ b/sysdeps/unix/sysv/linux/x86_64/tst-glibc-hwcaps-2.c > > @@ -0,0 +1,61 @@ > > +/* Check ISA level on shared object in glibc-hwcaps subdirectories. > > + Copyright (C) 2020 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 > > + . */ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +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); > > + int level = dso_isa_level (); > > + int ret; > > + switch (level) > > + { > > + case 1: > > + /* The default libx86-64-isa-level.so should be used. */ > > + printf ("The default shared library is used.\n"); > > + if ((isa_level & GNU_PROPERTY_X86_ISA_1_V4) != 0) > > + 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-v2 should be ignored on lesser CPU. */ > > + printf ("x86-64 ISA level 4 shared library in x86-64-v2 is used.\n"); > > + if ((isa_level & GNU_PROPERTY_X86_ISA_1_V4) != 0) > > + ret = EXIT_SUCCESS; > > + else > > + ret = EXIT_FAILURE; > > + break; > > + default: > > + abort (); > > + } > > + return ret; > > +} > > + > > +#include > > 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 > > +#include > > diff --git a/sysdeps/x86/dl-isa-level.h b/sysdeps/x86/dl-isa-level.h > > new file mode 100644 > > index 0000000000..c6ed8fb9d2 > > --- /dev/null > > +++ b/sysdeps/x86/dl-isa-level.h > > @@ -0,0 +1,32 @@ > > +/* Support for reading ISA level in /etc/ld.so.cache files written by > > + Linux ldconfig. x86 version. > > + Copyright (C) 2020 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 > > + . */ > > + > > +#include > > + > > +/* 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) > > +{ > > + const struct cpu_features *cpu_features = __get_cpu_features (); > > + unsigned int isa_level > > + = 1 << ((entry->hwcap >> 32) & DL_CACHE_HWCAP_ISA_LEVEL_MASK); > > + > > + return (isa_level & cpu_features->isa_1) == isa_level; > > +} > > Ok. Here is the updated patch. OK for master? Thanks. -- H.J.