This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Spurious undefined reference error?


On Thu, Dec 20, 2012 at 03:19:25PM -0800, Dan Kegel wrote:
> On Thu, Dec 20, 2012 at 12:00 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
> >> The problem was not present on ubuntu 10.04
> >
> > I think Ubuntu changed linker command-line options passed from GCC
> > driver.  Please compare the linker command-line options
> 
> On ubuntu 12.04, the extra options
>   --no-add-needed --as-needed
> appear on the collect2 commandline.
> 
> Adding  -Wl,--no-add-needed -Wl,--as-needed  to the g++ commandline on
> ubuntu 10.04 replicates the link failure on the previously working
> system.
> Adding -Wl,--no-as-needed  on ubuntu 12.04 works around the problem.

Using your testcase from
http://sourceware.org/bugzilla/show_bug.cgi?id=13141#c1
I could not reproduce this problem on my x86_64 Ubuntu 11.10 system.
ld says
GNU ld (GNU Binutils for Ubuntu) 2.21.53.20110810

Nor did I see a problem when using current mainline ld.  For both
versions of ld, we get a DT_NEEDED entry for libm in both libf1.so and
the main app.  Which is odd because --no-copy-dt-needed-entries was in
effect when linking app and there was no command line reference to
libm.  So I dug around a little to see why libm is somehow special and
found we're picking up libm via elf32.em:check_ld_so_conf(), which
calls search_needed() with needed.by == NULL, and that results in this
piece of code in try_needed() not seeing libm as a dependent library.

  /* Tell the ELF linker that we don't want the output file to have a
     DT_NEEDED entry for this file at all if the entry is from a file
     with DYN_NO_ADD_NEEDED.  */
  if (needed->by != NULL
      && (bfd_elf_get_dyn_lib_class (needed->by) & DYN_NO_ADD_NEEDED) != 0)
    link_class |= DYN_NO_NEEDED | DYN_NO_ADD_NEEDED;

Easily enough fixed.  I'll probably be blamed for breaking a number
of projects with this change, but of course all I'm doing here is
making http://sourceware.org/ml/binutils/2011-08/msg00129.html
effective.

	* emultempl/elf32.em (gld${EMULATION_NAME}_check_ld_so_conf): Replace
	"name" param with a bfd_link_needed_list pointer.  Update caller.
	(gld${EMULATION_NAME}_check_ld_elf_hints): Likewise.

Index: ld/emultempl/elf32.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/elf32.em,v
retrieving revision 1.234
diff -u -p -r1.234 elf32.em
--- ld/emultempl/elf32.em	6 Dec 2012 00:25:18 -0000	1.234
+++ ld/emultempl/elf32.em	8 Jan 2013 05:27:24 -0000
@@ -569,7 +569,8 @@ EOF
 #endif
 
 static bfd_boolean
-gld${EMULATION_NAME}_check_ld_elf_hints (const char *name, int force)
+gld${EMULATION_NAME}_check_ld_elf_hints (const struct bfd_link_needed_list *l,
+					 int force)
 {
   static bfd_boolean initialized;
   static char *ld_elf_hints;
@@ -612,10 +613,9 @@ gld${EMULATION_NAME}_check_ld_elf_hints 
   if (ld_elf_hints == NULL)
     return FALSE;
 
-  needed.by = NULL;
-  needed.name = name;
-  return gld${EMULATION_NAME}_search_needed (ld_elf_hints, & needed,
-					     force);
+  needed.by = l->by;
+  needed.name = l->name;
+  return gld${EMULATION_NAME}_search_needed (ld_elf_hints, &needed, force);
 }
 EOF
     # FreeBSD
@@ -787,7 +787,8 @@ gld${EMULATION_NAME}_parse_ld_so_conf
 }
 
 static bfd_boolean
-gld${EMULATION_NAME}_check_ld_so_conf (const char *name, int force)
+gld${EMULATION_NAME}_check_ld_so_conf (const struct bfd_link_needed_list *l,
+				       int force)
 {
   static bfd_boolean initialized;
   static char *ld_so_conf;
@@ -824,8 +825,8 @@ gld${EMULATION_NAME}_check_ld_so_conf (c
     return FALSE;
 
 
-  needed.by = NULL;
-  needed.name = name;
+  needed.by = l->by;
+  needed.name = l->name;
   return gld${EMULATION_NAME}_search_needed (ld_so_conf, &needed, force);
 }
 
@@ -1308,7 +1309,7 @@ if [ "x${USE_LIBPATH}" = xyes ] ; then
   case ${target} in
     *-*-freebsd* | *-*-dragonfly*)
       fragment <<EOF
-	  if (gld${EMULATION_NAME}_check_ld_elf_hints (l->name, force))
+	  if (gld${EMULATION_NAME}_check_ld_elf_hints (l, force))
 	    break;
 EOF
     # FreeBSD
@@ -1317,7 +1318,7 @@ EOF
     *-*-linux-* | *-*-k*bsd*-* | *-*-gnu*)
     # Linux
       fragment <<EOF
-	  if (gld${EMULATION_NAME}_check_ld_so_conf (l->name, force))
+	  if (gld${EMULATION_NAME}_check_ld_so_conf (l, force))
 	    break;
 
 EOF

-- 
Alan Modra
Australia Development Lab, IBM


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