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