This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Re: Another MIPS multigot patch
- From: Daniel Jacobowitz <drow at mvista dot com>
- To: binutils at sources dot redhat dot com
- Date: Tue, 10 Feb 2004 17:59:38 -0500
- Subject: Re: Another MIPS multigot patch
- References: <87he0we569.fsf@redhat.com> <20031122173959.GA6247@nevyn.them.org> <874qwwusg1.fsf@redhat.com> <20031123012406.GA11321@nevyn.them.org> <20040129144621.GA18176@nevyn.them.org> <87znc6px4u.fsf@redhat.com> <20040129161858.GG18176@nevyn.them.org> <87isiupsb7.fsf@redhat.com> <20040129180348.GI18176@nevyn.them.org> <87znc3yg6i.fsf@redhat.com>
On Sat, Jan 31, 2004 at 09:13:57PM +0000, Richard Sandiford wrote:
> Daniel Jacobowitz <drow@mvista.com> writes:
> >> >> - Are the !h and h->root.dynindx checks still needed after this?
> >> >> (Not sure off-hand.)
> >> >
> >> > The !h test is no longer necessary. The dynindx check still is.
> >> > h->root.dynindx == -1 will be handled by SYMBOL_REFERENCES_LOCAL, but
> >> > otherwise (if info->shared) a low dynindx and a high dynindx will be
> >> > both return FALSE.
> >>
> >> I don't know what you mean here. Do you have an example?
> >
> > Well, at the basic level, for a symbol with dynindx > 0 and dynindx <
> > mips_elf_get_global_gotsym SYMBOL_REFERENCES_LOCAL will return false
> > (if info->shared).
>
> That shouldn't happen. mips_elf_get_global_gotsym_index is the value
> associated with DT_MIPS_GOTSYM, i.e., the index of the first global GOT
> entry. Anything in the range [0,mips_elf_get_global_gotsym_index] is
> supposed to bind locally.
Considering that the relatively recent _bfd_elf_symbol_refs_local_p is
not used from the MIPS code, I would have been amazed if it agreed on
all counts. Indeed it does not. I did this:
+ /* If this symbol got a global GOT entry, we might have to decay
+ GOT_PAGE/GOT_OFST to GOT_DISP/addend. We check whether we need
+ to decay, because if we don't need to it's possible that no GOT
+ entry was allocated in this input BFD's GOT for this reference
+ (it might be in some other GOT, and out of range). */
+ if (h && (h->root.dynindx
+ < mips_elf_get_global_gotsym_index (elf_hash_table (info)
+ ->dynobj)))
+ BFD_ASSERT (_bfd_elf_symbol_refs_local_p (h, info, 1));
+ local_p = local_p || _bfd_elf_symbol_refs_local_p (h, info, 1);
and built world; the assertion failed a number of times. The related
assertion in mips_elf_global_got_index did also:
BFD_ASSERT (h->dynindx >= global_got_dynindx);
The first example I checked was while building ranlib. The symbol was
_xexit_cleanup, a global function pointer. No visibility tricks
involved, although it resolves from the shared libbfd rather than the
included static libiberty. It failed both assertions:
(gdb) p h->dynindx
$4 = 8
(gdb) p global_got_dynindx
$5 = 14
(gdb) p _bfd_elf_symbol_refs_local_p (h, info, 1)
$6 = 0
I would prefer to investigate this problem separately from the original
patch, which was needed for large applications to link on n64. But if
you prefer then we can keep digging - I don't have time to figure out
what the problem with _xexit_cleanup is right now. I have long
suspected that MIPS's crazy unique GOT handling did not honor the
symbol pre-emption rules properly.
--
Daniel Jacobowitz
MontaVista Software Debian GNU/Linux Developer