This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Re: Another MIPS multigot patch
Daniel Jacobowitz <drow@false.org> writes:
> I have put it at:
> http://www.false.org/~drow/binutils-mips-got.tgz
Thanks. In hindsight, I really should have been able to work it
out from your description, sorry about that.
I think the problem is simply that check_relocs() was only checking
whether the symbol was defined, not whether the symbol was defined
by a regular or shared object.
The patch below seems to do the trick. I'll run a bootstrap on irix,
but since you seem to trip over the problem more often, it'd be great
if you could give it a spin.
I've attached a shell archive (to be run from the top level of the
build directory). Before the patch, a.x needlessly had a global GOT
entry for gs. After the patch, both a.x and b.x only have a global
GOT entry for "us".
Richard
* elfxx-mips.c (mips_elf_calculate_relocation): Use
_bfd_elf_symbol_refs_local_p to decide whether to decay
a GOT_PAGE/GOT_OFST pair to GOT_DISP/addend.
(_bfd_mips_elf_check_relocs): Add a global GOT entry for GOT_PAGE
relocs if the symbol wasn't defined by a regular object file.
Don't check the symbol's dynindx.
Index: bfd/elfxx-mips.c
===================================================================
RCS file: /cvs/src/src/bfd/elfxx-mips.c,v
retrieving revision 1.89
diff -u -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.89 elfxx-mips.c
--- bfd/elfxx-mips.c 9 Feb 2004 08:04:00 -0000 1.89
+++ bfd/elfxx-mips.c 15 Feb 2004 21:24:41 -0000
@@ -3261,12 +3261,9 @@ mips_elf_calculate_relocation (bfd *abfd
{
case R_MIPS_GOT_PAGE:
case R_MIPS_GOT_OFST:
- /* If this symbol got a global GOT entry, we have to decay
- GOT_PAGE/GOT_OFST to GOT_DISP/addend. */
- local_p = local_p || ! h
- || (h->root.dynindx
- < mips_elf_get_global_gotsym_index (elf_hash_table (info)
- ->dynobj));
+ /* We need to decay to GOT_DISP/addend if the symbol doesn't
+ bind locally. */
+ local_p = local_p || _bfd_elf_symbol_refs_local_p (&h->root, info, 1);
if (local_p || r_type == R_MIPS_GOT_OFST)
break;
/* Fall through. */
@@ -5384,25 +5381,10 @@ _bfd_mips_elf_check_relocs (bfd *abfd, s
hmips = (struct mips_elf_link_hash_entry *)
hmips->root.root.u.i.link;
- if ((hmips->root.root.type == bfd_link_hash_defined
- || hmips->root.root.type == bfd_link_hash_defweak)
- && hmips->root.root.u.def.section
+ if ((hmips->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)
&& ! (info->shared && ! info->symbolic
&& ! (hmips->root.elf_link_hash_flags
- & ELF_LINK_FORCED_LOCAL))
- /* If we've encountered any other relocation
- referencing the symbol, we'll have marked it as
- dynamic, and, even though we might be able to get
- rid of the GOT entry should we know for sure all
- previous relocations were GOT_PAGE ones, at this
- point we can't tell, so just keep using the
- symbol as dynamic. This is very important in the
- multi-got case, since we don't decide whether to
- decay GOT_PAGE to GOT_DISP on a per-GOT basis: if
- the symbol is dynamic, we'll need a GOT entry for
- every GOT in which the symbol is referenced with
- a GOT_PAGE relocation. */
- && hmips->root.dynindx == -1)
+ & ELF_LINK_FORCED_LOCAL)))
break;
}
/* Fall through. */
cat <<EOF > a.s
.globl __start
.globl gs
__start:
gs:
ls:
lw \$4,%got_page(us)(\$gp)
addiu \$4,\$4,%got_ofst(us)
lw \$4,%got_page(gs)(\$gp)
addiu \$4,\$4,%got_ofst(gs)
lw \$4,%got_page(ls)(\$gp)
addiu \$4,\$4,%got_ofst(ls)
EOF
cat <<EOF > b.s
.globl us
.globl gs
us:
gs:
ls:
lw \$4,%got_page(us)(\$gp)
addiu \$4,\$4,%got_ofst(us)
lw \$4,%got_page(gs)(\$gp)
addiu \$4,\$4,%got_ofst(gs)
lw \$4,%got_page(ls)(\$gp)
addiu \$4,\$4,%got_ofst(ls)
EOF
./gas/as-new a.s -o a.o
./gas/as-new b.s -o b.o
./ld/ld-new b.o -o b.so -shared
./ld/ld-new b.so a.o -o a.x
./ld/ld-new a.o b.so -o b.x