about summary refs log tree commit diff
path: root/sysdeps
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
parentd89d0afad4551a808b15510795f965aed147a834 (diff)
downloadglibc-45eca4d141c047950db48c69c8941163d0a61fcd.tar.gz
glibc-45eca4d141c047950db48c69c8941163d0a61fcd.tar.xz
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')
-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;
+}