This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: Spurious undefined reference error?
- From: Alan Modra <amodra at gmail dot com>
- To: Dan Kegel <dank at kegel dot com>
- Cc: "H.J. Lu" <hjl dot tools at gmail dot com>, binutils at sourceware dot org
- Date: Tue, 8 Jan 2013 16:40:09 +1030
- Subject: Re: Spurious undefined reference error?
- References: <CAPF-yOaSkoNNH=aPQuzWtvRYP=K5emyBKMwu6A747VTHR92vZQ@mail.gmail.com> <CAPF-yOYrHF6q1QfrLDfuaozrWpA36=au93VjkQnGU+crKaX4jg@mail.gmail.com> <CAMe9rOr3nBTKJniT5JUYbYyMMCWpoHnDY9863CG84oQ8mv0Uww@mail.gmail.com> <CAPF-yOavcV2xu74ey7PTB60=8Rycodi2Y2fXs44NgmCHMKXezg@mail.gmail.com>
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