1 /* Support for reading /etc/ld.so.cache files written by Linux ldconfig.
2 Copyright (C) 1999-2023 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
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.
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
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
28 #ifndef _DL_CACHE_DEFAULT_ID
29 # define _DL_CACHE_DEFAULT_ID 3
32 #ifndef _dl_cache_check_flags
33 # define _dl_cache_check_flags(flags) \
34 ((flags) == 1 || (flags) == _DL_CACHE_DEFAULT_ID)
38 # define LD_SO_CACHE SYSCONFDIR "/ld.so.cache"
41 #ifndef add_system_dir
42 # define add_system_dir(dir) add_dir (dir)
45 #define CACHEMAGIC "ld.so-1.7.0"
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:
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
69 int32_t flags
; /* This is 1 for an ELF library. */
70 uint32_t key
, value
; /* String table indices. */
75 char magic
[sizeof CACHEMAGIC
- 1];
77 struct file_entry libs
[0];
80 #define CACHEMAGIC_NEW "glibc-ld.so.cache"
81 #define CACHE_VERSION "1.1"
82 #define CACHEMAGIC_VERSION_NEW CACHEMAGIC_NEW CACHE_VERSION
89 /* Fields shared with struct file_entry. */
90 struct file_entry entry
;
91 /* Also expose these fields directly. */
94 int32_t flags
; /* This is 1 for an ELF library. */
95 uint32_t key
, value
; /* String table indices. */
98 uint32_t osversion_unused
; /* Required OS version (unused). */
99 uint64_t hwcap
; /* Hwcap entry. */
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
107 #define DL_CACHE_HWCAP_EXTENSION (1ULL << 62)
109 /* The number of the ISA level bits in the upper 32 bits of the hwcap
111 #define DL_CACHE_HWCAP_ISA_LEVEL_COUNT 10
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)
117 /* Return true if the ENTRY->hwcap value indicates that
118 DL_CACHE_HWCAP_EXTENSION is used. */
120 dl_cache_hwcap_extension (struct file_entry_new
*entry
)
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));
129 /* See flags member of struct cache_file_new below. */
132 /* No endianness information available. An old ldconfig version
133 without endianness support wrote the file. */
134 cache_file_new_flags_endian_unset
= 0,
136 /* Cache is invalid and should be ignored. */
137 cache_file_new_flags_endian_invalid
= 1,
139 /* Cache format is little endian. */
140 cache_file_new_flags_endian_little
= 2,
142 /* Cache format is big endian. */
143 cache_file_new_flags_endian_big
= 3,
145 /* Bit mask to extract the cache_file_new_flags_endian_*
147 cache_file_new_flags_endian_mask
= 3,
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
),
157 struct cache_file_new
159 char magic
[sizeof CACHEMAGIC_NEW
- 1];
160 char version
[sizeof CACHE_VERSION
- 1];
161 uint32_t nlibs
; /* Number of entries. */
162 uint32_t len_strings
; /* Size of string table. */
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.
168 The remaining bits are unused and should be generated as zero and
169 ignored by readers. */
172 uint8_t padding_unsed
[3]; /* Not used, for future extensions. */
174 /* File offset of the extension directory. See struct
175 cache_extension below. Must be a multiple of four. */
176 uint32_t extension_offset
;
178 uint32_t unused
[3]; /* Leave space for future extensions
179 and align to 8 byte boundary. */
180 struct file_entry_new libs
[0]; /* Entries describing libraries. */
181 /* After this the string table of size len_strings is found. */
183 _Static_assert (sizeof (struct cache_file_new
) == 48,
184 "size of struct cache_file_new");
186 /* Returns false if *CACHE has the wrong endianness for this
187 architecture, and true if the endianness matches (or is
190 cache_file_new_matches_endian (const struct cache_file_new
*cache
)
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
);
200 /* Randomly chosen magic value, which allows for additional
201 consistency verification. */
202 enum { cache_extension_magic
= (uint32_t) -358342284 };
204 /* Tag values for different kinds of extension sections. Similar to
206 enum cache_extension_tag
208 /* Array of bytes containing the glibc version that generated this
210 cache_extension_tag_generator
,
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.
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
,
223 /* Total number of known cache extension tags. */
224 cache_extension_count
227 /* Element in the array following struct cache_extension. Similar to
228 an ELF section header. */
229 struct cache_extension_section
231 /* Type of the extension section. A enum cache_extension_tag value. */
234 /* Extension-specific flags. Currently generated as zero. */
237 /* Offset from the start of the file for the data in this extension
238 section. Specific extensions can have alignment constraints. */
241 /* Length in bytes of the extension data. Specific extensions may
242 have size requirements. */
246 /* The extension directory in the cache. An array of struct
247 cache_extension_section entries. */
248 struct cache_extension
250 uint32_t magic
; /* Always cache_extension_magic. */
251 uint32_t count
; /* Number of following entries. */
253 /* count section descriptors of type struct cache_extension_section
255 struct cache_extension_section sections
[];
258 /* A relocated version of struct cache_extension_section. */
259 struct cache_extension_loaded
261 /* Address and size of this extension section. base is NULL if the
262 section is missing from the file. */
266 /* Flags from struct cache_extension_section. */
270 /* All supported extension sections, relocated. Filled in by
271 cache_extension_load below. */
272 struct cache_extension_all_loaded
274 struct cache_extension_loaded sections
[cache_extension_count
];
277 /* Performs basic data validation based on section tag, and removes
278 the sections which are invalid. */
280 cache_extension_verify (struct cache_extension_all_loaded
*loaded
)
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)
298 static bool __attribute__ ((unused
))
299 cache_extension_load (const struct cache_file_new
*cache
,
300 const void *file_base
, size_t file_size
,
301 struct cache_extension_all_loaded
*loaded
)
303 memset (loaded
, 0, sizeof (*loaded
));
304 if (cache
->extension_offset
== 0)
305 /* No extensions present. This is not a format error. */
307 if ((cache
->extension_offset
% 4) != 0)
308 /* Extension offset is misaligned. */
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. */
316 const struct cache_extension
*ext
= file_base
+ cache
->extension_offset
;
317 if (ext
->magic
!= cache_extension_magic
)
319 if (__builtin_mul_overflow (ext
->count
,
320 sizeof (struct cache_extension_section
),
322 || __builtin_add_overflow (cache
->extension_offset
323 + sizeof (struct cache_extension
), size_tmp
,
325 || size_tmp
> file_size
)
326 /* Extension array extends beyond the end of the file. */
328 for (uint32_t i
= 0; i
< ext
->count
; ++i
)
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. */
336 uint32_t tag
= ext
->sections
[i
].tag
;
337 if (tag
>= cache_extension_count
)
338 /* Tag is out of range and unrecognized. */
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
;
344 cache_extension_verify (loaded
);
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)))
353 extern int _dl_cache_libcmp (const char *p1
, const char *p2
) attribute_hidden
;
355 #endif /* _DL_CACHE_H */