From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
To: libc-alpha@sourceware.org, Florian Weimer <fweimer@redhat.com>
Subject: Re: [PATCH 27/28] elf: Process glibc-hwcaps subdirectories in ldconfig
Date: Tue, 27 Oct 2020 14:28:25 -0300 [thread overview]
Message-ID: <ceb0e27b-f30e-890a-a188-8f886e5d9852@linaro.org> (raw)
In-Reply-To: <ffef62d3152bb2565849c002550ac533ab809249.1601569371.git.fweimer@redhat.com>
On 01/10/2020 13:34, Florian Weimer via Libc-alpha wrote:
> Libraries from these subdirectories are added to the cache
> with a special hwcap bit DL_CACHE_HWCAP_EXTENSION, so that
> they are ignored by older dynamic loaders.
Looks goods in general, some comments below.
> ---
> elf/cache.c | 258 ++++++++++++++++++++++++++++++++-----
> elf/ldconfig.c | 153 +++++++++++++++++++---
> sysdeps/generic/dl-cache.h | 51 +++++++-
> sysdeps/generic/ldconfig.h | 18 ++-
> 4 files changed, 426 insertions(+), 54 deletions(-)
>
> diff --git a/elf/cache.c b/elf/cache.c
> index eda3da98a7..7ce4ca9870 100644
> --- a/elf/cache.c
> +++ b/elf/cache.c
> @@ -40,6 +40,105 @@
> /* Used to store library names, paths, and other strings. */
> struct stringtable strings;
>
> +/* Keeping track of "glibc-hwcaps" subdirectories. During cache
> + construction, a linear search by name is performed to deduplicate
> + entries. */
> +struct glibc_hwcaps_subdirectory
> +{
> + struct glibc_hwcaps_subdirectory *next;
> +
> + /* Interned string with the subdirectory name. */
> + struct stringtable_entry *name;
> +
> + /* Array index in the cache_extension_tag_glibc_hwcaps section in
> + the stored cached file. This is computed after all the
> + subdirectories have been processed, so that subdirectory names in
> + the extension section can be sorted. */
> + uint32_t section_index;
> +
> + /* True if the subdirectory is actually used for anything. */
> + bool used;
> +};
> +
Ok.
> +const char *
> +glibc_hwcaps_subdirectory_name (struct glibc_hwcaps_subdirectory *dir)
> +{
> + return dir->name->string;
> +}
> +
> +/* Linked list of known hwcaps subdirecty names. */
> +static struct glibc_hwcaps_subdirectory *hwcaps;
> +
> +struct glibc_hwcaps_subdirectory *
> +new_glibc_hwcaps_subdirectory (const char *name)
> +{
> + struct stringtable_entry *name_interned
> + = stringtable_intern (&strings, name);
> + for (struct glibc_hwcaps_subdirectory *p = hwcaps; p != NULL; p = p->next)
> + if (p->name == name_interned)
> + return p;
> + struct glibc_hwcaps_subdirectory *p = xmalloc (sizeof (p));
> + p->next = hwcaps;
> + p->name = name_interned;
> + p->section_index = 0;
> + p->used = false;
> + hwcaps = p;
> + return p;
> +}
> +
Ok.
> +/* Helper for sorting struct glibc_hwcaps_subdirectory elements by
> + name. */
> +static int
> +assign_glibc_hwcaps_indices_compare (const void *l, const void *r)
> +{
> + const struct glibc_hwcaps_subdirectory *left
> + = *(struct glibc_hwcaps_subdirectory **)l;
> + const struct glibc_hwcaps_subdirectory *right
> + = *(struct glibc_hwcaps_subdirectory **)r;
> + return strcmp (left->name->string, right->name->string);
> +}
> +
Maybe:
strcmp (glibc_hwcaps_subdirectory_name (left),
glibc_hwcaps_subdirectory_name (right));
> +/* Count the number of hwcaps subdirectories which are actually
> + used. */
> +static size_t
> +glibc_hwcaps_count (void)
> +{
> + size_t count = 0;
> + for (struct glibc_hwcaps_subdirectory *p = hwcaps; p != NULL; p = p->next)
> + if (p->used)
> + ++count;
> + return count;
> +}
> +
Ok.
> +/* Compute the section_index fields for all */
> +static void
> +assign_glibc_hwcaps_indices (void)
> +{
> + /* Convert the linked list into an array, so that we can use qsort.
> + Only copy the subdirectories which are actually used. */
> + size_t count = glibc_hwcaps_count ();
> + struct glibc_hwcaps_subdirectory **array
> + = xmalloc (sizeof (*array) * count);
> + {
> + size_t i = 0;
> + for (struct glibc_hwcaps_subdirectory *p = hwcaps; p != NULL; p = p->next)
> + if (p->used)
> + {
> + array[i] = p;
> + ++i;
> + }
> + assert (i == count);
Do we need this assert? I think it would make sense if hwcaps is modified
concurrently, which does not seem the case.
> + }
> +
> + qsort (array, count, sizeof (*array), assign_glibc_hwcaps_indices_compare);
> +
> + /* Assign the array indices. */
> + for (size_t i = 0; i < count; ++i)
> + array[i]->section_index = i;
> +
> + free (array);
> +}
> +
Ok.
> struct cache_entry
> {
> struct stringtable_entry *lib; /* Library name. */
> @@ -48,6 +147,10 @@ struct cache_entry
> unsigned int osversion; /* Required OS version. */
> uint64_t hwcap; /* Important hardware capabilities. */
> int bits_hwcap; /* Number of bits set in hwcap. */
> +
> + /* glibc-hwcaps subdirectory. If not NULL, hwcap must be zero. */
> + struct glibc_hwcaps_subdirectory *hwcaps;
> +
> struct cache_entry *next; /* Next entry in list. */
> };
>
Ok.
> @@ -60,7 +163,7 @@ static const char *flag_descr[] =
> /* Print a single entry. */
> static void
> print_entry (const char *lib, int flag, unsigned int osversion,
> - uint64_t hwcap, const char *key)
> + uint64_t hwcap, const char *hwcap_string, const char *key)
> {
> printf ("\t%s (", lib);
> switch (flag & FLAG_TYPE_MASK)
> @@ -132,7 +235,9 @@ print_entry (const char *lib, int flag, unsigned int osversion,
> printf (",%d", flag & FLAG_REQUIRED_MASK);
> break;
> }
> - if (hwcap != 0)
> + if (hwcap_string != NULL)
> + printf (", hwcap: \"%s\"", hwcap_string);
> + else if (hwcap != 0)
> printf (", hwcap: %#.16" PRIx64, hwcap);
> if (osversion != 0)
> {
Ok.
> @@ -158,6 +263,29 @@ print_entry (const char *lib, int flag, unsigned int osversion,
> printf (") => %s\n", key);
> }
>
> +/* Returns the string with the name of the glibcs-hwcaps subdirectory
> + associated with ENTRY->hwcap. file_base must be the base address
> + for string table indices. */
> +static const char *
> +glibc_hwcaps_string (struct cache_extension_all_loaded *ext,
> + const void *file_base, size_t file_size,
> + struct file_entry_new *entry)
> +{
> + const uint32_t *hwcaps_array
> + = ext->sections[cache_extension_tag_glibc_hwcaps].base;
> + if (dl_cache_hwcap_extension (entry) && hwcaps_array != NULL)
> + {
> + uint32_t index = (uint32_t) entry->hwcap;
> + if (index < ext->sections[cache_extension_tag_glibc_hwcaps].size / 4)
> + {
> + uint32_t string_table_index = hwcaps_array[index];
> + if (string_table_index < file_size)
> + return file_base + string_table_index;
> + }
> + }
> + return NULL;
> +}
> +
Ok.
> /* Print an error and exit if the new-file cache is internally
> inconsistent. */
> static void
> @@ -167,9 +295,7 @@ check_new_cache (struct cache_file_new *cache)
> error (EXIT_FAILURE, 0, _("Cache file has wrong endianness.\n"));
> }
>
> -/* Print the extension information at the cache at start address
> - FILE_BASE, of ltength FILE_SIZE bytes. The new-format cache header
> - is at CACHE, and the file name for diagnostics is CACHE_NAME. */
> +/* Print the extension information in *EXT. */
> static void
> print_extensions (struct cache_extension_all_loaded *ext)
> {
> @@ -266,7 +392,7 @@ print_cache (const char *cache_name)
> /* Print everything. */
> for (unsigned int i = 0; i < cache->nlibs; i++)
> print_entry (cache_data + cache->libs[i].key,
> - cache->libs[i].flags, 0, 0,
> + cache->libs[i].flags, 0, 0, NULL,
> cache_data + cache->libs[i].value);
> }
> else if (format == 1)
Ok.
> @@ -281,11 +407,16 @@ print_cache (const char *cache_name)
>
> /* Print everything. */
> for (unsigned int i = 0; i < cache_new->nlibs; i++)
> - print_entry (cache_data + cache_new->libs[i].key,
> - cache_new->libs[i].flags,
> - cache_new->libs[i].osversion,
> - cache_new->libs[i].hwcap,
> - cache_data + cache_new->libs[i].value);
> + {
> + const char *hwcaps_string
> + = glibc_hwcaps_string (&ext, cache, cache_size,
> + &cache_new->libs[i]);
> + print_entry (cache_data + cache_new->libs[i].key,
> + cache_new->libs[i].flags,
> + cache_new->libs[i].osversion,
> + cache_new->libs[i].hwcap, hwcaps_string,
> + cache_data + cache_new->libs[i].value);
> + }
> print_extensions (&ext);
> }
> /* Cleanup. */
Ok.
> @@ -311,8 +442,22 @@ compare (const struct cache_entry *e1, const struct cache_entry *e2)
> return 1;
> else if (e1->flags > e2->flags)
> return -1;
> + /* Keep the glibc-hwcaps extension entries before the regular
> + entries, and sort them by their names. search_cache in
> + dl-cache.c stops searching once the first non-extension entry
> + is found, so the extension entries need to come first. */
> + else if (e1->hwcaps != NULL && e2->hwcaps == NULL)
> + return -1;
> + else if (e1->hwcaps == NULL && e2->hwcaps != NULL)
> + return 1;
> + else if (e1->hwcaps != NULL && e2->hwcaps != NULL)
> + {
> + res = strcmp (e1->hwcaps->name->string, e2->hwcaps->name->string);
Maybe:
res = strcmp (glibc_hwcaps_subdirectory_name (e1->hwcaps),
glibc_hwcaps_subdirectory_name (e2->hwcaps));
> + if (res != 0)
> + return res;
> + }
> /* Sort by most specific hwcap. */
> - else if (e2->bits_hwcap > e1->bits_hwcap)
> + if (e2->bits_hwcap > e1->bits_hwcap)
> return 1;
> else if (e2->bits_hwcap < e1->bits_hwcap)
> return -1;
Ok.
> @@ -337,30 +482,65 @@ enum
> * sizeof (struct cache_extension_section)))
> };
>
> -/* Write the cache extensions to FD. The extension directory is
> - assumed to be located at CACHE_EXTENSION_OFFSET. */
> +/* Write the cache extensions to FD. The string table is shifted by
> + STRING_TABLE_OFFSET. The extension directory is assumed to be
> + located at CACHE_EXTENSION_OFFSET. assign_glibc_hwcaps_indices
> + must have been called. */
> static void
> -write_extensions (int fd, uint32_t cache_extension_offset)
> +write_extensions (int fd, uint32_t str_offset,
> + uint32_t cache_extension_offset)
> {
> assert ((cache_extension_offset % 4) == 0);
>
> + /* The length and contents of the glibc-hwcaps section. */
> + uint32_t hwcaps_count = glibc_hwcaps_count ();
> + uint32_t hwcaps_offset = cache_extension_offset + cache_extension_size;
> + uint32_t hwcaps_size = hwcaps_count * sizeof (uint32_t);
> + uint32_t *hwcaps_array = xmalloc (hwcaps_size);
> + for (struct glibc_hwcaps_subdirectory *p = hwcaps; p != NULL; p = p->next)
> + if (p->used)
> + hwcaps_array[p->section_index] = str_offset + p->name->offset;
> +
> + /* This is the offset of the generator string. */
> + uint32_t generator_offset = hwcaps_offset;
> + if (hwcaps_count == 0)
> + /* There is no section for the hwcaps subdirectories. */
> + generator_offset -= sizeof (struct cache_extension_section);
> + else
> + /* The string table indices for the hwcaps subdirectories shift
> + the generator string backwards. */
> + generator_offset += hwcaps_count * sizeof (uint32_t);
Maybe
generator_offset += hwcaps_size;
> +
> struct cache_extension *ext = xmalloc (cache_extension_size);
> ext->magic = cache_extension_magic;
> - ext->count = cache_extension_count;
>
> - for (int i = 0; i < cache_extension_count; ++i)
> - {
> - ext->sections[i].tag = i;
> - ext->sections[i].flags = 0;
> - }
Ok, although maybe you could refactor the 'elf: Add extension mechanism to ld.so.cache'
to avoid add such code.
> + /* Extension index current being filled. */
> + size_t xid = 0;
>
> const char *generator
> = "ldconfig " PKGVERSION RELEASE " release version " VERSION;
> - ext->sections[cache_extension_tag_generator].offset
> - = cache_extension_offset + cache_extension_size;
> - ext->sections[cache_extension_tag_generator].size = strlen (generator);
> + ext->sections[xid].tag = cache_extension_tag_generator;
> + ext->sections[xid].flags = 0;
> + ext->sections[xid].offset = generator_offset;
> + ext->sections[xid].size = strlen (generator);
> +
> + if (hwcaps_count > 0)
> + {
> + ++xid;
> + ext->sections[xid].tag = cache_extension_tag_glibc_hwcaps;
> + ext->sections[xid].flags = 0;
> + ext->sections[xid].offset = hwcaps_offset;
> + ext->sections[xid].size = hwcaps_size;
> + }
> +
> + ++xid;
> + ext->count = xid;
> + assert (xid <= cache_extension_count);
Would it make more sense to reference the index directly using the
enumeration instead or add an assert to check if the index is within
the expected size?
>
> - if (write (fd, ext, cache_extension_size) != cache_extension_size
> + size_t ext_size = (offsetof (struct cache_extension, sections)
> + + xid * sizeof (struct cache_extension_section));
So here we could just use cache_extension_count instead of 'xid' (with
the advantage that we certify at compile-time that only know
cache_extension_count will be written on the file).
> + if (write (fd, ext, ext_size) != ext_size
> + || write (fd, hwcaps_array, hwcaps_size) != hwcaps_size
> || write (fd, generator, strlen (generator)) != strlen (generator))
> error (EXIT_FAILURE, errno, _("Writing of cache extension data failed"));
>
> @@ -373,6 +553,8 @@ save_cache (const char *cache_name)
> {
> /* The cache entries are sorted already, save them in this order. */
>
> + assign_glibc_hwcaps_indices ();
> +
> struct cache_entry *entry;
> /* Number of cache entries. */
> int cache_entry_count = 0;
Ok.
> @@ -474,7 +656,11 @@ save_cache (const char *cache_name)
> struct. */
> file_entries_new->libs[idx_new].flags = entry->flags;
> file_entries_new->libs[idx_new].osversion = entry->osversion;
> - file_entries_new->libs[idx_new].hwcap = entry->hwcap;
> + 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;
> file_entries_new->libs[idx_new].key
> = str_offset + entry->lib->offset;
> file_entries_new->libs[idx_new].value
Ok.
> @@ -554,7 +740,7 @@ save_cache (const char *cache_name)
> /* Align file position to 4. */
> off64_t old_offset = lseek64 (fd, extension_offset, SEEK_SET);
> assert ((unsigned long long int) (extension_offset - old_offset) < 4);
> - write_extensions (fd, extension_offset);
> + write_extensions (fd, str_offset, extension_offset);
> }
>
> /* Make sure user can always read cache file */
Ok.
> @@ -588,8 +774,9 @@ save_cache (const char *cache_name)
>
> /* Add one library to the cache. */
> void
> -add_to_cache (const char *path, const char *lib, int flags,
> - unsigned int osversion, uint64_t hwcap)
> +add_to_cache (const char *path, const char *filename, const char *soname,
> + int flags, unsigned int osversion, uint64_t hwcap,
> + struct glibc_hwcaps_subdirectory *hwcaps)
> {
> struct cache_entry *new_entry = xmalloc (sizeof (*new_entry));
>
> @@ -597,11 +784,11 @@ add_to_cache (const char *path, const char *lib, int flags,
> {
> /* Use a small, on-stack buffer in most cases. */
> char buf[200];
> - int ret = snprintf (buf, sizeof (buf), "%s/%s", path, lib);
> + int ret = snprintf (buf, sizeof (buf), "%s/%s", path, filename);
> if (ret < 0 || ret >= sizeof (buf) - 1)
> {
> char *p;
> - if (asprintf (&p, "%s/%s", path, lib) < 0)
> + if (asprintf (&p, "%s/%s", path, filename) < 0)
> error (EXIT_FAILURE, errno, _("Could not create library path"));
> path_interned = stringtable_intern (&strings, p);
> free (p);
Ok.
> @@ -610,13 +797,20 @@ add_to_cache (const char *path, const char *lib, int flags,
> path_interned = stringtable_intern (&strings, buf);
> }
>
> - new_entry->lib = stringtable_intern (&strings, lib);
> + new_entry->lib = stringtable_intern (&strings, soname);
> new_entry->path = path_interned;
> new_entry->flags = flags;
> new_entry->osversion = osversion;
> new_entry->hwcap = hwcap;
> + new_entry->hwcaps = hwcaps;
> new_entry->bits_hwcap = 0;
>
> + if (hwcaps != NULL)
> + {
> + assert (hwcap == 0);
> + hwcaps->used = true;
> + }
> +
> /* Count the number of bits set in the masked value. */
> for (size_t i = 0;
> (~((1ULL << i) - 1) & hwcap) != 0 && i < 8 * sizeof (hwcap); ++i)
Ok.
> diff --git a/elf/ldconfig.c b/elf/ldconfig.c
> index 3768267bac..3136601de7 100644
> --- a/elf/ldconfig.c
> +++ b/elf/ldconfig.c
> @@ -16,6 +16,7 @@
> along with this program; if not, see <https://www.gnu.org/licenses/>. */
>
> #define PROCINFO_CLASS static
> +#include <assert.h>
> #include <alloca.h>
> #include <argp.h>
> #include <dirent.h>
> @@ -41,6 +42,7 @@
>
> #include <ldconfig.h>
> #include <dl-cache.h>
> +#include <dl-hwcaps.h>
>
> #include <dl-procinfo.h>
>
> @@ -85,6 +87,10 @@ struct dir_entry
> dev_t dev;
> const char *from_file;
> int from_line;
> +
> + /* Non-NULL for subdirectories under a glibc-hwcaps subdirectory. */
> + struct glibc_hwcaps_subdirectory *hwcaps;
> +
> struct dir_entry *next;
> };
>
Ok.
> @@ -339,17 +345,20 @@ new_sub_entry (const struct dir_entry *entry, const char *path,
> new_entry->from_line = entry->from_line;
> new_entry->path = xstrdup (path);
> new_entry->flag = entry->flag;
> + new_entry->hwcaps = NULL;
> new_entry->next = NULL;
> new_entry->ino = st->st_ino;
> new_entry->dev = st->st_dev;
> return new_entry;
> }
>
> -/* Add a single directory entry. */
> -static void
> +/* Add a single directory entry. Return true if the directory is
> + actually added (because it is not a duplicate). */
> +static bool
> add_single_dir (struct dir_entry *entry, int verbose)
> {
> struct dir_entry *ptr, *prev;
> + bool added = true;
>
> ptr = dir_entries;
> prev = ptr;
> @@ -369,6 +378,7 @@ add_single_dir (struct dir_entry *entry, int verbose)
> ptr->flag = entry->flag;
> free (entry->path);
> free (entry);
> + added = false;
> break;
> }
> prev = ptr;
> @@ -379,6 +389,73 @@ add_single_dir (struct dir_entry *entry, int verbose)
> dir_entries = entry;
> else if (ptr == NULL)
> prev->next = entry;
> + return added;
> +}
> +
Ok.
> +/* Check if PATH contains a "glibc-hwcaps" subdirectory. If so, queue
> + its subdirectories for glibc-hwcaps processing. */
> +static void
> +add_glibc_hwcaps_subdirectories (struct dir_entry *entry, const char *path)
> +{
> + /* glibc-hwcaps subdirectories do not nest. */
> + assert (entry->hwcaps == NULL);
> +
> + char *glibc_hwcaps;
> + if (asprintf (&glibc_hwcaps, "%s/" GLIBC_HWCAPS_SUBDIRECTORY, path) < 0)
> + error (EXIT_FAILURE, errno, _("Could not form glibc-hwcaps path"));
> +
> + DIR *dir = opendir (glibc_hwcaps);
> + if (dir != NULL)
> + {
> + while (true)
> + {
> + errno = 0;
> + struct dirent64 *e = readdir64 (dir);
> + if (e == NULL)
> + {
> + if (errno == 0)
> + break;
> + else
> + error (EXIT_FAILURE, errno, _("Listing directory %s"), path);
> + }
> +
> + /* Ignore hidden subdirectories, including "." and "..", and
> + regular files. File names containing a ':' cannot be
> + looked up by the dynamic loader, so skip those as
> + well. */
> + if (e->d_name[0] == '.' || e->d_type == DT_REG
> + || strchr (e->d_name, ':') != NULL)
> + continue;
> +
> + /* See if this entry eventually resolves to a directory. */
> + struct stat64 st;
> + if (fstatat64 (dirfd (dir), e->d_name, &st, 0) < 0)
> + /* Ignore unreadable entries. */
> + continue;
> +
> + if (S_ISDIR (st.st_mode))
> + {
> + /* This is a directory, so it needs to be scanned for
> + libraries, associated with the hwcaps implied by the
> + subdirectory name. */
> + char *new_path;
> + if (asprintf (&new_path, "%s/" GLIBC_HWCAPS_SUBDIRECTORY "/%s",
> + /* Use non-canonicalized path here. */
> + entry->path, e->d_name) < 0)
> + error (EXIT_FAILURE, errno,
> + _("Could not form glibc-hwcaps path"));
> + struct dir_entry *new_entry = new_sub_entry (entry, new_path,
> + &st);
> + free (new_path);
> + new_entry->hwcaps = new_glibc_hwcaps_subdirectory (e->d_name);
> + add_single_dir (new_entry, 0);
> + }
> + }
> +
> + closedir (dir);
> + }
> +
> + free (glibc_hwcaps);
> }
>
> /* Add one directory to the list of directories to process. */
Ok.
> @@ -387,6 +464,7 @@ add_dir_1 (const char *line, const char *from_file, int from_line)
> {
> unsigned int i;
> struct dir_entry *entry = xmalloc (sizeof (struct dir_entry));
> + entry->hwcaps = NULL;
> entry->next = NULL;
>
> entry->from_file = strdup (from_file);
> @@ -444,7 +522,9 @@ add_dir_1 (const char *line, const char *from_file, int from_line)
> entry->ino = stat_buf.st_ino;
> entry->dev = stat_buf.st_dev;
>
> - add_single_dir (entry, 1);
> + if (add_single_dir (entry, 1))
> + /* Add glibc-hwcaps subdirectories if present. */
> + add_glibc_hwcaps_subdirectories (entry, path);
> }
>
> if (opt_chroot)
Ok.
> @@ -696,15 +776,27 @@ struct dlib_entry
> static void
> search_dir (const struct dir_entry *entry)
> {
> - uint64_t hwcap = path_hwcap (entry->path);
> - if (opt_verbose)
> + uint64_t hwcap;
> + if (entry->hwcaps == NULL)
> {
> - if (hwcap != 0)
> - printf ("%s: (hwcap: %#.16" PRIx64 ")", entry->path, hwcap);
> - else
> - printf ("%s:", entry->path);
> - printf (_(" (from %s:%d)\n"), entry->from_file, entry->from_line);
> + hwcap = path_hwcap (entry->path);
> + if (opt_verbose)
> + {
> + if (hwcap != 0)
> + printf ("%s: (hwcap: %#.16" PRIx64 ")", entry->path, hwcap);
> + else
> + printf ("%s:", entry->path);
> + }
> }
> + else
> + {
> + hwcap = 0;
> + if (opt_verbose)
> + printf ("%s: (hwcap: \"%s\")", entry->path,
> + glibc_hwcaps_subdirectory_name (entry->hwcaps));
> + }
> + if (opt_verbose)
> + printf (_(" (from %s:%d)\n"), entry->from_file, entry->from_line);
>
> char *dir_name;
> char *real_file_name;
Ok.
> @@ -746,13 +838,15 @@ search_dir (const struct dir_entry *entry)
> && direntry->d_type != DT_DIR)
> continue;
> /* Does this file look like a shared library or is it a hwcap
> - subdirectory? The dynamic linker is also considered as
> + subdirectory (if not already processing a glibc-hwcaps
> + subdirectory)? The dynamic linker is also considered as
> shared library. */
> if (((strncmp (direntry->d_name, "lib", 3) != 0
> && strncmp (direntry->d_name, "ld-", 3) != 0)
> || strstr (direntry->d_name, ".so") == NULL)
> && (direntry->d_type == DT_REG
> - || !is_hwcap_platform (direntry->d_name)))
> + || (entry->hwcaps == NULL
> + && !is_hwcap_platform (direntry->d_name))))
> continue;
>
> size_t len = strlen (direntry->d_name);
Ok.
> @@ -838,7 +932,10 @@ search_dir (const struct dir_entry *entry)
> else
> is_dir = S_ISDIR (lstat_buf.st_mode);
>
> - if (is_dir && is_hwcap_platform (direntry->d_name))
> + /* No descending into subdirectories if this directory is a
> + glibc-hwcaps subdirectory (which are not recursive). */
> + if (entry->hwcaps == NULL
> + && is_dir && is_hwcap_platform (direntry->d_name))
> {
> if (!is_link
> && direntry->d_type != DT_UNKNOWN
is_dir is an 'int', maybe make it a boolean?
> @@ -1029,13 +1126,31 @@ search_dir (const struct dir_entry *entry)
> struct dlib_entry *dlib_ptr;
> for (dlib_ptr = dlibs; dlib_ptr != NULL; dlib_ptr = dlib_ptr->next)
> {
> - /* Don't create links to links. */
> - if (dlib_ptr->is_link == 0)
> - create_links (dir_name, entry->path, dlib_ptr->name,
> - dlib_ptr->soname);
> + /* The cached file name is the soname for non-glibc-hwcaps
> + subdirectories (relying on symbolic links; this helps with
> + library updates that change the file name), and the actual
> + file for glibc-hwcaps subdirectories. */
> + const char *filename;
> + if (entry->hwcaps == NULL)
> + {
> + /* Don't create links to links. */
> + if (dlib_ptr->is_link == 0)
> + create_links (dir_name, entry->path, dlib_ptr->name,
> + dlib_ptr->soname);
> + filename = dlib_ptr->soname;
> + }
> + else
> + {
> + /* Do not create links in glibc-hwcaps subdirectories, but
> + still log the cache addition. */
> + if (opt_verbose)
> + printf ("\t%s -> %s\n", dlib_ptr->soname, dlib_ptr->name);
> + filename = dlib_ptr->name;
> + }
> if (opt_build_cache)
> - add_to_cache (entry->path, dlib_ptr->soname, dlib_ptr->flag,
> - dlib_ptr->osversion, hwcap);
> + add_to_cache (entry->path, filename, dlib_ptr->soname,
> + dlib_ptr->flag, dlib_ptr->osversion,
> + hwcap, entry->hwcaps);
> }
>
> /* Free all resources. */
Ok.
> diff --git a/sysdeps/generic/dl-cache.h b/sysdeps/generic/dl-cache.h
> index fec209509d..66b0312ac1 100644
> --- a/sysdeps/generic/dl-cache.h
> +++ b/sysdeps/generic/dl-cache.h
> @@ -81,7 +81,6 @@ struct cache_file
> #define CACHE_VERSION "1.1"
> #define CACHEMAGIC_VERSION_NEW CACHEMAGIC_NEW CACHE_VERSION
>
> -
Spurious line removal.
> struct file_entry_new
> {
> union
> @@ -99,6 +98,23 @@ struct file_entry_new
> uint64_t hwcap; /* Hwcap entry. */
> };
>
> +/* 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);
> +}
> +
> /* See flags member of struct cache_file_new below. */
> enum
> {
Ok.
> @@ -161,6 +177,17 @@ enum cache_extension_tag
> cache file. */
> cache_extension_tag_generator,
>
> + /* glibc-hwcaps subdirectory information. An array of uint32_t
> + values, which are indices into the string table. The strings
> + are sorted lexicographically (according to strcmp). The extra
> + level of indirection (instead of using string table indices
> + directly) allows the dynamic loader to compute the preference
> + order of the hwcaps names more efficiently.
> +
> + For this section, 4-byte alignment is required, and the section
> + size must be a multiple of 4. */
> + cache_extension_tag_glibc_hwcaps,
> +
> /* Total number of known cache extension tags. */
> cache_extension_count
> };
Ok.
> @@ -215,6 +242,27 @@ struct cache_extension_all_loaded
> struct cache_extension_loaded sections[cache_extension_count];
> };
>
> +/* Performs basic data validation based on section tag, and removes
> + the sections which are invalid. */
> +static void
> +cache_extension_verify (struct cache_extension_all_loaded *loaded)
> +{
> + {
> + /* Section must not be empty, it must be aligned at 4 bytes, and
> + the size must be a multiple of 4. */
> + struct cache_extension_loaded *hwcaps
> + = &loaded->sections[cache_extension_tag_glibc_hwcaps];
> + if (hwcaps->size == 0
> + || ((uintptr_t) hwcaps->base % 4) != 0
> + || (hwcaps->size % 4) != 0)
> + {
> + hwcaps->base = NULL;
> + hwcaps->size = 0;
> + hwcaps->flags = 0;
> + }
> + }
> +}
> +
Ok.
> static bool __attribute__ ((unused))
> cache_extension_load (const struct cache_file_new *cache,
> const void *file_base, size_t file_size,
> @@ -261,6 +309,7 @@ cache_extension_load (const struct cache_file_new *cache,
> loaded->sections[tag].size = ext->sections[i].size;
> loaded->sections[tag].flags = ext->sections[i].flags;
> }
> + cache_extension_verify (loaded);
> return true;
> }
>
Ok.
> diff --git a/sysdeps/generic/ldconfig.h b/sysdeps/generic/ldconfig.h
> index b64aab0064..30a76481aa 100644
> --- a/sysdeps/generic/ldconfig.h
> +++ b/sysdeps/generic/ldconfig.h
> @@ -57,8 +57,22 @@ extern void init_cache (void);
>
> extern void save_cache (const char *cache_name);
>
> -extern void add_to_cache (const char *path, const char *lib, int flags,
> - unsigned int osversion, uint64_t hwcap);
> +struct glibc_hwcaps_subdirectory;
> +
> +/* Return a struct describing the subdirectory for NAME. Reuse an
> + existing struct if it exists. */
> +struct glibc_hwcaps_subdirectory *new_glibc_hwcaps_subdirectory
> + (const char *name);
> +
> +/* Returns the name that was specified when
> + add_glibc_hwcaps_subdirectory was called. */
> +const char *glibc_hwcaps_subdirectory_name
> + (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,
> + struct glibc_hwcaps_subdirectory *);
>
> extern void init_aux_cache (void);
>
>
Ok.
next prev parent reply other threads:[~2020-10-27 17:28 UTC|newest]
Thread overview: 103+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-10-01 16:31 [PATCH 00/28] glibc-hwcaps support Florian Weimer
2020-10-01 16:31 ` [PATCH 01/28] elf: Do not search HWCAP subdirectories in statically linked binaries Florian Weimer
2020-10-01 18:22 ` Adhemerval Zanella
2020-10-01 18:24 ` Carlos O'Donell
2020-10-01 18:29 ` Adhemerval Zanella
2020-10-01 20:24 ` Carlos O'Donell
2020-10-01 16:31 ` [PATCH 02/28] elf: Implement __rtld_malloc_is_full Florian Weimer
2020-10-01 18:23 ` Adhemerval Zanella
2020-10-08 9:44 ` Florian Weimer
2020-10-01 16:31 ` [PATCH 03/28] elf: Implement _dl_write Florian Weimer
2020-10-05 19:46 ` Adhemerval Zanella
2020-10-01 16:31 ` [PATCH 04/28] elf: Extract command-line/environment variables state from rtld.c Florian Weimer
2020-10-06 20:45 ` Adhemerval Zanella
2020-10-08 11:32 ` Florian Weimer
2020-10-01 16:32 ` [PATCH 05/28] elf: Move ld.so error/help output to _dl_usage Florian Weimer
2020-10-06 21:06 ` Adhemerval Zanella
2020-10-08 12:19 ` Florian Weimer
2020-10-01 16:32 ` [PATCH 06/28] elf: Record whether paths come from LD_LIBRARY_PATH or --library-path Florian Weimer
2020-10-07 16:39 ` Adhemerval Zanella
2020-10-07 16:49 ` Florian Weimer
2020-10-01 16:32 ` [PATCH 07/28] elf: Implement ld.so --help Florian Weimer
2020-10-07 17:16 ` Adhemerval Zanella
2020-10-08 13:13 ` Florian Weimer
2020-10-01 16:32 ` [PATCH 08/28] elf: Implement ld.so --version Florian Weimer
2020-10-07 18:36 ` Adhemerval Zanella
2020-10-07 18:38 ` Adhemerval Zanella
2020-10-08 13:37 ` Florian Weimer
2020-10-01 16:32 ` [PATCH 09/28] scripts/update-copyrights: Update csu/version.c, elf/dl-usage.c Florian Weimer
2020-10-07 18:41 ` Adhemerval Zanella
2020-10-01 16:32 ` [PATCH 10/28] elf: Use the term "program interpreter" in the ld.so help message Florian Weimer
2020-10-07 21:08 ` Adhemerval Zanella
2020-10-08 14:08 ` Florian Weimer
2020-10-01 16:32 ` [PATCH 11/28] elf: Print the full name of the dynamic loader " Florian Weimer
2020-10-08 12:38 ` Adhemerval Zanella
2020-10-01 16:32 ` [PATCH 12/28] elf: Make __rtld_env_path_list and __rtld_search_dirs global variables Florian Weimer
2020-10-08 13:27 ` Adhemerval Zanella
2020-10-01 16:32 ` [PATCH 13/28] elf: Add library search path information to ld.so --help Florian Weimer
2020-10-08 16:22 ` Adhemerval Zanella
2020-10-01 16:33 ` [PATCH 14/28] elf: Enhance ld.so --help to print HWCAP subdirectories Florian Weimer
2020-10-08 16:27 ` Adhemerval Zanella
2020-10-09 8:18 ` Florian Weimer
2020-10-09 13:49 ` Matheus Castanho
2020-10-09 17:08 ` Florian Weimer
2020-10-09 17:12 ` Florian Weimer
2020-10-09 18:54 ` Matheus Castanho
2020-10-12 9:47 ` Florian Weimer
2020-10-01 16:33 ` [PATCH 15/28] elf: Do not pass GLRO(dl_platform), GLRO(dl_platformlen) to _dl_important_hwcaps Florian Weimer
2020-10-08 18:04 ` Adhemerval Zanella
2020-10-01 16:33 ` [PATCH 16/28] elf: Add glibc-hwcaps support for LD_LIBRARY_PATH Florian Weimer
2020-10-08 10:13 ` Szabolcs Nagy
2020-10-09 9:08 ` Florian Weimer
2020-10-09 10:50 ` Szabolcs Nagy
2020-10-09 10:55 ` Florian Weimer
2020-10-09 11:03 ` Szabolcs Nagy
2020-10-08 23:16 ` Paul A. Clarke
2020-10-09 8:56 ` Florian Weimer
2020-10-09 13:19 ` Adhemerval Zanella
2020-10-12 11:54 ` Florian Weimer
2020-10-01 16:33 ` [PATCH 17/28] x86_64: Add glibc-hwcaps support Florian Weimer
2020-10-01 16:33 ` [PATCH 18/28] powerpc64le: " Florian Weimer
2020-10-01 18:56 ` Paul A. Clarke
2020-10-05 9:47 ` Florian Weimer
2020-10-05 19:15 ` Paul A. Clarke
2020-10-06 12:20 ` Florian Weimer
2020-10-06 17:45 ` Paul A. Clarke
2020-10-09 9:06 ` Florian Weimer
2020-10-01 16:33 ` [PATCH 19/28] s390x: Add " Florian Weimer
2020-10-01 16:33 ` [PATCH 20/28] aarch64: " Florian Weimer
2020-10-14 13:46 ` Adhemerval Zanella
2020-10-14 14:08 ` Florian Weimer
2020-10-14 14:15 ` Adhemerval Zanella
2020-10-14 14:37 ` Szabolcs Nagy
2020-10-14 14:43 ` Adhemerval Zanella
2020-10-14 15:13 ` Florian Weimer
2020-10-14 14:44 ` Florian Weimer
2020-10-14 15:09 ` Szabolcs Nagy
2020-10-01 16:33 ` [PATCH 21/28] elf: Add endianness markup to ld.so.cache Florian Weimer
2020-10-14 14:07 ` Adhemerval Zanella
2020-10-01 16:33 ` [PATCH 22/28] elf: Add extension mechanism " Florian Weimer
2020-10-15 17:52 ` Adhemerval Zanella
2020-10-30 12:22 ` Florian Weimer
2020-11-03 12:45 ` Adhemerval Zanella
2020-11-03 15:30 ` Florian Weimer
2020-10-01 16:34 ` [PATCH 23/28] elf: Unify old and new format cache handling code in ld.so Florian Weimer
2020-10-16 14:37 ` Adhemerval Zanella
2020-10-30 13:22 ` Florian Weimer
2020-11-03 13:02 ` Adhemerval Zanella
2020-10-01 16:34 ` [PATCH 24/28] elf: Implement a string table for ldconfig, with tail merging Florian Weimer
2020-10-20 14:25 ` Adhemerval Zanella
2020-10-30 17:08 ` Florian Weimer
2020-11-03 13:05 ` Adhemerval Zanella
2020-11-03 15:29 ` Florian Weimer
2020-10-01 16:34 ` [PATCH 25/28] elf: Implement tail merging of strings in ldconfig Florian Weimer
2020-10-22 21:08 ` Adhemerval Zanella
2020-10-30 17:36 ` Florian Weimer
2020-10-01 16:34 ` [PATCH 26/28] elf: In ldconfig, extract the new_sub_entry function from search_dir Florian Weimer
2020-10-27 13:15 ` Adhemerval Zanella
2020-10-01 16:34 ` [PATCH 27/28] elf: Process glibc-hwcaps subdirectories in ldconfig Florian Weimer
2020-10-27 17:28 ` Adhemerval Zanella [this message]
2020-11-04 11:57 ` Florian Weimer
2020-10-01 16:34 ` [PATCH 28/28] elf: Add glibc-hwcaps subdirectory support to ld.so cache processing Florian Weimer
2020-10-01 16:50 ` [PATCH 00/28] glibc-hwcaps support H.J. Lu
2020-10-01 16:54 ` Florian Weimer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=ceb0e27b-f30e-890a-a188-8f886e5d9852@linaro.org \
--to=adhemerval.zanella@linaro.org \
--cc=fweimer@redhat.com \
--cc=libc-alpha@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).