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