Use C11 atomics instead of atomic_increment(_val)
[glibc.git] / elf / cache.c
blobf5f3ef8c4db48ed445c439bc57c48bd27d1471fd
1 /* Copyright (C) 1999-2022 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published
6 by the Free Software Foundation; version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, see <https://www.gnu.org/licenses/>. */
17 #include <assert.h>
18 #include <errno.h>
19 #include <error.h>
20 #include <dirent.h>
21 #include <inttypes.h>
22 #include <libgen.h>
23 #include <libintl.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <stdint.h>
29 #include <sys/fcntl.h>
30 #include <sys/mman.h>
31 #include <sys/param.h>
32 #include <sys/stat.h>
33 #include <sys/types.h>
35 #include <ldconfig.h>
36 #include <dl-cache.h>
37 #include <version.h>
38 #include <stringtable.h>
40 /* Used to store library names, paths, and other strings. */
41 static struct stringtable strings;
43 /* Keeping track of "glibc-hwcaps" subdirectories. During cache
44 construction, a linear search by name is performed to deduplicate
45 entries. */
46 struct glibc_hwcaps_subdirectory
48 struct glibc_hwcaps_subdirectory *next;
50 /* Interned string with the subdirectory name. */
51 struct stringtable_entry *name;
53 /* Array index in the cache_extension_tag_glibc_hwcaps section in
54 the stored cached file. This is computed after all the
55 subdirectories have been processed, so that subdirectory names in
56 the extension section can be sorted. */
57 uint32_t section_index;
59 /* True if the subdirectory is actually used for anything. */
60 bool used;
63 const char *
64 glibc_hwcaps_subdirectory_name (const struct glibc_hwcaps_subdirectory *dir)
66 return dir->name->string;
69 /* Linked list of known hwcaps subdirecty names. */
70 static struct glibc_hwcaps_subdirectory *hwcaps;
72 struct glibc_hwcaps_subdirectory *
73 new_glibc_hwcaps_subdirectory (const char *name)
75 struct stringtable_entry *name_interned = stringtable_add (&strings, name);
76 for (struct glibc_hwcaps_subdirectory *p = hwcaps; p != NULL; p = p->next)
77 if (p->name == name_interned)
78 return p;
79 struct glibc_hwcaps_subdirectory *p = xmalloc (sizeof (*p));
80 p->next = hwcaps;
81 p->name = name_interned;
82 p->section_index = 0;
83 p->used = false;
84 hwcaps = p;
85 return p;
88 /* Helper for sorting struct glibc_hwcaps_subdirectory elements by
89 name. */
90 static int
91 assign_glibc_hwcaps_indices_compare (const void *l, const void *r)
93 const struct glibc_hwcaps_subdirectory *left
94 = *(struct glibc_hwcaps_subdirectory **)l;
95 const struct glibc_hwcaps_subdirectory *right
96 = *(struct glibc_hwcaps_subdirectory **)r;
97 return strcmp (glibc_hwcaps_subdirectory_name (left),
98 glibc_hwcaps_subdirectory_name (right));
101 /* Count the number of hwcaps subdirectories which are actually
102 used. */
103 static size_t
104 glibc_hwcaps_count (void)
106 size_t count = 0;
107 for (struct glibc_hwcaps_subdirectory *p = hwcaps; p != NULL; p = p->next)
108 if (p->used)
109 ++count;
110 return count;
113 /* Compute the section_index fields for all */
114 static void
115 assign_glibc_hwcaps_indices (void)
117 /* Convert the linked list into an array, so that we can use qsort.
118 Only copy the subdirectories which are actually used. */
119 size_t count = glibc_hwcaps_count ();
120 struct glibc_hwcaps_subdirectory **array
121 = xmalloc (sizeof (*array) * count);
123 size_t i = 0;
124 for (struct glibc_hwcaps_subdirectory *p = hwcaps; p != NULL; p = p->next)
125 if (p->used)
127 array[i] = p;
128 ++i;
130 assert (i == count);
133 qsort (array, count, sizeof (*array), assign_glibc_hwcaps_indices_compare);
135 /* Assign the array indices. */
136 for (size_t i = 0; i < count; ++i)
137 array[i]->section_index = i;
139 free (array);
142 struct cache_entry
144 struct stringtable_entry *lib; /* Library name. */
145 struct stringtable_entry *path; /* Path to find library. */
146 int flags; /* Flags to indicate kind of library. */
147 unsigned int isa_level; /* Required ISA level. */
148 uint64_t hwcap; /* Important hardware capabilities. */
149 int bits_hwcap; /* Number of bits set in hwcap. */
151 /* glibc-hwcaps subdirectory. If not NULL, hwcap must be zero. */
152 struct glibc_hwcaps_subdirectory *hwcaps;
154 struct cache_entry *next; /* Next entry in list. */
157 /* List of all cache entries. */
158 static struct cache_entry *entries;
160 /* libc4, ELF and libc5 are unsupported. */
161 static const char *flag_descr[] =
162 { "libc4", "ELF", "libc5", "libc6"};
164 /* Print a single entry. */
165 static void
166 print_entry (const char *lib, int flag, uint64_t hwcap,
167 const char *hwcap_string, const char *key)
169 printf ("\t%s (", lib);
170 switch (flag & FLAG_TYPE_MASK)
172 case FLAG_ELF_LIBC6:
173 fputs (flag_descr[flag & FLAG_TYPE_MASK], stdout);
174 break;
175 default:
176 fputs (_("unknown or unsupported flag"), stdout);
177 break;
179 switch (flag & FLAG_REQUIRED_MASK)
181 case FLAG_SPARC_LIB64:
182 fputs (",64bit", stdout);
183 break;
184 case FLAG_IA64_LIB64:
185 fputs (",IA-64", stdout);
186 break;
187 case FLAG_X8664_LIB64:
188 fputs (",x86-64", stdout);
189 break;
190 case FLAG_S390_LIB64:
191 fputs (",64bit", stdout);
192 break;
193 case FLAG_POWERPC_LIB64:
194 fputs (",64bit", stdout);
195 break;
196 case FLAG_MIPS64_LIBN32:
197 fputs (",N32", stdout);
198 break;
199 case FLAG_MIPS64_LIBN64:
200 fputs (",64bit", stdout);
201 break;
202 case FLAG_X8664_LIBX32:
203 fputs (",x32", stdout);
204 break;
205 case FLAG_ARM_LIBHF:
206 fputs (",hard-float", stdout);
207 break;
208 case FLAG_AARCH64_LIB64:
209 fputs (",AArch64", stdout);
210 break;
211 /* Uses the ARM soft-float ABI. */
212 case FLAG_ARM_LIBSF:
213 fputs (",soft-float", stdout);
214 break;
215 case FLAG_MIPS_LIB32_NAN2008:
216 fputs (",nan2008", stdout);
217 break;
218 case FLAG_MIPS64_LIBN32_NAN2008:
219 fputs (",N32,nan2008", stdout);
220 break;
221 case FLAG_MIPS64_LIBN64_NAN2008:
222 fputs (",64bit,nan2008", stdout);
223 break;
224 case FLAG_RISCV_FLOAT_ABI_SOFT:
225 fputs (",soft-float", stdout);
226 break;
227 case FLAG_RISCV_FLOAT_ABI_DOUBLE:
228 fputs (",double-float", stdout);
229 break;
230 case 0:
231 break;
232 default:
233 printf (",%d", flag & FLAG_REQUIRED_MASK);
234 break;
236 if (hwcap_string != NULL)
237 printf (", hwcap: \"%s\"", hwcap_string);
238 else if (hwcap != 0)
239 printf (", hwcap: %#.16" PRIx64, hwcap);
240 printf (") => %s\n", key);
243 /* Returns the string with the name of the glibcs-hwcaps subdirectory
244 associated with ENTRY->hwcap. file_base must be the base address
245 for string table indices. */
246 static const char *
247 glibc_hwcaps_string (struct cache_extension_all_loaded *ext,
248 const void *file_base, size_t file_size,
249 struct file_entry_new *entry)
251 const uint32_t *hwcaps_array
252 = ext->sections[cache_extension_tag_glibc_hwcaps].base;
253 if (dl_cache_hwcap_extension (entry) && hwcaps_array != NULL)
255 uint32_t index = (uint32_t) entry->hwcap;
256 if (index < ext->sections[cache_extension_tag_glibc_hwcaps].size / 4)
258 uint32_t string_table_index = hwcaps_array[index];
259 if (string_table_index < file_size)
260 return file_base + string_table_index;
263 return NULL;
266 /* Print an error and exit if the new-file cache is internally
267 inconsistent. */
268 static void
269 check_new_cache (struct cache_file_new *cache)
271 if (! cache_file_new_matches_endian (cache))
272 error (EXIT_FAILURE, 0, _("Cache file has wrong endianness.\n"));
275 /* Print the extension information in *EXT. */
276 static void
277 print_extensions (struct cache_extension_all_loaded *ext)
279 if (ext->sections[cache_extension_tag_generator].base != NULL)
281 fputs (_("Cache generated by: "), stdout);
282 fwrite (ext->sections[cache_extension_tag_generator].base, 1,
283 ext->sections[cache_extension_tag_generator].size, stdout);
284 putchar ('\n');
288 /* Print the whole cache file, if a file contains the new cache format
289 hidden in the old one, print the contents of the new format. */
290 void
291 print_cache (const char *cache_name)
293 int fd = open (cache_name, O_RDONLY);
294 if (fd < 0)
295 error (EXIT_FAILURE, errno, _("Can't open cache file %s\n"), cache_name);
297 struct stat st;
298 if (fstat (fd, &st) < 0
299 /* No need to map the file if it is empty. */
300 || st.st_size == 0)
302 close (fd);
303 return;
306 struct cache_file *cache
307 = mmap (NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
308 if (cache == MAP_FAILED)
309 error (EXIT_FAILURE, errno, _("mmap of cache file failed.\n"));
311 size_t cache_size = st.st_size;
312 if (cache_size < sizeof (struct cache_file))
313 error (EXIT_FAILURE, 0, _("File is not a cache file.\n"));
315 struct cache_file_new *cache_new = NULL;
316 const char *cache_data;
317 int format = 0;
319 if (memcmp (cache->magic, CACHEMAGIC, sizeof CACHEMAGIC - 1))
321 /* This can only be the new format without the old one. */
322 cache_new = (struct cache_file_new *) cache;
324 if (memcmp (cache_new->magic, CACHEMAGIC_NEW, sizeof CACHEMAGIC_NEW - 1)
325 || memcmp (cache_new->version, CACHE_VERSION,
326 sizeof CACHE_VERSION - 1))
327 error (EXIT_FAILURE, 0, _("File is not a cache file.\n"));
328 check_new_cache (cache_new);
329 format = 1;
330 /* This is where the strings start. */
331 cache_data = (const char *) cache_new;
333 else
335 /* Check for corruption, avoiding overflow. */
336 if ((cache_size - sizeof (struct cache_file)) / sizeof (struct file_entry)
337 < cache->nlibs)
338 error (EXIT_FAILURE, 0, _("File is not a cache file.\n"));
340 size_t offset = ALIGN_CACHE (sizeof (struct cache_file)
341 + (cache->nlibs
342 * sizeof (struct file_entry)));
343 /* This is where the strings start. */
344 cache_data = (const char *) &cache->libs[cache->nlibs];
346 /* Check for a new cache embedded in the old format. */
347 if (cache_size
348 > (offset + sizeof (struct cache_file_new)))
351 cache_new = (struct cache_file_new *) ((void *)cache + offset);
353 if (memcmp (cache_new->magic, CACHEMAGIC_NEW,
354 sizeof CACHEMAGIC_NEW - 1) == 0
355 && memcmp (cache_new->version, CACHE_VERSION,
356 sizeof CACHE_VERSION - 1) == 0)
358 check_new_cache (cache_new);
359 cache_data = (const char *) cache_new;
360 format = 1;
365 if (format == 0)
367 printf (_("%d libs found in cache `%s'\n"), cache->nlibs, cache_name);
369 /* Print everything. */
370 for (unsigned int i = 0; i < cache->nlibs; i++)
371 print_entry (cache_data + cache->libs[i].key,
372 cache->libs[i].flags, 0, NULL,
373 cache_data + cache->libs[i].value);
375 else if (format == 1)
377 struct cache_extension_all_loaded ext;
378 if (!cache_extension_load (cache_new, cache, cache_size, &ext))
379 error (EXIT_FAILURE, 0,
380 _("Malformed extension data in cache file %s\n"), cache_name);
382 printf (_("%d libs found in cache `%s'\n"),
383 cache_new->nlibs, cache_name);
385 /* Print everything. */
386 for (unsigned int i = 0; i < cache_new->nlibs; i++)
388 const char *hwcaps_string
389 = glibc_hwcaps_string (&ext, cache, cache_size,
390 &cache_new->libs[i]);
391 print_entry (cache_data + cache_new->libs[i].key,
392 cache_new->libs[i].flags,
393 cache_new->libs[i].hwcap, hwcaps_string,
394 cache_data + cache_new->libs[i].value);
396 print_extensions (&ext);
398 /* Cleanup. */
399 munmap (cache, cache_size);
400 close (fd);
403 /* Initialize cache data structures. */
404 void
405 init_cache (void)
407 entries = NULL;
410 static int
411 compare (const struct cache_entry *e1, const struct cache_entry *e2)
413 /* We need to swap entries here to get the correct sort order. */
414 int res = _dl_cache_libcmp (e2->lib->string, e1->lib->string);
415 if (res == 0)
417 if (e1->flags < e2->flags)
418 return 1;
419 else if (e1->flags > e2->flags)
420 return -1;
421 /* Keep the glibc-hwcaps extension entries before the regular
422 entries, and sort them by their names. search_cache in
423 dl-cache.c stops searching once the first non-extension entry
424 is found, so the extension entries need to come first. */
425 else if (e1->hwcaps != NULL && e2->hwcaps == NULL)
426 return -1;
427 else if (e1->hwcaps == NULL && e2->hwcaps != NULL)
428 return 1;
429 else if (e1->hwcaps != NULL && e2->hwcaps != NULL)
431 res = strcmp (glibc_hwcaps_subdirectory_name (e1->hwcaps),
432 glibc_hwcaps_subdirectory_name (e2->hwcaps));
433 if (res != 0)
434 return res;
436 /* Sort by most specific hwcap. */
437 if (e2->bits_hwcap > e1->bits_hwcap)
438 return 1;
439 else if (e2->bits_hwcap < e1->bits_hwcap)
440 return -1;
441 else if (e2->hwcap > e1->hwcap)
442 return 1;
443 else if (e2->hwcap < e1->hwcap)
444 return -1;
446 return res;
449 /* Size of the cache extension directory. All tags are assumed to be
450 present. */
451 enum
453 cache_extension_size = (offsetof (struct cache_extension, sections)
454 + (cache_extension_count
455 * sizeof (struct cache_extension_section)))
458 /* Write the cache extensions to FD. The string table is shifted by
459 STRING_TABLE_OFFSET. The extension directory is assumed to be
460 located at CACHE_EXTENSION_OFFSET. assign_glibc_hwcaps_indices
461 must have been called. */
462 static void
463 write_extensions (int fd, uint32_t str_offset,
464 uint32_t cache_extension_offset)
466 assert ((cache_extension_offset % 4) == 0);
468 /* The length and contents of the glibc-hwcaps section. */
469 uint32_t hwcaps_count = glibc_hwcaps_count ();
470 uint32_t hwcaps_offset = cache_extension_offset + cache_extension_size;
471 uint32_t hwcaps_size = hwcaps_count * sizeof (uint32_t);
472 uint32_t *hwcaps_array = xmalloc (hwcaps_size);
473 for (struct glibc_hwcaps_subdirectory *p = hwcaps; p != NULL; p = p->next)
474 if (p->used)
475 hwcaps_array[p->section_index] = str_offset + p->name->offset;
477 /* This is the offset of the generator string. */
478 uint32_t generator_offset = hwcaps_offset;
479 if (hwcaps_count == 0)
480 /* There is no section for the hwcaps subdirectories. */
481 generator_offset -= sizeof (struct cache_extension_section);
482 else
483 /* The string table indices for the hwcaps subdirectories shift
484 the generator string backwards. */
485 generator_offset += hwcaps_size;
487 struct cache_extension *ext = xmalloc (cache_extension_size);
488 ext->magic = cache_extension_magic;
490 /* Extension index current being filled. */
491 size_t xid = 0;
493 const char *generator
494 = "ldconfig " PKGVERSION RELEASE " release version " VERSION;
495 ext->sections[xid].tag = cache_extension_tag_generator;
496 ext->sections[xid].flags = 0;
497 ext->sections[xid].offset = generator_offset;
498 ext->sections[xid].size = strlen (generator);
500 if (hwcaps_count > 0)
502 ++xid;
503 ext->sections[xid].tag = cache_extension_tag_glibc_hwcaps;
504 ext->sections[xid].flags = 0;
505 ext->sections[xid].offset = hwcaps_offset;
506 ext->sections[xid].size = hwcaps_size;
509 ++xid;
510 ext->count = xid;
511 assert (xid <= cache_extension_count);
513 size_t ext_size = (offsetof (struct cache_extension, sections)
514 + xid * sizeof (struct cache_extension_section));
515 if (write (fd, ext, ext_size) != ext_size
516 || write (fd, hwcaps_array, hwcaps_size) != hwcaps_size
517 || write (fd, generator, strlen (generator)) != strlen (generator))
518 error (EXIT_FAILURE, errno, _("Writing of cache extension data failed"));
520 free (hwcaps_array);
521 free (ext);
524 /* Compute the hwcap value from ENTRY. */
525 static inline uint64_t
526 compute_hwcap_value (struct cache_entry *entry)
528 if (entry->isa_level > DL_CACHE_HWCAP_ISA_LEVEL_MASK)
529 error (EXIT_FAILURE, 0, _("%s: ISA level is too high (%d > %d)"),
530 entry->path->string, entry->isa_level,
531 DL_CACHE_HWCAP_ISA_LEVEL_MASK);
532 return (DL_CACHE_HWCAP_EXTENSION
533 | (((uint64_t) entry->isa_level) << 32)
534 | entry->hwcaps->section_index);
537 /* Save the contents of the cache. */
538 void
539 save_cache (const char *cache_name)
541 /* The cache entries are sorted already, save them in this order. */
543 assign_glibc_hwcaps_indices ();
545 struct cache_entry *entry;
546 /* Number of cache entries. */
547 int cache_entry_count = 0;
548 /* The old format doesn't contain hwcap entries and doesn't contain
549 libraries in subdirectories with hwcaps entries. Count therefore
550 also all entries with hwcap == 0. */
551 int cache_entry_old_count = 0;
553 for (entry = entries; entry != NULL; entry = entry->next)
555 ++cache_entry_count;
556 if (entry->hwcap == 0)
557 ++cache_entry_old_count;
560 struct stringtable_finalized strings_finalized;
561 stringtable_finalize (&strings, &strings_finalized);
563 /* Create the on disk cache structure. */
564 struct cache_file *file_entries = NULL;
565 size_t file_entries_size = 0;
567 if (opt_format != opt_format_new)
569 /* struct cache_file_new is 64-bit aligned on some arches while
570 only 32-bit aligned on other arches. Duplicate last old
571 cache entry so that new cache in ld.so.cache can be used by
572 both. */
573 if (opt_format != opt_format_old)
574 cache_entry_old_count = (cache_entry_old_count + 1) & ~1;
576 /* And the list of all entries in the old format. */
577 file_entries_size = sizeof (struct cache_file)
578 + cache_entry_old_count * sizeof (struct file_entry);
579 file_entries = xmalloc (file_entries_size);
581 /* Fill in the header. */
582 memset (file_entries, '\0', sizeof (struct cache_file));
583 memcpy (file_entries->magic, CACHEMAGIC, sizeof CACHEMAGIC - 1);
585 file_entries->nlibs = cache_entry_old_count;
588 struct cache_file_new *file_entries_new = NULL;
589 size_t file_entries_new_size = 0;
591 if (opt_format != opt_format_old)
593 /* And the list of all entries in the new format. */
594 file_entries_new_size = sizeof (struct cache_file_new)
595 + cache_entry_count * sizeof (struct file_entry_new);
596 file_entries_new = xmalloc (file_entries_new_size);
598 /* Fill in the header. */
599 memset (file_entries_new, '\0', sizeof (struct cache_file_new));
600 memcpy (file_entries_new->magic, CACHEMAGIC_NEW,
601 sizeof CACHEMAGIC_NEW - 1);
602 memcpy (file_entries_new->version, CACHE_VERSION,
603 sizeof CACHE_VERSION - 1);
605 file_entries_new->nlibs = cache_entry_count;
606 file_entries_new->len_strings = strings_finalized.size;
607 file_entries_new->flags = cache_file_new_flags_endian_current;
610 /* Pad for alignment of cache_file_new. */
611 size_t pad = ALIGN_CACHE (file_entries_size) - file_entries_size;
613 /* If we have both formats, we hide the new format in the strings
614 table, we have to adjust all string indices for this so that
615 old libc5/glibc 2 dynamic linkers just ignore them. */
616 unsigned int str_offset;
617 if (opt_format != opt_format_old)
618 str_offset = file_entries_new_size;
619 else
620 str_offset = 0;
622 /* An array for all strings. */
623 int idx_old;
624 int idx_new;
626 for (idx_old = 0, idx_new = 0, entry = entries; entry != NULL;
627 entry = entry->next, ++idx_new)
629 if (opt_format != opt_format_new && entry->hwcap == 0)
631 file_entries->libs[idx_old].flags = entry->flags;
632 /* XXX: Actually we can optimize here and remove duplicates. */
633 file_entries->libs[idx_old].key = str_offset + pad;
634 file_entries->libs[idx_new].key = str_offset + entry->lib->offset;
635 file_entries->libs[idx_new].value
636 = str_offset + entry->path->offset;
638 if (opt_format != opt_format_old)
640 /* We could subtract file_entries_new_size from str_offset -
641 not doing so makes the code easier, the string table
642 always begins at the beginning of the new cache
643 struct. */
644 file_entries_new->libs[idx_new].flags = entry->flags;
645 file_entries_new->libs[idx_new].osversion_unused = 0;
646 if (entry->hwcaps == NULL)
647 file_entries_new->libs[idx_new].hwcap = entry->hwcap;
648 else
649 file_entries_new->libs[idx_new].hwcap
650 = compute_hwcap_value (entry);
651 file_entries_new->libs[idx_new].key
652 = str_offset + entry->lib->offset;
653 file_entries_new->libs[idx_new].value
654 = str_offset + entry->path->offset;
657 /* Ignore entries with hwcap for old format. */
658 if (entry->hwcap == 0)
659 ++idx_old;
662 /* Duplicate last old cache entry if needed. */
663 if (opt_format != opt_format_new
664 && idx_old < cache_entry_old_count)
665 file_entries->libs[idx_old] = file_entries->libs[idx_old - 1];
667 /* Compute the location of the extension directory. This
668 implementation puts the directory after the string table. The
669 size computation matches the write calls below. The extension
670 directory does not exist with format 0, so the value does not
671 matter. */
672 uint32_t extension_offset = 0;
673 if (opt_format != opt_format_new)
674 extension_offset += file_entries_size;
675 if (opt_format != opt_format_old)
677 if (opt_format != opt_format_new)
678 extension_offset += pad;
679 extension_offset += file_entries_new_size;
681 extension_offset += strings_finalized.size;
682 extension_offset = roundup (extension_offset, 4); /* Provide alignment. */
683 if (opt_format != opt_format_old)
684 file_entries_new->extension_offset = extension_offset;
686 /* Write out the cache. */
688 /* Write cache first to a temporary file and rename it later. */
689 char *temp_name = xmalloc (strlen (cache_name) + 2);
690 sprintf (temp_name, "%s~", cache_name);
692 /* Create file. */
693 int fd = open (temp_name, O_CREAT|O_WRONLY|O_TRUNC|O_NOFOLLOW,
694 S_IRUSR|S_IWUSR);
695 if (fd < 0)
696 error (EXIT_FAILURE, errno, _("Can't create temporary cache file %s"),
697 temp_name);
699 /* Write contents. */
700 if (opt_format != opt_format_new)
702 if (write (fd, file_entries, file_entries_size)
703 != (ssize_t) file_entries_size)
704 error (EXIT_FAILURE, errno, _("Writing of cache data failed"));
706 if (opt_format != opt_format_old)
708 /* Align cache. */
709 if (opt_format != opt_format_new)
711 char zero[pad];
712 memset (zero, '\0', pad);
713 if (write (fd, zero, pad) != (ssize_t) pad)
714 error (EXIT_FAILURE, errno, _("Writing of cache data failed"));
716 if (write (fd, file_entries_new, file_entries_new_size)
717 != (ssize_t) file_entries_new_size)
718 error (EXIT_FAILURE, errno, _("Writing of cache data failed"));
721 if (write (fd, strings_finalized.strings, strings_finalized.size)
722 != (ssize_t) strings_finalized.size)
723 error (EXIT_FAILURE, errno, _("Writing of cache data failed"));
725 if (opt_format != opt_format_old)
727 /* Align file position to 4. */
728 __attribute__ ((unused)) off64_t old_offset
729 = lseek64 (fd, extension_offset, SEEK_SET);
730 assert ((unsigned long long int) (extension_offset - old_offset) < 4);
731 write_extensions (fd, str_offset, extension_offset);
734 /* Make sure user can always read cache file */
735 if (chmod (temp_name, S_IROTH|S_IRGRP|S_IRUSR|S_IWUSR))
736 error (EXIT_FAILURE, errno,
737 _("Changing access rights of %s to %#o failed"), temp_name,
738 S_IROTH|S_IRGRP|S_IRUSR|S_IWUSR);
740 /* Make sure that data is written to disk. */
741 if (fsync (fd) != 0 || close (fd) != 0)
742 error (EXIT_FAILURE, errno, _("Writing of cache data failed"));
744 /* Move temporary to its final location. */
745 if (rename (temp_name, cache_name))
746 error (EXIT_FAILURE, errno, _("Renaming of %s to %s failed"), temp_name,
747 cache_name);
749 /* Free all allocated memory. */
750 free (file_entries_new);
751 free (file_entries);
752 free (strings_finalized.strings);
753 free (temp_name);
755 while (entries)
757 entry = entries;
758 entries = entries->next;
759 free (entry);
764 /* Add one library to the cache. */
765 void
766 add_to_cache (const char *path, const char *filename, const char *soname,
767 int flags, unsigned int isa_level, uint64_t hwcap,
768 struct glibc_hwcaps_subdirectory *hwcaps)
770 struct cache_entry *new_entry = xmalloc (sizeof (*new_entry));
772 struct stringtable_entry *path_interned;
774 char *p;
775 if (asprintf (&p, "%s/%s", path, filename) < 0)
776 error (EXIT_FAILURE, errno, _("Could not create library path"));
777 path_interned = stringtable_add (&strings, p);
778 free (p);
781 new_entry->lib = stringtable_add (&strings, soname);
782 new_entry->path = path_interned;
783 new_entry->flags = flags;
784 new_entry->isa_level = isa_level;
785 new_entry->hwcap = hwcap;
786 new_entry->hwcaps = hwcaps;
787 new_entry->bits_hwcap = 0;
789 if (hwcaps != NULL)
791 assert (hwcap == 0);
792 hwcaps->used = true;
795 /* Count the number of bits set in the masked value. */
796 for (size_t i = 0;
797 (~((1ULL << i) - 1) & hwcap) != 0 && i < 8 * sizeof (hwcap); ++i)
798 if ((hwcap & (1ULL << i)) != 0)
799 ++new_entry->bits_hwcap;
802 /* Keep the list sorted - search for right place to insert. */
803 struct cache_entry *ptr = entries;
804 struct cache_entry *prev = entries;
805 while (ptr != NULL)
807 if (compare (ptr, new_entry) > 0)
808 break;
809 prev = ptr;
810 ptr = ptr->next;
812 /* Is this the first entry? */
813 if (ptr == entries)
815 new_entry->next = entries;
816 entries = new_entry;
818 else
820 new_entry->next = prev->next;
821 prev->next = new_entry;
826 /* Auxiliary cache. */
828 struct aux_cache_entry_id
830 uint64_t ino;
831 uint64_t ctime;
832 uint64_t size;
833 uint64_t dev;
836 struct aux_cache_entry
838 struct aux_cache_entry_id id;
839 int flags;
840 unsigned int isa_level;
841 int used;
842 char *soname;
843 struct aux_cache_entry *next;
846 #define AUX_CACHEMAGIC "glibc-ld.so.auxcache-1.0"
848 struct aux_cache_file_entry
850 struct aux_cache_entry_id id; /* Unique id of entry. */
851 int32_t flags; /* This is 1 for an ELF library. */
852 uint32_t soname; /* String table indice. */
853 uint32_t isa_level; /* Required ISA level. */
856 /* ldconfig maintains an auxiliary cache file that allows
857 only reading those libraries that have changed since the last iteration.
858 For this for each library some information is cached in the auxiliary
859 cache. */
860 struct aux_cache_file
862 char magic[sizeof AUX_CACHEMAGIC - 1];
863 uint32_t nlibs; /* Number of entries. */
864 uint32_t len_strings; /* Size of string table. */
865 struct aux_cache_file_entry libs[0]; /* Entries describing libraries. */
866 /* After this the string table of size len_strings is found. */
869 static const unsigned int primes[] =
871 1021, 2039, 4093, 8191, 16381, 32749, 65521, 131071, 262139,
872 524287, 1048573, 2097143, 4194301, 8388593, 16777213, 33554393,
873 67108859, 134217689, 268435399, 536870909, 1073741789, 2147483647
876 static size_t aux_hash_size;
877 static struct aux_cache_entry **aux_hash;
879 /* Simplistic hash function for aux_cache_entry_id. */
880 static unsigned int
881 aux_cache_entry_id_hash (struct aux_cache_entry_id *id)
883 uint64_t ret = ((id->ino * 11 + id->ctime) * 11 + id->size) * 11 + id->dev;
884 return ret ^ (ret >> 32);
887 static size_t nextprime (size_t x)
889 for (unsigned int i = 0; i < sizeof (primes) / sizeof (primes[0]); ++i)
890 if (primes[i] >= x)
891 return primes[i];
892 return x;
895 void
896 init_aux_cache (void)
898 aux_hash_size = primes[3];
899 aux_hash = xcalloc (aux_hash_size, sizeof (struct aux_cache_entry *));
903 search_aux_cache (struct stat *stat_buf, int *flags, unsigned int *isa_level,
904 char **soname)
906 struct aux_cache_entry_id id;
907 id.ino = (uint64_t) stat_buf->st_ino;
908 id.ctime = (uint64_t) stat_buf->st_ctime;
909 id.size = (uint64_t) stat_buf->st_size;
910 id.dev = (uint64_t) stat_buf->st_dev;
912 unsigned int hash = aux_cache_entry_id_hash (&id);
913 struct aux_cache_entry *entry;
914 for (entry = aux_hash[hash % aux_hash_size]; entry; entry = entry->next)
915 if (id.ino == entry->id.ino
916 && id.ctime == entry->id.ctime
917 && id.size == entry->id.size
918 && id.dev == entry->id.dev)
920 *flags = entry->flags;
921 *isa_level = entry->isa_level;
922 if (entry->soname != NULL)
923 *soname = xstrdup (entry->soname);
924 else
925 *soname = NULL;
926 entry->used = 1;
927 return 1;
930 return 0;
933 static void
934 insert_to_aux_cache (struct aux_cache_entry_id *id, int flags,
935 unsigned int isa_level, const char *soname, int used)
937 size_t hash = aux_cache_entry_id_hash (id) % aux_hash_size;
938 struct aux_cache_entry *entry;
939 for (entry = aux_hash[hash]; entry; entry = entry->next)
940 if (id->ino == entry->id.ino
941 && id->ctime == entry->id.ctime
942 && id->size == entry->id.size
943 && id->dev == entry->id.dev)
944 abort ();
946 size_t len = soname ? strlen (soname) + 1 : 0;
947 entry = xmalloc (sizeof (struct aux_cache_entry) + len);
948 entry->id = *id;
949 entry->flags = flags;
950 entry->isa_level = isa_level;
951 entry->used = used;
952 if (soname != NULL)
953 entry->soname = memcpy ((char *) (entry + 1), soname, len);
954 else
955 entry->soname = NULL;
956 entry->next = aux_hash[hash];
957 aux_hash[hash] = entry;
960 void
961 add_to_aux_cache (struct stat *stat_buf, int flags, unsigned int isa_level,
962 const char *soname)
964 struct aux_cache_entry_id id;
965 id.ino = (uint64_t) stat_buf->st_ino;
966 id.ctime = (uint64_t) stat_buf->st_ctime;
967 id.size = (uint64_t) stat_buf->st_size;
968 id.dev = (uint64_t) stat_buf->st_dev;
969 insert_to_aux_cache (&id, flags, isa_level, soname, 1);
972 /* Load auxiliary cache to search for unchanged entries. */
973 void
974 load_aux_cache (const char *aux_cache_name)
976 int fd = open (aux_cache_name, O_RDONLY);
977 if (fd < 0)
979 init_aux_cache ();
980 return;
983 struct stat st;
984 if (fstat (fd, &st) < 0 || st.st_size < sizeof (struct aux_cache_file))
986 close (fd);
987 init_aux_cache ();
988 return;
991 size_t aux_cache_size = st.st_size;
992 struct aux_cache_file *aux_cache
993 = mmap (NULL, aux_cache_size, PROT_READ, MAP_PRIVATE, fd, 0);
994 if (aux_cache == MAP_FAILED
995 || aux_cache_size < sizeof (struct aux_cache_file)
996 || memcmp (aux_cache->magic, AUX_CACHEMAGIC, sizeof AUX_CACHEMAGIC - 1)
997 || aux_cache_size != (sizeof (struct aux_cache_file)
998 + aux_cache->nlibs * sizeof (struct aux_cache_file_entry)
999 + aux_cache->len_strings))
1001 if (aux_cache != MAP_FAILED)
1002 munmap (aux_cache, aux_cache_size);
1004 close (fd);
1005 init_aux_cache ();
1006 return;
1009 aux_hash_size = nextprime (aux_cache->nlibs);
1010 aux_hash = xcalloc (aux_hash_size, sizeof (struct aux_cache_entry *));
1012 const char *aux_cache_data
1013 = (const char *) &aux_cache->libs[aux_cache->nlibs];
1014 for (unsigned int i = 0; i < aux_cache->nlibs; ++i)
1015 insert_to_aux_cache (&aux_cache->libs[i].id,
1016 aux_cache->libs[i].flags,
1017 aux_cache->libs[i].isa_level,
1018 aux_cache->libs[i].soname == 0
1019 ? NULL : aux_cache_data + aux_cache->libs[i].soname,
1022 munmap (aux_cache, aux_cache_size);
1023 close (fd);
1026 /* Save the contents of the auxiliary cache. */
1027 void
1028 save_aux_cache (const char *aux_cache_name)
1030 /* Count the length of all sonames. We start with empty string. */
1031 size_t total_strlen = 1;
1032 /* Number of cache entries. */
1033 int cache_entry_count = 0;
1035 for (size_t i = 0; i < aux_hash_size; ++i)
1036 for (struct aux_cache_entry *entry = aux_hash[i];
1037 entry != NULL; entry = entry->next)
1038 if (entry->used)
1040 ++cache_entry_count;
1041 if (entry->soname != NULL)
1042 total_strlen += strlen (entry->soname) + 1;
1045 /* Auxiliary cache. */
1046 size_t file_entries_size
1047 = sizeof (struct aux_cache_file)
1048 + cache_entry_count * sizeof (struct aux_cache_file_entry);
1049 struct aux_cache_file *file_entries
1050 = xmalloc (file_entries_size + total_strlen);
1052 /* Fill in the header of the auxiliary cache. */
1053 memset (file_entries, '\0', sizeof (struct aux_cache_file));
1054 memcpy (file_entries->magic, AUX_CACHEMAGIC, sizeof AUX_CACHEMAGIC - 1);
1056 file_entries->nlibs = cache_entry_count;
1057 file_entries->len_strings = total_strlen;
1059 /* Initial String offset for auxiliary cache is always after the
1060 special empty string. */
1061 unsigned int str_offset = 1;
1063 /* An array for all strings. */
1064 char *str = (char *) file_entries + file_entries_size;
1065 *str++ = '\0';
1067 size_t idx = 0;
1068 for (size_t i = 0; i < aux_hash_size; ++i)
1069 for (struct aux_cache_entry *entry = aux_hash[i];
1070 entry != NULL; entry = entry->next)
1071 if (entry->used)
1073 file_entries->libs[idx].id = entry->id;
1074 file_entries->libs[idx].flags = entry->flags;
1075 if (entry->soname == NULL)
1076 file_entries->libs[idx].soname = 0;
1077 else
1079 file_entries->libs[idx].soname = str_offset;
1081 size_t len = strlen (entry->soname) + 1;
1082 str = mempcpy (str, entry->soname, len);
1083 str_offset += len;
1085 file_entries->libs[idx++].isa_level = entry->isa_level;
1088 /* Write out auxiliary cache file. */
1089 /* Write auxiliary cache first to a temporary file and rename it later. */
1091 char *temp_name = xmalloc (strlen (aux_cache_name) + 2);
1092 sprintf (temp_name, "%s~", aux_cache_name);
1094 /* Check that directory exists and create if needed. */
1095 char *dir = strdupa (aux_cache_name);
1096 dir = dirname (dir);
1098 struct stat st;
1099 if (stat (dir, &st) < 0)
1101 if (mkdir (dir, 0700) < 0)
1102 goto out_fail;
1105 /* Create file. */
1106 int fd = open (temp_name, O_CREAT|O_WRONLY|O_TRUNC|O_NOFOLLOW,
1107 S_IRUSR|S_IWUSR);
1108 if (fd < 0)
1109 goto out_fail;
1111 bool fail = ((write (fd, file_entries, file_entries_size + total_strlen)
1112 != (ssize_t) (file_entries_size + total_strlen))
1113 || fdatasync (fd) != 0);
1115 fail |= close (fd) != 0;
1117 if (fail)
1119 unlink (temp_name);
1120 goto out_fail;
1123 /* Move temporary to its final location. */
1124 if (rename (temp_name, aux_cache_name))
1125 unlink (temp_name);
1127 out_fail:
1128 /* Free allocated memory. */
1129 free (temp_name);
1130 free (file_entries);