This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: binutils 2.19.92 linker broke with --as-needed flag
- From: Alan Modra <amodra at gmail dot com>
- To: Vincent Wen <wenvincent90 at gmail dot com>
- Cc: binutils at sourceware dot org
- Date: Wed, 13 Feb 2013 11:22:53 +1030
- Subject: Re: binutils 2.19.92 linker broke with --as-needed flag
- References: <CAF_=-cACCz1d-tr+Etmdk4jWYwLh5NA5kKom=x3OiMGwyRjzqQ@mail.gmail.com>
On Mon, Feb 04, 2013 at 05:58:37PM -0800, Vincent Wen wrote:
> The linker broke when as-need flag is added.
>
> /bin/sh ../libtool --tag=CC --mode=link mipsel-linux-gcc -I../include -g
> -O2 -Wl,--as-needed -o test-example test.o ../lib/libTestGcc.la
> libtool: link: mipsel-linux-gcc -I../include -g -O2 -Wl,--as-needed -o
> .libs/test-example test.o ../lib/.libs/libTestGcc.so -Wl,-rpath
> -Wl,/usr/local/lib
> ../lib/.libs/libTestGcc.so:(.got+0x0): multiple definition of
> `_GLOBAL_OFFSET_TABLE_'
I think mips was broken before --as-needed. mips seems to want a
dynamic _GLOBAL_OFFSET_TABLE_ symbol in shared libs, presumably for
use by ld.so. However, a global symbol will be resolved by ld.so
according to the ELF rules which will result in the symbol being
resolved to the first definition seen in a breadth first search of the
application and its shared libraries. That means the value in the
first shared lib. So the value seen in other shared libs is wrong.
_GLOBAL_OFFSET_TABLE_ must resolve locally.
So _GLOBAL_OFFSET_TABLE_ must at least be STV_PROTECTED, and could be
STV_HIDDEN as you do in your patch.
> --- a/bfd/elfxx-mips.c 2013-02-01 03:26:00.000000000 -0800
> +++ b/bfd/elfxx-mips.c 2013-02-01 03:26:16.000000000 -0800
> @@ -4681,6 +4681,7 @@
> h->non_elf = 0;
> h->def_regular = 1;
> h->type = STT_OBJECT;
> + h->other = STV_HIDDEN;
> elf_hash_table (info)->hgot = h;
>
> if (info->shared
The trouble with this is that making it STV_HIDDEN results in no
dynamic _GLOBAL_OFFSET_TABLE_ symbol at all, due to the following code
in bfd_elf_link_record_dynamic_symbol.
/* XXX: The ABI draft says the linker must turn hidden and
internal symbols into STB_LOCAL symbols when producing the
DSO. However, if ld.so honors st_other in the dynamic table,
this would not be necessary. */
switch (ELF_ST_VISIBILITY (h->other))
{
case STV_INTERNAL:
case STV_HIDDEN:
if (h->root.type != bfd_link_hash_undefined
&& h->root.type != bfd_link_hash_undefweak)
{
h->forced_local = 1;
if (!elf_hash_table (info)->is_relocatable_executable)
return TRUE;
}
Now that code is also wrong, I think. The "return TRUE" should never
happen.
--
Alan Modra
Australia Development Lab, IBM