universally apply our cflags (no vsx, no altivec..)
[glibc.git] / elf / cache.c
1 /* Copyright (C) 1999-2022 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
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.
8
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.
13
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/>. */
16
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>
34
35 #include <ldconfig.h>
36 #include <dl-cache.h>
37 #include <version.h>
38 #include <stringtable.h>
39
40 /* Used to store library names, paths, and other strings. */
41 static struct stringtable strings;
42
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
47 {
48 struct glibc_hwcaps_subdirectory *next;
49
50 /* Interned string with the subdirectory name. */
51 struct stringtable_entry *name;
52
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;
58
59 /* True if the subdirectory is actually used for anything. */
60 bool used;
61 };
62
63 const char *
64 glibc_hwcaps_subdirectory_name (const struct glibc_hwcaps_subdirectory *dir)
65 {
66 return dir->name->string;
67 }
68
69 /* Linked list of known hwcaps subdirecty names. */
70 static struct glibc_hwcaps_subdirectory *hwcaps;
71
72 struct glibc_hwcaps_subdirectory *
73 new_glibc_hwcaps_subdirectory (const char *name)
74 {
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;
86 }
87
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)
92 {
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));
99 }
100
101 /* Count the number of hwcaps subdirectories which are actually
102 used. */
103 static size_t
104 glibc_hwcaps_count (void)
105 {
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;
111 }
112
113 /* Compute the section_index fields for all */
114 static void
115 assign_glibc_hwcaps_indices (void)
116 {
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);
122 {
123 size_t i = 0;
124 for (struct glibc_hwcaps_subdirectory *p = hwcaps; p != NULL; p = p->next)
125 if (p->used)
126 {
127 array[i] = p;
128 ++i;
129 }
130 assert (i == count);
131 }
132
133 qsort (array, count, sizeof (*array), assign_glibc_hwcaps_indices_compare);
134
135 /* Assign the array indices. */
136 for (size_t i = 0; i < count; ++i)
137 array[i]->section_index = i;
138
139 free (array);
140 }
141
142 struct cache_entry
143 {
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. */
150
151 /* glibc-hwcaps subdirectory. If not NULL, hwcap must be zero. */
152 struct glibc_hwcaps_subdirectory *hwcaps;
153
154 struct cache_entry *next; /* Next entry in list. */
155 };
156
157 /* List of all cache entries. */
158 static struct cache_entry *entries;
159
160 static const char *flag_descr[] =
161 { "libc4", "ELF", "libc5", "libc6"};
162
163 /* Print a single entry. */
164 static void
165 print_entry (const char *lib, int flag, uint64_t hwcap,
166 const char *hwcap_string, const char *key)
167 {
168 printf ("\t%s (", lib);
169 switch (flag & FLAG_TYPE_MASK)
170 {
171 case FLAG_LIBC4:
172 case FLAG_ELF:
173 case FLAG_ELF_LIBC5:
174 case FLAG_ELF_LIBC6:
175 fputs (flag_descr[flag & FLAG_TYPE_MASK], stdout);
176 break;
177 default:
178 fputs (_("unknown"), stdout);
179 break;
180 }
181 switch (flag & FLAG_REQUIRED_MASK)
182 {
183 case FLAG_SPARC_LIB64:
184 fputs (",64bit", stdout);
185 break;
186 case FLAG_IA64_LIB64:
187 fputs (",IA-64", stdout);
188 break;
189 case FLAG_X8664_LIB64:
190 fputs (",x86-64", stdout);
191 break;
192 case FLAG_S390_LIB64:
193 fputs (",64bit", stdout);
194 break;
195 case FLAG_POWERPC_LIB64:
196 fputs (",64bit", stdout);
197 break;
198 case FLAG_MIPS64_LIBN32:
199 fputs (",N32", stdout);
200 break;
201 case FLAG_MIPS64_LIBN64:
202 fputs (",64bit", stdout);
203 break;
204 case FLAG_X8664_LIBX32:
205 fputs (",x32", stdout);
206 break;
207 case FLAG_ARM_LIBHF:
208 fputs (",hard-float", stdout);
209 break;
210 case FLAG_AARCH64_LIB64:
211 fputs (",AArch64", stdout);
212 break;
213 /* Uses the ARM soft-float ABI. */
214 case FLAG_ARM_LIBSF:
215 fputs (",soft-float", stdout);
216 break;
217 case FLAG_MIPS_LIB32_NAN2008:
218 fputs (",nan2008", stdout);
219 break;
220 case FLAG_MIPS64_LIBN32_NAN2008:
221 fputs (",N32,nan2008", stdout);
222 break;
223 case FLAG_MIPS64_LIBN64_NAN2008:
224 fputs (",64bit,nan2008", stdout);
225 break;
226 case FLAG_RISCV_FLOAT_ABI_SOFT:
227 fputs (",soft-float", stdout);
228 break;
229 case FLAG_RISCV_FLOAT_ABI_DOUBLE:
230 fputs (",double-float", stdout);
231 break;
232 case 0:
233 break;
234 default:
235 printf (",%d", flag & FLAG_REQUIRED_MASK);
236 break;
237 }
238 if (hwcap_string != NULL)
239 printf (", hwcap: \"%s\"", hwcap_string);
240 else if (hwcap != 0)
241 printf (", hwcap: %#.16" PRIx64, hwcap);
242 printf (") => %s\n", key);
243 }
244
245 /* Returns the string with the name of the glibcs-hwcaps subdirectory
246 associated with ENTRY->hwcap. file_base must be the base address
247 for string table indices. */
248 static const char *
249 glibc_hwcaps_string (struct cache_extension_all_loaded *ext,
250 const void *file_base, size_t file_size,
251 struct file_entry_new *entry)
252 {
253 const uint32_t *hwcaps_array
254 = ext->sections[cache_extension_tag_glibc_hwcaps].base;
255 if (dl_cache_hwcap_extension (entry) && hwcaps_array != NULL)
256 {
257 uint32_t index = (uint32_t) entry->hwcap;
258 if (index < ext->sections[cache_extension_tag_glibc_hwcaps].size / 4)
259 {
260 uint32_t string_table_index = hwcaps_array[index];
261 if (string_table_index < file_size)
262 return file_base + string_table_index;
263 }
264 }
265 return NULL;
266 }
267
268 /* Print an error and exit if the new-file cache is internally
269 inconsistent. */
270 static void
271 check_new_cache (struct cache_file_new *cache)
272 {
273 if (! cache_file_new_matches_endian (cache))
274 error (EXIT_FAILURE, 0, _("Cache file has wrong endianness.\n"));
275 }
276
277 /* Print the extension information in *EXT. */
278 static void
279 print_extensions (struct cache_extension_all_loaded *ext)
280 {
281 if (ext->sections[cache_extension_tag_generator].base != NULL)
282 {
283 fputs (_("Cache generated by: "), stdout);
284 fwrite (ext->sections[cache_extension_tag_generator].base, 1,
285 ext->sections[cache_extension_tag_generator].size, stdout);
286 putchar ('\n');
287 }
288 }
289
290 /* Print the whole cache file, if a file contains the new cache format
291 hidden in the old one, print the contents of the new format. */
292 void
293 print_cache (const char *cache_name)
294 {
295 int fd = open (cache_name, O_RDONLY);
296 if (fd < 0)
297 error (EXIT_FAILURE, errno, _("Can't open cache file %s\n"), cache_name);
298
299 struct stat st;
300 if (fstat (fd, &st) < 0
301 /* No need to map the file if it is empty. */
302 || st.st_size == 0)
303 {
304 close (fd);
305 return;
306 }
307
308 struct cache_file *cache
309 = mmap (NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
310 if (cache == MAP_FAILED)
311 error (EXIT_FAILURE, errno, _("mmap of cache file failed.\n"));
312
313 size_t cache_size = st.st_size;
314 if (cache_size < sizeof (struct cache_file))
315 error (EXIT_FAILURE, 0, _("File is not a cache file.\n"));
316
317 struct cache_file_new *cache_new = NULL;
318 const char *cache_data;
319 int format = 0;
320
321 if (memcmp (cache->magic, CACHEMAGIC, sizeof CACHEMAGIC - 1))
322 {
323 /* This can only be the new format without the old one. */
324 cache_new = (struct cache_file_new *) cache;
325
326 if (memcmp (cache_new->magic, CACHEMAGIC_NEW, sizeof CACHEMAGIC_NEW - 1)
327 || memcmp (cache_new->version, CACHE_VERSION,
328 sizeof CACHE_VERSION - 1))
329 error (EXIT_FAILURE, 0, _("File is not a cache file.\n"));
330 check_new_cache (cache_new);
331 format = 1;
332 /* This is where the strings start. */
333 cache_data = (const char *) cache_new;
334 }
335 else
336 {
337 /* Check for corruption, avoiding overflow. */
338 if ((cache_size - sizeof (struct cache_file)) / sizeof (struct file_entry)
339 < cache->nlibs)
340 error (EXIT_FAILURE, 0, _("File is not a cache file.\n"));
341
342 size_t offset = ALIGN_CACHE (sizeof (struct cache_file)
343 + (cache->nlibs
344 * sizeof (struct file_entry)));
345 /* This is where the strings start. */
346 cache_data = (const char *) &cache->libs[cache->nlibs];
347
348 /* Check for a new cache embedded in the old format. */
349 if (cache_size
350 > (offset + sizeof (struct cache_file_new)))
351 {
352
353 cache_new = (struct cache_file_new *) ((void *)cache + offset);
354
355 if (memcmp (cache_new->magic, CACHEMAGIC_NEW,
356 sizeof CACHEMAGIC_NEW - 1) == 0
357 && memcmp (cache_new->version, CACHE_VERSION,
358 sizeof CACHE_VERSION - 1) == 0)
359 {
360 check_new_cache (cache_new);
361 cache_data = (const char *) cache_new;
362 format = 1;
363 }
364 }
365 }
366
367 if (format == 0)
368 {
369 printf (_("%d libs found in cache `%s'\n"), cache->nlibs, cache_name);
370
371 /* Print everything. */
372 for (unsigned int i = 0; i < cache->nlibs; i++)
373 print_entry (cache_data + cache->libs[i].key,
374 cache->libs[i].flags, 0, NULL,
375 cache_data + cache->libs[i].value);
376 }
377 else if (format == 1)
378 {
379 struct cache_extension_all_loaded ext;
380 if (!cache_extension_load (cache_new, cache, cache_size, &ext))
381 error (EXIT_FAILURE, 0,
382 _("Malformed extension data in cache file %s\n"), cache_name);
383
384 printf (_("%d libs found in cache `%s'\n"),
385 cache_new->nlibs, cache_name);
386
387 /* Print everything. */
388 for (unsigned int i = 0; i < cache_new->nlibs; i++)
389 {
390 const char *hwcaps_string
391 = glibc_hwcaps_string (&ext, cache, cache_size,
392 &cache_new->libs[i]);
393 print_entry (cache_data + cache_new->libs[i].key,
394 cache_new->libs[i].flags,
395 cache_new->libs[i].hwcap, hwcaps_string,
396 cache_data + cache_new->libs[i].value);
397 }
398 print_extensions (&ext);
399 }
400 /* Cleanup. */
401 munmap (cache, cache_size);
402 close (fd);
403 }
404
405 /* Initialize cache data structures. */
406 void
407 init_cache (void)
408 {
409 entries = NULL;
410 }
411
412 static int
413 compare (const struct cache_entry *e1, const struct cache_entry *e2)
414 {
415 /* We need to swap entries here to get the correct sort order. */
416 int res = _dl_cache_libcmp (e2->lib->string, e1->lib->string);
417 if (res == 0)
418 {
419 if (e1->flags < e2->flags)
420 return 1;
421 else if (e1->flags > e2->flags)
422 return -1;
423 /* Keep the glibc-hwcaps extension entries before the regular
424 entries, and sort them by their names. search_cache in
425 dl-cache.c stops searching once the first non-extension entry
426 is found, so the extension entries need to come first. */
427 else if (e1->hwcaps != NULL && e2->hwcaps == NULL)
428 return -1;
429 else if (e1->hwcaps == NULL && e2->hwcaps != NULL)
430 return 1;
431 else if (e1->hwcaps != NULL && e2->hwcaps != NULL)
432 {
433 res = strcmp (glibc_hwcaps_subdirectory_name (e1->hwcaps),
434 glibc_hwcaps_subdirectory_name (e2->hwcaps));
435 if (res != 0)
436 return res;
437 }
438 /* Sort by most specific hwcap. */
439 if (e2->bits_hwcap > e1->bits_hwcap)
440 return 1;
441 else if (e2->bits_hwcap < e1->bits_hwcap)
442 return -1;
443 else if (e2->hwcap > e1->hwcap)
444 return 1;
445 else if (e2->hwcap < e1->hwcap)
446 return -1;
447 }
448 return res;
449 }
450
451 /* Size of the cache extension directory. All tags are assumed to be
452 present. */
453 enum
454 {
455 cache_extension_size = (offsetof (struct cache_extension, sections)
456 + (cache_extension_count
457 * sizeof (struct cache_extension_section)))
458 };
459
460 /* Write the cache extensions to FD. The string table is shifted by
461 STRING_TABLE_OFFSET. The extension directory is assumed to be
462 located at CACHE_EXTENSION_OFFSET. assign_glibc_hwcaps_indices
463 must have been called. */
464 static void
465 write_extensions (int fd, uint32_t str_offset,
466 uint32_t cache_extension_offset)
467 {
468 assert ((cache_extension_offset % 4) == 0);
469
470 /* The length and contents of the glibc-hwcaps section. */
471 uint32_t hwcaps_count = glibc_hwcaps_count ();
472 uint32_t hwcaps_offset = cache_extension_offset + cache_extension_size;
473 uint32_t hwcaps_size = hwcaps_count * sizeof (uint32_t);
474 uint32_t *hwcaps_array = xmalloc (hwcaps_size);
475 for (struct glibc_hwcaps_subdirectory *p = hwcaps; p != NULL; p = p->next)
476 if (p->used)
477 hwcaps_array[p->section_index] = str_offset + p->name->offset;
478
479 /* This is the offset of the generator string. */
480 uint32_t generator_offset = hwcaps_offset;
481 if (hwcaps_count == 0)
482 /* There is no section for the hwcaps subdirectories. */
483 generator_offset -= sizeof (struct cache_extension_section);
484 else
485 /* The string table indices for the hwcaps subdirectories shift
486 the generator string backwards. */
487 generator_offset += hwcaps_size;
488
489 struct cache_extension *ext = xmalloc (cache_extension_size);
490 ext->magic = cache_extension_magic;
491
492 /* Extension index current being filled. */
493 size_t xid = 0;
494
495 const char *generator
496 = "ldconfig " PKGVERSION RELEASE " release version " VERSION;
497 ext->sections[xid].tag = cache_extension_tag_generator;
498 ext->sections[xid].flags = 0;
499 ext->sections[xid].offset = generator_offset;
500 ext->sections[xid].size = strlen (generator);
501
502 if (hwcaps_count > 0)
503 {
504 ++xid;
505 ext->sections[xid].tag = cache_extension_tag_glibc_hwcaps;
506 ext->sections[xid].flags = 0;
507 ext->sections[xid].offset = hwcaps_offset;
508 ext->sections[xid].size = hwcaps_size;
509 }
510
511 ++xid;
512 ext->count = xid;
513 assert (xid <= cache_extension_count);
514
515 size_t ext_size = (offsetof (struct cache_extension, sections)
516 + xid * sizeof (struct cache_extension_section));
517 if (write (fd, ext, ext_size) != ext_size
518 || write (fd, hwcaps_array, hwcaps_size) != hwcaps_size
519 || write (fd, generator, strlen (generator)) != strlen (generator))
520 error (EXIT_FAILURE, errno, _("Writing of cache extension data failed"));
521
522 free (hwcaps_array);
523 free (ext);
524 }
525
526 /* Compute the hwcap value from ENTRY. */
527 static inline uint64_t
528 compute_hwcap_value (struct cache_entry *entry)
529 {
530 if (entry->isa_level > DL_CACHE_HWCAP_ISA_LEVEL_MASK)
531 error (EXIT_FAILURE, 0, _("%s: ISA level is too high (%d > %d)"),
532 entry->path->string, entry->isa_level,
533 DL_CACHE_HWCAP_ISA_LEVEL_MASK);
534 return (DL_CACHE_HWCAP_EXTENSION
535 | (((uint64_t) entry->isa_level) << 32)
536 | entry->hwcaps->section_index);
537 }
538
539 /* Save the contents of the cache. */
540 void
541 save_cache (const char *cache_name)
542 {
543 /* The cache entries are sorted already, save them in this order. */
544
545 assign_glibc_hwcaps_indices ();
546
547 struct cache_entry *entry;
548 /* Number of cache entries. */
549 int cache_entry_count = 0;
550 /* The old format doesn't contain hwcap entries and doesn't contain
551 libraries in subdirectories with hwcaps entries. Count therefore
552 also all entries with hwcap == 0. */
553 int cache_entry_old_count = 0;
554
555 for (entry = entries; entry != NULL; entry = entry->next)
556 {
557 ++cache_entry_count;
558 if (entry->hwcap == 0)
559 ++cache_entry_old_count;
560 }
561
562 struct stringtable_finalized strings_finalized;
563 stringtable_finalize (&strings, &strings_finalized);
564
565 /* Create the on disk cache structure. */
566 struct cache_file *file_entries = NULL;
567 size_t file_entries_size = 0;
568
569 if (opt_format != opt_format_new)
570 {
571 /* struct cache_file_new is 64-bit aligned on some arches while
572 only 32-bit aligned on other arches. Duplicate last old
573 cache entry so that new cache in ld.so.cache can be used by
574 both. */
575 if (opt_format != opt_format_old)
576 cache_entry_old_count = (cache_entry_old_count + 1) & ~1;
577
578 /* And the list of all entries in the old format. */
579 file_entries_size = sizeof (struct cache_file)
580 + cache_entry_old_count * sizeof (struct file_entry);
581 file_entries = xmalloc (file_entries_size);
582
583 /* Fill in the header. */
584 memset (file_entries, '\0', sizeof (struct cache_file));
585 memcpy (file_entries->magic, CACHEMAGIC, sizeof CACHEMAGIC - 1);
586
587 file_entries->nlibs = cache_entry_old_count;
588 }
589
590 struct cache_file_new *file_entries_new = NULL;
591 size_t file_entries_new_size = 0;
592
593 if (opt_format != opt_format_old)
594 {
595 /* And the list of all entries in the new format. */
596 file_entries_new_size = sizeof (struct cache_file_new)
597 + cache_entry_count * sizeof (struct file_entry_new);
598 file_entries_new = xmalloc (file_entries_new_size);
599
600 /* Fill in the header. */
601 memset (file_entries_new, '\0', sizeof (struct cache_file_new));
602 memcpy (file_entries_new->magic, CACHEMAGIC_NEW,
603 sizeof CACHEMAGIC_NEW - 1);
604 memcpy (file_entries_new->version, CACHE_VERSION,
605 sizeof CACHE_VERSION - 1);
606
607 file_entries_new->nlibs = cache_entry_count;
608 file_entries_new->len_strings = strings_finalized.size;
609 file_entries_new->flags = cache_file_new_flags_endian_current;
610 }
611
612 /* Pad for alignment of cache_file_new. */
613 size_t pad = ALIGN_CACHE (file_entries_size) - file_entries_size;
614
615 /* If we have both formats, we hide the new format in the strings
616 table, we have to adjust all string indices for this so that
617 old libc5/glibc 2 dynamic linkers just ignore them. */
618 unsigned int str_offset;
619 if (opt_format != opt_format_old)
620 str_offset = file_entries_new_size;
621 else
622 str_offset = 0;
623
624 /* An array for all strings. */
625 int idx_old;
626 int idx_new;
627
628 for (idx_old = 0, idx_new = 0, entry = entries; entry != NULL;
629 entry = entry->next, ++idx_new)
630 {
631 if (opt_format != opt_format_new && entry->hwcap == 0)
632 {
633 file_entries->libs[idx_old].flags = entry->flags;
634 /* XXX: Actually we can optimize here and remove duplicates. */
635 file_entries->libs[idx_old].key = str_offset + pad;
636 file_entries->libs[idx_new].key = str_offset + entry->lib->offset;
637 file_entries->libs[idx_new].value
638 = str_offset + entry->path->offset;
639 }
640 if (opt_format != opt_format_old)
641 {
642 /* We could subtract file_entries_new_size from str_offset -
643 not doing so makes the code easier, the string table
644 always begins at the beginning of the new cache
645 struct. */
646 file_entries_new->libs[idx_new].flags = entry->flags;
647 file_entries_new->libs[idx_new].osversion_unused = 0;
648 if (entry->hwcaps == NULL)
649 file_entries_new->libs[idx_new].hwcap = entry->hwcap;
650 else
651 file_entries_new->libs[idx_new].hwcap
652 = compute_hwcap_value (entry);
653 file_entries_new->libs[idx_new].key
654 = str_offset + entry->lib->offset;
655 file_entries_new->libs[idx_new].value
656 = str_offset + entry->path->offset;
657 }
658
659 /* Ignore entries with hwcap for old format. */
660 if (entry->hwcap == 0)
661 ++idx_old;
662 }
663
664 /* Duplicate last old cache entry if needed. */
665 if (opt_format != opt_format_new
666 && idx_old < cache_entry_old_count)
667 file_entries->libs[idx_old] = file_entries->libs[idx_old - 1];
668
669 /* Compute the location of the extension directory. This
670 implementation puts the directory after the string table. The
671 size computation matches the write calls below. The extension
672 directory does not exist with format 0, so the value does not
673 matter. */
674 uint32_t extension_offset = 0;
675 if (opt_format != opt_format_new)
676 extension_offset += file_entries_size;
677 if (opt_format != opt_format_old)
678 {
679 if (opt_format != opt_format_new)
680 extension_offset += pad;
681 extension_offset += file_entries_new_size;
682 }
683 extension_offset += strings_finalized.size;
684 extension_offset = roundup (extension_offset, 4); /* Provide alignment. */
685 if (opt_format != opt_format_old)
686 file_entries_new->extension_offset = extension_offset;
687
688 /* Write out the cache. */
689
690 /* Write cache first to a temporary file and rename it later. */
691 char *temp_name = xmalloc (strlen (cache_name) + 2);
692 sprintf (temp_name, "%s~", cache_name);
693
694 /* Create file. */
695 int fd = open (temp_name, O_CREAT|O_WRONLY|O_TRUNC|O_NOFOLLOW,
696 S_IRUSR|S_IWUSR);
697 if (fd < 0)
698 error (EXIT_FAILURE, errno, _("Can't create temporary cache file %s"),
699 temp_name);
700
701 /* Write contents. */
702 if (opt_format != opt_format_new)
703 {
704 if (write (fd, file_entries, file_entries_size)
705 != (ssize_t) file_entries_size)
706 error (EXIT_FAILURE, errno, _("Writing of cache data failed"));
707 }
708 if (opt_format != opt_format_old)
709 {
710 /* Align cache. */
711 if (opt_format != opt_format_new)
712 {
713 char zero[pad];
714 memset (zero, '\0', pad);
715 if (write (fd, zero, pad) != (ssize_t) pad)
716 error (EXIT_FAILURE, errno, _("Writing of cache data failed"));
717 }
718 if (write (fd, file_entries_new, file_entries_new_size)
719 != (ssize_t) file_entries_new_size)
720 error (EXIT_FAILURE, errno, _("Writing of cache data failed"));
721 }
722
723 if (write (fd, strings_finalized.strings, strings_finalized.size)
724 != (ssize_t) strings_finalized.size)
725 error (EXIT_FAILURE, errno, _("Writing of cache data failed"));
726
727 if (opt_format != opt_format_old)
728 {
729 /* Align file position to 4. */
730 __attribute__ ((unused)) off64_t old_offset
731 = lseek64 (fd, extension_offset, SEEK_SET);
732 assert ((unsigned long long int) (extension_offset - old_offset) < 4);
733 write_extensions (fd, str_offset, extension_offset);
734 }
735
736 /* Make sure user can always read cache file */
737 if (chmod (temp_name, S_IROTH|S_IRGRP|S_IRUSR|S_IWUSR))
738 error (EXIT_FAILURE, errno,
739 _("Changing access rights of %s to %#o failed"), temp_name,
740 S_IROTH|S_IRGRP|S_IRUSR|S_IWUSR);
741
742 /* Make sure that data is written to disk. */
743 if (fsync (fd) != 0 || close (fd) != 0)
744 error (EXIT_FAILURE, errno, _("Writing of cache data failed"));
745
746 /* Move temporary to its final location. */
747 if (rename (temp_name, cache_name))
748 error (EXIT_FAILURE, errno, _("Renaming of %s to %s failed"), temp_name,
749 cache_name);
750
751 /* Free all allocated memory. */
752 free (file_entries_new);
753 free (file_entries);
754 free (strings_finalized.strings);
755 free (temp_name);
756
757 while (entries)
758 {
759 entry = entries;
760 entries = entries->next;
761 free (entry);
762 }
763 }
764
765
766 /* Add one library to the cache. */
767 void
768 add_to_cache (const char *path, const char *filename, const char *soname,
769 int flags, unsigned int isa_level, uint64_t hwcap,
770 struct glibc_hwcaps_subdirectory *hwcaps)
771 {
772 struct cache_entry *new_entry = xmalloc (sizeof (*new_entry));
773
774 struct stringtable_entry *path_interned;
775 {
776 char *p;
777 if (asprintf (&p, "%s/%s", path, filename) < 0)
778 error (EXIT_FAILURE, errno, _("Could not create library path"));
779 path_interned = stringtable_add (&strings, p);
780 free (p);
781 }
782
783 new_entry->lib = stringtable_add (&strings, soname);
784 new_entry->path = path_interned;
785 new_entry->flags = flags;
786 new_entry->isa_level = isa_level;
787 new_entry->hwcap = hwcap;
788 new_entry->hwcaps = hwcaps;
789 new_entry->bits_hwcap = 0;
790
791 if (hwcaps != NULL)
792 {
793 assert (hwcap == 0);
794 hwcaps->used = true;
795 }
796
797 /* Count the number of bits set in the masked value. */
798 for (size_t i = 0;
799 (~((1ULL << i) - 1) & hwcap) != 0 && i < 8 * sizeof (hwcap); ++i)
800 if ((hwcap & (1ULL << i)) != 0)
801 ++new_entry->bits_hwcap;
802
803
804 /* Keep the list sorted - search for right place to insert. */
805 struct cache_entry *ptr = entries;
806 struct cache_entry *prev = entries;
807 while (ptr != NULL)
808 {
809 if (compare (ptr, new_entry) > 0)
810 break;
811 prev = ptr;
812 ptr = ptr->next;
813 }
814 /* Is this the first entry? */
815 if (ptr == entries)
816 {
817 new_entry->next = entries;
818 entries = new_entry;
819 }
820 else
821 {
822 new_entry->next = prev->next;
823 prev->next = new_entry;
824 }
825 }
826
827
828 /* Auxiliary cache. */
829
830 struct aux_cache_entry_id
831 {
832 uint64_t ino;
833 uint64_t ctime;
834 uint64_t size;
835 uint64_t dev;
836 };
837
838 struct aux_cache_entry
839 {
840 struct aux_cache_entry_id id;
841 int flags;
842 unsigned int isa_level;
843 int used;
844 char *soname;
845 struct aux_cache_entry *next;
846 };
847
848 #define AUX_CACHEMAGIC "glibc-ld.so.auxcache-1.0"
849
850 struct aux_cache_file_entry
851 {
852 struct aux_cache_entry_id id; /* Unique id of entry. */
853 int32_t flags; /* This is 1 for an ELF library. */
854 uint32_t soname; /* String table indice. */
855 uint32_t isa_level; /* Required ISA level. */
856 };
857
858 /* ldconfig maintains an auxiliary cache file that allows
859 only reading those libraries that have changed since the last iteration.
860 For this for each library some information is cached in the auxiliary
861 cache. */
862 struct aux_cache_file
863 {
864 char magic[sizeof AUX_CACHEMAGIC - 1];
865 uint32_t nlibs; /* Number of entries. */
866 uint32_t len_strings; /* Size of string table. */
867 struct aux_cache_file_entry libs[0]; /* Entries describing libraries. */
868 /* After this the string table of size len_strings is found. */
869 };
870
871 static const unsigned int primes[] =
872 {
873 1021, 2039, 4093, 8191, 16381, 32749, 65521, 131071, 262139,
874 524287, 1048573, 2097143, 4194301, 8388593, 16777213, 33554393,
875 67108859, 134217689, 268435399, 536870909, 1073741789, 2147483647
876 };
877
878 static size_t aux_hash_size;
879 static struct aux_cache_entry **aux_hash;
880
881 /* Simplistic hash function for aux_cache_entry_id. */
882 static unsigned int
883 aux_cache_entry_id_hash (struct aux_cache_entry_id *id)
884 {
885 uint64_t ret = ((id->ino * 11 + id->ctime) * 11 + id->size) * 11 + id->dev;
886 return ret ^ (ret >> 32);
887 }
888
889 static size_t nextprime (size_t x)
890 {
891 for (unsigned int i = 0; i < sizeof (primes) / sizeof (primes[0]); ++i)
892 if (primes[i] >= x)
893 return primes[i];
894 return x;
895 }
896
897 void
898 init_aux_cache (void)
899 {
900 aux_hash_size = primes[3];
901 aux_hash = xcalloc (aux_hash_size, sizeof (struct aux_cache_entry *));
902 }
903
904 int
905 search_aux_cache (struct stat *stat_buf, int *flags, unsigned int *isa_level,
906 char **soname)
907 {
908 struct aux_cache_entry_id id;
909 id.ino = (uint64_t) stat_buf->st_ino;
910 id.ctime = (uint64_t) stat_buf->st_ctime;
911 id.size = (uint64_t) stat_buf->st_size;
912 id.dev = (uint64_t) stat_buf->st_dev;
913
914 unsigned int hash = aux_cache_entry_id_hash (&id);
915 struct aux_cache_entry *entry;
916 for (entry = aux_hash[hash % aux_hash_size]; entry; entry = entry->next)
917 if (id.ino == entry->id.ino
918 && id.ctime == entry->id.ctime
919 && id.size == entry->id.size
920 && id.dev == entry->id.dev)
921 {
922 *flags = entry->flags;
923 *isa_level = entry->isa_level;
924 if (entry->soname != NULL)
925 *soname = xstrdup (entry->soname);
926 else
927 *soname = NULL;
928 entry->used = 1;
929 return 1;
930 }
931
932 return 0;
933 }
934
935 static void
936 insert_to_aux_cache (struct aux_cache_entry_id *id, int flags,
937 unsigned int isa_level, const char *soname, int used)
938 {
939 size_t hash = aux_cache_entry_id_hash (id) % aux_hash_size;
940 struct aux_cache_entry *entry;
941 for (entry = aux_hash[hash]; entry; entry = entry->next)
942 if (id->ino == entry->id.ino
943 && id->ctime == entry->id.ctime
944 && id->size == entry->id.size
945 && id->dev == entry->id.dev)
946 abort ();
947
948 size_t len = soname ? strlen (soname) + 1 : 0;
949 entry = xmalloc (sizeof (struct aux_cache_entry) + len);
950 entry->id = *id;
951 entry->flags = flags;
952 entry->isa_level = isa_level;
953 entry->used = used;
954 if (soname != NULL)
955 entry->soname = memcpy ((char *) (entry + 1), soname, len);
956 else
957 entry->soname = NULL;
958 entry->next = aux_hash[hash];
959 aux_hash[hash] = entry;
960 }
961
962 void
963 add_to_aux_cache (struct stat *stat_buf, int flags, unsigned int isa_level,
964 const char *soname)
965 {
966 struct aux_cache_entry_id id;
967 id.ino = (uint64_t) stat_buf->st_ino;
968 id.ctime = (uint64_t) stat_buf->st_ctime;
969 id.size = (uint64_t) stat_buf->st_size;
970 id.dev = (uint64_t) stat_buf->st_dev;
971 insert_to_aux_cache (&id, flags, isa_level, soname, 1);
972 }
973
974 /* Load auxiliary cache to search for unchanged entries. */
975 void
976 load_aux_cache (const char *aux_cache_name)
977 {
978 int fd = open (aux_cache_name, O_RDONLY);
979 if (fd < 0)
980 {
981 init_aux_cache ();
982 return;
983 }
984
985 struct stat st;
986 if (fstat (fd, &st) < 0 || st.st_size < sizeof (struct aux_cache_file))
987 {
988 close (fd);
989 init_aux_cache ();
990 return;
991 }
992
993 size_t aux_cache_size = st.st_size;
994 struct aux_cache_file *aux_cache
995 = mmap (NULL, aux_cache_size, PROT_READ, MAP_PRIVATE, fd, 0);
996 if (aux_cache == MAP_FAILED
997 || aux_cache_size < sizeof (struct aux_cache_file)
998 || memcmp (aux_cache->magic, AUX_CACHEMAGIC, sizeof AUX_CACHEMAGIC - 1)
999 || aux_cache_size != (sizeof (struct aux_cache_file)
1000 + aux_cache->nlibs * sizeof (struct aux_cache_file_entry)
1001 + aux_cache->len_strings))
1002 {
1003 if (aux_cache != MAP_FAILED)
1004 munmap (aux_cache, aux_cache_size);
1005
1006 close (fd);
1007 init_aux_cache ();
1008 return;
1009 }
1010
1011 aux_hash_size = nextprime (aux_cache->nlibs);
1012 aux_hash = xcalloc (aux_hash_size, sizeof (struct aux_cache_entry *));
1013
1014 const char *aux_cache_data
1015 = (const char *) &aux_cache->libs[aux_cache->nlibs];
1016 for (unsigned int i = 0; i < aux_cache->nlibs; ++i)
1017 insert_to_aux_cache (&aux_cache->libs[i].id,
1018 aux_cache->libs[i].flags,
1019 aux_cache->libs[i].isa_level,
1020 aux_cache->libs[i].soname == 0
1021 ? NULL : aux_cache_data + aux_cache->libs[i].soname,
1022 0);
1023
1024 munmap (aux_cache, aux_cache_size);
1025 close (fd);
1026 }
1027
1028 /* Save the contents of the auxiliary cache. */
1029 void
1030 save_aux_cache (const char *aux_cache_name)
1031 {
1032 /* Count the length of all sonames. We start with empty string. */
1033 size_t total_strlen = 1;
1034 /* Number of cache entries. */
1035 int cache_entry_count = 0;
1036
1037 for (size_t i = 0; i < aux_hash_size; ++i)
1038 for (struct aux_cache_entry *entry = aux_hash[i];
1039 entry != NULL; entry = entry->next)
1040 if (entry->used)
1041 {
1042 ++cache_entry_count;
1043 if (entry->soname != NULL)
1044 total_strlen += strlen (entry->soname) + 1;
1045 }
1046
1047 /* Auxiliary cache. */
1048 size_t file_entries_size
1049 = sizeof (struct aux_cache_file)
1050 + cache_entry_count * sizeof (struct aux_cache_file_entry);
1051 struct aux_cache_file *file_entries
1052 = xmalloc (file_entries_size + total_strlen);
1053
1054 /* Fill in the header of the auxiliary cache. */
1055 memset (file_entries, '\0', sizeof (struct aux_cache_file));
1056 memcpy (file_entries->magic, AUX_CACHEMAGIC, sizeof AUX_CACHEMAGIC - 1);
1057
1058 file_entries->nlibs = cache_entry_count;
1059 file_entries->len_strings = total_strlen;
1060
1061 /* Initial String offset for auxiliary cache is always after the
1062 special empty string. */
1063 unsigned int str_offset = 1;
1064
1065 /* An array for all strings. */
1066 char *str = (char *) file_entries + file_entries_size;
1067 *str++ = '\0';
1068
1069 size_t idx = 0;
1070 for (size_t i = 0; i < aux_hash_size; ++i)
1071 for (struct aux_cache_entry *entry = aux_hash[i];
1072 entry != NULL; entry = entry->next)
1073 if (entry->used)
1074 {
1075 file_entries->libs[idx].id = entry->id;
1076 file_entries->libs[idx].flags = entry->flags;
1077 if (entry->soname == NULL)
1078 file_entries->libs[idx].soname = 0;
1079 else
1080 {
1081 file_entries->libs[idx].soname = str_offset;
1082
1083 size_t len = strlen (entry->soname) + 1;
1084 str = mempcpy (str, entry->soname, len);
1085 str_offset += len;
1086 }
1087 file_entries->libs[idx++].isa_level = entry->isa_level;
1088 }
1089
1090 /* Write out auxiliary cache file. */
1091 /* Write auxiliary cache first to a temporary file and rename it later. */
1092
1093 char *temp_name = xmalloc (strlen (aux_cache_name) + 2);
1094 sprintf (temp_name, "%s~", aux_cache_name);
1095
1096 /* Check that directory exists and create if needed. */
1097 char *dir = strdupa (aux_cache_name);
1098 dir = dirname (dir);
1099
1100 struct stat st;
1101 if (stat (dir, &st) < 0)
1102 {
1103 if (mkdir (dir, 0700) < 0)
1104 goto out_fail;
1105 }
1106
1107 /* Create file. */
1108 int fd = open (temp_name, O_CREAT|O_WRONLY|O_TRUNC|O_NOFOLLOW,
1109 S_IRUSR|S_IWUSR);
1110 if (fd < 0)
1111 goto out_fail;
1112
1113 bool fail = ((write (fd, file_entries, file_entries_size + total_strlen)
1114 != (ssize_t) (file_entries_size + total_strlen))
1115 || fdatasync (fd) != 0);
1116
1117 fail |= close (fd) != 0;
1118
1119 if (fail)
1120 {
1121 unlink (temp_name);
1122 goto out_fail;
1123 }
1124
1125 /* Move temporary to its final location. */
1126 if (rename (temp_name, aux_cache_name))
1127 unlink (temp_name);
1128
1129 out_fail:
1130 /* Free allocated memory. */
1131 free (temp_name);
1132 free (file_entries);
1133 }