Update INSTALL with package versions that are known to work
[glibc.git] / elf / cache.c
blobc01d30207218573fa6e47209560e561de1d1998e
1 /* Copyright (C) 1999-2021 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Andreas Jaeger <aj@suse.de>, 1999.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, see <https://www.gnu.org/licenses/>. */
18 #include <assert.h>
19 #include <errno.h>
20 #include <error.h>
21 #include <dirent.h>
22 #include <inttypes.h>
23 #include <libgen.h>
24 #include <libintl.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <unistd.h>
29 #include <stdint.h>
30 #include <sys/fcntl.h>
31 #include <sys/mman.h>
32 #include <sys/param.h>
33 #include <sys/stat.h>
34 #include <sys/types.h>
36 #include <ldconfig.h>
37 #include <dl-cache.h>
38 #include <version.h>
39 #include <stringtable.h>
41 /* Used to store library names, paths, and other strings. */
42 static struct stringtable strings;
44 /* Keeping track of "glibc-hwcaps" subdirectories. During cache
45 construction, a linear search by name is performed to deduplicate
46 entries. */
47 struct glibc_hwcaps_subdirectory
49 struct glibc_hwcaps_subdirectory *next;
51 /* Interned string with the subdirectory name. */
52 struct stringtable_entry *name;
54 /* Array index in the cache_extension_tag_glibc_hwcaps section in
55 the stored cached file. This is computed after all the
56 subdirectories have been processed, so that subdirectory names in
57 the extension section can be sorted. */
58 uint32_t section_index;
60 /* True if the subdirectory is actually used for anything. */
61 bool used;
64 const char *
65 glibc_hwcaps_subdirectory_name (const struct glibc_hwcaps_subdirectory *dir)
67 return dir->name->string;
70 /* Linked list of known hwcaps subdirecty names. */
71 static struct glibc_hwcaps_subdirectory *hwcaps;
73 struct glibc_hwcaps_subdirectory *
74 new_glibc_hwcaps_subdirectory (const char *name)
76 struct stringtable_entry *name_interned = stringtable_add (&strings, name);
77 for (struct glibc_hwcaps_subdirectory *p = hwcaps; p != NULL; p = p->next)
78 if (p->name == name_interned)
79 return p;
80 struct glibc_hwcaps_subdirectory *p = xmalloc (sizeof (*p));
81 p->next = hwcaps;
82 p->name = name_interned;
83 p->section_index = 0;
84 p->used = false;
85 hwcaps = p;
86 return p;
89 /* Helper for sorting struct glibc_hwcaps_subdirectory elements by
90 name. */
91 static int
92 assign_glibc_hwcaps_indices_compare (const void *l, const void *r)
94 const struct glibc_hwcaps_subdirectory *left
95 = *(struct glibc_hwcaps_subdirectory **)l;
96 const struct glibc_hwcaps_subdirectory *right
97 = *(struct glibc_hwcaps_subdirectory **)r;
98 return strcmp (glibc_hwcaps_subdirectory_name (left),
99 glibc_hwcaps_subdirectory_name (right));
102 /* Count the number of hwcaps subdirectories which are actually
103 used. */
104 static size_t
105 glibc_hwcaps_count (void)
107 size_t count = 0;
108 for (struct glibc_hwcaps_subdirectory *p = hwcaps; p != NULL; p = p->next)
109 if (p->used)
110 ++count;
111 return count;
114 /* Compute the section_index fields for all */
115 static void
116 assign_glibc_hwcaps_indices (void)
118 /* Convert the linked list into an array, so that we can use qsort.
119 Only copy the subdirectories which are actually used. */
120 size_t count = glibc_hwcaps_count ();
121 struct glibc_hwcaps_subdirectory **array
122 = xmalloc (sizeof (*array) * count);
124 size_t i = 0;
125 for (struct glibc_hwcaps_subdirectory *p = hwcaps; p != NULL; p = p->next)
126 if (p->used)
128 array[i] = p;
129 ++i;
131 assert (i == count);
134 qsort (array, count, sizeof (*array), assign_glibc_hwcaps_indices_compare);
136 /* Assign the array indices. */
137 for (size_t i = 0; i < count; ++i)
138 array[i]->section_index = i;
140 free (array);
143 struct cache_entry
145 struct stringtable_entry *lib; /* Library name. */
146 struct stringtable_entry *path; /* Path to find library. */
147 int flags; /* Flags to indicate kind of library. */
148 unsigned int osversion; /* Required OS version. */
149 unsigned int isa_level; /* Required ISA level. */
150 uint64_t hwcap; /* Important hardware capabilities. */
151 int bits_hwcap; /* Number of bits set in hwcap. */
153 /* glibc-hwcaps subdirectory. If not NULL, hwcap must be zero. */
154 struct glibc_hwcaps_subdirectory *hwcaps;
156 struct cache_entry *next; /* Next entry in list. */
159 /* List of all cache entries. */
160 static struct cache_entry *entries;
162 static const char *flag_descr[] =
163 { "libc4", "ELF", "libc5", "libc6"};
165 /* Print a single entry. */
166 static void
167 print_entry (const char *lib, int flag, unsigned int osversion,
168 uint64_t hwcap, const char *hwcap_string, const char *key)
170 printf ("\t%s (", lib);
171 switch (flag & FLAG_TYPE_MASK)
173 case FLAG_LIBC4:
174 case FLAG_ELF:
175 case FLAG_ELF_LIBC5:
176 case FLAG_ELF_LIBC6:
177 fputs (flag_descr[flag & FLAG_TYPE_MASK], stdout);
178 break;
179 default:
180 fputs (_("unknown"), stdout);
181 break;
183 switch (flag & FLAG_REQUIRED_MASK)
185 case FLAG_SPARC_LIB64:
186 fputs (",64bit", stdout);
187 break;
188 case FLAG_IA64_LIB64:
189 fputs (",IA-64", stdout);
190 break;
191 case FLAG_X8664_LIB64:
192 fputs (",x86-64", stdout);
193 break;
194 case FLAG_S390_LIB64:
195 fputs (",64bit", stdout);
196 break;
197 case FLAG_POWERPC_LIB64:
198 fputs (",64bit", stdout);
199 break;
200 case FLAG_MIPS64_LIBN32:
201 fputs (",N32", stdout);
202 break;
203 case FLAG_MIPS64_LIBN64:
204 fputs (",64bit", stdout);
205 break;
206 case FLAG_X8664_LIBX32:
207 fputs (",x32", stdout);
208 break;
209 case FLAG_ARM_LIBHF:
210 fputs (",hard-float", stdout);
211 break;
212 case FLAG_AARCH64_LIB64:
213 fputs (",AArch64", stdout);
214 break;
215 /* Uses the ARM soft-float ABI. */
216 case FLAG_ARM_LIBSF:
217 fputs (",soft-float", stdout);
218 break;
219 case FLAG_MIPS_LIB32_NAN2008:
220 fputs (",nan2008", stdout);
221 break;
222 case FLAG_MIPS64_LIBN32_NAN2008:
223 fputs (",N32,nan2008", stdout);
224 break;
225 case FLAG_MIPS64_LIBN64_NAN2008:
226 fputs (",64bit,nan2008", stdout);
227 break;
228 case FLAG_RISCV_FLOAT_ABI_SOFT:
229 fputs (",soft-float", stdout);
230 break;
231 case FLAG_RISCV_FLOAT_ABI_DOUBLE:
232 fputs (",double-float", stdout);
233 break;
234 case 0:
235 break;
236 default:
237 printf (",%d", flag & FLAG_REQUIRED_MASK);
238 break;
240 if (hwcap_string != NULL)
241 printf (", hwcap: \"%s\"", hwcap_string);
242 else if (hwcap != 0)
243 printf (", hwcap: %#.16" PRIx64, hwcap);
244 if (osversion != 0)
246 static const char *const abi_tag_os[] =
248 [0] = "Linux",
249 [1] = "Hurd",
250 [2] = "Solaris",
251 [3] = "FreeBSD",
252 [4] = "kNetBSD",
253 [5] = "Syllable",
254 [6] = N_("Unknown OS")
256 #define MAXTAG (sizeof abi_tag_os / sizeof abi_tag_os[0] - 1)
257 unsigned int os = osversion >> 24;
259 printf (_(", OS ABI: %s %d.%d.%d"),
260 _(abi_tag_os[os > MAXTAG ? MAXTAG : os]),
261 (osversion >> 16) & 0xff,
262 (osversion >> 8) & 0xff,
263 osversion & 0xff);
265 printf (") => %s\n", key);
268 /* Returns the string with the name of the glibcs-hwcaps subdirectory
269 associated with ENTRY->hwcap. file_base must be the base address
270 for string table indices. */
271 static const char *
272 glibc_hwcaps_string (struct cache_extension_all_loaded *ext,
273 const void *file_base, size_t file_size,
274 struct file_entry_new *entry)
276 const uint32_t *hwcaps_array
277 = ext->sections[cache_extension_tag_glibc_hwcaps].base;
278 if (dl_cache_hwcap_extension (entry) && hwcaps_array != NULL)
280 uint32_t index = (uint32_t) entry->hwcap;
281 if (index < ext->sections[cache_extension_tag_glibc_hwcaps].size / 4)
283 uint32_t string_table_index = hwcaps_array[index];
284 if (string_table_index < file_size)
285 return file_base + string_table_index;
288 return NULL;
291 /* Print an error and exit if the new-file cache is internally
292 inconsistent. */
293 static void
294 check_new_cache (struct cache_file_new *cache)
296 if (! cache_file_new_matches_endian (cache))
297 error (EXIT_FAILURE, 0, _("Cache file has wrong endianness.\n"));
300 /* Print the extension information in *EXT. */
301 static void
302 print_extensions (struct cache_extension_all_loaded *ext)
304 if (ext->sections[cache_extension_tag_generator].base != NULL)
306 fputs (_("Cache generated by: "), stdout);
307 fwrite (ext->sections[cache_extension_tag_generator].base, 1,
308 ext->sections[cache_extension_tag_generator].size, stdout);
309 putchar ('\n');
313 /* Print the whole cache file, if a file contains the new cache format
314 hidden in the old one, print the contents of the new format. */
315 void
316 print_cache (const char *cache_name)
318 int fd = open (cache_name, O_RDONLY);
319 if (fd < 0)
320 error (EXIT_FAILURE, errno, _("Can't open cache file %s\n"), cache_name);
322 struct stat64 st;
323 if (__fstat64 (fd, &st) < 0
324 /* No need to map the file if it is empty. */
325 || st.st_size == 0)
327 close (fd);
328 return;
331 struct cache_file *cache
332 = mmap (NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
333 if (cache == MAP_FAILED)
334 error (EXIT_FAILURE, errno, _("mmap of cache file failed.\n"));
336 size_t cache_size = st.st_size;
337 if (cache_size < sizeof (struct cache_file))
338 error (EXIT_FAILURE, 0, _("File is not a cache file.\n"));
340 struct cache_file_new *cache_new = NULL;
341 const char *cache_data;
342 int format = 0;
344 if (memcmp (cache->magic, CACHEMAGIC, sizeof CACHEMAGIC - 1))
346 /* This can only be the new format without the old one. */
347 cache_new = (struct cache_file_new *) cache;
349 if (memcmp (cache_new->magic, CACHEMAGIC_NEW, sizeof CACHEMAGIC_NEW - 1)
350 || memcmp (cache_new->version, CACHE_VERSION,
351 sizeof CACHE_VERSION - 1))
352 error (EXIT_FAILURE, 0, _("File is not a cache file.\n"));
353 check_new_cache (cache_new);
354 format = 1;
355 /* This is where the strings start. */
356 cache_data = (const char *) cache_new;
358 else
360 /* Check for corruption, avoiding overflow. */
361 if ((cache_size - sizeof (struct cache_file)) / sizeof (struct file_entry)
362 < cache->nlibs)
363 error (EXIT_FAILURE, 0, _("File is not a cache file.\n"));
365 size_t offset = ALIGN_CACHE (sizeof (struct cache_file)
366 + (cache->nlibs
367 * sizeof (struct file_entry)));
368 /* This is where the strings start. */
369 cache_data = (const char *) &cache->libs[cache->nlibs];
371 /* Check for a new cache embedded in the old format. */
372 if (cache_size
373 > (offset + sizeof (struct cache_file_new)))
376 cache_new = (struct cache_file_new *) ((void *)cache + offset);
378 if (memcmp (cache_new->magic, CACHEMAGIC_NEW,
379 sizeof CACHEMAGIC_NEW - 1) == 0
380 && memcmp (cache_new->version, CACHE_VERSION,
381 sizeof CACHE_VERSION - 1) == 0)
383 check_new_cache (cache_new);
384 cache_data = (const char *) cache_new;
385 format = 1;
390 if (format == 0)
392 printf (_("%d libs found in cache `%s'\n"), cache->nlibs, cache_name);
394 /* Print everything. */
395 for (unsigned int i = 0; i < cache->nlibs; i++)
396 print_entry (cache_data + cache->libs[i].key,
397 cache->libs[i].flags, 0, 0, NULL,
398 cache_data + cache->libs[i].value);
400 else if (format == 1)
402 struct cache_extension_all_loaded ext;
403 if (!cache_extension_load (cache_new, cache, cache_size, &ext))
404 error (EXIT_FAILURE, 0,
405 _("Malformed extension data in cache file %s\n"), cache_name);
407 printf (_("%d libs found in cache `%s'\n"),
408 cache_new->nlibs, cache_name);
410 /* Print everything. */
411 for (unsigned int i = 0; i < cache_new->nlibs; i++)
413 const char *hwcaps_string
414 = glibc_hwcaps_string (&ext, cache, cache_size,
415 &cache_new->libs[i]);
416 print_entry (cache_data + cache_new->libs[i].key,
417 cache_new->libs[i].flags,
418 cache_new->libs[i].osversion,
419 cache_new->libs[i].hwcap, hwcaps_string,
420 cache_data + cache_new->libs[i].value);
422 print_extensions (&ext);
424 /* Cleanup. */
425 munmap (cache, cache_size);
426 close (fd);
429 /* Initialize cache data structures. */
430 void
431 init_cache (void)
433 entries = NULL;
436 static int
437 compare (const struct cache_entry *e1, const struct cache_entry *e2)
439 /* We need to swap entries here to get the correct sort order. */
440 int res = _dl_cache_libcmp (e2->lib->string, e1->lib->string);
441 if (res == 0)
443 if (e1->flags < e2->flags)
444 return 1;
445 else if (e1->flags > e2->flags)
446 return -1;
447 /* Keep the glibc-hwcaps extension entries before the regular
448 entries, and sort them by their names. search_cache in
449 dl-cache.c stops searching once the first non-extension entry
450 is found, so the extension entries need to come first. */
451 else if (e1->hwcaps != NULL && e2->hwcaps == NULL)
452 return -1;
453 else if (e1->hwcaps == NULL && e2->hwcaps != NULL)
454 return 1;
455 else if (e1->hwcaps != NULL && e2->hwcaps != NULL)
457 res = strcmp (glibc_hwcaps_subdirectory_name (e1->hwcaps),
458 glibc_hwcaps_subdirectory_name (e2->hwcaps));
459 if (res != 0)
460 return res;
462 /* Sort by most specific hwcap. */
463 if (e2->bits_hwcap > e1->bits_hwcap)
464 return 1;
465 else if (e2->bits_hwcap < e1->bits_hwcap)
466 return -1;
467 else if (e2->hwcap > e1->hwcap)
468 return 1;
469 else if (e2->hwcap < e1->hwcap)
470 return -1;
471 if (e2->osversion > e1->osversion)
472 return 1;
473 if (e2->osversion < e1->osversion)
474 return -1;
476 return res;
479 /* Size of the cache extension directory. All tags are assumed to be
480 present. */
481 enum
483 cache_extension_size = (offsetof (struct cache_extension, sections)
484 + (cache_extension_count
485 * sizeof (struct cache_extension_section)))
488 /* Write the cache extensions to FD. The string table is shifted by
489 STRING_TABLE_OFFSET. The extension directory is assumed to be
490 located at CACHE_EXTENSION_OFFSET. assign_glibc_hwcaps_indices
491 must have been called. */
492 static void
493 write_extensions (int fd, uint32_t str_offset,
494 uint32_t cache_extension_offset)
496 assert ((cache_extension_offset % 4) == 0);
498 /* The length and contents of the glibc-hwcaps section. */
499 uint32_t hwcaps_count = glibc_hwcaps_count ();
500 uint32_t hwcaps_offset = cache_extension_offset + cache_extension_size;
501 uint32_t hwcaps_size = hwcaps_count * sizeof (uint32_t);
502 uint32_t *hwcaps_array = xmalloc (hwcaps_size);
503 for (struct glibc_hwcaps_subdirectory *p = hwcaps; p != NULL; p = p->next)
504 if (p->used)
505 hwcaps_array[p->section_index] = str_offset + p->name->offset;
507 /* This is the offset of the generator string. */
508 uint32_t generator_offset = hwcaps_offset;
509 if (hwcaps_count == 0)
510 /* There is no section for the hwcaps subdirectories. */
511 generator_offset -= sizeof (struct cache_extension_section);
512 else
513 /* The string table indices for the hwcaps subdirectories shift
514 the generator string backwards. */
515 generator_offset += hwcaps_size;
517 struct cache_extension *ext = xmalloc (cache_extension_size);
518 ext->magic = cache_extension_magic;
520 /* Extension index current being filled. */
521 size_t xid = 0;
523 const char *generator
524 = "ldconfig " PKGVERSION RELEASE " release version " VERSION;
525 ext->sections[xid].tag = cache_extension_tag_generator;
526 ext->sections[xid].flags = 0;
527 ext->sections[xid].offset = generator_offset;
528 ext->sections[xid].size = strlen (generator);
530 if (hwcaps_count > 0)
532 ++xid;
533 ext->sections[xid].tag = cache_extension_tag_glibc_hwcaps;
534 ext->sections[xid].flags = 0;
535 ext->sections[xid].offset = hwcaps_offset;
536 ext->sections[xid].size = hwcaps_size;
539 ++xid;
540 ext->count = xid;
541 assert (xid <= cache_extension_count);
543 size_t ext_size = (offsetof (struct cache_extension, sections)
544 + xid * sizeof (struct cache_extension_section));
545 if (write (fd, ext, ext_size) != ext_size
546 || write (fd, hwcaps_array, hwcaps_size) != hwcaps_size
547 || write (fd, generator, strlen (generator)) != strlen (generator))
548 error (EXIT_FAILURE, errno, _("Writing of cache extension data failed"));
550 free (ext);
553 /* Compute the hwcap value from ENTRY. */
554 static inline uint64_t
555 compute_hwcap_value (struct cache_entry *entry)
557 if (entry->isa_level > DL_CACHE_HWCAP_ISA_LEVEL_MASK)
558 error (EXIT_FAILURE, 0, _("%s: ISA level is too high (%d > %d)"),
559 entry->path->string, entry->isa_level,
560 DL_CACHE_HWCAP_ISA_LEVEL_MASK);
561 return (DL_CACHE_HWCAP_EXTENSION
562 | (((uint64_t) entry->isa_level) << 32)
563 | entry->hwcaps->section_index);
566 /* Save the contents of the cache. */
567 void
568 save_cache (const char *cache_name)
570 /* The cache entries are sorted already, save them in this order. */
572 assign_glibc_hwcaps_indices ();
574 struct cache_entry *entry;
575 /* Number of cache entries. */
576 int cache_entry_count = 0;
577 /* The old format doesn't contain hwcap entries and doesn't contain
578 libraries in subdirectories with hwcaps entries. Count therefore
579 also all entries with hwcap == 0. */
580 int cache_entry_old_count = 0;
582 for (entry = entries; entry != NULL; entry = entry->next)
584 ++cache_entry_count;
585 if (entry->hwcap == 0)
586 ++cache_entry_old_count;
589 struct stringtable_finalized strings_finalized;
590 stringtable_finalize (&strings, &strings_finalized);
592 /* Create the on disk cache structure. */
593 struct cache_file *file_entries = NULL;
594 size_t file_entries_size = 0;
596 if (opt_format != opt_format_new)
598 /* struct cache_file_new is 64-bit aligned on some arches while
599 only 32-bit aligned on other arches. Duplicate last old
600 cache entry so that new cache in ld.so.cache can be used by
601 both. */
602 if (opt_format != opt_format_old)
603 cache_entry_old_count = (cache_entry_old_count + 1) & ~1;
605 /* And the list of all entries in the old format. */
606 file_entries_size = sizeof (struct cache_file)
607 + cache_entry_old_count * sizeof (struct file_entry);
608 file_entries = xmalloc (file_entries_size);
610 /* Fill in the header. */
611 memset (file_entries, '\0', sizeof (struct cache_file));
612 memcpy (file_entries->magic, CACHEMAGIC, sizeof CACHEMAGIC - 1);
614 file_entries->nlibs = cache_entry_old_count;
617 struct cache_file_new *file_entries_new = NULL;
618 size_t file_entries_new_size = 0;
620 if (opt_format != opt_format_old)
622 /* And the list of all entries in the new format. */
623 file_entries_new_size = sizeof (struct cache_file_new)
624 + cache_entry_count * sizeof (struct file_entry_new);
625 file_entries_new = xmalloc (file_entries_new_size);
627 /* Fill in the header. */
628 memset (file_entries_new, '\0', sizeof (struct cache_file_new));
629 memcpy (file_entries_new->magic, CACHEMAGIC_NEW,
630 sizeof CACHEMAGIC_NEW - 1);
631 memcpy (file_entries_new->version, CACHE_VERSION,
632 sizeof CACHE_VERSION - 1);
634 file_entries_new->nlibs = cache_entry_count;
635 file_entries_new->len_strings = strings_finalized.size;
636 file_entries_new->flags = cache_file_new_flags_endian_current;
639 /* Pad for alignment of cache_file_new. */
640 size_t pad = ALIGN_CACHE (file_entries_size) - file_entries_size;
642 /* If we have both formats, we hide the new format in the strings
643 table, we have to adjust all string indices for this so that
644 old libc5/glibc 2 dynamic linkers just ignore them. */
645 unsigned int str_offset;
646 if (opt_format != opt_format_old)
647 str_offset = file_entries_new_size;
648 else
649 str_offset = 0;
651 /* An array for all strings. */
652 int idx_old;
653 int idx_new;
655 for (idx_old = 0, idx_new = 0, entry = entries; entry != NULL;
656 entry = entry->next, ++idx_new)
658 if (opt_format != opt_format_new && entry->hwcap == 0)
660 file_entries->libs[idx_old].flags = entry->flags;
661 /* XXX: Actually we can optimize here and remove duplicates. */
662 file_entries->libs[idx_old].key = str_offset + pad;
663 file_entries->libs[idx_new].key = str_offset + entry->lib->offset;
664 file_entries->libs[idx_new].value
665 = str_offset + entry->path->offset;
667 if (opt_format != opt_format_old)
669 /* We could subtract file_entries_new_size from str_offset -
670 not doing so makes the code easier, the string table
671 always begins at the beginning of the new cache
672 struct. */
673 file_entries_new->libs[idx_new].flags = entry->flags;
674 file_entries_new->libs[idx_new].osversion = entry->osversion;
675 if (entry->hwcaps == NULL)
676 file_entries_new->libs[idx_new].hwcap = entry->hwcap;
677 else
678 file_entries_new->libs[idx_new].hwcap
679 = compute_hwcap_value (entry);
680 file_entries_new->libs[idx_new].key
681 = str_offset + entry->lib->offset;
682 file_entries_new->libs[idx_new].value
683 = str_offset + entry->path->offset;
686 /* Ignore entries with hwcap for old format. */
687 if (entry->hwcap == 0)
688 ++idx_old;
691 /* Duplicate last old cache entry if needed. */
692 if (opt_format != opt_format_new
693 && idx_old < cache_entry_old_count)
694 file_entries->libs[idx_old] = file_entries->libs[idx_old - 1];
696 /* Compute the location of the extension directory. This
697 implementation puts the directory after the string table. The
698 size computation matches the write calls below. The extension
699 directory does not exist with format 0, so the value does not
700 matter. */
701 uint32_t extension_offset = 0;
702 if (opt_format != opt_format_new)
703 extension_offset += file_entries_size;
704 if (opt_format != opt_format_old)
706 if (opt_format != opt_format_new)
707 extension_offset += pad;
708 extension_offset += file_entries_new_size;
710 extension_offset += strings_finalized.size;
711 extension_offset = roundup (extension_offset, 4); /* Provide alignment. */
712 if (opt_format != opt_format_old)
713 file_entries_new->extension_offset = extension_offset;
715 /* Write out the cache. */
717 /* Write cache first to a temporary file and rename it later. */
718 char *temp_name = xmalloc (strlen (cache_name) + 2);
719 sprintf (temp_name, "%s~", cache_name);
721 /* Create file. */
722 int fd = open (temp_name, O_CREAT|O_WRONLY|O_TRUNC|O_NOFOLLOW,
723 S_IRUSR|S_IWUSR);
724 if (fd < 0)
725 error (EXIT_FAILURE, errno, _("Can't create temporary cache file %s"),
726 temp_name);
728 /* Write contents. */
729 if (opt_format != opt_format_new)
731 if (write (fd, file_entries, file_entries_size)
732 != (ssize_t) file_entries_size)
733 error (EXIT_FAILURE, errno, _("Writing of cache data failed"));
735 if (opt_format != opt_format_old)
737 /* Align cache. */
738 if (opt_format != opt_format_new)
740 char zero[pad];
741 memset (zero, '\0', pad);
742 if (write (fd, zero, pad) != (ssize_t) pad)
743 error (EXIT_FAILURE, errno, _("Writing of cache data failed"));
745 if (write (fd, file_entries_new, file_entries_new_size)
746 != (ssize_t) file_entries_new_size)
747 error (EXIT_FAILURE, errno, _("Writing of cache data failed"));
750 if (write (fd, strings_finalized.strings, strings_finalized.size)
751 != (ssize_t) strings_finalized.size)
752 error (EXIT_FAILURE, errno, _("Writing of cache data failed"));
754 if (opt_format != opt_format_old)
756 /* Align file position to 4. */
757 off64_t old_offset = lseek64 (fd, extension_offset, SEEK_SET);
758 assert ((unsigned long long int) (extension_offset - old_offset) < 4);
759 write_extensions (fd, str_offset, extension_offset);
762 /* Make sure user can always read cache file */
763 if (chmod (temp_name, S_IROTH|S_IRGRP|S_IRUSR|S_IWUSR))
764 error (EXIT_FAILURE, errno,
765 _("Changing access rights of %s to %#o failed"), temp_name,
766 S_IROTH|S_IRGRP|S_IRUSR|S_IWUSR);
768 /* Make sure that data is written to disk. */
769 if (fsync (fd) != 0 || close (fd) != 0)
770 error (EXIT_FAILURE, errno, _("Writing of cache data failed"));
772 /* Move temporary to its final location. */
773 if (rename (temp_name, cache_name))
774 error (EXIT_FAILURE, errno, _("Renaming of %s to %s failed"), temp_name,
775 cache_name);
777 /* Free all allocated memory. */
778 free (file_entries_new);
779 free (file_entries);
780 free (strings_finalized.strings);
782 while (entries)
784 entry = entries;
785 entries = entries->next;
786 free (entry);
791 /* Add one library to the cache. */
792 void
793 add_to_cache (const char *path, const char *filename, const char *soname,
794 int flags, unsigned int osversion,
795 unsigned int isa_level, uint64_t hwcap,
796 struct glibc_hwcaps_subdirectory *hwcaps)
798 struct cache_entry *new_entry = xmalloc (sizeof (*new_entry));
800 struct stringtable_entry *path_interned;
802 char *p;
803 if (asprintf (&p, "%s/%s", path, filename) < 0)
804 error (EXIT_FAILURE, errno, _("Could not create library path"));
805 path_interned = stringtable_add (&strings, p);
806 free (p);
809 new_entry->lib = stringtable_add (&strings, soname);
810 new_entry->path = path_interned;
811 new_entry->flags = flags;
812 new_entry->osversion = osversion;
813 new_entry->isa_level = isa_level;
814 new_entry->hwcap = hwcap;
815 new_entry->hwcaps = hwcaps;
816 new_entry->bits_hwcap = 0;
818 if (hwcaps != NULL)
820 assert (hwcap == 0);
821 hwcaps->used = true;
824 /* Count the number of bits set in the masked value. */
825 for (size_t i = 0;
826 (~((1ULL << i) - 1) & hwcap) != 0 && i < 8 * sizeof (hwcap); ++i)
827 if ((hwcap & (1ULL << i)) != 0)
828 ++new_entry->bits_hwcap;
831 /* Keep the list sorted - search for right place to insert. */
832 struct cache_entry *ptr = entries;
833 struct cache_entry *prev = entries;
834 while (ptr != NULL)
836 if (compare (ptr, new_entry) > 0)
837 break;
838 prev = ptr;
839 ptr = ptr->next;
841 /* Is this the first entry? */
842 if (ptr == entries)
844 new_entry->next = entries;
845 entries = new_entry;
847 else
849 new_entry->next = prev->next;
850 prev->next = new_entry;
855 /* Auxiliary cache. */
857 struct aux_cache_entry_id
859 uint64_t ino;
860 uint64_t ctime;
861 uint64_t size;
862 uint64_t dev;
865 struct aux_cache_entry
867 struct aux_cache_entry_id id;
868 int flags;
869 unsigned int osversion;
870 unsigned int isa_level;
871 int used;
872 char *soname;
873 struct aux_cache_entry *next;
876 #define AUX_CACHEMAGIC "glibc-ld.so.auxcache-1.0"
878 struct aux_cache_file_entry
880 struct aux_cache_entry_id id; /* Unique id of entry. */
881 int32_t flags; /* This is 1 for an ELF library. */
882 uint32_t soname; /* String table indice. */
883 uint32_t osversion; /* Required OS version. */
884 uint32_t isa_level; /* Required ISA level. */
887 /* ldconfig maintains an auxiliary cache file that allows
888 only reading those libraries that have changed since the last iteration.
889 For this for each library some information is cached in the auxiliary
890 cache. */
891 struct aux_cache_file
893 char magic[sizeof AUX_CACHEMAGIC - 1];
894 uint32_t nlibs; /* Number of entries. */
895 uint32_t len_strings; /* Size of string table. */
896 struct aux_cache_file_entry libs[0]; /* Entries describing libraries. */
897 /* After this the string table of size len_strings is found. */
900 static const unsigned int primes[] =
902 1021, 2039, 4093, 8191, 16381, 32749, 65521, 131071, 262139,
903 524287, 1048573, 2097143, 4194301, 8388593, 16777213, 33554393,
904 67108859, 134217689, 268435399, 536870909, 1073741789, 2147483647
907 static size_t aux_hash_size;
908 static struct aux_cache_entry **aux_hash;
910 /* Simplistic hash function for aux_cache_entry_id. */
911 static unsigned int
912 aux_cache_entry_id_hash (struct aux_cache_entry_id *id)
914 uint64_t ret = ((id->ino * 11 + id->ctime) * 11 + id->size) * 11 + id->dev;
915 return ret ^ (ret >> 32);
918 static size_t nextprime (size_t x)
920 for (unsigned int i = 0; i < sizeof (primes) / sizeof (primes[0]); ++i)
921 if (primes[i] >= x)
922 return primes[i];
923 return x;
926 void
927 init_aux_cache (void)
929 aux_hash_size = primes[3];
930 aux_hash = xcalloc (aux_hash_size, sizeof (struct aux_cache_entry *));
934 search_aux_cache (struct stat64 *stat_buf, int *flags,
935 unsigned int *osversion, unsigned int *isa_level,
936 char **soname)
938 struct aux_cache_entry_id id;
939 id.ino = (uint64_t) stat_buf->st_ino;
940 id.ctime = (uint64_t) stat_buf->st_ctime;
941 id.size = (uint64_t) stat_buf->st_size;
942 id.dev = (uint64_t) stat_buf->st_dev;
944 unsigned int hash = aux_cache_entry_id_hash (&id);
945 struct aux_cache_entry *entry;
946 for (entry = aux_hash[hash % aux_hash_size]; entry; entry = entry->next)
947 if (id.ino == entry->id.ino
948 && id.ctime == entry->id.ctime
949 && id.size == entry->id.size
950 && id.dev == entry->id.dev)
952 *flags = entry->flags;
953 *osversion = entry->osversion;
954 *isa_level = entry->isa_level;
955 if (entry->soname != NULL)
956 *soname = xstrdup (entry->soname);
957 else
958 *soname = NULL;
959 entry->used = 1;
960 return 1;
963 return 0;
966 static void
967 insert_to_aux_cache (struct aux_cache_entry_id *id, int flags,
968 unsigned int osversion, unsigned int isa_level,
969 const char *soname, int used)
971 size_t hash = aux_cache_entry_id_hash (id) % aux_hash_size;
972 struct aux_cache_entry *entry;
973 for (entry = aux_hash[hash]; entry; entry = entry->next)
974 if (id->ino == entry->id.ino
975 && id->ctime == entry->id.ctime
976 && id->size == entry->id.size
977 && id->dev == entry->id.dev)
978 abort ();
980 size_t len = soname ? strlen (soname) + 1 : 0;
981 entry = xmalloc (sizeof (struct aux_cache_entry) + len);
982 entry->id = *id;
983 entry->flags = flags;
984 entry->osversion = osversion;
985 entry->isa_level = isa_level;
986 entry->used = used;
987 if (soname != NULL)
988 entry->soname = memcpy ((char *) (entry + 1), soname, len);
989 else
990 entry->soname = NULL;
991 entry->next = aux_hash[hash];
992 aux_hash[hash] = entry;
995 void
996 add_to_aux_cache (struct stat64 *stat_buf, int flags,
997 unsigned int osversion, unsigned int isa_level,
998 const char *soname)
1000 struct aux_cache_entry_id id;
1001 id.ino = (uint64_t) stat_buf->st_ino;
1002 id.ctime = (uint64_t) stat_buf->st_ctime;
1003 id.size = (uint64_t) stat_buf->st_size;
1004 id.dev = (uint64_t) stat_buf->st_dev;
1005 insert_to_aux_cache (&id, flags, osversion, isa_level, soname, 1);
1008 /* Load auxiliary cache to search for unchanged entries. */
1009 void
1010 load_aux_cache (const char *aux_cache_name)
1012 int fd = open (aux_cache_name, O_RDONLY);
1013 if (fd < 0)
1015 init_aux_cache ();
1016 return;
1019 struct stat64 st;
1020 if (__fstat64 (fd, &st) < 0 || st.st_size < sizeof (struct aux_cache_file))
1022 close (fd);
1023 init_aux_cache ();
1024 return;
1027 size_t aux_cache_size = st.st_size;
1028 struct aux_cache_file *aux_cache
1029 = mmap (NULL, aux_cache_size, PROT_READ, MAP_PRIVATE, fd, 0);
1030 if (aux_cache == MAP_FAILED
1031 || aux_cache_size < sizeof (struct aux_cache_file)
1032 || memcmp (aux_cache->magic, AUX_CACHEMAGIC, sizeof AUX_CACHEMAGIC - 1)
1033 || aux_cache_size != (sizeof (struct aux_cache_file)
1034 + aux_cache->nlibs * sizeof (struct aux_cache_file_entry)
1035 + aux_cache->len_strings))
1037 close (fd);
1038 init_aux_cache ();
1039 return;
1042 aux_hash_size = nextprime (aux_cache->nlibs);
1043 aux_hash = xcalloc (aux_hash_size, sizeof (struct aux_cache_entry *));
1045 const char *aux_cache_data
1046 = (const char *) &aux_cache->libs[aux_cache->nlibs];
1047 for (unsigned int i = 0; i < aux_cache->nlibs; ++i)
1048 insert_to_aux_cache (&aux_cache->libs[i].id,
1049 aux_cache->libs[i].flags,
1050 aux_cache->libs[i].osversion,
1051 aux_cache->libs[i].isa_level,
1052 aux_cache->libs[i].soname == 0
1053 ? NULL : aux_cache_data + aux_cache->libs[i].soname,
1056 munmap (aux_cache, aux_cache_size);
1057 close (fd);
1060 /* Save the contents of the auxiliary cache. */
1061 void
1062 save_aux_cache (const char *aux_cache_name)
1064 /* Count the length of all sonames. We start with empty string. */
1065 size_t total_strlen = 1;
1066 /* Number of cache entries. */
1067 int cache_entry_count = 0;
1069 for (size_t i = 0; i < aux_hash_size; ++i)
1070 for (struct aux_cache_entry *entry = aux_hash[i];
1071 entry != NULL; entry = entry->next)
1072 if (entry->used)
1074 ++cache_entry_count;
1075 if (entry->soname != NULL)
1076 total_strlen += strlen (entry->soname) + 1;
1079 /* Auxiliary cache. */
1080 size_t file_entries_size
1081 = sizeof (struct aux_cache_file)
1082 + cache_entry_count * sizeof (struct aux_cache_file_entry);
1083 struct aux_cache_file *file_entries
1084 = xmalloc (file_entries_size + total_strlen);
1086 /* Fill in the header of the auxiliary cache. */
1087 memset (file_entries, '\0', sizeof (struct aux_cache_file));
1088 memcpy (file_entries->magic, AUX_CACHEMAGIC, sizeof AUX_CACHEMAGIC - 1);
1090 file_entries->nlibs = cache_entry_count;
1091 file_entries->len_strings = total_strlen;
1093 /* Initial String offset for auxiliary cache is always after the
1094 special empty string. */
1095 unsigned int str_offset = 1;
1097 /* An array for all strings. */
1098 char *str = (char *) file_entries + file_entries_size;
1099 *str++ = '\0';
1101 size_t idx = 0;
1102 for (size_t i = 0; i < aux_hash_size; ++i)
1103 for (struct aux_cache_entry *entry = aux_hash[i];
1104 entry != NULL; entry = entry->next)
1105 if (entry->used)
1107 file_entries->libs[idx].id = entry->id;
1108 file_entries->libs[idx].flags = entry->flags;
1109 if (entry->soname == NULL)
1110 file_entries->libs[idx].soname = 0;
1111 else
1113 file_entries->libs[idx].soname = str_offset;
1115 size_t len = strlen (entry->soname) + 1;
1116 str = mempcpy (str, entry->soname, len);
1117 str_offset += len;
1119 file_entries->libs[idx].osversion = entry->osversion;
1120 file_entries->libs[idx++].isa_level = entry->isa_level;
1123 /* Write out auxiliary cache file. */
1124 /* Write auxiliary cache first to a temporary file and rename it later. */
1126 char *temp_name = xmalloc (strlen (aux_cache_name) + 2);
1127 sprintf (temp_name, "%s~", aux_cache_name);
1129 /* Check that directory exists and create if needed. */
1130 char *dir = strdupa (aux_cache_name);
1131 dir = dirname (dir);
1133 struct stat64 st;
1134 if (stat64 (dir, &st) < 0)
1136 if (mkdir (dir, 0700) < 0)
1137 goto out_fail;
1140 /* Create file. */
1141 int fd = open (temp_name, O_CREAT|O_WRONLY|O_TRUNC|O_NOFOLLOW,
1142 S_IRUSR|S_IWUSR);
1143 if (fd < 0)
1144 goto out_fail;
1146 if (write (fd, file_entries, file_entries_size + total_strlen)
1147 != (ssize_t) (file_entries_size + total_strlen)
1148 || fdatasync (fd) != 0
1149 || close (fd) != 0)
1151 unlink (temp_name);
1152 goto out_fail;
1155 /* Move temporary to its final location. */
1156 if (rename (temp_name, aux_cache_name))
1157 unlink (temp_name);
1159 out_fail:
1160 /* Free allocated memory. */
1161 free (temp_name);
1162 free (file_entries);