Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 17 Apr 2000 20:40:21 +0200
From:      Bjoern Fischer <bfischer@Techfak.Uni-Bielefeld.DE>
To:        FreeBSD-gnats-submit@freebsd.org
Cc:        bfischer@TechFak.Uni-Bielefeld.DE, bjoern@no-support.loc
Subject:   gnu/18061: [PATCH] /usr/bin/ld (GNU ld 2.9.1) ignores rpath in shlibs
Message-ID:  <200004170647.IAA00538@broccoli.no-support.loc>

next in thread | raw e-mail | index | archive | help


>Number:         18061
>Category:       gnu
>Synopsis:       /usr/bin/ld (GNU ld 2.9.1) ignores rpath in shared libraries
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Mon Apr 17 11:50:02 PDT 2000
>Closed-Date:
>Last-Modified:
>Originator:     Bjoern Fischer <bfischer@TechFak.Uni-Bielefeld.DE>
>Release:        FreeBSD 4.0-STABLE i386
>Organization:
No-Support
>Environment:

Any FreeBSD platform w/ ELF ABI.

>Description:

GNU ld ignores the rpath compiled into shared libraries
when going through the needed list at link time.

Imagine following scenario:

  library libA:

    /vol/foo/lib/libA.so
      needed: libB.so
      rpath:  /vol/bar/lib

  library libB:

    /vol/bar/lib/libB.so

Now one links a binary against libA:

  gcc -o foobar foobar.o -L/vol/foo/lib -R/vol/foo/lib -lA

The above will fail because ld won't find libB.so at link
time. The ld error message suggests that one should use
-rpath to fix this. This is even worse:
With -rpath /vol/bar/lib the path is hardcoded into the
resulting binary, which is nonsense. You want to use
-rpath-link.

But generally you should not need to specify the location
of libB.so at all, since libA.so is fully self contained
and the runtime linker will find all libraries needed for
the foobar executable w/o /vol/bar/lib in it's rpath.

>How-To-Repeat:

See description.

>Fix:

I don't know the proper method for changes in /usr/src/contrib/.
so I changed everything in place. Maybe the changes should be
moved to /usr/src/gnu/. making source imports easier.

The changes were promoted to the GNU maintainers and it is
probable that this or a similiar fix will be incorporated
into the next binutils release.

BTW: What is the common policy, how well tested should submitted
patches be? I did a buildworld and some tests for the new feature.

--- ./contrib/binutils/bfd/elflink.h	2000/04/16 17:11:15	1.1
+++ ./contrib/binutils/bfd/elflink.h	2000/04/16 20:40:13
@@ -852,6 +852,8 @@
 	  Elf_External_Dyn *extdynend;
 	  int elfsec;
 	  unsigned long link;
+	  int pass;
+	  char *rpath = NULL;
 
 	  dynbuf = (Elf_External_Dyn *) bfd_malloc ((size_t) s->_raw_size);
 	  if (dynbuf == NULL)
@@ -866,43 +868,78 @@
 	    goto error_return;
 	  link = elf_elfsections (abfd)[elfsec]->sh_link;
 
-	  extdyn = dynbuf;
-	  extdynend = extdyn + s->_raw_size / sizeof (Elf_External_Dyn);
-	  for (; extdyn < extdynend; extdyn++)
+	  /* pass0: Look for rpath tag and save the value.
+	     pass1: Look for soname and needed tags.
+		    Reference rpath in each bfd_link_needed_list entry. */
+	  for (pass = 0; pass <= 1; pass++)
 	    {
-	      Elf_Internal_Dyn dyn;
 
-	      elf_swap_dyn_in (abfd, extdyn, &dyn);
-	      if (dyn.d_tag == DT_SONAME)
+	      extdyn = dynbuf;
+	      extdynend = extdyn + s->_raw_size / sizeof (Elf_External_Dyn);
+	      for (; extdyn < extdynend; extdyn++)
 		{
-		  name = bfd_elf_string_from_elf_section (abfd, link,
-							  dyn.d_un.d_val);
-		  if (name == NULL)
-		    goto error_return;
-		}
-	      if (dyn.d_tag == DT_NEEDED)
-		{
-		  struct bfd_link_needed_list *n, **pn;
-		  char *fnm, *anm;
+		  Elf_Internal_Dyn dyn;
+
+		  elf_swap_dyn_in (abfd, extdyn, &dyn);
 
-		  n = ((struct bfd_link_needed_list *)
-		       bfd_alloc (abfd, sizeof (struct bfd_link_needed_list)));
-		  fnm = bfd_elf_string_from_elf_section (abfd, link,
-							 dyn.d_un.d_val);
-		  if (n == NULL || fnm == NULL)
-		    goto error_return;
-		  anm = bfd_alloc (abfd, strlen (fnm) + 1);
-		  if (anm == NULL)
-		    goto error_return;
-		  strcpy (anm, fnm);
-		  n->name = anm;
-		  n->by = abfd;
-		  n->next = NULL;
-		  for (pn = &elf_hash_table (info)->needed;
-		       *pn != NULL;
-		       pn = &(*pn)->next)
-		    ;
-		  *pn = n;
+		  if (pass == 0)
+		    {
+		      if (dyn.d_tag == DT_RPATH)
+			{
+			  /* DT_RPATH is not expected to occur more than
+			     once in a dynamic section. */
+			  if (rpath == NULL)
+			    {
+			      char *string;
+
+			      string =
+				bfd_elf_string_from_elf_section (abfd, link,
+								dyn.d_un.d_val);
+			      rpath = bfd_alloc (abfd, strlen(string) + 1);
+			      if (rpath == NULL)
+				goto error_return;
+			      strcpy (rpath, string);
+			    }
+			}
+		    }
+		  else /* pass != 0 */
+		    {
+
+		      if (dyn.d_tag == DT_SONAME)
+			{
+			  name = bfd_elf_string_from_elf_section (abfd, link,
+								dyn.d_un.d_val);
+			  if (name == NULL)
+			    goto error_return;
+			}
+		      if (dyn.d_tag == DT_NEEDED)
+			{
+			  struct bfd_link_needed_list *n, **pn;
+			  char *fnm, *anm;
+
+			  n = ((struct bfd_link_needed_list *)
+			  bfd_alloc (abfd,
+				     sizeof (struct bfd_link_needed_list)));
+			  fnm = bfd_elf_string_from_elf_section (abfd, link,
+								dyn.d_un.d_val);
+			  if (n == NULL || fnm == NULL)
+			    goto error_return;
+			  anm = bfd_alloc (abfd, strlen (fnm) + 1);
+			  if (anm == NULL)
+			    goto error_return;
+			  strcpy (anm, fnm);
+
+			  n->name = anm;
+			  n->by = abfd;
+			  n->rpath = rpath;
+			  n->next = NULL;
+			  for (pn = &elf_hash_table (info)->needed;
+			       *pn != NULL;
+			       pn = &(*pn)->next)
+			    ;
+			  *pn = n;
+			}
+		    } /* pass == 0 */
 		}
 	    }
 
--- ./contrib/binutils/ld/emultempl/elf32.em	2000/04/14 23:05:41	1.1
+++ ./contrib/binutils/ld/emultempl/elf32.em	2000/04/16 20:43:46
@@ -340,7 +340,8 @@
       /* We need to find this file and include the symbol table.  We
 	 want to search for the file in the same way that the dynamic
 	 linker will search.  That means that we want to use
-	 rpath_link, rpath, then the environment variable
+	 command line rpath_link, hardcompiled rpath in shared objects,
+	 command line rpath, then the environment variable
 	 LD_LIBRARY_PATH (native only), then the linker script
 	 LIB_SEARCH_DIRS.  We do not search using the -L arguments.
 
@@ -355,6 +356,8 @@
 
 	  if (gld${EMULATION_NAME}_search_needed (command_line.rpath_link,
 						  l->name, force))
+	    break;
+	  if (gld${EMULATION_NAME}_search_needed (l->rpath, l->name, force))
 	    break;
 	  if (gld${EMULATION_NAME}_search_needed (command_line.rpath,
 						  l->name, force))

--- ./gnu/usr.bin/binutils/libbfd/i386/bfd.h	2000/04/15 11:14:30	1.1
+++ ./gnu/usr.bin/binutils/libbfd/i386/bfd.h	2000/04/16 17:51:09
@@ -598,6 +598,7 @@
 {
   struct bfd_link_needed_list *next;
   bfd *by;
+  const char *rpath;
   const char *name;
 };
 

>Release-Note:
>Audit-Trail:
>Unformatted:


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200004170647.IAA00538>