From 45eca4d141c047950db48c69c8941163d0a61fcd Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Sun, 7 May 2000 21:23:56 +0000 Subject: Update. 2000-05-06 Bruno Haible * iconv/gconv_open.c (__gconv_open): If __gconv_find_transform returned != __GCONV_OK, there is nothing to clean up. 2000-05-06 Bruno Haible * intl/tst-gettext.c (main): Disable possibly existing LC_CTYPE and OUTPUT_CHARSET environment variables. 2000-05-06 Andreas Jaeger * 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 * 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 * intl/dcigettext.c (dcigettext): Fix interpretation of tsearch return value. --- sysdeps/generic/dl-cache.c | 275 +++++++++++++++++++++++---------------------- sysdeps/generic/dl-cache.h | 100 ++++++++++++++++- 2 files changed, 238 insertions(+), 137 deletions(-) (limited to 'sysdeps/generic') 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 #include + /* 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; +} -- cgit v1.2.3