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