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: binutils 2.19.92 linker broke with --as-needed flag


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


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