summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog10
-rw-r--r--FAQ14
-rw-r--r--sysdeps/generic/dl-cache.c150
3 files changed, 139 insertions, 35 deletions
diff --git a/ChangeLog b/ChangeLog
index 6a098f277d..b15ff9a7d0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,9 +1,15 @@
+1999-04-10 Ulrich Drepper <drepper@cygnus.com>
+
+ * sysdeps/generic/dl-cache.c (_dl_load_cache_lookup): Rewrite to
+ use binary search.
+ Based on a patch by Jakub Jelinek <jj@sunsite.ms.mff.cuni.cz>.
+
1999-04-08 Andreas Jaeger <aj@arthur.rhein-neckar.de>
* scripts/test-installation.pl (installation_problem): Skip
libnss1_* libraries from glibc-compat add-on.
-Wed Apr 7 22:52:39 1999 H.J. Lu <hjl@gnu.org>
+1999-04-07 H.J. Lu <hjl@gnu.org>
* io/Versions (__dup2, __pipe): Added to GLIBC_2.0 for
libstdc++ 2.7.2.
@@ -11,7 +17,7 @@ Wed Apr 7 22:52:39 1999 H.J. Lu <hjl@gnu.org>
1999-04-08 Andreas Jaeger <aj@arthur.rhein-neckar.de>
- * manual/install.texi (Reporting Bugs): Add section about reported
+ * manual/install.texi (Reporting Bugs): Add section about reported
bugs and correct email address of glibcbug script.
1999-04-01 Thorsten Kukuk <kukuk@suse.de>
diff --git a/FAQ b/FAQ
index dcc6426a9e..65d1e7d3d7 100644
--- a/FAQ
+++ b/FAQ
@@ -1417,16 +1417,10 @@ completely.
the Perl db modules the testsuite is not passed. This did not
happen with db-1, gdbm, or ndbm.
-{UD} You are using an outdated copy of the DB_File Perl module. In fact db-2
-finally removed the handling of zero-sized keys which was one of the features
-tested by the old Perl testsuite and therefore you see an error. But this
-never was documented and guaranteed, only broken programs used this feature.
-
-Consequently db-2 does not need to support this feature and instead signals
-an error which leads to easier debugging. The DB_File module maintainer
-Paul Marquess <pmarquess@bfsec.bt.co.uk> acknowledged this change and fixed
-the testsuite so that if you use DB_File v1.60 or later you should not have
-any more problems with db-2.
+{MK} Db-2 does not support zero-sized keys. The Perl testsuite
+tests the support for zero-sized keys and therefore fails when db-2 is
+used. The Perl folks are looking for a solution, but thus far have
+not found a satisfactory one.
3.14. The pow() inline function I get when including <math.h> is broken.
diff --git a/sysdeps/generic/dl-cache.c b/sysdeps/generic/dl-cache.c
index f14cf96da1..ee7080bc8e 100644
--- a/sysdeps/generic/dl-cache.c
+++ b/sysdeps/generic/dl-cache.c
@@ -1,5 +1,5 @@
/* Support for reading /etc/ld.so.cache files written by Linux ldconfig.
- Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1996, 1997, 1998, 1999 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
@@ -52,13 +52,56 @@ static size_t cachesize;
binaries. */
int _dl_correct_cache_id = 3;
+/* 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;
+}
+
+
/* Look up NAME in ld.so.cache and return the file name stored there,
or null if none is found. */
const char *
_dl_load_cache_lookup (const char *name)
{
- unsigned int i;
+ int left, right, middle;
+ int cmpres;
+ const char *cache_data;
const char *best;
/* Print a message if the loading of libs is traced. */
@@ -87,28 +130,89 @@ _dl_load_cache_lookup (const char *name)
/* Previously looked for the cache file and didn't find it. */
return NULL;
+ /* This is where the strings start. */
+ cache_data = (const char *) &cache->libs[cache->nlibs];
+
best = NULL;
- for (i = 0; i < cache->nlibs; ++i)
- if ((cache->libs[i].flags == 1 ||
- cache->libs[i].flags == 3) && /* ELF library entry. */
- /* Make sure string table indices are not bogus before using them. */
- cache->libs[i].key < cachesize - sizeof *cache &&
- cache->libs[i].value < cachesize - sizeof *cache &&
- /* Does the name match? */
- ! strcmp (name, ((const char *) &cache->libs[cache->nlibs] +
- cache->libs[i].key)))
- {
- if ((best == NULL) || (cache->libs[i].flags == _dl_correct_cache_id))
- {
- best = ((const char *) &cache->libs[cache->nlibs]
- + cache->libs[i].value);
-
- if (cache->libs[i].flags == _dl_correct_cache_id)
- /* We've found an exact match for the shared object and no
- general `ELF' release. Stop searching. */
- break;
- }
- }
+
+ /* 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)
+ {
+ /* Make sure string table indices are not bogus before using them. */
+ if (cache->libs[middle].key >= cachesize - sizeof *cache)
+ {
+ 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. */
+ && cache->libs[middle - 1].key < cachesize - sizeof *cache
+ /* Actually compare the entry. */
+ && strcmp (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. */
+ && (cache->libs[middle].key >= cachesize - sizeof *cache
+ || strcmp (name, cache_data + cache->libs[middle].key) != 0))
+ break;
+
+ flags = cache->libs[middle].flags;
+ if ((flags == 1 || flags == 3)
+ && cache->libs[middle].value < cachesize - sizeof *cache)
+ {
+ 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);
+ }
/* Print our result if wanted. */
if (_dl_debug_libs && best != NULL)