This is the mail archive of the libc-hacker@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: More on 32bit/64bit ABIs under Linux


Hi!

Below is attached how I wanted to solve the multiple ABIs issues for the
linker. IMHO it is bad that by default ld only warns you about incompatible
ABIs, but happily links things together, but I haven't changed anything in
that respect. What I did in the patch bellow, is: if it is looking for a
library in the search path (ie. one uses -lc or whatever), then it checks
for each library in that path with the desired name if it is compatible or
not (it is a little bit more complicated for ar libraries with different
object formats where the patch bellow assumes it is not compatible if it
does not find any compatible object in it). If it is not compatible, it
continues searching in the search path and if it does not find any
compatible library, it gives you the incompatible one which was first in the
search path. As this changes the behaviour of linker, I added a switch
--skip-on-mismatch, which turns on this behaviour.
With such a patch, you can choose the filesystem layout for the different
ABIs you like. Either you have separate directories, like I proposed, e.g.
/lib, /lib64, /usr/lib, /usr/lib64, etc. in which case it matters only
what's the order of paths with the same ABIs.
You call linker something like 
ld -m elf64_sparc --skip-on-mismatch -Y P,/usr/lib64 -dynamic-linker /lib64/ld-linux.so.2 -L/usr/lib64 -L/lib64
Or you can e.g. put both your
ABI library formats into the same paths, e.g.
/lib/libc.so.6 and /lib/libc64.so.6 etc. In that case, you will use the -A
ld option, e.g.
ld -m elf64_sparc --skip-on-mismatch -Y P,/usr/lib -A64 -dynamic-linker /lib/ld-linux64.so.2 -L/usr/lib -L/lib
In the first case it won't matter much if a user adds e.g. a library path
with 32bit ABI libs into the path, as those will be skipped.

I'd like to hear comments and thought about it.
A thing still missing to get such a scheme working would be some kind of
conditionals in the linker scripts, as e.g. /usr/lib/libc.so on glibc
systems is a linker script and it would be desirable to write there where it
can really find the libraries. Something like either:
IFTARGET (elf32_sparc)
GROUP ( /lib/libc.so.6 /usr/lib/libc_nonshared.a )
ELSE
GROUP ( /lib64/libc.so.6 /usr/lib64/libc_nonshared.a )
ENDIF

or
IFTARGET (elf32_sparc)
GROUP ( /lib/libc.so.6 /usr/lib/libc_nonshared.a )
ELSE
GROUP ( /lib/libc64.so.6 /usr/lib/libc_nonshared64.a )
ENDIF

--- gas-990422/ld/lexsup.c.jj	Thu Apr 22 10:15:35 1999
+++ gas-990422/ld/lexsup.c	Fri Apr 30 11:40:43 1999
@@ -120,6 +120,7 @@ int parsing_defsym = 0;
 #define OPTION_NO_CHECK_SECTIONS	(OPTION_CHECK_SECTIONS + 1)
 #define OPTION_MPC860C0                 (OPTION_NO_CHECK_SECTIONS + 1)
 #define OPTION_NO_UNDEFINED		(OPTION_MPC860C0 + 1)
+#define OPTION_SKIP_MISMATCH		(OPTION_NO_UNDEFINED + 1)
 
 /* The long options.  This structure is used for both the option
    parsing and the help text.  */
@@ -313,6 +314,8 @@ static const struct ld_option ld_options
       '\0', NULL, N_("Create a shared library"), ONE_DASH },
   { {"Bshareable", no_argument, NULL, OPTION_SHARED }, /* FreeBSD.  */
       '\0', NULL, NULL, ONE_DASH },
+  { {"skip-on-mismatch", no_argument, NULL, OPTION_SKIP_MISMATCH},
+      '\0', NULL, N_("Keep searching if mismatched input file is found in the path"), TWO_DASHES},
   { {"sort-common", no_argument, NULL, OPTION_SORT_COMMON},
       '\0', NULL, N_("Sort common symbols by size"), TWO_DASHES },
   { {"sort_common", no_argument, NULL, OPTION_SORT_COMMON},
@@ -799,6 +802,9 @@ parse_args (argc, argv)
 	    link_info.shared = true;
 	  else
 	    einfo (_("%P%F: -shared not supported\n"));
+	  break;
+	case OPTION_SKIP_MISMATCH:
+	  command_line.skip_on_mismatch = true;
 	  break;
 	case 'h':		/* Used on Solaris.  */
 	case OPTION_SONAME:
--- gas-990422/ld/ldmain.c.jj	Thu Apr 22 10:15:33 1999
+++ gas-990422/ld/ldmain.c	Fri Apr 30 11:40:19 1999
@@ -203,6 +203,7 @@ main (argc, argv)
   command_line.interpreter = NULL;
   command_line.rpath = NULL;
   command_line.warn_mismatch = true;
+  command_line.skip_on_mismatch = false;
   command_line.check_section_addresses = true;
 
   /* We initialize DEMANGLING based on the environment variable
--- gas-990422/ld/ld.h.jj	Thu Apr 22 10:15:30 1999
+++ gas-990422/ld/ld.h	Fri Apr 30 11:39:52 1999
@@ -128,6 +128,11 @@ typedef struct
   /* If true (which is the default), warn about mismatched input
      files.  */
   boolean warn_mismatch;
+  
+  /* If true and a mismatching file is found during -l searching,
+     skip it and continue searching for another file in the search
+     path.   */
+  boolean skip_on_mismatch;
 
   /* Remove unreferenced sections?  */
   boolean gc_sections;
--- gas-990422/ld/ldfile.c.jj	Thu Apr 22 10:15:32 1999
+++ gas-990422/ld/ldfile.c	Fri Apr 30 12:51:36 1999
@@ -132,6 +132,7 @@ ldfile_open_file_search (arch, entry, li
      const char *suffix;
 {
   search_dirs_type *search;
+  int state = 0;
 
   /* If this is not an archive, try to open it in the current
      directory first.  */
@@ -142,11 +143,14 @@ ldfile_open_file_search (arch, entry, li
     }
 
   for (search = search_head;
-       search != (search_dirs_type *)NULL;
+       search != (search_dirs_type *)NULL ||
+       (state == 1 &&
+        (search = search_head) != (search_dirs_type *)NULL);
        search = search->next) 
     {
       char *string;
 
+      if (state == 1) state++;
       if (entry->dynamic && ! link_info.relocateable)
 	{
 	  if (ldemul_open_dynamic_archive (arch, search, entry))
@@ -177,8 +181,47 @@ ldfile_open_file_search (arch, entry, li
 
       if (ldfile_try_open_bfd (string, entry))
 	{
-	  entry->filename = string;
-	  return true;
+	
+	  if (!command_line.skip_on_mismatch || state == 2)
+	    {
+	      entry->filename = string;
+	      return true;
+	    }
+	    
+	  if (bfd_check_format (entry->the_bfd, bfd_archive))
+	    {
+	      bfd *arfile = NULL;
+	      
+	      for (;;)
+	        {
+	          arfile = bfd_openr_next_archived_file (entry->the_bfd, arfile);
+	          
+	          if (arfile == NULL)
+		    break;
+	            
+	          if (bfd_check_format (arfile, bfd_object) &&
+	              bfd_arch_get_compatible (arfile, output_bfd))
+	            break;
+
+	        }
+
+	      if (arfile)
+	        state = 2;
+	    }
+	  else if (bfd_arch_get_compatible (entry->the_bfd, output_bfd))
+	    state = 2;
+	    
+	  if (state == 2)
+	    {
+	      entry->filename = string;
+	      return true;
+	    }
+
+	  if (!state) state++;
+	  info_msg (_("skipping %s because it has incompatible architecture\n"), string);
+	  bfd_close(entry->the_bfd);
+	  entry->the_bfd = NULL;
+	                                              
 	}
 
       free (string);


Cheers,
    Jakub
___________________________________________________________________
Jakub Jelinek | jj@sunsite.mff.cuni.cz | http://sunsite.mff.cuni.cz
Administrator of SunSITE Czech Republic, MFF, Charles University
___________________________________________________________________
UltraLinux  |  http://ultra.linux.cz/  |  http://ultra.penguin.cz/
Linux version 2.2.7 on a sparc64 machine (3958.37 BogoMips)
___________________________________________________________________


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