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]

ldconfig alignment patch



Here's a new patch which aligns struct cache_file_new correctly.
I've tested this on ix86 and alpha.  Could others please also test it?
David, I'm especially interested in your test results.

Thanks,
Andreas


2000-05-16  Andreas Jaeger  <aj@suse.de>, 
            David Huggins-Daines <dhd@linuxcare.com>

	* sysdeps/generic/dl-cache.c (_dl_load_cache_lookup): Set
	cache_data in case of only new cache format correctly.

	* sysdeps/generic/dl-cache.c (_dl_load_cache_lookup): Align struct
	cache_file_new.

	* sysdeps/generic/dl-cache.h (ALIGN_CACHE): New macro to align
	struct cache_file_new.

	* elf/cache.c (save_cache): Fix str_offset if only new cache is
	present.

	* elf/cache.c (save_cache): Align struct new_file_cache.
	(print_cache): Likewise.

============================================================
Index: sysdeps/generic/dl-cache.c
--- sysdeps/generic/dl-cache.c	2000/05/07 21:23:20	1.21
+++ sysdeps/generic/dl-cache.c	2000/05/16 06:19:57
@@ -52,7 +52,7 @@
     right = cache->nlibs - 1;						  \
     middle = (left + right) / 2;					  \
     cmpres = 1;								  \
-    									  \
+									  \
     while (left <= right)						  \
       {									  \
 	/* Make sure string table indices are not bogus before using	  \
@@ -121,7 +121,7 @@
 		  {							  \
 		    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	  \
@@ -166,14 +166,16 @@
       if (file && cachesize > sizeof *cache &&
 	  !memcmp (file, CACHEMAGIC, sizeof CACHEMAGIC - 1))
 	{
+	  size_t offset;
 	  /* 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))
+	  offset = ALIGN_CACHE (sizeof (struct cache_file)
+				+ cache->nlibs * sizeof (struct file_entry));
+
+	  cache_new = (struct cache_file_new *) ((void *)cache + offset);
+	  if (cachesize < (offset + sizeof (struct cache_file_new))
 	      || memcmp (cache_new->magic, CACHEMAGIC_NEW,
 			  sizeof CACHEMAGIC_NEW - 1)
 	      || memcmp (cache_new->version, CACHE_VERSION,
@@ -202,9 +204,6 @@
     /* 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)
@@ -213,6 +212,9 @@
       unsigned long int *hwcap;
       weak_extern (_dl_hwcap);
 
+      /* This is where the strings start.  */
+      cache_data = (const char *) cache_new;
+
       hwcap = &_dl_hwcap;
 
 #define HWCAP_CHECK							     \
@@ -221,9 +223,13 @@
       SEARCH_CACHE (cache_new);
     }
   else
+    {
+      /* This is where the strings start.  */
+      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)
============================================================
Index: sysdeps/generic/dl-cache.h
--- sysdeps/generic/dl-cache.h	2000/05/07 21:23:35	1.2
+++ sysdeps/generic/dl-cache.h	2000/05/16 06:19:57
@@ -32,12 +32,14 @@
 /* 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
+	old_magic
 	nlibs
 	libs[0]
 	...
 	libs[nlibs-1]
-	new magic
+	pad, new magic needs to be aligned
+	     - this is string[0] for the old format
+	new magic - this is string[0] for the new format
 	newnlibs
 	...
 	newlibs[0]
@@ -81,6 +83,11 @@
   struct file_entry_new libs[0]; /* Entries describing libraries.  */
   /* After this the string table of size len_strings is found.  */
 };
+
+/* Used to align cache_file_new.  */
+#define ALIGN_CACHE(addr)				\
+(((addr) + __alignof__ (struct cache_file_new) -1)	\
+ & (~(__alignof__ (struct cache_file_new) - 1)))
 
 static int
 _dl_cache_libcmp (const char *p1, const char *p2)
============================================================
Index: elf/cache.c
--- elf/cache.c	2000/05/07 21:19:22	1.4
+++ elf/cache.c	2000/05/16 06:19:58
@@ -49,7 +49,6 @@
 static const char *flag_descr[] =
 { "libc4", "ELF", "libc5", "libc6"};
 
-
 /* Print a single entry.  */
 static void
 print_entry (const char *lib, int flag, unsigned long int hwcap, const char *key)
@@ -130,25 +129,29 @@
 	error (EXIT_FAILURE, 0, _("File is not a cache file.\n"));
       format = 1;
       /* This is where the strings start.  */
-      cache_data = (const char *) cache;
+      cache_data = (const char *) cache_new;
     }
   else
     {
+      size_t offset = ALIGN_CACHE (sizeof (struct cache_file)
+				   + cache->nlibs * sizeof (struct file_entry));
       /* This is where the strings start.  */
       cache_data = (const char *) &cache->libs[cache->nlibs];
 
       /* 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)))
+	  (offset + sizeof (struct cache_file_new)))
 	{
-	  cache_new = (struct cache_file_new *) cache_data;
+
+	  cache_new = (struct cache_file_new *) ((void *)cache + offset);
 
 	  if (!memcmp (cache_new->magic, CACHEMAGIC_NEW, sizeof CACHEMAGIC_NEW - 1)
 	      && !memcmp (cache_new->version, CACHE_VERSION,
 			  sizeof CACHE_VERSION - 1))
-	    format = 1;
+	    {
+	      cache_data = (const char *) cache_new;
+	      format = 1;
+	    }
 	}
     }
 
@@ -230,6 +233,8 @@
   int cache_entry_count = 0;
   /* Number of normal cache entries.  */
   int cache_entry_old_count = 0;
+  /* Pad for alignment of cache_file_new.  */
+  size_t pad;
 
   /* The cache entries are sorted already, save them in this order. */
 
@@ -280,11 +285,13 @@
       file_entries_new->nlibs = cache_entry_count;
       file_entries_new->len_strings = total_strlen;
     }
-
+  
+  pad = ALIGN_CACHE (file_entries_size) - file_entries_size;
+  
   /* If we have both formats, we hide the new format in the strings
      table, we have to adjust all string indices for this so that
      old libc5/glibc 2 dynamic linkers just ignore them.  */
-  if (opt_format == 1)
+  if (opt_format != 0)
     str_offset = file_entries_new_size;
   else
     str_offset = 0;
@@ -298,7 +305,7 @@
 	{
 	  file_entries->libs[idx_old].flags = entry->flags;
 	  /* XXX: Actually we can optimize here and remove duplicates.  */
-	  file_entries->libs[idx_old].key = str_offset;
+	  file_entries->libs[idx_old].key = str_offset + pad;
 	}
       if (opt_format != 0)
 	{
@@ -317,7 +324,7 @@
       str_offset += len + 1;
       /* Then the path.  */
       if (opt_format != 2)
-	file_entries->libs[idx_old].value = str_offset;
+	file_entries->libs[idx_old].value = str_offset + pad;
       if (opt_format != 0)
 	file_entries_new->libs[idx_new].value = str_offset;
       len = strlen (entry->path);
@@ -354,6 +361,13 @@
     }
   if (opt_format != 0)
     {
+      /* Align cache.  */
+      if (opt_format != 2)
+	{
+	  char zero [pad];
+	  if (write (fd, zero, pad) != (ssize_t)pad)
+	    error (EXIT_FAILURE, errno, _("Writing of cache data failed"));
+	}
       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"));

-- 
 Andreas Jaeger
  SuSE Labs aj@suse.de
   private aj@arthur.inka.de


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