aboutsummaryrefslogtreecommitdiff
path: root/sysdeps/generic
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2000-05-07 21:23:56 +0000
committerUlrich Drepper <drepper@redhat.com>2000-05-07 21:23:56 +0000
commit45eca4d141c047950db48c69c8941163d0a61fcd (patch)
tree66035482a9beed5f14699227294ac902b32a5106 /sysdeps/generic
parentd89d0afad4551a808b15510795f965aed147a834 (diff)
downloadglibc-45eca4d141c047950db48c69c8941163d0a61fcd.tar
glibc-45eca4d141c047950db48c69c8941163d0a61fcd.tar.gz
glibc-45eca4d141c047950db48c69c8941163d0a61fcd.tar.bz2
glibc-45eca4d141c047950db48c69c8941163d0a61fcd.zip
Update.
2000-05-06 Bruno Haible <haible@clisp.cons.org> * iconv/gconv_open.c (__gconv_open): If __gconv_find_transform returned != __GCONV_OK, there is nothing to clean up. 2000-05-06 Bruno Haible <haible@clisp.cons.org> * intl/tst-gettext.c (main): Disable possibly existing LC_CTYPE and OUTPUT_CHARSET environment variables. 2000-05-06 Andreas Jaeger <aj@suse.de> * sysdeps/generic/dl-cache.h (struct file_entry_new): New. (struct cache_file_new): New. (struct file_entry): New (moved from cache.c). (struct cache_file): New (moved from cache.c). * sysdeps/generic/dl-cache.c (SEARCH_CACHE): New macro, broken out from _dl_load_cache_lookup. (_dl_load_cache_lookup): Move search to SEARCH_CACHE macro, handle the different cache formats. New variable cache_new for new format. * elf/ldconfig.h: Change according to changes in cache.c and ldconfig.c; remove cache_libcmp; add opt_format. * elf/ldconfig.c: Include "dl-cache.h" and "dl-procinfo.h"; remove stuff that's defined in those headers. Add hwcap to struct lib_entry. (opt_format): New variable to select cache format. (options): Add format parameter. (is_hwcap): New function. (path_hwcap): New function. (parse_opt): Handle new format parameter. (search_dir): Handle hwcap, search also subdirectories with hwcap. * elf/cache.c (_GNU_SOURCE): Removed. Not needed anymore since ldconfig is part of glibc. Include dl-cache.h and remove stuff that's defined there. (struct cache_entry): Add new member hwcap. (print_entry): Print hwcap, cleanup a bit. (print_cache): Print new and old formats. (compare): Use _dl_cache_libcmp from dl-cache.h; handle hwcap. (save_cache): Save new and old formats. (add_to_cache): Handle hwcap. * sysdeps/generic/dl-cache.c (_dl_cache_libcmp): Moved from here... * sysdeps/generic/dl-cache.h (_dl_cache_libcmp): ...to here. * sysdeps/generic/dl-cache.c (LD_SO_CACHE): Moved from here... * sysdeps/generic/dl-cache.h (LD_SO_CACHE): ...to here. * sysdeps/generic/dl-cache.c (CACHEMAGIC): Moved from here... * sysdeps/generic/dl-cache.h (CACHEMAGIC): ...to here. 2000-05-05 Bruno Haible <haible@clisp.cons.org> * intl/dcigettext.c (alignof): New macro. (_nl_find_msg): Use it instead of __alignof__. Pass correct output buffer length to __gconv/iconv. If malloc (freemem_size) fails, set freemem_size to 0. 2000-05-05 Bruno Haible <haible@clisp.cons.org> * intl/dcigettext.c (dcigettext): Fix interpretation of tsearch return value.
Diffstat (limited to 'sysdeps/generic')
-rw-r--r--sysdeps/generic/dl-cache.c275
-rw-r--r--sysdeps/generic/dl-cache.h100
2 files changed, 238 insertions, 137 deletions
diff --git a/sysdeps/generic/dl-cache.c b/sysdeps/generic/dl-cache.c
index 2ab13d8d3f..28fab0b19e 100644
--- a/sysdeps/generic/dl-cache.c
+++ b/sysdeps/generic/dl-cache.c
@@ -22,31 +22,16 @@
#include <sys/mman.h>
#include <dl-cache.h>
+
/* System-dependent function to read a file's whole contents
in the most convenient manner available. */
extern void *_dl_sysdep_read_whole_file (const char *filename,
size_t *filesize_ptr,
int mmap_prot);
-#ifndef LD_SO_CACHE
-# define LD_SO_CACHE "/etc/ld.so.cache"
-#endif
-
-#define CACHEMAGIC "ld.so-1.7.0"
-
-struct cache_file
- {
- char magic[sizeof CACHEMAGIC - 1];
- unsigned int nlibs;
- struct
- {
- int flags; /* This is 1 for an ELF library. */
- unsigned int key, value; /* String table indices. */
- } libs[0];
- };
-
/* 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. */
@@ -56,45 +41,100 @@ static size_t cachesize;
binaries. */
int _dl_correct_cache_id = _DL_CACHE_DEFAULT_ID;
-/* Helper function which must match the one in ldconfig, so that
- we rely on the same sort order. */
-static int
-_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;
-}
+#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; \
+ middle = (left + right) / 2; \
+ cmpres = 1; \
+ \
+ while (left <= right) \
+ { \
+ /* Make sure string table indices are not bogus before using \
+ them. */ \
+ if (! _dl_cache_verify_ptr (cache->libs[middle].key)) \
+ { \
+ cmpres = 1; \
+ break; \
+ } \
+ \
+ /* Actually compare the entry with the key. */ \
+ cmpres = _dl_cache_libcmp (name, \
+ cache_data + cache->libs[middle].key); \
+ if (cmpres == 0) \
+ /* Found it. */ \
+ break; \
+ \
+ if (cmpres < 0) \
+ left = middle + 1; \
+ else \
+ right = middle - 1; \
+ \
+ middle = (left + right) / 2; \
+ } \
+ \
+ if (cmpres == 0) \
+ { \
+ /* 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 \
+ /* Make sure string table indices are not bogus before \
+ using them. */ \
+ && _dl_cache_verify_ptr (cache->libs[middle - 1].key) \
+ /* Actually compare the entry. */ \
+ && (_dl_cache_libcmp (name, \
+ cache_data \
+ + cache->libs[middle - 1].key) \
+ == 0)) \
+ --middle; \
+ \
+ do \
+ { \
+ int flags; \
+ \
+ /* 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 (cache->libs[middle].key) \
+ || (_dl_cache_libcmp (name, \
+ cache_data \
+ + cache->libs[middle].key) \
+ != 0))) \
+ break; \
+ \
+ flags = cache->libs[middle].flags; \
+ if (_dl_cache_check_flags (flags) \
+ && _dl_cache_verify_ptr (cache->libs[middle].value)) \
+ { \
+ if (best == NULL || flags == _dl_correct_cache_id) \
+ { \
+ HWCAP_CHECK; \
+ best = cache_data + cache->libs[middle].value; \
+ \
+ if (flags == _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); \
+ } \
+ } \
+while (0)
+
/* Look up NAME in ld.so.cache and return the file name stored there,
@@ -117,10 +157,38 @@ _dl_load_cache_lookup (const char *name)
/* 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 && cachesize > sizeof *cache &&
!memcmp (file, CACHEMAGIC, sizeof CACHEMAGIC - 1))
- /* Looks ok. */
- cache = file;
+ {
+ /* Looks ok. */
+ cache = file;
+
+ /* Check for new version. */
+ cache_new = (struct cache_file_new *) &cache->libs[cache->nlibs];
+ if (cachesize <
+ (sizeof (struct cache_file) + cache->nlibs * sizeof (struct file_entry)
+ + sizeof (struct cache_file_new))
+ || memcmp (cache_new->magic, CACHEMAGIC_NEW,
+ sizeof CACHEMAGIC_NEW - 1)
+ || memcmp (cache_new->version, CACHE_VERSION,
+ sizeof CACHE_VERSION - 1))
+ cache_new = (void *) -1;
+ }
+ else if (file && cachesize > sizeof *cache_new)
+ {
+ cache_new = (struct cache_file_new *) file;
+ if (memcmp (cache_new->magic, CACHEMAGIC_NEW,
+ sizeof CACHEMAGIC_NEW - 1)
+ || memcmp (cache_new->version, CACHE_VERSION,
+ sizeof CACHE_VERSION - 1))
+ cache_new = (void *) -1;
+ }
else
{
if (file)
@@ -139,88 +207,23 @@ _dl_load_cache_lookup (const char *name)
best = NULL;
- /* We use binary search since the table is sorted in the cache file.
- It is important to use the same algorithm as used while generating
- the cache file. */
- left = 0;
- right = cache->nlibs - 1;
- middle = (left + right) / 2;
- cmpres = 1;
-
- while (left <= right)
+ if (cache_new != (void *) -1)
{
- /* Make sure string table indices are not bogus before using them. */
- if (! _dl_cache_verify_ptr (cache->libs[middle].key))
- {
- cmpres = 1;
- break;
- }
+ /* This file ends in static libraries where we don't have a hwcap. */
+ unsigned long int *hwcap;
+ weak_extern (_dl_hwcap);
- /* Actually compare the entry with the key. */
- cmpres = _dl_cache_libcmp (name, cache_data + cache->libs[middle].key);
- if (cmpres == 0)
- /* Found it. */
- break;
+ hwcap = &_dl_hwcap;
- if (cmpres < 0)
- left = middle + 1;
- else
- right = middle - 1;
-
- middle = (left + right) / 2;
- }
-
- if (cmpres == 0)
- {
- /* 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
- /* Make sure string table indices are not bogus before
- using them. */
- && _dl_cache_verify_ptr (cache->libs[middle - 1].key)
- /* Actually compare the entry. */
- && (_dl_cache_libcmp (name,
- cache_data + cache->libs[middle - 1].key)
- == 0))
- --middle;
-
- do
- {
- int flags;
-
- /* 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 (cache->libs[middle].key)
- || (_dl_cache_libcmp (name,
- cache_data + cache->libs[middle].key)
- != 0)))
- break;
-
- flags = cache->libs[middle].flags;
- if (_dl_cache_check_flags (flags)
- && _dl_cache_verify_ptr (cache->libs[middle].value))
- {
- if (best == NULL || flags == _dl_correct_cache_id)
- {
- best = cache_data + cache->libs[middle].value;
-
- if (flags == _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);
+#define HWCAP_CHECK \
+ if (hwcap && (cache_new->libs[middle].hwcap & *hwcap) > _dl_hwcap) \
+ continue
+ SEARCH_CACHE (cache_new);
}
+ else
+#undef HWCAP_CHECK
+#define HWCAP_CHECK do {} while (0)
+ SEARCH_CACHE (cache);
/* Print our result if wanted. */
if (_dl_debug_libs && best != NULL)
diff --git a/sysdeps/generic/dl-cache.h b/sysdeps/generic/dl-cache.h
index 579c261af1..4eb64cf557 100644
--- a/sysdeps/generic/dl-cache.h
+++ b/sysdeps/generic/dl-cache.h
@@ -1,5 +1,5 @@
/* Support for reading /etc/ld.so.cache files written by Linux ldconfig.
- Copyright (C) 1999 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2000 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
@@ -21,3 +21,101 @@
#define _dl_cache_check_flags(flags) \
((flags) == 1 || (flags) == _DL_CACHE_DEFAULT_ID)
+
+
+#ifndef LD_SO_CACHE
+# define LD_SO_CACHE "/etc/ld.so.cache"
+#endif
+
+#define CACHEMAGIC "ld.so-1.7.0"
+
+/* libc5 and glibc 2.0/2.1 use the same format. For glibc 2.2 another
+ format has been added in a compatible way:
+ The beginning of the string table is used for the new table:
+ old_magic
+ nlibs
+ libs[0]
+ ...
+ libs[nlibs-1]
+ new magic
+ newnlibs
+ ...
+ newlibs[0]
+ ...
+ newlibs[newnlibs-1]
+ string 1
+ string 2
+ ...
+*/
+struct file_entry
+{
+ int flags; /* This is 1 for an ELF library. */
+ unsigned int key, value; /* String table indices. */
+};
+
+struct cache_file
+{
+ char magic[sizeof CACHEMAGIC - 1];
+ unsigned int nlibs;
+ struct file_entry libs[0];
+};
+
+#define CACHEMAGIC_NEW "glibc-ld.so.cache"
+#define CACHE_VERSION "1.0"
+
+
+struct file_entry_new
+{
+ int flags; /* This is 1 for an ELF library. */
+ unsigned int key, value; /* String table indices. */
+ unsigned long hwcap; /* Hwcap entry. */
+};
+
+struct cache_file_new
+{
+ char magic[sizeof CACHEMAGIC_NEW - 1];
+ char version[sizeof CACHE_VERSION - 1];
+ unsigned int nlibs; /* Number of entries. */
+ unsigned int len_strings; /* Size of string table. */
+ unsigned int unused[4]; /* Leave space for future extensions. */
+ struct file_entry_new libs[0]; /* Entries describing libraries. */
+ /* After this the string table of size len_strings is found. */
+};
+
+static int
+_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;
+}