This is the mail archive of the libc-alpha@sourceware.cygnus.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: Problem with new ld.so.cache format on 64-bit machines


Andreas Jaeger <aj@suse.de> writes:

> Can you send a patch that works for you on alpha, please?

No problem...

One other thing I noticed when writing this patch is that it appears
that _dl_load_cache_lookup() would not actually have worked in the
case where there is only the new-style index in the cache, because
cache_data was always calculated using 'cache' (which would be NULL in
the case where no old-style cache index was present).  I think (but
I'm not sure) that this should fix that as well.

--- glibc-cvs/sysdeps/generic/dl-cache.c	Fri May 12 14:20:11 2000
+++ glibc-cvs/sysdeps/generic/dl-cache.c.patched	Fri May 12 14:09:50 2000
@@ -166,14 +166,24 @@
       if (file && cachesize > sizeof *cache &&
 	  !memcmp (file, CACHEMAGIC, sizeof CACHEMAGIC - 1))
 	{
+	  /* Alignment pad between old and new, used in calculations below */
+	  int pad;
+
 	  /* Looks ok.  */
 	  cache = file;
 
+	  pad = (sizeof (unsigned long)
+		 - (cache->nlibs * sizeof (struct file_entry)
+		    % sizeof (unsigned long))) % sizeof (unsigned long);
+
 	  /* Check for new version.  */
-	  cache_new = (struct cache_file_new *) &cache->libs[cache->nlibs];
+	  cache_new = (struct cache_file_new *)
+		  ((char *) &cache->libs[cache->nlibs] + pad);
+
 	  if (cachesize <
-	      (sizeof (struct cache_file) + cache->nlibs * sizeof (struct file_entry)
-	       + sizeof (struct cache_file_new))
+	      (sizeof (struct cache_file)
+	       + cache->nlibs * sizeof (struct file_entry)
+	       + pad + sizeof (struct cache_file_new))
 	      || memcmp (cache_new->magic, CACHEMAGIC_NEW,
 			  sizeof CACHEMAGIC_NEW - 1)
 	      || memcmp (cache_new->version, CACHE_VERSION,
@@ -202,15 +212,14 @@
     /* 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;
 
   if (cache_new != (void *) -1)
     {
       /* This file ends in static libraries where we don't have a hwcap.  */
       unsigned long int *hwcap;
+
+      cache_data = (const char *) cache_new;
       weak_extern (_dl_hwcap);
 
       hwcap = &_dl_hwcap;
@@ -221,9 +230,12 @@
       SEARCH_CACHE (cache_new);
     }
   else
+    {
+      cache_data = (const char *) &cache->libs[cache->nlibs];
 #undef HWCAP_CHECK
 #define HWCAP_CHECK do {} while (0)
-    SEARCH_CACHE (cache);
+      SEARCH_CACHE (cache);
+    }
 
   /* Print our result if wanted.  */
   if (_dl_debug_libs && best != NULL)
--- glibc-cvs/elf/cache.c	Fri May 12 14:20:11 2000
+++ glibc-cvs/elf/cache.c.patched	Fri May 12 14:04:22 2000
@@ -134,14 +134,19 @@
     }
   else
     {
+      /* Alignment pad between old and new, used in calculations below */
+      int pad  = (sizeof (unsigned long)
+		  - (cache->nlibs * sizeof (struct file_entry)
+		     % sizeof (unsigned long))) % sizeof (unsigned long);
+
       /* This is where the strings start.  */
-      cache_data = (const char *) &cache->libs[cache->nlibs];
+      cache_data = (const char *) &cache->libs[cache->nlibs] + pad;
 
       /* Check for a new cache embedded in the old format.  */
       if (cache_size >
 	  (sizeof (struct cache_file)
 	   + cache->nlibs * sizeof (struct file_entry)
-	   + sizeof (struct cache_file_new)))
+	   + pad + sizeof (struct cache_file_new)))
 	{
 	  cache_new = (struct cache_file_new *) cache_data;
 
@@ -354,6 +359,15 @@
     }
   if (opt_format != 0)
     {
+      /* The new style cache must be aligned to sizeof(unsigned long) */
+      int pad = ((sizeof (unsigned long)
+		  - file_entries_size % sizeof (unsigned long))
+		 % sizeof (unsigned long));
+      if (pad) {
+	char zero[sizeof(unsigned long)];
+	memset(zero, 0, sizeof(zero));
+	write(fd, zero, pad);
+      }
       if (write (fd, file_entries_new, file_entries_new_size)
 	  != (ssize_t)file_entries_new_size)
 	error (EXIT_FAILURE, errno, _("Writing of cache data failed"));


-- 
David Huggins-Daines, Senior GNU/Linux Consultant, Linuxcare, Inc.
613.562.1239 desk, 613.223.0225 mobile
dhd@linuxcare.com, http://www.linuxcare.com/
Linuxcare. Support for the revolution.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]