This is the mail archive of the libc-hacker@sources.redhat.com mailing list for the glibc project.

Note that libc-hacker is a closed list. You may look at the archives of this list, but subscription and posting are not open.


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

[PATCH] Use .note.ABI-tag in DSOs


Hi!

The following patch adds .note.ABI-tag to glibc DSOs, and disallows loading
DSOs which are built for newer kernels than installed. The --enable-kernel
info is stored in ld.so.cache as well.
Note to Ulrich, the patch I've sent earlier today contained a bug in
dl-cache.c, this one seems to work properly.

2001-03-05  Jakub Jelinek  <jakub@redhat.com>

	* csu/Makefile (abi-tag.h): Define OS and version separately, allow
	version to be overriden from config.h.
	* csu/abi-note.S: Use OS and version separately, include config.h.
	* elf/dl-load.c (_dl_osversion): New.
	(_dl_map_object_from_fd): Kill some warnings.
	(open_verify): Check .note.ABI-tag of the library if present.
	* elf/Makefile (CPPFLAGS-dl-load.c): Add -I$(csu-objpfx).
	* elf/cache.c (struct cache_entry): Add osversion.
	(print_entry): Print osversion.
	(print_cache): Pass osversion to it.
	(compare): Sort according to osversion.
	(save_cache): Set osversion.
	(add_to_cache): Add osversion argument.
	* elf/ldconfig.h (add_to_cache, process_file, process_elf_file): Add
	osversion argument.
	* elf/readlib.c (process_file): Likewise.
	* sysdeps/generic/readelflib.c (process_elf_file): Likewise.
	* sysdeps/unix/sysv/linux/ia64/readelflib.c (process_elf_file,
	process_elf32_file, process_elf64_file): Likewise.
	* sysdeps/unix/sysv/linux/i386/readelflib.c (process_elf_file,
	process_elf32_file, process_elf64_file): Likewise.
	* sysdeps/unix/sysv/linux/sparc/readelflib.c (process_elf_file,
	process_elf32_file, process_elf64_file): Likewise.
	* elf/ldconfig.c (manual_link, search_dir): Pass it.
	* sysdeps/generic/dl-cache.c (_dl_load_cache_lookup): Check
	osversion.
	* sysdeps/generic/ldsodefs.h (_dl_osversion): Declare.
	* sysdeps/unix/sysv/linux/init-first.c: Include ldsodefs.h.
	* sysdeps/unix/sysv/linux/dl-osinfo.h (DL_SYSDEP_OSCHECK): Save kernel
	version in _dl_osversion.
	* sysdeps/unix/sysv/linux/configure.in: Define __ABI_TAG_VERSION.
	* sysdeps/unix/sysv/linux/configure: Rebuilt.
	* Makerules (build-shlib-helper, build-module-helper): New.
	(build-shlib, build-module-helper): Make sure .note.ABI-tag comes
	early.
	* config.h.in (__ABI_TAG_VERSION): Add.

--- libc/csu/Makefile.jj	Mon Mar  5 11:57:45 2001
+++ libc/csu/Makefile	Mon Mar  5 12:52:56 2001
@@ -168,12 +168,17 @@ $(objpfx)abi-tag.h: $(..)abi-tags
 	$(make-target-directory)
 	rm -f $@.new
 	sed -e 's/#.*$$//' -e '/^[	]*$$/d' $< | \
-	while read conf tag; do \
+	while read conf tagos tagver; do \
 	  test `expr '$(config-machine)-$(config-vendor)-$(config-os)' \
 		     : "$$conf"` != 0 || continue; \
-	  echo "$$tag" | \
-	  sed -e 's/[^0-9xXa-fA-F]/ /g' -e 's/ *$$//' \
-	      -e 's/ /,/g' -e 's/^ */#define ABI_TAG /' > $@.new; \
+	  ( echo "$$tagos" | \
+	    sed -e 's/[^0-9xXa-fA-F 	]//' \
+		-e 's/^/#define __ABI_TAG_OS /'; \
+	    echo "#ifndef __ABI_TAG_VERSION"; \
+	    echo "$$tagver" | \
+	    sed -e 's/[^0-9xXa-fA-F]/ /g' -e 's/ *$$//' \
+	      -e 's/ /,/g' -e 's/^/# define __ABI_TAG_VERSION /'; \
+	    echo "#endif" ) > $@.new; \
 	done
 	if test -r $@.new; then mv -f $@.new $@; \
 	else echo >&2 'This configuration not matched in $<'; exit 1; fi
--- libc/csu/abi-note.S.jj	Thu Nov 23 14:41:37 2000
+++ libc/csu/abi-note.S	Mon Mar  5 12:53:09 2001
@@ -1,5 +1,5 @@
 /* Special .init and .fini section support.
-   Copyright (C) 1997 Free Software Foundation, Inc.
+   Copyright (C) 1997, 2001 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it
@@ -54,6 +54,7 @@ offset	length	contents	
    identify the earliest release of that OS that supports this ABI.
    See abi-tags (top level) for details. */
 
+#include <config.h>
 #include <abi-tag.h>		/* OS-specific ABI tag value */
 	
 /* The linker (GNU ld 2.8 and later) recognizes an allocated section whose
@@ -67,5 +68,6 @@ offset	length	contents	
 	.long  1		/* note type */
 0:	.asciz "GNU"		/* vendor name */
 1:	.align 4		
-2:	.long ABI_TAG		/* note data: the ABI tag */
+2:	.long __ABI_TAG_OS	/* note data: the ABI tag */
+	.long __ABI_TAG_VERSION
 3:	.align 4		/* pad out section */
--- libc/elf/dl-load.c.jj	Fri Mar  2 13:44:29 2001
+++ libc/elf/dl-load.c	Mon Mar  5 16:19:11 2001
@@ -30,6 +30,8 @@
 #include <sys/stat.h>
 #include <sys/types.h>
 #include "dynamic-link.h"
+#include <abi-tag.h>
+#include <dl-osinfo.h>
 
 #include <dl-dst.h>
 
@@ -111,6 +113,8 @@ struct filebuf
 
 size_t _dl_pagesize;
 
+unsigned int _dl_osversion;
+
 int _dl_clktck;
 
 extern const char *_dl_platform;
@@ -1061,12 +1065,12 @@ _dl_map_object_from_fd (const char *name
   if (__builtin_expect (_dl_debug_mask & DL_DEBUG_FILES, 0))
     _dl_debug_printf ("  dynamic: 0x%0*lx  base: 0x%0*lx   size: 0x%0*Zx\n"
 		      "    entry: 0x%0*lx  phdr: 0x%0*lx  phnum:   %*u\n\n",
-		      sizeof (void *) * 2, (unsigned long int) l->l_ld,
-		      sizeof (void *) * 2, (unsigned long int) l->l_addr,
-		      sizeof (void *) * 2, maplength,
-		      sizeof (void *) * 2, (unsigned long int) l->l_entry,
-		      sizeof (void *) * 2, (unsigned long int) l->l_phdr,
-		      sizeof (void *) * 2, l->l_phnum);
+		      (int) sizeof (void *) * 2, (unsigned long int) l->l_ld,
+		      (int) sizeof (void *) * 2, (unsigned long int) l->l_addr,
+		      (int) sizeof (void *) * 2, maplength,
+		      (int) sizeof (void *) * 2, (unsigned long int) l->l_entry,
+		      (int) sizeof (void *) * 2, (unsigned long int) l->l_phdr,
+		      (int) sizeof (void *) * 2, l->l_phnum);
 
   elf_get_dynamic_info (l);
 
@@ -1213,6 +1217,10 @@ open_verify (const char *name, struct fi
     [EI_OSABI] = ELFOSABI_SYSV,
     [EI_ABIVERSION] = 0
   };
+  static const struct {
+    ElfW(Word) vendorlen, datalen, type;
+    char vendor [4];
+  } expected_note = { 4, 16, 1, "GNU" };
   int fd;
 
   /* Open the file.  We always open files read-only.  */
@@ -1220,6 +1228,10 @@ open_verify (const char *name, struct fi
   if (fd != -1)
     {
       ElfW(Ehdr) *ehdr;
+      ElfW(Phdr) *phdr, *ph;
+      ElfW(Word) *abi_note, abi_note_buf[8];
+      unsigned int osversion;
+      size_t maplength;
 
       /* We successfully openened the file.  Now verify it is a file
 	 we can use.  */
@@ -1287,12 +1299,7 @@ open_verify (const char *name, struct fi
 	lose (0, fd, name, NULL, NULL,
 	      N_("ELF file version does not match current one"));
       if (! __builtin_expect (elf_machine_matches_host (ehdr), 1))
-	{
-	close_and_out:
-	  __close (fd);
-	  __set_errno (ENOENT);
-	  fd = -1;
-	}
+	goto close_and_out;
       else if (__builtin_expect (ehdr->e_phentsize, sizeof (ElfW(Phdr)))
 	       != sizeof (ElfW(Phdr)))
 	lose (0, fd, name, NULL, NULL,
@@ -1301,6 +1308,50 @@ open_verify (const char *name, struct fi
 	       && __builtin_expect (ehdr->e_type, ET_EXEC) != ET_EXEC)
 	lose (0, fd, name, NULL, NULL,
 	      N_("only ET_DYN and ET_EXEC can be loaded"));
+
+      maplength = ehdr->e_phnum * sizeof (ElfW(Phdr));
+      if (ehdr->e_phoff + maplength <= fbp->len)
+	phdr = (void *) (fbp->buf + ehdr->e_phoff);
+      else
+	{
+	  phdr = alloca (maplength);
+	  __lseek (fd, SEEK_SET, ehdr->e_phoff);
+	  if (__libc_read (fd, (void *) phdr, maplength) != maplength)
+	    lose (errno, fd, name, NULL, NULL, N_("cannot read file data"));
+	}
+
+      /* Check .note.ABI-tag if present.  */
+      for (ph = phdr; ph < &phdr[ehdr->e_phnum]; ++ph)
+	if (ph->p_type == PT_NOTE && ph->p_filesz == 32 && ph->p_align >= 4)
+	  {
+	    if (ph->p_offset + 32 <= fbp->len)
+	      abi_note = (void *) (fbp->buf + ph->p_offset);
+	    else
+	      {
+		__lseek (fd, SEEK_SET, ph->p_offset);
+		if (__libc_read (fd, (void *) abi_note_buf, 32) != 32)
+		  lose (errno, fd, name, NULL, NULL,
+			N_("cannot read file data"));
+		abi_note = abi_note_buf;
+	      }
+
+	    if (memcmp (abi_note, &expected_note, sizeof (expected_note)))
+	      continue;
+
+	    osversion = (abi_note [5] & 0xff) * 65536
+			+ (abi_note [6] & 0xff) * 256
+			+ (abi_note [7] & 0xff);
+	    if (abi_note [4] != __ABI_TAG_OS
+		|| (_dl_osversion && _dl_osversion < osversion))
+	      {
+	      close_and_out:
+		__close (fd);
+		__set_errno (ENOENT);
+		fd = -1;
+	      }
+
+	    break;
+	  }
     }
 
   return fd;
--- libc/elf/Makefile.jj	Mon Mar  5 11:57:47 2001
+++ libc/elf/Makefile	Mon Mar  5 13:48:02 2001
@@ -188,7 +188,7 @@ $(objpfx)trusted-dirs.st: Makefile $(..)
 	| $(AWK) -f gen-trusted-dirs.awk > ${@:st=T};
 	$(move-if-change) ${@:st=T} ${@:st=h}
 	touch $@
-CPPFLAGS-dl-load.c = -I$(objpfx).
+CPPFLAGS-dl-load.c = -I$(objpfx). -I$(csu-objpfx).
 
 ifeq (yes,$(build-shared))
 $(inst_slibdir)/$(rtld-version-installed-name): $(objpfx)ld.so $(+force)
--- libc/elf/ldconfig.c.jj	Tue Feb  6 11:19:58 2001
+++ libc/elf/ldconfig.c	Mon Mar  5 17:47:20 2001
@@ -463,6 +463,7 @@ manual_link (char *library)
   char *soname;
   struct stat64 stat_buf;
   int flag;
+  unsigned int osversion;
 
   /* Prepare arguments for create_links call.  Split library name in
      directory and filename first.  Since path is allocated, we've got
@@ -527,7 +528,8 @@ manual_link (char *library)
       free (path);
       return;
     }
-  if (process_file (real_library, library, libname, &flag, &soname, 0))
+  if (process_file (real_library, library, libname, &flag, &osversion,
+		    &soname, 0))
     {
       error (0, 0, _("No link created since soname could not be found for %s"),
 	     library);
@@ -588,6 +590,7 @@ search_dir (const struct dir_entry *entr
   struct stat64 stat_buf;
   int is_link;
   uint64_t hwcap = path_hwcap (entry->path);
+  unsigned int osversion;
 
   file_name_len = PATH_MAX;
   file_name = alloca (file_name_len);
@@ -703,7 +706,7 @@ search_dir (const struct dir_entry *entr
 	real_name = real_file_name;
 
       if (process_file (real_name, file_name, direntry->d_name, &flag,
-			&soname, is_link))
+			&osversion, &soname, is_link))
 	{
 	  if (real_name != real_file_name)
 	    free (real_name);
@@ -800,7 +803,8 @@ search_dir (const struct dir_entry *entr
 	create_links (dir_name, entry->path, dlib_ptr->name,
 		      dlib_ptr->soname);
       if (opt_build_cache)
-	add_to_cache (entry->path, dlib_ptr->soname, dlib_ptr->flag, hwcap);
+	add_to_cache (entry->path, dlib_ptr->soname, dlib_ptr->flag, osversion,
+		      hwcap);
     }
 
   /* Free all resources.  */
--- libc/elf/readlib.c.jj	Sat Sep 30 07:46:11 2000
+++ libc/elf/readlib.c	Mon Mar  5 15:27:34 2001
@@ -69,7 +69,8 @@ static struct known_names known_libs [] 
 /* Returns 0 if everything is ok, != 0 in case of error.  */
 int
 process_file (const char *real_file_name, const char *file_name,
-	      const char *lib, int *flag, char **soname, int is_link)
+	      const char *lib, int *flag, unsigned int *osversion,
+	      char **soname, int is_link)
 {
   FILE *file;
   struct stat64 statbuf;
@@ -160,8 +161,8 @@ process_file (const char *real_file_name
       goto done;
     }
 
-  if (process_elf_file (file_name, lib, flag, soname, file_contents,
-			statbuf.st_size))
+  if (process_elf_file (file_name, lib, flag, osversion, soname,
+			file_contents, statbuf.st_size))
     ret = 1;
 
  done:
--- libc/elf/ldconfig.h.jj	Mon Nov 20 13:47:58 2000
+++ libc/elf/ldconfig.h	Mon Mar  5 15:44:36 2001
@@ -39,17 +39,17 @@ extern void init_cache (void);
 extern void save_cache (const char *cache_name);
 
 extern void add_to_cache (const char *path, const char *lib, int flags,
-			  uint64_t hwcap);
+			  unsigned int osversion, uint64_t hwcap);
 
 /* Declared in readlib.c.  */
 extern int process_file (const char *real_file_name, const char *file_name,
-			 const char *lib, int *flag, char **soname,
-			 int is_link);
+			 const char *lib, int *flag, unsigned int *osversion,
+			 char **soname, int is_link);
 
 /* Declared in readelflib.c.  */
 extern int process_elf_file (const char *file_name, const char *lib, int *flag,
-			     char **soname, void *file_contents,
-			     size_t file_length);
+			     unsigned int *osversion, char **soname,
+			     void *file_contents, size_t file_length);
 
 /* Declared in chroot_canon.c.  */
 extern char *chroot_canon (const char *chroot, const char *name);
--- libc/elf/cache.c.jj	Mon Mar  5 11:56:21 2001
+++ libc/elf/cache.c	Mon Mar  5 17:54:56 2001
@@ -39,6 +39,7 @@ struct cache_entry
   char *lib;			/* Library name.  */
   char *path;			/* Path to find library.  */
   int flags;			/* Flags to indicate kind of library.  */
+  unsigned int osversion;	/* Required OS version.  */
   uint64_t hwcap;		/* Important hardware capabilities.  */
   int bits_hwcap;		/* Number of bits set in hwcap.  */
   struct cache_entry *next;	/* Next entry in list.  */
@@ -52,7 +53,8 @@ static const char *flag_descr[] =
 
 /* Print a single entry.  */
 static void
-print_entry (const char *lib, int flag, uint64_t hwcap, const char *key)
+print_entry (const char *lib, int flag, unsigned int osversion,
+	     uint64_t hwcap, const char *key)
 {
   printf ("\t%s (", lib);
   switch (flag & FLAG_TYPE_MASK)
@@ -85,6 +87,23 @@ print_entry (const char *lib, int flag, 
     }
   if (hwcap != 0)
     printf (", hwcap: 0x%" PRIx64, hwcap);
+  if (osversion != 0)
+    {
+      static const char * const abi_tag_os [] =
+      {
+	[0] = "Linux",
+	[1] = "Hurd",
+	[2] = "Solaris",
+	[3] = "Unknown OS"
+      };
+      unsigned int os = osversion >> 24;
+
+      printf (", OS ABI: %s %d.%d.%d",
+	      abi_tag_os [os > 3 ? 3 : os],
+	      (osversion >> 16) & 0xff,
+	      (osversion >> 8) & 0xff,
+	      osversion & 0xff);
+    }
   printf (") => %s\n", key);
 }
 
@@ -167,7 +186,7 @@ print_cache (const char *cache_name)
       /* Print everything.  */
       for (i = 0; i < cache->nlibs; i++)
 	print_entry (cache_data + cache->libs[i].key,
-		     cache->libs[i].flags, 0,
+		     cache->libs[i].flags, 0, 0,
 		     cache_data + cache->libs[i].value);
     }
   else if (format == 1)
@@ -178,6 +197,7 @@ print_cache (const char *cache_name)
       for (i = 0; i < cache_new->nlibs; i++)
 	print_entry (cache_data + cache_new->libs[i].key,
 		     cache_new->libs[i].flags,
+		     cache_new->libs[i].osversion,
 		     cache_new->libs[i].hwcap,
 		     cache_data + cache_new->libs[i].value);
     }
@@ -217,6 +237,10 @@ int compare (const struct cache_entry *e
 	return 1;
       else if (e2->hwcap < e1->hwcap)
 	return -1;
+      if (e2->osversion > e1->osversion)
+	return 1;
+      if (e2->osversion < e1->osversion)
+	return -1;
     }
   return res;
 }
@@ -319,9 +343,9 @@ save_cache (const char *cache_name)
 	     always begins at the beginning of the the new cache
 	     struct.  */
 	  file_entries_new->libs[idx_new].flags = entry->flags;
+	  file_entries_new->libs[idx_new].osversion = entry->osversion;
 	  file_entries_new->libs[idx_new].hwcap = entry->hwcap;
 	  file_entries_new->libs[idx_new].key = str_offset;
-	  file_entries_new->libs[idx_new].__unused = 0;
 	}
       len = strlen (entry->lib);
       str = stpcpy (str, entry->lib);
@@ -414,7 +438,7 @@ save_cache (const char *cache_name)
 /* Add one library to the cache.  */
 void
 add_to_cache (const char *path, const char *lib, int flags,
-	      uint64_t hwcap)
+	      unsigned int osversion, uint64_t hwcap)
 {
   struct cache_entry *new_entry, *ptr, *prev;
   char *full_path;
@@ -430,6 +454,7 @@ add_to_cache (const char *path, const ch
   new_entry->lib = xstrdup (lib);
   new_entry->path = full_path;
   new_entry->flags = flags;
+  new_entry->osversion = osversion;
   new_entry->hwcap = hwcap;
   new_entry->bits_hwcap = 0;
 
--- libc/sysdeps/generic/ldsodefs.h.jj	Fri Mar  2 13:44:46 2001
+++ libc/sysdeps/generic/ldsodefs.h	Mon Mar  5 13:59:26 2001
@@ -173,6 +173,9 @@ extern char **_dl_argv;
 /* Cached value of `getpagesize ()'.  */
 extern size_t _dl_pagesize;
 
+/* OS version.  */
+extern unsigned int _dl_osversion;
+
 /* File descriptor referring to the zero-fill device.  */
 extern int _dl_zerofd;
 
--- libc/sysdeps/generic/dl-cache.h.jj	Thu Nov  2 08:52:18 2000
+++ libc/sysdeps/generic/dl-cache.h	Mon Mar  5 14:42:00 2001
@@ -76,7 +76,7 @@ struct file_entry_new
 {
   int32_t flags;		/* This is 1 for an ELF library.  */
   uint32_t key, value;		/* String table indices.  */
-  uint32_t __unused;		/* Align next field always on 8 byte boundary.	*/
+  uint32_t osversion;		/* Required OS version.	 */
   uint64_t hwcap;		/* Hwcap entry.	 */
 };
 
--- libc/sysdeps/generic/readelflib.c.jj	Thu Nov 30 13:17:23 2000
+++ libc/sysdeps/generic/readelflib.c	Mon Mar  5 16:23:48 2001
@@ -1,4 +1,4 @@
-/* Copyright (C) 1999, 2000 Free Software Foundation, Inc.
+/* Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Andreas Jaeger <aj@suse.de>, 1999 and
 		  Jakub Jelinek <jakub@redhat.com>, 1999.
@@ -41,7 +41,8 @@ do								\
 /* Returns 0 if everything is ok, != 0 in case of error.  */
 int
 process_elf_file (const char *file_name, const char *lib, int *flag,
-		  char **soname, void *file_contents, size_t file_length)
+		  unsigned int *osversion, char **soname, void *file_contents,
+		  size_t file_length)
 {
   int i;
   unsigned int j;
@@ -56,6 +57,7 @@ process_elf_file (const char *file_name,
   char *dynamic_strings;  
 
   elf_header = (ElfW(Ehdr) *) file_contents;
+  *osversion = 0;
 
   if (elf_header->e_ident [EI_CLASS] != ElfW (CLASS))
     {
@@ -110,6 +112,7 @@ process_elf_file (const char *file_name,
 	  dynamic_addr = segment->p_offset;
 	  dynamic_size = segment->p_filesz;
 	  break;
+
 	case PT_INTERP:
 	  program_interpreter = (char *) (file_contents + segment->p_offset);
 	  check_ptr (program_interpreter);
@@ -123,6 +126,21 @@ process_elf_file (const char *file_name,
 		break;
 	      }
 	  break;
+
+	case PT_NOTE:
+	  if (!*osversion && segment->p_filesz == 32 && segment->p_align >= 4)
+	    {
+	      ElfW(Word) *abi_note = (ElfW(Word) *) (file_contents
+						     + segment->p_offset);
+	      if (abi_note [0] == 4 && abi_note [1] == 16 && abi_note [2] == 1
+		  && memcmp (abi_note + 3, "GNU", 4) == 0)
+		*osversion = (abi_note [4] << 24) |
+			     ((abi_note [5] & 0xff) << 16) |
+			     ((abi_note [6] & 0xff) << 8) |
+			     (abi_note [7] & 0xff);
+	    }
+	  break;
+
 	default:
 	  break;
 	}
--- libc/sysdeps/generic/dl-cache.c.jj	Fri Mar  2 17:39:33 2001
+++ libc/sysdeps/generic/dl-cache.c	Mon Mar  5 20:30:15 2001
@@ -228,6 +228,8 @@ _dl_load_cache_lookup (const char *name)
 
       /* Only accept hwcap if it's for the right platform.  */
 #define HWCAP_CHECK							       \
+      if (_dl_osversion	&& cache_new->libs[middle].osversion > _dl_osversion)  \
+	continue;							       \
       if (_DL_PLATFORMS_COUNT && platform != -1				       \
 	  && (cache_new->libs[middle].hwcap & _DL_HWCAP_PLATFORM) != 0	       \
 	  && (cache_new->libs[middle].hwcap & _DL_HWCAP_PLATFORM) != platform) \
--- libc/sysdeps/unix/sysv/linux/ia64/readelflib.c.jj	Sat Sep 30 00:42:21 2000
+++ libc/sysdeps/unix/sysv/linux/ia64/readelflib.c	Mon Mar  5 15:26:04 2001
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 Free Software Foundation, Inc.
+/* Copyright (C) 2000, 2001 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
@@ -18,25 +18,28 @@
 
 
 int process_elf32_file (const char *file_name, const char *lib, int *flag,
-			char **soname, void *file_contents, size_t file_length);
+			unsigned int *osversion, char **soname,
+			void *file_contents, size_t file_length);
 int process_elf64_file (const char *file_name, const char *lib, int *flag,
-			char **soname, void *file_contents, size_t file_length);
+			unsigned int *osversion, char **soname,
+			void *file_contents, size_t file_length);
 
 /* Returns 0 if everything is ok, != 0 in case of error.  */
 int
 process_elf_file (const char *file_name, const char *lib, int *flag,
-		  char **soname, void *file_contents, size_t file_length)
+		  unsigned int *osversion, char **soname,
+		  void *file_contents, size_t file_length)
 {
   ElfW(Ehdr) *elf_header = (ElfW(Ehdr) *) file_contents;
   int ret;
 
   if (elf_header->e_ident [EI_CLASS] == ELFCLASS32)
-    return process_elf32_file (file_name, lib, flag, soname, file_contents,
-				file_length);
+    return process_elf32_file (file_name, lib, flag, osversion, soname,
+			       file_contents, file_length);
   else
     {
-      ret = process_elf64_file (file_name, lib, flag, soname, file_contents,
-				 file_length);
+      ret = process_elf64_file (file_name, lib, flag, osversion, soname,
+				file_contents, file_length);
       /* Intel 64bit libraries are always libc.so.6+.  */
       if (!ret)
 	*flag = FLAG_IA64_LIB64|FLAG_ELF_LIBC6;
--- libc/sysdeps/unix/sysv/linux/i386/readelflib.c.jj	Sat Sep 30 23:46:37 2000
+++ libc/sysdeps/unix/sysv/linux/i386/readelflib.c	Mon Mar  5 15:23:58 2001
@@ -1,4 +1,4 @@
-/* Copyright (C) 1999, 2000 Free Software Foundation, Inc.
+/* Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Andreas Jaeger <aj@suse.de>, 1999 and
 		  Jakub Jelinek <jakub@redhat.com>, 2000.
@@ -20,23 +20,24 @@
 
 
 int process_elf32_file (const char *file_name, const char *lib, int *flag,
-			char **soname, void *file_contents,
-			size_t file_length);
+			unsigned int *osversion, char **soname,
+			void *file_contents, size_t file_length);
 int process_elf64_file (const char *file_name, const char *lib, int *flag,
-			char **soname, void *file_contents,
-			size_t file_length);
+			unsigned int *osversion, char **soname,
+			void *file_contents, size_t file_length);
 
 /* Returns 0 if everything is ok, != 0 in case of error.  */
 int
 process_elf_file (const char *file_name, const char *lib, int *flag,
-		  char **soname, void *file_contents, size_t file_length)
+		  unsigned int *osversion, char **soname, void *file_contents,
+		  size_t file_length)
 {
   ElfW(Ehdr) *elf_header = (ElfW(Ehdr) *) file_contents;
   int ret;
 
   if (elf_header->e_ident [EI_CLASS] == ELFCLASS32)
-    return process_elf32_file (file_name, lib, flag, soname, file_contents,
-			       file_length);
+    return process_elf32_file (file_name, lib, flag, osversion, soname,
+			       file_contents, file_length);
   else
     {
       switch (elf_header->e_machine)
@@ -50,8 +51,8 @@ process_elf_file (const char *file_name,
 	  return 1;
 	}
 
-      ret = process_elf64_file (file_name, lib, flag, soname, file_contents,
-				file_length);
+      ret = process_elf64_file (file_name, lib, flag, osversion, soname,
+				file_contents, file_length);
       /* IA64/X86-64 64bit libraries are always libc.so.6+.  */
       if (!ret)
 	switch (elf_header->e_machine)
--- libc/sysdeps/unix/sysv/linux/sparc/readelflib.c.jj	Wed May 31 23:03:01 2000
+++ libc/sysdeps/unix/sysv/linux/sparc/readelflib.c	Mon Mar  5 15:26:42 2001
@@ -1,4 +1,4 @@
-/* Copyright (C) 1999 Free Software Foundation, Inc.
+/* Copyright (C) 1999, 2001 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Andreas Jaeger <aj@suse.de>, 1999 and
 		  Jakub Jelinek <jakub@redhat.com>, 1999.
@@ -20,27 +20,28 @@
 
 
 int process_elf32_file (const char *file_name, const char *lib, int *flag,
-			char **soname, void *file_contents,
-			size_t file_length);
+			unsigned int *osversion, char **soname,
+			void *file_contents, size_t file_length);
 int process_elf64_file (const char *file_name, const char *lib, int *flag,
-			char **soname, void *file_contents,
-			size_t file_length);
+			unsigned int *osversion, char **soname,
+			void *file_contents, size_t file_length);
 
 /* Returns 0 if everything is ok, != 0 in case of error.  */
 int
 process_elf_file (const char *file_name, const char *lib, int *flag,
-		  char **soname, void *file_contents, size_t file_length)
+		  unsigned int *osversion, char **soname, void *file_contents,
+		  size_t file_length)
 {
   ElfW(Ehdr) *elf_header = (ElfW(Ehdr) *) file_contents;
   int ret;
 
   if (elf_header->e_ident [EI_CLASS] == ELFCLASS32)
-    return process_elf32_file (file_name, lib, flag, soname, file_contents,
-			       file_length);
+    return process_elf32_file (file_name, lib, flag, osversion, soname,
+			       file_contents, file_length);
   else
     {
-      ret = process_elf64_file (file_name, lib, flag, soname, file_contents,
-				file_length);
+      ret = process_elf64_file (file_name, lib, flag, osversion, soname,
+				file_contents, file_length);
       /* Sparc 64bit libraries are always libc.so.6+.  */
       if (!ret)
 	*flag = FLAG_SPARC_LIB64|FLAG_ELF_LIBC6;
--- libc/sysdeps/unix/sysv/linux/configure.in.jj	Thu Nov  2 08:52:21 2000
+++ libc/sysdeps/unix/sysv/linux/configure.in	Mon Mar  5 12:55:27 2001
@@ -74,6 +74,7 @@ if test -n "$minimum_kernel"; then
   AC_MSG_CHECKING(for kernel header at least $minimum_kernel)
 changequote(,)dnl
   decnum=`echo "$minimum_kernel.0.0.0" | sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/(\1 * 65536 + \2 * 256 + \3)/'`;
+  abinum=`echo "$minimum_kernel.0.0.0" | sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\1,\2,\3/'`;
 changequote([,])dnl
   AC_EGREP_CPP([eat flaming death], [#include <linux/version.h>
 #if LINUX_VERSION_CODE < $decnum
@@ -82,6 +83,7 @@ eat flaming death
   AC_MSG_RESULT($libc_minimum_kernel)
   if test "$libc_minimum_kernel" = ok; then
     AC_DEFINE_UNQUOTED(__LINUX_KERNEL_VERSION, $decnum)
+    AC_DEFINE_UNQUOTED(__ABI_TAG_VERSION, $abinum)
   else
     AC_MSG_ERROR([*** The available kernel headers are older than the requested
 *** compatible kernel version])
--- libc/sysdeps/unix/sysv/linux/configure.jj	Thu Nov  2 08:52:21 2000
+++ libc/sysdeps/unix/sysv/linux/configure	Mon Mar  5 12:55:39 2001
@@ -87,6 +87,7 @@ if test -n "$minimum_kernel"; then
   echo $ac_n "checking for kernel header at least $minimum_kernel""... $ac_c" 1>&6
 echo "configure:89: checking for kernel header at least $minimum_kernel" >&5
   decnum=`echo "$minimum_kernel.0.0.0" | sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/(\1 * 65536 + \2 * 256 + \3)/'`;
+  abinum=`echo "$minimum_kernel.0.0.0" | sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\1,\2,\3/'`;
   cat > conftest.$ac_ext <<EOF
 #line 92 "configure"
 #include "confdefs.h"
@@ -109,6 +110,10 @@ rm -f conftest*
   if test "$libc_minimum_kernel" = ok; then
     cat >> confdefs.h <<EOF
 #define __LINUX_KERNEL_VERSION $decnum
+EOF
+
+    cat >> confdefs.h <<EOF
+#define __ABI_TAG_VERSION $abinum
 EOF
 
   else
--- libc/sysdeps/unix/sysv/linux/dl-osinfo.h.jj	Fri Mar  2 13:44:59 2001
+++ libc/sysdeps/unix/sysv/linux/dl-osinfo.h	Mon Mar  5 14:15:01 2001
@@ -102,5 +102,7 @@ dl_fatal (const char *str)
 	if (version < __LINUX_KERNEL_VERSION)				      \
 	  /* Not sufficent.  */						      \
 	  FATAL ("FATAL: kernel too old\n");				      \
+									      \
+	_dl_osversion = version;					      \
       }									      \
   } while (0)
--- libc/sysdeps/unix/sysv/linux/init-first.c.jj	Wed Jan 31 16:35:23 2001
+++ libc/sysdeps/unix/sysv/linux/init-first.c	Mon Mar  5 14:21:19 2001
@@ -29,6 +29,7 @@
 #include <libc-internal.h>
 
 #ifndef SHARED
+# include <ldsodefs.h>
 # include "dl-osinfo.h"
 #endif
 
--- libc/Makerules.jj	Fri Feb  9 13:50:59 2001
+++ libc/Makerules	Mon Mar  5 17:54:09 2001
@@ -413,29 +413,75 @@ endif
 lib%.so: lib%_pic.a $(+preinit) $(+postinit) $(+interp)
 	$(build-shlib)
 
-define build-shlib
-$(LINK.o) -shared -Wl,-O1 -o $@ $(sysdep-LDFLAGS) $(config-LDFLAGS)  \
+define build-shlib-helper
+$(LINK.o) -shared -Wl,-O1 $(sysdep-LDFLAGS) $(config-LDFLAGS) \
 	  $(extra-B-$(@F:lib%.so=%).so) -B$(csu-objpfx) \
 	  $(extra-B-$(@F:lib%.so=%).so) $(load-map-file) \
 	  -Wl,-soname=lib$(libprefix)$(@F:lib%.so=%).so$($(@F)-version) \
 	  $(LDFLAGS.so) $(LDFLAGS-$(@F:lib%.so=%).so) \
-	  -L$(subst :, -L,$(rpath-link)) -Wl,-rpath-link=$(rpath-link) \
-	  -Wl,--whole-archive \
+	  -L$(subst :, -L,$(rpath-link)) -Wl,-rpath-link=$(rpath-link)
+endef
+
+ifeq (yes,$(elf))
+# binutils only position loadable notes into the first page for binaries,
+# not for shared objects
+define build-shlib
+$(build-shlib-helper) \
+	  -o $@.new $(csu-objpfx)/abi-note.o -Wl,--verbose \
+	  $(LDLIBS-$(@F:lib%.so=%).so) 2>&1 | \
+	  sed -e '/^=========/,/^=========/!d;/^=========/d' \
+	      -e 's/^.*\.hash[ 	]*:.*$$/  .note.ABI-tag : { *(.note.ABI-tag) } &/' \
+	  > $@.lds; \
+	  rm -f $@.new; \
+	  $(build-shlib-helper) -o $@ -T $@.lds \
+	  -Wl,--whole-archive $(csu-objpfx)/abi-note.o \
+	  $(filter-out $(map-file) $(+preinit) $(+postinit),$^) \
+	  $(no-whole-archive) $(LDLIBS-$(@F:lib%.so=%).so); \
+	  rm -f $@.lds
+endef
+else
+define build-shlib
+$(build-shlib-helper) \
+	  -o $@ -Wl,--whole-archive \
 	  $(filter-out $(map-file) $(+preinit) $(+postinit),$^) \
 	  $(no-whole-archive) $(LDLIBS-$(@F:lib%.so=%).so)
 endef
+endif
+
+define build-module-helper \
+$(LINK.o) -shared $(sysdep-LDFLAGS) $(config-LDFLAGS) \
+	  -B$(csu-objpfx) $(load-map-file) \
+	  $(LDFLAGS.so) $(LDFLAGS-$(@F:%.so=%).so) \
+	  -L$(subst :, -L,$(rpath-link)) -Wl,-rpath-link=$(rpath-link)
+endef
 
 # This macro is similar to build-shlib but it does not define a soname
 # and it does not depend on the destination name to start with `lib'.
+ifeq (yes,$(elf))
+# binutils only position loadable notes into the first page for binaries,
+# not for shared objects
 define build-module
-$(LINK.o) -shared -o $@ $(sysdep-LDFLAGS) $(config-LDFLAGS)  \
-	  -B$(csu-objpfx) $(load-map-file) \
-	  $(LDFLAGS.so) $(LDFLAGS-$(@F:%.so=%).so) \
-	  -L$(subst :, -L,$(rpath-link)) -Wl,-rpath-link=$(rpath-link) \
-	  -Wl,--whole-archive \
+$(build-module-helper) \
+	  -o $@.new $(csu-objpfx)/abi-note.o -Wl,--verbose \
+	  $(LDLIBS-$(@F:lib%.so=%).so) 2>&1 | \
+	  sed -e '/^=========/,/^=========/!d;/^=========/d' \
+	      -e 's/^.*\.hash[ 	]*:.*$$/  .note.ABI-tag : { *(.note.ABI-tag) } &/' \
+	  > $@.lds; \
+	  rm -f $@.new; \
+	  $(build-module-helper) -o $@ -T $@.lds \
+	  -Wl,--whole-archive $(csu-objpfx)/abi-note.o \
+	  $(filter-out $(map-file) $(+preinit) $(+postinit),$^) \
+	  $(no-whole-archive) $(LDLIBS-$(@F:lib%.so=%).so); \
+	  rm -f $@.lds
+endef
+else
+define build-module
+$(build-module-helper) \
+	  -o $@ -Wl,--whole-archive \
 	  $(filter-out $(map-file) $(+preinit) $(+postinit),$^) \
 	  $(no-whole-archive) $(LDLIBS-$(@F:%.so=%).so)
 endef
+endif
 
 # Don't try to use -lc when making libc.so itself.
 # Also omits crti.o and crtn.o, which we do not want
--- libc/config.h.in.jj	Fri Dec  8 13:52:11 2000
+++ libc/config.h.in	Mon Mar  5 12:57:08 2001
@@ -93,6 +93,9 @@
 /* Linux specific: minimum supported kernel version.  */
 #undef	__LINUX_KERNEL_VERSION
 
+/* Override abi-tags ABI version if necessary.  */
+#undef  __ABI_TAG_VERSION
+
 /* An extension in gcc 2.96 and up allows the subtraction of two
    local labels.  */
 #undef	HAVE_SUBTRACT_LOCAL_LABELS

	Jakub


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