]> git.ipfire.org Git - thirdparty/glibc.git/blame - sysdeps/generic/dl-cache.h
Update copyright dates with scripts/update-copyrights
[thirdparty/glibc.git] / sysdeps / generic / dl-cache.h
CommitLineData
c41baa79 1/* Support for reading /etc/ld.so.cache files written by Linux ldconfig.
6d7e8eda 2 Copyright (C) 1999-2023 Free Software Foundation, Inc.
c41baa79
UD
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
c41baa79
UD
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41bdb6e2 13 Lesser General Public License for more details.
c41baa79 14
41bdb6e2 15 You should have received a copy of the GNU Lesser General Public
59ba27a6 16 License along with the GNU C Library; if not, see
5a82c748 17 <https://www.gnu.org/licenses/>. */
c41baa79 18
84ba719b
FW
19#ifndef _DL_CACHE_H
20#define _DL_CACHE_H
21
22#include <endian.h>
23#include <stdbool.h>
dfb3f101 24#include <stddef.h>
a8fd59b0 25#include <stdint.h>
dfb3f101 26#include <string.h>
a8fd59b0 27
e25054c4
AJ
28#ifndef _DL_CACHE_DEFAULT_ID
29# define _DL_CACHE_DEFAULT_ID 3
30#endif
c41baa79 31
e25054c4
AJ
32#ifndef _dl_cache_check_flags
33# define _dl_cache_check_flags(flags) \
c41baa79 34 ((flags) == 1 || (flags) == _DL_CACHE_DEFAULT_ID)
e25054c4 35#endif
45eca4d1
UD
36
37#ifndef LD_SO_CACHE
8ca91b36 38# define LD_SO_CACHE SYSCONFDIR "/ld.so.cache"
45eca4d1
UD
39#endif
40
bd89c0b5
UD
41#ifndef add_system_dir
42# define add_system_dir(dir) add_dir (dir)
43#endif
44
45eca4d1
UD
45#define CACHEMAGIC "ld.so-1.7.0"
46
47/* libc5 and glibc 2.0/2.1 use the same format. For glibc 2.2 another
48 format has been added in a compatible way:
49 The beginning of the string table is used for the new table:
e25054c4 50 old_magic
45eca4d1
UD
51 nlibs
52 libs[0]
53 ...
54 libs[nlibs-1]
e25054c4
AJ
55 pad, new magic needs to be aligned
56 - this is string[0] for the old format
57 new magic - this is string[0] for the new format
45eca4d1
UD
58 newnlibs
59 ...
60 newlibs[0]
61 ...
62 newlibs[newnlibs-1]
63 string 1
64 string 2
65 ...
66*/
67struct file_entry
68{
de1a9197
FW
69 int32_t flags; /* This is 1 for an ELF library. */
70 uint32_t key, value; /* String table indices. */
45eca4d1
UD
71};
72
73struct cache_file
74{
75 char magic[sizeof CACHEMAGIC - 1];
76 unsigned int nlibs;
77 struct file_entry libs[0];
78};
79
80#define CACHEMAGIC_NEW "glibc-ld.so.cache"
a8fd59b0 81#define CACHE_VERSION "1.1"
ea029468 82#define CACHEMAGIC_VERSION_NEW CACHEMAGIC_NEW CACHE_VERSION
45eca4d1
UD
83
84
85struct file_entry_new
86{
de1a9197
FW
87 union
88 {
89 /* Fields shared with struct file_entry. */
90 struct file_entry entry;
91 /* Also expose these fields directly. */
92 struct
93 {
94 int32_t flags; /* This is 1 for an ELF library. */
95 uint32_t key, value; /* String table indices. */
96 };
97 };
c628c229 98 uint32_t osversion_unused; /* Required OS version (unused). */
a8fd59b0 99 uint64_t hwcap; /* Hwcap entry. */
45eca4d1
UD
100};
101
b44ac4f4
FW
102/* This bit in the hwcap field of struct file_entry_new indicates that
103 the lower 32 bits contain an index into the
104 cache_extension_tag_glibc_hwcaps section. Older glibc versions do
105 not know about this HWCAP bit, so they will ignore these
106 entries. */
107#define DL_CACHE_HWCAP_EXTENSION (1ULL << 62)
108
efbbd9c3
L
109/* The number of the ISA level bits in the upper 32 bits of the hwcap
110 field. */
111#define DL_CACHE_HWCAP_ISA_LEVEL_COUNT 10
112
113/* The mask of the ISA level bits in the hwcap field. */
114#define DL_CACHE_HWCAP_ISA_LEVEL_MASK \
115 ((1 << DL_CACHE_HWCAP_ISA_LEVEL_COUNT) -1)
116
b44ac4f4
FW
117/* Return true if the ENTRY->hwcap value indicates that
118 DL_CACHE_HWCAP_EXTENSION is used. */
119static inline bool
120dl_cache_hwcap_extension (struct file_entry_new *entry)
121{
efbbd9c3
L
122 /* This is an hwcap extension if only the DL_CACHE_HWCAP_EXTENSION bit
123 is set, ignoring the lower 32 bits as well as the ISA level bits in
124 the upper 32 bits. */
125 return (((entry->hwcap >> 32) & ~DL_CACHE_HWCAP_ISA_LEVEL_MASK)
126 == (DL_CACHE_HWCAP_EXTENSION >> 32));
b44ac4f4
FW
127}
128
84ba719b
FW
129/* See flags member of struct cache_file_new below. */
130enum
131 {
132 /* No endianness information available. An old ldconfig version
133 without endianness support wrote the file. */
134 cache_file_new_flags_endian_unset = 0,
135
136 /* Cache is invalid and should be ignored. */
137 cache_file_new_flags_endian_invalid = 1,
138
139 /* Cache format is little endian. */
140 cache_file_new_flags_endian_little = 2,
141
142 /* Cache format is big endian. */
143 cache_file_new_flags_endian_big = 3,
144
145 /* Bit mask to extract the cache_file_new_flags_endian_*
146 values. */
147 cache_file_new_flags_endian_mask = 3,
148
149 /* Expected value of the endian bits in the flags member for the
150 current architecture. */
151 cache_file_new_flags_endian_current
152 = (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
153 ? cache_file_new_flags_endian_little
154 : cache_file_new_flags_endian_big),
155 };
156
45eca4d1
UD
157struct cache_file_new
158{
159 char magic[sizeof CACHEMAGIC_NEW - 1];
160 char version[sizeof CACHE_VERSION - 1];
a8fd59b0
AJ
161 uint32_t nlibs; /* Number of entries. */
162 uint32_t len_strings; /* Size of string table. */
84ba719b
FW
163
164 /* flags & cache_file_new_flags_endian_mask is one of the values
165 cache_file_new_flags_endian_unset, cache_file_new_flags_endian_invalid,
166 cache_file_new_flags_endian_little, cache_file_new_flags_endian_big.
167
168 The remaining bits are unused and should be generated as zero and
169 ignored by readers. */
170 uint8_t flags;
171
172 uint8_t padding_unsed[3]; /* Not used, for future extensions. */
173
dfb3f101
FW
174 /* File offset of the extension directory. See struct
175 cache_extension below. Must be a multiple of four. */
176 uint32_t extension_offset;
177
178 uint32_t unused[3]; /* Leave space for future extensions
a8fd59b0 179 and align to 8 byte boundary. */
45eca4d1 180 struct file_entry_new libs[0]; /* Entries describing libraries. */
a8fd59b0 181 /* After this the string table of size len_strings is found. */
45eca4d1 182};
84ba719b
FW
183_Static_assert (sizeof (struct cache_file_new) == 48,
184 "size of struct cache_file_new");
185
186/* Returns false if *CACHE has the wrong endianness for this
187 architecture, and true if the endianness matches (or is
188 unknown). */
189static inline bool
190cache_file_new_matches_endian (const struct cache_file_new *cache)
191{
192 /* A zero value for cache->flags means that no endianness
193 information is available. */
194 return cache->flags == 0
195 || ((cache->flags & cache_file_new_flags_endian_big)
196 == cache_file_new_flags_endian_current);
197}
198
45eca4d1 199
dfb3f101
FW
200/* Randomly chosen magic value, which allows for additional
201 consistency verification. */
202enum { cache_extension_magic = (uint32_t) -358342284 };
203
204/* Tag values for different kinds of extension sections. Similar to
205 SHT_* constants. */
206enum cache_extension_tag
207 {
208 /* Array of bytes containing the glibc version that generated this
209 cache file. */
210 cache_extension_tag_generator,
211
b44ac4f4
FW
212 /* glibc-hwcaps subdirectory information. An array of uint32_t
213 values, which are indices into the string table. The strings
214 are sorted lexicographically (according to strcmp). The extra
215 level of indirection (instead of using string table indices
216 directly) allows the dynamic loader to compute the preference
217 order of the hwcaps names more efficiently.
218
219 For this section, 4-byte alignment is required, and the section
220 size must be a multiple of 4. */
221 cache_extension_tag_glibc_hwcaps,
222
dfb3f101
FW
223 /* Total number of known cache extension tags. */
224 cache_extension_count
225 };
226
227/* Element in the array following struct cache_extension. Similar to
228 an ELF section header. */
229struct cache_extension_section
230{
231 /* Type of the extension section. A enum cache_extension_tag value. */
232 uint32_t tag;
233
234 /* Extension-specific flags. Currently generated as zero. */
235 uint32_t flags;
236
237 /* Offset from the start of the file for the data in this extension
238 section. Specific extensions can have alignment constraints. */
239 uint32_t offset;
240
241 /* Length in bytes of the extension data. Specific extensions may
242 have size requirements. */
243 uint32_t size;
244};
245
246/* The extension directory in the cache. An array of struct
247 cache_extension_section entries. */
248struct cache_extension
249{
250 uint32_t magic; /* Always cache_extension_magic. */
251 uint32_t count; /* Number of following entries. */
252
253 /* count section descriptors of type struct cache_extension_section
254 follow. */
255 struct cache_extension_section sections[];
256};
257
258/* A relocated version of struct cache_extension_section. */
259struct cache_extension_loaded
260{
261 /* Address and size of this extension section. base is NULL if the
262 section is missing from the file. */
263 const void *base;
264 size_t size;
265
266 /* Flags from struct cache_extension_section. */
267 uint32_t flags;
268};
269
270/* All supported extension sections, relocated. Filled in by
271 cache_extension_load below. */
272struct cache_extension_all_loaded
273{
274 struct cache_extension_loaded sections[cache_extension_count];
275};
276
b44ac4f4
FW
277/* Performs basic data validation based on section tag, and removes
278 the sections which are invalid. */
279static void
280cache_extension_verify (struct cache_extension_all_loaded *loaded)
281{
282 {
283 /* Section must not be empty, it must be aligned at 4 bytes, and
284 the size must be a multiple of 4. */
285 struct cache_extension_loaded *hwcaps
286 = &loaded->sections[cache_extension_tag_glibc_hwcaps];
287 if (hwcaps->size == 0
288 || ((uintptr_t) hwcaps->base % 4) != 0
289 || (hwcaps->size % 4) != 0)
290 {
291 hwcaps->base = NULL;
292 hwcaps->size = 0;
293 hwcaps->flags = 0;
294 }
295 }
296}
297
dfb3f101
FW
298static bool __attribute__ ((unused))
299cache_extension_load (const struct cache_file_new *cache,
300 const void *file_base, size_t file_size,
301 struct cache_extension_all_loaded *loaded)
302{
303 memset (loaded, 0, sizeof (*loaded));
304 if (cache->extension_offset == 0)
305 /* No extensions present. This is not a format error. */
306 return true;
307 if ((cache->extension_offset % 4) != 0)
308 /* Extension offset is misaligned. */
309 return false;
310 size_t size_tmp;
311 if (__builtin_add_overflow (cache->extension_offset,
312 sizeof (struct cache_extension), &size_tmp)
313 || size_tmp > file_size)
314 /* Extension extends beyond the end of the file. */
315 return false;
316 const struct cache_extension *ext = file_base + cache->extension_offset;
317 if (ext->magic != cache_extension_magic)
318 return false;
319 if (__builtin_mul_overflow (ext->count,
320 sizeof (struct cache_extension_section),
321 &size_tmp)
322 || __builtin_add_overflow (cache->extension_offset
323 + sizeof (struct cache_extension), size_tmp,
324 &size_tmp)
325 || size_tmp > file_size)
326 /* Extension array extends beyond the end of the file. */
327 return false;
328 for (uint32_t i = 0; i < ext->count; ++i)
329 {
330 if (__builtin_add_overflow (ext->sections[i].offset,
331 ext->sections[i].size, &size_tmp)
332 || size_tmp > file_size)
333 /* Extension data extends beyond the end of the file. */
334 return false;
335
336 uint32_t tag = ext->sections[i].tag;
337 if (tag >= cache_extension_count)
338 /* Tag is out of range and unrecognized. */
339 continue;
340 loaded->sections[tag].base = file_base + ext->sections[i].offset;
341 loaded->sections[tag].size = ext->sections[i].size;
342 loaded->sections[tag].flags = ext->sections[i].flags;
343 }
b44ac4f4 344 cache_extension_verify (loaded);
dfb3f101
FW
345 return true;
346}
347
e25054c4
AJ
348/* Used to align cache_file_new. */
349#define ALIGN_CACHE(addr) \
350(((addr) + __alignof__ (struct cache_file_new) -1) \
351 & (~(__alignof__ (struct cache_file_new) - 1)))
352
17e00cc6 353extern int _dl_cache_libcmp (const char *p1, const char *p2) attribute_hidden;
84ba719b
FW
354
355#endif /* _DL_CACHE_H */