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 *
glibc_hwcaps_subdirectory_name(const struct glibc_hwcaps_subdirectory * dir)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 *
new_glibc_hwcaps_subdirectory(const char * name)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
assign_glibc_hwcaps_indices_compare(const void * l,const void * r)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
glibc_hwcaps_count(void)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
assign_glibc_hwcaps_indices(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
print_entry(const char * lib,int flag,uint64_t hwcap,const char * hwcap_string,const char * key)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 *
glibc_hwcaps_string(struct cache_extension_all_loaded * ext,const void * file_base,size_t file_size,struct file_entry_new * entry)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
check_new_cache(struct cache_file_new * cache)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
print_extensions(struct cache_extension_all_loaded * ext)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
print_cache(const char * cache_name)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
init_cache(void)407 init_cache (void)
408 {
409   entries = NULL;
410 }
411 
412 static int
compare(const struct cache_entry * e1,const struct cache_entry * e2)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
write_extensions(int fd,uint32_t str_offset,uint32_t cache_extension_offset)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
compute_hwcap_value(struct cache_entry * entry)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
save_cache(const char * cache_name)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
add_to_cache(const char * path,const char * filename,const char * soname,int flags,unsigned int isa_level,uint64_t hwcap,struct glibc_hwcaps_subdirectory * hwcaps)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
aux_cache_entry_id_hash(struct aux_cache_entry_id * id)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 
nextprime(size_t x)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
init_aux_cache(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
search_aux_cache(struct stat * stat_buf,int * flags,unsigned int * isa_level,char ** soname)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
insert_to_aux_cache(struct aux_cache_entry_id * id,int flags,unsigned int isa_level,const char * soname,int used)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
add_to_aux_cache(struct stat * stat_buf,int flags,unsigned int isa_level,const char * soname)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
load_aux_cache(const char * aux_cache_name)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
save_aux_cache(const char * aux_cache_name)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 }
1134