1 /* Copyright (C) 1999-2003,2005,2006,2007,2011 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Andreas Jaeger <aj@suse.de>, 1999.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, see <http://www.gnu.org/licenses/>. */
28 #include <sys/fcntl.h>
31 #include <sys/types.h>
38 char *lib; /* Library name. */
39 char *path; /* Path to find library. */
40 int flags; /* Flags to indicate kind of library. */
41 unsigned int osversion; /* Required OS version. */
42 uint64_t hwcap; /* Important hardware capabilities. */
43 int bits_hwcap; /* Number of bits set in hwcap. */
44 struct cache_entry *next; /* Next entry in list. */
47 /* List of all cache entries. */
48 static struct cache_entry *entries;
50 static const char *flag_descr[] =
51 { "libc4", "ELF", "libc5", "libc6"};
53 /* Print a single entry. */
55 print_entry (const char *lib, int flag, unsigned int osversion,
56 uint64_t hwcap, const char *key)
58 printf ("\t%s (", lib);
59 switch (flag & FLAG_TYPE_MASK)
65 fputs (flag_descr[flag & FLAG_TYPE_MASK], stdout);
68 fputs (_("unknown"), stdout);
71 switch (flag & FLAG_REQUIRED_MASK)
73 case FLAG_SPARC_LIB64:
74 fputs (",64bit", stdout);
77 fputs (",IA-64", stdout);
79 case FLAG_X8664_LIB64:
80 fputs (",x86-64", stdout);
83 fputs (",64bit", stdout);
85 case FLAG_POWERPC_LIB64:
86 fputs (",64bit", stdout);
88 case FLAG_MIPS64_LIBN32:
89 fputs (",N32", stdout);
91 case FLAG_MIPS64_LIBN64:
92 fputs (",64bit", stdout);
96 printf (",%d", flag & FLAG_REQUIRED_MASK);
100 printf (", hwcap: %#.16" PRIx64, hwcap);
103 static const char *const abi_tag_os[] =
111 [6] = N_("Unknown OS")
113 #define MAXTAG (sizeof abi_tag_os / sizeof abi_tag_os[0] - 1)
114 unsigned int os = osversion >> 24;
116 printf (_(", OS ABI: %s %d.%d.%d"),
117 _(abi_tag_os[os > MAXTAG ? MAXTAG : os]),
118 (osversion >> 16) & 0xff,
119 (osversion >> 8) & 0xff,
122 printf (") => %s\n", key);
126 /* Print the whole cache file, if a file contains the new cache format
127 hidden in the old one, print the contents of the new format. */
129 print_cache (const char *cache_name)
131 int fd = open (cache_name, O_RDONLY);
133 error (EXIT_FAILURE, errno, _("Can't open cache file %s\n"), cache_name);
136 if (fstat64 (fd, &st) < 0
137 /* No need to map the file if it is empty. */
144 struct cache_file *cache
145 = mmap (NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
146 if (cache == MAP_FAILED)
147 error (EXIT_FAILURE, errno, _("mmap of cache file failed.\n"));
149 size_t cache_size = st.st_size;
150 if (cache_size < sizeof (struct cache_file))
151 error (EXIT_FAILURE, 0, _("File is not a cache file.\n"));
153 struct cache_file_new *cache_new = NULL;
154 const char *cache_data;
157 if (memcmp (cache->magic, CACHEMAGIC, sizeof CACHEMAGIC - 1))
159 /* This can only be the new format without the old one. */
160 cache_new = (struct cache_file_new *) cache;
162 if (memcmp (cache_new->magic, CACHEMAGIC_NEW, sizeof CACHEMAGIC_NEW - 1)
163 || memcmp (cache_new->version, CACHE_VERSION,
164 sizeof CACHE_VERSION - 1))
165 error (EXIT_FAILURE, 0, _("File is not a cache file.\n"));
167 /* This is where the strings start. */
168 cache_data = (const char *) cache_new;
172 size_t offset = ALIGN_CACHE (sizeof (struct cache_file)
174 * sizeof (struct file_entry)));
175 /* This is where the strings start. */
176 cache_data = (const char *) &cache->libs[cache->nlibs];
178 /* Check for a new cache embedded in the old format. */
180 (offset + sizeof (struct cache_file_new)))
183 cache_new = (struct cache_file_new *) ((void *)cache + offset);
185 if (memcmp (cache_new->magic, CACHEMAGIC_NEW,
186 sizeof CACHEMAGIC_NEW - 1) == 0
187 && memcmp (cache_new->version, CACHE_VERSION,
188 sizeof CACHE_VERSION - 1) == 0)
190 cache_data = (const char *) cache_new;
198 printf (_("%d libs found in cache `%s'\n"), cache->nlibs, cache_name);
200 /* Print everything. */
201 for (unsigned int i = 0; i < cache->nlibs; i++)
202 print_entry (cache_data + cache->libs[i].key,
203 cache->libs[i].flags, 0, 0,
204 cache_data + cache->libs[i].value);
206 else if (format == 1)
208 printf (_("%d libs found in cache `%s'\n"),
209 cache_new->nlibs, cache_name);
211 /* Print everything. */
212 for (unsigned int i = 0; i < cache_new->nlibs; i++)
213 print_entry (cache_data + cache_new->libs[i].key,
214 cache_new->libs[i].flags,
215 cache_new->libs[i].osversion,
216 cache_new->libs[i].hwcap,
217 cache_data + cache_new->libs[i].value);
220 munmap (cache, cache_size);
224 /* Initialize cache data structures. */
232 compare (const struct cache_entry *e1, const struct cache_entry *e2)
234 /* We need to swap entries here to get the correct sort order. */
235 int res = _dl_cache_libcmp (e2->lib, e1->lib);
238 if (e1->flags < e2->flags)
240 else if (e1->flags > e2->flags)
242 /* Sort by most specific hwcap. */
243 else if (e2->bits_hwcap > e1->bits_hwcap)
245 else if (e2->bits_hwcap < e1->bits_hwcap)
247 else if (e2->hwcap > e1->hwcap)
249 else if (e2->hwcap < e1->hwcap)
251 if (e2->osversion > e1->osversion)
253 if (e2->osversion < e1->osversion)
259 /* Save the contents of the cache. */
261 save_cache (const char *cache_name)
263 /* The cache entries are sorted already, save them in this order. */
265 /* Count the length of all strings. */
266 /* The old format doesn't contain hwcap entries and doesn't contain
267 libraries in subdirectories with hwcaps entries. Count therefore
268 also all entries with hwcap == 0. */
269 size_t total_strlen = 0;
270 struct cache_entry *entry;
271 /* Number of cache entries. */
272 int cache_entry_count = 0;
273 /* Number of normal cache entries. */
274 int cache_entry_old_count = 0;
276 for (entry = entries; entry != NULL; entry = entry->next)
278 /* Account the final NULs. */
279 total_strlen += strlen (entry->lib) + strlen (entry->path) + 2;
281 if (entry->hwcap == 0)
282 ++cache_entry_old_count;
285 /* Create the on disk cache structure. */
286 struct cache_file *file_entries = NULL;
287 size_t file_entries_size = 0;
291 /* struct cache_file_new is 64-bit aligned on some arches while
292 only 32-bit aligned on other arches. Duplicate last old
293 cache entry so that new cache in ld.so.cache can be used by
296 cache_entry_old_count = (cache_entry_old_count + 1) & ~1;
298 /* And the list of all entries in the old format. */
299 file_entries_size = sizeof (struct cache_file)
300 + cache_entry_old_count * sizeof (struct file_entry);
301 file_entries = xmalloc (file_entries_size);
303 /* Fill in the header. */
304 memset (file_entries, '\0', sizeof (struct cache_file));
305 memcpy (file_entries->magic, CACHEMAGIC, sizeof CACHEMAGIC - 1);
307 file_entries->nlibs = cache_entry_old_count;
310 struct cache_file_new *file_entries_new = NULL;
311 size_t file_entries_new_size = 0;
315 /* And the list of all entries in the new format. */
316 file_entries_new_size = sizeof (struct cache_file_new)
317 + cache_entry_count * sizeof (struct file_entry_new);
318 file_entries_new = xmalloc (file_entries_new_size);
320 /* Fill in the header. */
321 memset (file_entries_new, '\0', sizeof (struct cache_file_new));
322 memcpy (file_entries_new->magic, CACHEMAGIC_NEW,
323 sizeof CACHEMAGIC_NEW - 1);
324 memcpy (file_entries_new->version, CACHE_VERSION,
325 sizeof CACHE_VERSION - 1);
327 file_entries_new->nlibs = cache_entry_count;
328 file_entries_new->len_strings = total_strlen;
331 /* Pad for alignment of cache_file_new. */
332 size_t pad = ALIGN_CACHE (file_entries_size) - file_entries_size;
334 /* If we have both formats, we hide the new format in the strings
335 table, we have to adjust all string indices for this so that
336 old libc5/glibc 2 dynamic linkers just ignore them. */
337 unsigned int str_offset;
339 str_offset = file_entries_new_size;
343 /* An array for all strings. */
344 char *strings = xmalloc (total_strlen);
349 for (idx_old = 0, idx_new = 0, entry = entries; entry != NULL;
350 entry = entry->next, ++idx_new)
352 /* First the library. */
353 if (opt_format != 2 && entry->hwcap == 0)
355 file_entries->libs[idx_old].flags = entry->flags;
356 /* XXX: Actually we can optimize here and remove duplicates. */
357 file_entries->libs[idx_old].key = str_offset + pad;
361 /* We could subtract file_entries_new_size from str_offset -
362 not doing so makes the code easier, the string table
363 always begins at the beginning of the new cache
365 file_entries_new->libs[idx_new].flags = entry->flags;
366 file_entries_new->libs[idx_new].osversion = entry->osversion;
367 file_entries_new->libs[idx_new].hwcap = entry->hwcap;
368 file_entries_new->libs[idx_new].key = str_offset;
371 size_t len = strlen (entry->lib) + 1;
372 str = mempcpy (str, entry->lib, len);
375 if (opt_format != 2 && entry->hwcap == 0)
376 file_entries->libs[idx_old].value = str_offset + pad;
378 file_entries_new->libs[idx_new].value = str_offset;
379 len = strlen (entry->path) + 1;
380 str = mempcpy (str, entry->path, len);
382 /* Ignore entries with hwcap for old format. */
383 if (entry->hwcap == 0)
387 /* Duplicate last old cache entry if needed. */
389 && idx_old < cache_entry_old_count)
390 file_entries->libs[idx_old] = file_entries->libs[idx_old - 1];
392 /* Write out the cache. */
394 /* Write cache first to a temporary file and rename it later. */
395 char *temp_name = xmalloc (strlen (cache_name) + 2);
396 sprintf (temp_name, "%s~", cache_name);
399 int fd = open (temp_name, O_CREAT|O_WRONLY|O_TRUNC|O_NOFOLLOW,
402 error (EXIT_FAILURE, errno, _("Can't create temporary cache file %s"),
405 /* Write contents. */
408 if (write (fd, file_entries, file_entries_size)
409 != (ssize_t) file_entries_size)
410 error (EXIT_FAILURE, errno, _("Writing of cache data failed"));
418 memset (zero, '\0', pad);
419 if (write (fd, zero, pad) != (ssize_t) pad)
420 error (EXIT_FAILURE, errno, _("Writing of cache data failed"));
422 if (write (fd, file_entries_new, file_entries_new_size)
423 != (ssize_t) file_entries_new_size)
424 error (EXIT_FAILURE, errno, _("Writing of cache data failed"));
427 if (write (fd, strings, total_strlen) != (ssize_t) total_strlen
429 error (EXIT_FAILURE, errno, _("Writing of cache data failed"));
431 /* Make sure user can always read cache file */
432 if (chmod (temp_name, S_IROTH|S_IRGRP|S_IRUSR|S_IWUSR))
433 error (EXIT_FAILURE, errno,
434 _("Changing access rights of %s to %#o failed"), temp_name,
435 S_IROTH|S_IRGRP|S_IRUSR|S_IWUSR);
437 /* Move temporary to its final location. */
438 if (rename (temp_name, cache_name))
439 error (EXIT_FAILURE, errno, _("Renaming of %s to %s failed"), temp_name,
442 /* Free all allocated memory. */
443 free (file_entries_new);
450 entries = entries->next;
456 /* Add one library to the cache. */
458 add_to_cache (const char *path, const char *lib, int flags,
459 unsigned int osversion, uint64_t hwcap)
461 size_t liblen = strlen (lib) + 1;
462 size_t len = liblen + strlen (path) + 1;
463 struct cache_entry *new_entry
464 = xmalloc (sizeof (struct cache_entry) + liblen + len);
466 new_entry->lib = memcpy ((char *) (new_entry + 1), lib, liblen);
467 new_entry->path = new_entry->lib + liblen;
468 snprintf (new_entry->path, len, "%s/%s", path, lib);
469 new_entry->flags = flags;
470 new_entry->osversion = osversion;
471 new_entry->hwcap = hwcap;
472 new_entry->bits_hwcap = 0;
474 /* Count the number of bits set in the masked value. */
476 (~((1ULL << i) - 1) & hwcap) != 0 && i < 8 * sizeof (hwcap); ++i)
477 if ((hwcap & (1ULL << i)) != 0)
478 ++new_entry->bits_hwcap;
481 /* Keep the list sorted - search for right place to insert. */
482 struct cache_entry *ptr = entries;
483 struct cache_entry *prev = entries;
486 if (compare (ptr, new_entry) > 0)
491 /* Is this the first entry? */
494 new_entry->next = entries;
499 new_entry->next = prev->next;
500 prev->next = new_entry;
505 /* Auxiliary cache. */
507 struct aux_cache_entry_id
515 struct aux_cache_entry
517 struct aux_cache_entry_id id;
519 unsigned int osversion;
522 struct aux_cache_entry *next;
525 #define AUX_CACHEMAGIC "glibc-ld.so.auxcache-1.0"
527 struct aux_cache_file_entry
529 struct aux_cache_entry_id id; /* Unique id of entry. */
530 int32_t flags; /* This is 1 for an ELF library. */
531 uint32_t soname; /* String table indice. */
532 uint32_t osversion; /* Required OS version. */
536 /* ldconfig maintains an auxiliary cache file that allows
537 only reading those libraries that have changed since the last iteration.
538 For this for each library some information is cached in the auxiliary
540 struct aux_cache_file
542 char magic[sizeof AUX_CACHEMAGIC - 1];
543 uint32_t nlibs; /* Number of entries. */
544 uint32_t len_strings; /* Size of string table. */
545 struct aux_cache_file_entry libs[0]; /* Entries describing libraries. */
546 /* After this the string table of size len_strings is found. */
549 static const unsigned int primes[] =
551 1021, 2039, 4093, 8191, 16381, 32749, 65521, 131071, 262139,
552 524287, 1048573, 2097143, 4194301, 8388593, 16777213, 33554393,
553 67108859, 134217689, 268435399, 536870909, 1073741789, 2147483647
556 static size_t aux_hash_size;
557 static struct aux_cache_entry **aux_hash;
559 /* Simplistic hash function for aux_cache_entry_id. */
561 aux_cache_entry_id_hash (struct aux_cache_entry_id *id)
563 uint64_t ret = ((id->ino * 11 + id->ctime) * 11 + id->size) * 11 + id->dev;
564 return ret ^ (ret >> 32);
567 static size_t nextprime (size_t x)
569 for (unsigned int i = 0; i < sizeof (primes) / sizeof (primes[0]); ++i)
576 init_aux_cache (void)
578 aux_hash_size = primes[3];
579 aux_hash = xcalloc (aux_hash_size, sizeof (struct aux_cache_entry *));
583 search_aux_cache (struct stat64 *stat_buf, int *flags,
584 unsigned int *osversion, char **soname)
586 struct aux_cache_entry_id id;
587 id.ino = (uint64_t) stat_buf->st_ino;
588 id.ctime = (uint64_t) stat_buf->st_ctime;
589 id.size = (uint64_t) stat_buf->st_size;
590 id.dev = (uint64_t) stat_buf->st_dev;
592 unsigned int hash = aux_cache_entry_id_hash (&id);
593 struct aux_cache_entry *entry;
594 for (entry = aux_hash[hash % aux_hash_size]; entry; entry = entry->next)
595 if (id.ino == entry->id.ino
596 && id.ctime == entry->id.ctime
597 && id.size == entry->id.size
598 && id.dev == entry->id.dev)
600 *flags = entry->flags;
601 *osversion = entry->osversion;
602 if (entry->soname != NULL)
603 *soname = xstrdup (entry->soname);
614 insert_to_aux_cache (struct aux_cache_entry_id *id, int flags,
615 unsigned int osversion, const char *soname, int used)
617 size_t hash = aux_cache_entry_id_hash (id) % aux_hash_size;
618 struct aux_cache_entry *entry;
619 for (entry = aux_hash[hash]; entry; entry = entry->next)
620 if (id->ino == entry->id.ino
621 && id->ctime == entry->id.ctime
622 && id->size == entry->id.size
623 && id->dev == entry->id.dev)
626 size_t len = soname ? strlen (soname) + 1 : 0;
627 entry = xmalloc (sizeof (struct aux_cache_entry) + len);
629 entry->flags = flags;
630 entry->osversion = osversion;
633 entry->soname = memcpy ((char *) (entry + 1), soname, len);
635 entry->soname = NULL;
636 entry->next = aux_hash[hash];
637 aux_hash[hash] = entry;
641 add_to_aux_cache (struct stat64 *stat_buf, int flags,
642 unsigned int osversion, const char *soname)
644 struct aux_cache_entry_id id;
645 id.ino = (uint64_t) stat_buf->st_ino;
646 id.ctime = (uint64_t) stat_buf->st_ctime;
647 id.size = (uint64_t) stat_buf->st_size;
648 id.dev = (uint64_t) stat_buf->st_dev;
649 insert_to_aux_cache (&id, flags, osversion, soname, 1);
652 /* Load auxiliary cache to search for unchanged entries. */
654 load_aux_cache (const char *aux_cache_name)
656 int fd = open (aux_cache_name, O_RDONLY);
664 if (fstat64 (fd, &st) < 0 || st.st_size < sizeof (struct aux_cache_file))
671 size_t aux_cache_size = st.st_size;
672 struct aux_cache_file *aux_cache
673 = mmap (NULL, aux_cache_size, PROT_READ, MAP_PRIVATE, fd, 0);
674 if (aux_cache == MAP_FAILED
675 || aux_cache_size < sizeof (struct aux_cache_file)
676 || memcmp (aux_cache->magic, AUX_CACHEMAGIC, sizeof AUX_CACHEMAGIC - 1)
677 || aux_cache->nlibs >= aux_cache_size)
684 aux_hash_size = nextprime (aux_cache->nlibs);
685 aux_hash = xcalloc (aux_hash_size, sizeof (struct aux_cache_entry *));
687 const char *aux_cache_data
688 = (const char *) &aux_cache->libs[aux_cache->nlibs];
689 for (unsigned int i = 0; i < aux_cache->nlibs; ++i)
690 insert_to_aux_cache (&aux_cache->libs[i].id,
691 aux_cache->libs[i].flags,
692 aux_cache->libs[i].osversion,
693 aux_cache->libs[i].soname == 0
694 ? NULL : aux_cache_data + aux_cache->libs[i].soname,
697 munmap (aux_cache, aux_cache_size);
701 /* Save the contents of the auxiliary cache. */
703 save_aux_cache (const char *aux_cache_name)
705 /* Count the length of all sonames. We start with empty string. */
706 size_t total_strlen = 1;
707 /* Number of cache entries. */
708 int cache_entry_count = 0;
710 for (size_t i = 0; i < aux_hash_size; ++i)
711 for (struct aux_cache_entry *entry = aux_hash[i];
712 entry != NULL; entry = entry->next)
716 if (entry->soname != NULL)
717 total_strlen += strlen (entry->soname) + 1;
720 /* Auxiliary cache. */
721 size_t file_entries_size
722 = sizeof (struct aux_cache_file)
723 + cache_entry_count * sizeof (struct aux_cache_file_entry);
724 struct aux_cache_file *file_entries
725 = xmalloc (file_entries_size + total_strlen);
727 /* Fill in the header of the auxiliary cache. */
728 memset (file_entries, '\0', sizeof (struct aux_cache_file));
729 memcpy (file_entries->magic, AUX_CACHEMAGIC, sizeof AUX_CACHEMAGIC - 1);
731 file_entries->nlibs = cache_entry_count;
732 file_entries->len_strings = total_strlen;
734 /* Initial String offset for auxiliary cache is always after the
735 special empty string. */
736 unsigned int str_offset = 1;
738 /* An array for all strings. */
739 char *str = (char *) file_entries + file_entries_size;
743 for (size_t i = 0; i < aux_hash_size; ++i)
744 for (struct aux_cache_entry *entry = aux_hash[i];
745 entry != NULL; entry = entry->next)
748 file_entries->libs[idx].id = entry->id;
749 file_entries->libs[idx].flags = entry->flags;
750 if (entry->soname == NULL)
751 file_entries->libs[idx].soname = 0;
754 file_entries->libs[idx].soname = str_offset;
756 size_t len = strlen (entry->soname) + 1;
757 str = mempcpy (str, entry->soname, len);
760 file_entries->libs[idx].osversion = entry->osversion;
761 file_entries->libs[idx++].pad = 0;
764 /* Write out auxiliary cache file. */
765 /* Write auxiliary cache first to a temporary file and rename it later. */
767 char *temp_name = xmalloc (strlen (aux_cache_name) + 2);
768 sprintf (temp_name, "%s~", aux_cache_name);
770 /* Check that directory exists and create if needed. */
771 char *dir = strdupa (aux_cache_name);
775 if (stat64 (dir, &st) < 0)
777 if (mkdir (dir, 0700) < 0)
782 int fd = open (temp_name, O_CREAT|O_WRONLY|O_TRUNC|O_NOFOLLOW,
787 if (write (fd, file_entries, file_entries_size + total_strlen)
788 != (ssize_t) (file_entries_size + total_strlen)
795 /* Move temporary to its final location. */
796 if (rename (temp_name, aux_cache_name))
800 /* Free allocated memory. */