]> git.ipfire.org Git - thirdparty/glibc.git/blob - elf/cache.c
elf: Remove ldconfig kernel version check
[thirdparty/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 off64_t old_offset = lseek64 (fd, extension_offset, SEEK_SET);
731 assert ((unsigned long long int) (extension_offset - old_offset) < 4);
732 write_extensions (fd, str_offset, extension_offset);
733 }
734
735 /* Make sure user can always read cache file */
736 if (chmod (temp_name, S_IROTH|S_IRGRP|S_IRUSR|S_IWUSR))
737 error (EXIT_FAILURE, errno,
738 _("Changing access rights of %s to %#o failed"), temp_name,
739 S_IROTH|S_IRGRP|S_IRUSR|S_IWUSR);
740
741 /* Make sure that data is written to disk. */
742 if (fsync (fd) != 0 || close (fd) != 0)
743 error (EXIT_FAILURE, errno, _("Writing of cache data failed"));
744
745 /* Move temporary to its final location. */
746 if (rename (temp_name, cache_name))
747 error (EXIT_FAILURE, errno, _("Renaming of %s to %s failed"), temp_name,
748 cache_name);
749
750 /* Free all allocated memory. */
751 free (file_entries_new);
752 free (file_entries);
753 free (strings_finalized.strings);
754 free (temp_name);
755
756 while (entries)
757 {
758 entry = entries;
759 entries = entries->next;
760 free (entry);
761 }
762 }
763
764
765 /* Add one library to the cache. */
766 void
767 add_to_cache (const char *path, const char *filename, const char *soname,
768 int flags, unsigned int isa_level, uint64_t hwcap,
769 struct glibc_hwcaps_subdirectory *hwcaps)
770 {
771 struct cache_entry *new_entry = xmalloc (sizeof (*new_entry));
772
773 struct stringtable_entry *path_interned;
774 {
775 char *p;
776 if (asprintf (&p, "%s/%s", path, filename) < 0)
777 error (EXIT_FAILURE, errno, _("Could not create library path"));
778 path_interned = stringtable_add (&strings, p);
779 free (p);
780 }
781
782 new_entry->lib = stringtable_add (&strings, soname);
783 new_entry->path = path_interned;
784 new_entry->flags = flags;
785 new_entry->isa_level = isa_level;
786 new_entry->hwcap = hwcap;
787 new_entry->hwcaps = hwcaps;
788 new_entry->bits_hwcap = 0;
789
790 if (hwcaps != NULL)
791 {
792 assert (hwcap == 0);
793 hwcaps->used = true;
794 }
795
796 /* Count the number of bits set in the masked value. */
797 for (size_t i = 0;
798 (~((1ULL << i) - 1) & hwcap) != 0 && i < 8 * sizeof (hwcap); ++i)
799 if ((hwcap & (1ULL << i)) != 0)
800 ++new_entry->bits_hwcap;
801
802
803 /* Keep the list sorted - search for right place to insert. */
804 struct cache_entry *ptr = entries;
805 struct cache_entry *prev = entries;
806 while (ptr != NULL)
807 {
808 if (compare (ptr, new_entry) > 0)
809 break;
810 prev = ptr;
811 ptr = ptr->next;
812 }
813 /* Is this the first entry? */
814 if (ptr == entries)
815 {
816 new_entry->next = entries;
817 entries = new_entry;
818 }
819 else
820 {
821 new_entry->next = prev->next;
822 prev->next = new_entry;
823 }
824 }
825
826
827 /* Auxiliary cache. */
828
829 struct aux_cache_entry_id
830 {
831 uint64_t ino;
832 uint64_t ctime;
833 uint64_t size;
834 uint64_t dev;
835 };
836
837 struct aux_cache_entry
838 {
839 struct aux_cache_entry_id id;
840 int flags;
841 unsigned int isa_level;
842 int used;
843 char *soname;
844 struct aux_cache_entry *next;
845 };
846
847 #define AUX_CACHEMAGIC "glibc-ld.so.auxcache-1.0"
848
849 struct aux_cache_file_entry
850 {
851 struct aux_cache_entry_id id; /* Unique id of entry. */
852 int32_t flags; /* This is 1 for an ELF library. */
853 uint32_t soname; /* String table indice. */
854 uint32_t isa_level; /* Required ISA level. */
855 };
856
857 /* ldconfig maintains an auxiliary cache file that allows
858 only reading those libraries that have changed since the last iteration.
859 For this for each library some information is cached in the auxiliary
860 cache. */
861 struct aux_cache_file
862 {
863 char magic[sizeof AUX_CACHEMAGIC - 1];
864 uint32_t nlibs; /* Number of entries. */
865 uint32_t len_strings; /* Size of string table. */
866 struct aux_cache_file_entry libs[0]; /* Entries describing libraries. */
867 /* After this the string table of size len_strings is found. */
868 };
869
870 static const unsigned int primes[] =
871 {
872 1021, 2039, 4093, 8191, 16381, 32749, 65521, 131071, 262139,
873 524287, 1048573, 2097143, 4194301, 8388593, 16777213, 33554393,
874 67108859, 134217689, 268435399, 536870909, 1073741789, 2147483647
875 };
876
877 static size_t aux_hash_size;
878 static struct aux_cache_entry **aux_hash;
879
880 /* Simplistic hash function for aux_cache_entry_id. */
881 static unsigned int
882 aux_cache_entry_id_hash (struct aux_cache_entry_id *id)
883 {
884 uint64_t ret = ((id->ino * 11 + id->ctime) * 11 + id->size) * 11 + id->dev;
885 return ret ^ (ret >> 32);
886 }
887
888 static size_t nextprime (size_t x)
889 {
890 for (unsigned int i = 0; i < sizeof (primes) / sizeof (primes[0]); ++i)
891 if (primes[i] >= x)
892 return primes[i];
893 return x;
894 }
895
896 void
897 init_aux_cache (void)
898 {
899 aux_hash_size = primes[3];
900 aux_hash = xcalloc (aux_hash_size, sizeof (struct aux_cache_entry *));
901 }
902
903 int
904 search_aux_cache (struct stat *stat_buf, int *flags, unsigned int *isa_level,
905 char **soname)
906 {
907 struct aux_cache_entry_id id;
908 id.ino = (uint64_t) stat_buf->st_ino;
909 id.ctime = (uint64_t) stat_buf->st_ctime;
910 id.size = (uint64_t) stat_buf->st_size;
911 id.dev = (uint64_t) stat_buf->st_dev;
912
913 unsigned int hash = aux_cache_entry_id_hash (&id);
914 struct aux_cache_entry *entry;
915 for (entry = aux_hash[hash % aux_hash_size]; entry; entry = entry->next)
916 if (id.ino == entry->id.ino
917 && id.ctime == entry->id.ctime
918 && id.size == entry->id.size
919 && id.dev == entry->id.dev)
920 {
921 *flags = entry->flags;
922 *isa_level = entry->isa_level;
923 if (entry->soname != NULL)
924 *soname = xstrdup (entry->soname);
925 else
926 *soname = NULL;
927 entry->used = 1;
928 return 1;
929 }
930
931 return 0;
932 }
933
934 static void
935 insert_to_aux_cache (struct aux_cache_entry_id *id, int flags,
936 unsigned int isa_level, const char *soname, int used)
937 {
938 size_t hash = aux_cache_entry_id_hash (id) % aux_hash_size;
939 struct aux_cache_entry *entry;
940 for (entry = aux_hash[hash]; entry; entry = entry->next)
941 if (id->ino == entry->id.ino
942 && id->ctime == entry->id.ctime
943 && id->size == entry->id.size
944 && id->dev == entry->id.dev)
945 abort ();
946
947 size_t len = soname ? strlen (soname) + 1 : 0;
948 entry = xmalloc (sizeof (struct aux_cache_entry) + len);
949 entry->id = *id;
950 entry->flags = flags;
951 entry->isa_level = isa_level;
952 entry->used = used;
953 if (soname != NULL)
954 entry->soname = memcpy ((char *) (entry + 1), soname, len);
955 else
956 entry->soname = NULL;
957 entry->next = aux_hash[hash];
958 aux_hash[hash] = entry;
959 }
960
961 void
962 add_to_aux_cache (struct stat *stat_buf, int flags, unsigned int isa_level,
963 const char *soname)
964 {
965 struct aux_cache_entry_id id;
966 id.ino = (uint64_t) stat_buf->st_ino;
967 id.ctime = (uint64_t) stat_buf->st_ctime;
968 id.size = (uint64_t) stat_buf->st_size;
969 id.dev = (uint64_t) stat_buf->st_dev;
970 insert_to_aux_cache (&id, flags, isa_level, soname, 1);
971 }
972
973 /* Load auxiliary cache to search for unchanged entries. */
974 void
975 load_aux_cache (const char *aux_cache_name)
976 {
977 int fd = open (aux_cache_name, O_RDONLY);
978 if (fd < 0)
979 {
980 init_aux_cache ();
981 return;
982 }
983
984 struct stat st;
985 if (fstat (fd, &st) < 0 || st.st_size < sizeof (struct aux_cache_file))
986 {
987 close (fd);
988 init_aux_cache ();
989 return;
990 }
991
992 size_t aux_cache_size = st.st_size;
993 struct aux_cache_file *aux_cache
994 = mmap (NULL, aux_cache_size, PROT_READ, MAP_PRIVATE, fd, 0);
995 if (aux_cache == MAP_FAILED
996 || aux_cache_size < sizeof (struct aux_cache_file)
997 || memcmp (aux_cache->magic, AUX_CACHEMAGIC, sizeof AUX_CACHEMAGIC - 1)
998 || aux_cache_size != (sizeof (struct aux_cache_file)
999 + aux_cache->nlibs * sizeof (struct aux_cache_file_entry)
1000 + aux_cache->len_strings))
1001 {
1002 if (aux_cache != MAP_FAILED)
1003 munmap (aux_cache, aux_cache_size);
1004
1005 close (fd);
1006 init_aux_cache ();
1007 return;
1008 }
1009
1010 aux_hash_size = nextprime (aux_cache->nlibs);
1011 aux_hash = xcalloc (aux_hash_size, sizeof (struct aux_cache_entry *));
1012
1013 const char *aux_cache_data
1014 = (const char *) &aux_cache->libs[aux_cache->nlibs];
1015 for (unsigned int i = 0; i < aux_cache->nlibs; ++i)
1016 insert_to_aux_cache (&aux_cache->libs[i].id,
1017 aux_cache->libs[i].flags,
1018 aux_cache->libs[i].isa_level,
1019 aux_cache->libs[i].soname == 0
1020 ? NULL : aux_cache_data + aux_cache->libs[i].soname,
1021 0);
1022
1023 munmap (aux_cache, aux_cache_size);
1024 close (fd);
1025 }
1026
1027 /* Save the contents of the auxiliary cache. */
1028 void
1029 save_aux_cache (const char *aux_cache_name)
1030 {
1031 /* Count the length of all sonames. We start with empty string. */
1032 size_t total_strlen = 1;
1033 /* Number of cache entries. */
1034 int cache_entry_count = 0;
1035
1036 for (size_t i = 0; i < aux_hash_size; ++i)
1037 for (struct aux_cache_entry *entry = aux_hash[i];
1038 entry != NULL; entry = entry->next)
1039 if (entry->used)
1040 {
1041 ++cache_entry_count;
1042 if (entry->soname != NULL)
1043 total_strlen += strlen (entry->soname) + 1;
1044 }
1045
1046 /* Auxiliary cache. */
1047 size_t file_entries_size
1048 = sizeof (struct aux_cache_file)
1049 + cache_entry_count * sizeof (struct aux_cache_file_entry);
1050 struct aux_cache_file *file_entries
1051 = xmalloc (file_entries_size + total_strlen);
1052
1053 /* Fill in the header of the auxiliary cache. */
1054 memset (file_entries, '\0', sizeof (struct aux_cache_file));
1055 memcpy (file_entries->magic, AUX_CACHEMAGIC, sizeof AUX_CACHEMAGIC - 1);
1056
1057 file_entries->nlibs = cache_entry_count;
1058 file_entries->len_strings = total_strlen;
1059
1060 /* Initial String offset for auxiliary cache is always after the
1061 special empty string. */
1062 unsigned int str_offset = 1;
1063
1064 /* An array for all strings. */
1065 char *str = (char *) file_entries + file_entries_size;
1066 *str++ = '\0';
1067
1068 size_t idx = 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)
1073 {
1074 file_entries->libs[idx].id = entry->id;
1075 file_entries->libs[idx].flags = entry->flags;
1076 if (entry->soname == NULL)
1077 file_entries->libs[idx].soname = 0;
1078 else
1079 {
1080 file_entries->libs[idx].soname = str_offset;
1081
1082 size_t len = strlen (entry->soname) + 1;
1083 str = mempcpy (str, entry->soname, len);
1084 str_offset += len;
1085 }
1086 file_entries->libs[idx++].isa_level = entry->isa_level;
1087 }
1088
1089 /* Write out auxiliary cache file. */
1090 /* Write auxiliary cache first to a temporary file and rename it later. */
1091
1092 char *temp_name = xmalloc (strlen (aux_cache_name) + 2);
1093 sprintf (temp_name, "%s~", aux_cache_name);
1094
1095 /* Check that directory exists and create if needed. */
1096 char *dir = strdupa (aux_cache_name);
1097 dir = dirname (dir);
1098
1099 struct stat st;
1100 if (stat (dir, &st) < 0)
1101 {
1102 if (mkdir (dir, 0700) < 0)
1103 goto out_fail;
1104 }
1105
1106 /* Create file. */
1107 int fd = open (temp_name, O_CREAT|O_WRONLY|O_TRUNC|O_NOFOLLOW,
1108 S_IRUSR|S_IWUSR);
1109 if (fd < 0)
1110 goto out_fail;
1111
1112 bool fail = ((write (fd, file_entries, file_entries_size + total_strlen)
1113 != (ssize_t) (file_entries_size + total_strlen))
1114 || fdatasync (fd) != 0);
1115
1116 fail |= close (fd) != 0;
1117
1118 if (fail)
1119 {
1120 unlink (temp_name);
1121 goto out_fail;
1122 }
1123
1124 /* Move temporary to its final location. */
1125 if (rename (temp_name, aux_cache_name))
1126 unlink (temp_name);
1127
1128 out_fail:
1129 /* Free allocated memory. */
1130 free (temp_name);
1131 free (file_entries);
1132 }