mirror of
git://sourceware.org/git/glibc.git
synced 2024-12-27 04:41:02 +08:00
9c7ff11a5c
2003-06-11 Ulrich Drepper <drepper@redhat.com> * time/tzfile.c: Add a couple of __builtin_expect. Remove warnings gcc 3.3 shows. * argp/argp-help.c (hol_entry_short_iterate): Don't inline. * elf/dl-load.c (fillin_rpath): Likewise. (add_path): Likewise. * elf/dl-version.c (find_needed): Always inline. * elf/do-lookup.c (FCT): Don't inline. * iconv/Makefile: Extend vpath to intl subdir. (iconvconfig-modules): Add hash-string. * iconv/gconv_charset.h (strip): Don't inline. (upstr): Always inline. Move __gconv_compare_alias prototype to... * iconv/gconv_int.h: ...here. * iconv/gconv_db.c: Don't include gconv_charset.h. * iconv/gconv_conf.c (add_alias): Don't inline. (insert_module): Likewise. * iconv/gconv_simple.c (internal_ucs4_loop): Always inline. (internal_ucs4_loop_unaligned): Likewise. (internal_ucs4_loop_single): Likewise. (ucs4_internal_loop): Likewise. (ucs4_internal_loop_unaligned): Likewise. (ucs4_internal_loop_single): Likewise. (internal_ucs4le_loop): Always inline. (internal_ucs4le_loop_unaligned): Likewise. (internal_ucs4le_loop_single): Likewise. (ucs4le_internal_loop): Likewise. (ucs4le_internal_loop_unaligned): Likewise. (ucs4le_internal_loop_single): Likewise. * iconv/loop.c: Always inline the defined functions. * iconvdata/cns11642.h: Likewise. * iconvdata/cns11642l1.h: Likewise. * iconvdata/euc-kr.c: Likewise. * iconvdata/gb2312.h: Likewise. * iconvdata/jis0201.h: Likewise. * iconvdata/jis0208.h: Likewise. * iconvdata/jis0212.h: Likewise. * iconvdata/jisx0213.h: Likewise. * iconvdata/ksc5601.h: Likewise. * iconvdata/utf-7.c (base64): Don't inline. * include/libc-symbols.h (symbol_set_first_element): Add cast (symbol_set_end_p): Likewise. * include/set-hooks (RUN_HOOK): Likewise. * inet/Makefile (aux): Add ifreq. * intl/Makefile (aux): Add some entries from routines. Add hash-string. * intl/hash-string.c: New file. * intl/hash-string.h: Remove hash_string definition. Declare __hash_string. * iconv/gconv_cache.c (find_module_idx): Adjust hash_string caller. * iconv/iconvconfig.c (new_name): Likewise. * intl/dcigettext.c (_nl_find_msg): Likewise. * intl/loadmsgcat.c (_nl_load_domain): Likewise. * io/ftw.c (open_dir_stream): Always inline. (process_entry): Don't inline. * locale/findlocale.c: Include gconv_int.h. * locale/setlocale.c (new_composite_name): Don't inline. * locale/weight.h (findidx): Always inline. * locale/weightwc.h (findidx): Likewise. * locale/programs/linereader.c (lr_ignore_rest): Define here. * locale/programs/linereader.h (lr_ignore_rest): Don't define here, just declare it. (lr_getc): Always inline. (lr_ungetc): Likewise. * nss/nss_files/files-parse.c (parse_list): Likewise. * stdio-common/Makefile (aux): Add printf-parsemb and printf-parsewc. * stdio-common/_itoa.h (_itoa_word): Always inline. (_fitoa_word, _fitoa): Don't define here, only declare. * stdio-common/_itoa.c (_iftoa_word): Add here. (_fitoa): Likewise. * stdio-common/_itowa.h (_itowa_word): Always inline. * stdio-common/printf-parse.h (read_int): Don't inline. (find_spec): Don't define. Declare __find_specmb and __find_specwc. (parse_one_spec): Don't define. Declare __parse_one_specmb and __parse_one_specwc. * stdio-common/printf-parsemb.c: New file. * stdio-common/printf-parsewc.c: New file. * stdio-common/vfprintf.c: Update calls to find_spec and parse_one_spec for new names. * stdio-common/printf-prs.c: Likewise. Define DONT_NEED_READ_INT. * stdlib/Makefile (aux): Add grouping and groupingwc. * stdlib/grouping.c: New file. * stdlib/groupingwc.c: New file. * stdlib/grouping.h (correctly_grouped_prefix): Don't define here. Just prototype. * stdlib/rpmatch.c (try): Don't inline. * stdlib/strtod.c (round_and_return): Don't line. (str_to_mpn): Likewise. (__mpn_lshift_1): Always inline. Optimize only for constant count. Adjust for name change of correctly_grouped_prefix. * sysdeps/generic/strtol.c: Adjust for name change of correctly_grouped_prefix. * string/strxfrm.c (utf8_encode): Don't inline. * sysdeps/generic/dl-cache.c: Define _dl_cache_libcmp. * sysdeps/generic/dl-cache.h: Just declare _dl_cache_libcmp. * sysdeps/generic/ifreq.c: New file. * sysdeps/unix/sysv/linux/ifreq.c: New file. * sysdeps/generic/ifreq.h (__ifreq): Only declare here. * sysdeps/unix/sysv/linux/ifreq.h: Likewise. * sysdeps/generic/ldsodefs.h (_dl_name_match_p): Always inline. * sysdeps/generic/unwind-dw2-fde.c (start_fde_sort): Don't inline. (fde_split): Likewise. (fde_merge): Likewise. (end_fde_sort): Likewise. (init_object): Likewise. (binary_search_unencoded_fdes): Likewise. (binary_search_single_encoding_fdes): Likewise. (binary_search_mixed_encoding_fdes): Likewise. * sysdeps/generic/wordexp.c (w_addchar): Don't inline. * sysdeps/i386/dl-machine.c (elf_machine_runtime_setup): Always inline. * sysdeps/posix/sprofil.c (profil_count): Don't inline. * sysdeps/unix/sysv/linux/Makefile [subdir=io] (sysdep_routines): Add xstatconv. * sysdeps/unix/sysv/linux/xstatconv.h: New file. * sysdeps/unix/sysv/linux/xstatconv.c: Don't inline the function. Export them. Prepend __ to name. * sysdeps/unix/sysv/linux/Dist: Add xstatconv.h. * sysdeps/unix/sysv/linux/fxstat.c: Adjust for name change of conversion functions. * sysdeps/unix/sysv/linux/fxstat64.c: Likewise. * sysdeps/unix/sysv/linux/lxstat.c: Likewise. * sysdeps/unix/sysv/linux/lxstat64.c: Likewise. * sysdeps/unix/sysv/linux/xstat.c: Likewise. * sysdeps/unix/sysv/linux/xstat64.c: Likewise. * sysdeps/unix/sysv/linux/i386/fxstat.c: Likewise. * sysdeps/unix/sysv/linux/i386/lxstat.c: Likewise. * sysdeps/unix/sysv/linux/i386/xstat.c: Likewise. * sysdeps/unix/sysv/linux/pathconf.c (__statfs_link_max, __statfs_filesize_max, __statfs_symlinks): Define here. __ prepended to name. Change callers. * sysdeps/unix/sysv/linux/pathconf.h (__statfs_link_max, __statfs_filesize_max, __statfs_symlinks): Don't define here, just declare. * sysdeps/unix/sysv/linux/fpathconf.c: Change all callers. * time/tzfile.c (decode): Always inline. * wcsmbs/wcsnrtombs.c: Change type of inbuf to unsigned char*. Remove cast in tomb function call. * wcsmbs/wcsrtombs.c Likewise. * wcsmbs/wcstob.c: Introduce new temp variable to take pointer in tomb function call.
314 lines
9.6 KiB
C
314 lines
9.6 KiB
C
/* Support for reading /etc/ld.so.cache files written by Linux ldconfig.
|
|
Copyright (C) 1996-2002, 2003 Free Software Foundation, Inc.
|
|
This file is part of the GNU C Library.
|
|
|
|
The GNU C Library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2.1 of the License, or (at your option) any later version.
|
|
|
|
The GNU C Library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with the GNU C Library; if not, write to the Free
|
|
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
|
02111-1307 USA. */
|
|
|
|
#include <assert.h>
|
|
#include <unistd.h>
|
|
#include <ldsodefs.h>
|
|
#include <sys/mman.h>
|
|
#include <dl-cache.h>
|
|
#include <dl-procinfo.h>
|
|
|
|
#include <stdio-common/_itoa.h>
|
|
|
|
#ifndef _DL_PLATFORMS_COUNT
|
|
# define _DL_PLATFORMS_COUNT 0
|
|
#endif
|
|
|
|
/* This is the starting address and the size of the mmap()ed file. */
|
|
static struct cache_file *cache;
|
|
static struct cache_file_new *cache_new;
|
|
static size_t cachesize;
|
|
|
|
/* 1 if cache_data + PTR points into the cache. */
|
|
#define _dl_cache_verify_ptr(ptr) (ptr < cache_data_size)
|
|
|
|
#define SEARCH_CACHE(cache) \
|
|
/* We use binary search since the table is sorted in the cache file. \
|
|
The first matching entry in the table is returned. \
|
|
It is important to use the same algorithm as used while generating \
|
|
the cache file. */ \
|
|
do \
|
|
{ \
|
|
left = 0; \
|
|
right = cache->nlibs - 1; \
|
|
\
|
|
while (left <= right) \
|
|
{ \
|
|
__typeof__ (cache->libs[0].key) key; \
|
|
\
|
|
middle = (left + right) / 2; \
|
|
\
|
|
key = cache->libs[middle].key; \
|
|
\
|
|
/* Make sure string table indices are not bogus before using \
|
|
them. */ \
|
|
if (! _dl_cache_verify_ptr (key)) \
|
|
{ \
|
|
cmpres = 1; \
|
|
break; \
|
|
} \
|
|
\
|
|
/* Actually compare the entry with the key. */ \
|
|
cmpres = _dl_cache_libcmp (name, cache_data + key); \
|
|
if (__builtin_expect (cmpres == 0, 0)) \
|
|
{ \
|
|
/* Found it. LEFT now marks the last entry for which we \
|
|
know the name is correct. */ \
|
|
left = middle; \
|
|
\
|
|
/* There might be entries with this name before the one we \
|
|
found. So we have to find the beginning. */ \
|
|
while (middle > 0) \
|
|
{ \
|
|
__typeof__ (cache->libs[0].key) key; \
|
|
\
|
|
key = cache->libs[middle - 1].key; \
|
|
/* Make sure string table indices are not bogus before \
|
|
using them. */ \
|
|
if (! _dl_cache_verify_ptr (key) \
|
|
/* Actually compare the entry. */ \
|
|
|| _dl_cache_libcmp (name, cache_data + key) != 0) \
|
|
break; \
|
|
--middle; \
|
|
} \
|
|
\
|
|
do \
|
|
{ \
|
|
int flags; \
|
|
__typeof__ (cache->libs[0]) *lib = &cache->libs[middle]; \
|
|
\
|
|
/* Only perform the name test if necessary. */ \
|
|
if (middle > left \
|
|
/* We haven't seen this string so far. Test whether the \
|
|
index is ok and whether the name matches. Otherwise \
|
|
we are done. */ \
|
|
&& (! _dl_cache_verify_ptr (lib->key) \
|
|
|| (_dl_cache_libcmp (name, cache_data + lib->key) \
|
|
!= 0))) \
|
|
break; \
|
|
\
|
|
flags = lib->flags; \
|
|
if (_dl_cache_check_flags (flags) \
|
|
&& _dl_cache_verify_ptr (lib->value)) \
|
|
{ \
|
|
if (best == NULL || flags == GL(dl_correct_cache_id)) \
|
|
{ \
|
|
HWCAP_CHECK; \
|
|
best = cache_data + lib->value; \
|
|
\
|
|
if (flags == GL(dl_correct_cache_id)) \
|
|
/* We've found an exact match for the shared \
|
|
object and no general `ELF' release. Stop \
|
|
searching. */ \
|
|
break; \
|
|
} \
|
|
} \
|
|
} \
|
|
while (++middle <= right); \
|
|
break; \
|
|
} \
|
|
\
|
|
if (cmpres < 0) \
|
|
left = middle + 1; \
|
|
else \
|
|
right = middle - 1; \
|
|
} \
|
|
} \
|
|
while (0)
|
|
|
|
|
|
int
|
|
internal_function
|
|
_dl_cache_libcmp (const char *p1, const char *p2)
|
|
{
|
|
while (*p1 != '\0')
|
|
{
|
|
if (*p1 >= '0' && *p1 <= '9')
|
|
{
|
|
if (*p2 >= '0' && *p2 <= '9')
|
|
{
|
|
/* Must compare this numerically. */
|
|
int val1;
|
|
int val2;
|
|
|
|
val1 = *p1++ - '0';
|
|
val2 = *p2++ - '0';
|
|
while (*p1 >= '0' && *p1 <= '9')
|
|
val1 = val1 * 10 + *p1++ - '0';
|
|
while (*p2 >= '0' && *p2 <= '9')
|
|
val2 = val2 * 10 + *p2++ - '0';
|
|
if (val1 != val2)
|
|
return val1 - val2;
|
|
}
|
|
else
|
|
return 1;
|
|
}
|
|
else if (*p2 >= '0' && *p2 <= '9')
|
|
return -1;
|
|
else if (*p1 != *p2)
|
|
return *p1 - *p2;
|
|
else
|
|
{
|
|
++p1;
|
|
++p2;
|
|
}
|
|
}
|
|
return *p1 - *p2;
|
|
}
|
|
|
|
|
|
/* Look up NAME in ld.so.cache and return the file name stored there,
|
|
or null if none is found. */
|
|
|
|
const char *
|
|
internal_function
|
|
_dl_load_cache_lookup (const char *name)
|
|
{
|
|
int left, right, middle;
|
|
int cmpres;
|
|
const char *cache_data;
|
|
uint32_t cache_data_size;
|
|
const char *best;
|
|
|
|
/* Print a message if the loading of libs is traced. */
|
|
if (__builtin_expect (GL(dl_debug_mask) & DL_DEBUG_LIBS, 0))
|
|
INTUSE(_dl_debug_printf) (" search cache=%s\n", LD_SO_CACHE);
|
|
|
|
if (cache == NULL)
|
|
{
|
|
/* Read the contents of the file. */
|
|
void *file = _dl_sysdep_read_whole_file (LD_SO_CACHE, &cachesize,
|
|
PROT_READ);
|
|
|
|
/* We can handle three different cache file formats here:
|
|
- the old libc5/glibc2.0/2.1 format
|
|
- the old format with the new format in it
|
|
- only the new format
|
|
The following checks if the cache contains any of these formats. */
|
|
if (file != MAP_FAILED && cachesize > sizeof *cache
|
|
&& memcmp (file, CACHEMAGIC, sizeof CACHEMAGIC - 1) == 0)
|
|
{
|
|
size_t offset;
|
|
/* Looks ok. */
|
|
cache = file;
|
|
|
|
/* Check for new version. */
|
|
offset = ALIGN_CACHE (sizeof (struct cache_file)
|
|
+ cache->nlibs * sizeof (struct file_entry));
|
|
|
|
cache_new = (struct cache_file_new *) ((void *) cache + offset);
|
|
if (cachesize < (offset + sizeof (struct cache_file_new))
|
|
|| memcmp (cache_new->magic, CACHEMAGIC_VERSION_NEW,
|
|
sizeof CACHEMAGIC_VERSION_NEW - 1) != 0)
|
|
cache_new = (void *) -1;
|
|
}
|
|
else if (file != MAP_FAILED && cachesize > sizeof *cache_new
|
|
&& memcmp (file, CACHEMAGIC_VERSION_NEW,
|
|
sizeof CACHEMAGIC_VERSION_NEW - 1) == 0)
|
|
{
|
|
cache_new = file;
|
|
cache = file;
|
|
}
|
|
else
|
|
{
|
|
if (file != MAP_FAILED)
|
|
__munmap (file, cachesize);
|
|
cache = (void *) -1;
|
|
}
|
|
|
|
assert (cache != NULL);
|
|
}
|
|
|
|
if (cache == (void *) -1)
|
|
/* Previously looked for the cache file and didn't find it. */
|
|
return NULL;
|
|
|
|
best = NULL;
|
|
|
|
if (cache_new != (void *) -1)
|
|
{
|
|
/* This file ends in static libraries where we don't have a hwcap. */
|
|
unsigned long int *hwcap;
|
|
uint64_t platform;
|
|
#ifndef SHARED
|
|
weak_extern (_dl_hwcap);
|
|
#endif
|
|
|
|
/* This is where the strings start. */
|
|
cache_data = (const char *) cache_new;
|
|
|
|
/* Now we can compute how large the string table is. */
|
|
cache_data_size = (const char *) cache + cachesize - cache_data;
|
|
|
|
hwcap = &GL(dl_hwcap);
|
|
platform = _dl_string_platform (GL(dl_platform));
|
|
if (platform != (uint64_t) -1)
|
|
platform = 1ULL << platform;
|
|
|
|
/* Only accept hwcap if it's for the right platform. */
|
|
#define HWCAP_CHECK \
|
|
if (GL(dl_osversion) \
|
|
&& cache_new->libs[middle].osversion > GL(dl_osversion)) \
|
|
continue; \
|
|
if (_DL_PLATFORMS_COUNT && platform != -1 \
|
|
&& (lib->hwcap & _DL_HWCAP_PLATFORM) != 0 \
|
|
&& (lib->hwcap & _DL_HWCAP_PLATFORM) != platform) \
|
|
continue; \
|
|
if (hwcap \
|
|
&& ((lib->hwcap & *hwcap & ~_DL_HWCAP_PLATFORM) > *hwcap)) \
|
|
continue
|
|
SEARCH_CACHE (cache_new);
|
|
}
|
|
else
|
|
{
|
|
/* This is where the strings start. */
|
|
cache_data = (const char *) &cache->libs[cache->nlibs];
|
|
|
|
/* Now we can compute how large the string table is. */
|
|
cache_data_size = (const char *) cache + cachesize - cache_data;
|
|
|
|
#undef HWCAP_CHECK
|
|
#define HWCAP_CHECK do {} while (0)
|
|
SEARCH_CACHE (cache);
|
|
}
|
|
|
|
/* Print our result if wanted. */
|
|
if (__builtin_expect (GL(dl_debug_mask) & DL_DEBUG_LIBS, 0) && best != NULL)
|
|
INTUSE(_dl_debug_printf) (" trying file=%s\n", best);
|
|
|
|
return best;
|
|
}
|
|
|
|
#ifndef MAP_COPY
|
|
/* If the system does not support MAP_COPY we cannot leave the file open
|
|
all the time since this would create problems when the file is replaced.
|
|
Therefore we provide this function to close the file and open it again
|
|
once needed. */
|
|
void
|
|
_dl_unload_cache (void)
|
|
{
|
|
if (cache != NULL && cache != (struct cache_file *) -1)
|
|
{
|
|
__munmap (cache, cachesize);
|
|
cache = NULL;
|
|
}
|
|
}
|
|
INTDEF (_dl_unload_cache)
|
|
#endif
|