* elfxx-mips.c (mips_elf_calculate_relocation): Decay

GOT_PAGE/GOT_OFST referencing overridable symbol to
GOT_DISP/addend.
(_bfd_mips_elf_check_relocs): Handle GOT_PAGE referencing
global symbol as GOT_DISP.
This commit is contained in:
Alexandre Oliva 2003-04-11 01:56:49 +00:00
parent 9f34b04bdf
commit 0fdc1bf125
2 changed files with 69 additions and 3 deletions

View file

@ -1,3 +1,11 @@
2003-04-10 Alexandre Oliva <aoliva@redhat.com>
* elfxx-mips.c (mips_elf_calculate_relocation): Decay
GOT_PAGE/GOT_OFST referencing overridable symbol to
GOT_DISP/addend.
(_bfd_mips_elf_check_relocs): Handle GOT_PAGE referencing
global symbol as GOT_DISP.
2003-04-10 Bob Wilson <bob.wilson@acm.org>
* elf32-xtensa.c (elf_xtensa_relocate_section): Don't continue to the

View file

@ -3196,6 +3196,13 @@ mips_elf_calculate_relocation (abfd, input_bfd, input_section, info,
and we're going to need it, get it now. */
switch (r_type)
{
case R_MIPS_GOT_PAGE:
/* If we didn't create a dynamic index for this symbol, it can
be regarded as local. */
if (local_p || ! h || h->root.dynindx < 0)
break;
/* Fall through. */
case R_MIPS_CALL16:
case R_MIPS_GOT16:
case R_MIPS_GOT_DISP:
@ -3206,7 +3213,11 @@ mips_elf_calculate_relocation (abfd, input_bfd, input_section, info,
/* Find the index into the GOT where this value is located. */
if (!local_p)
{
BFD_ASSERT (addend == 0);
/* GOT_PAGE may take a non-zero addend, that is ignored in a
GOT_PAGE relocation that decays to GOT_DISP because the
symbol turns out to be global. The addend is then added
as GOT_OFST. */
BFD_ASSERT (addend == 0 || r_type == R_MIPS_GOT_PAGE);
g = mips_elf_global_got_index (elf_hash_table (info)->dynobj,
input_bfd,
(struct elf_link_hash_entry *) h);
@ -3220,7 +3231,7 @@ mips_elf_calculate_relocation (abfd, input_bfd, input_section, info,
We must initialize this entry in the GOT. */
bfd *tmpbfd = elf_hash_table (info)->dynobj;
asection *sgot = mips_elf_got_section (tmpbfd, FALSE);
MIPS_ELF_PUT_WORD (tmpbfd, symbol + addend, sgot->contents + g);
MIPS_ELF_PUT_WORD (tmpbfd, symbol, sgot->contents + g);
}
}
else if (r_type == R_MIPS_GOT16 || r_type == R_MIPS_CALL16)
@ -3439,6 +3450,7 @@ mips_elf_calculate_relocation (abfd, input_bfd, input_section, info,
/* Fall through. */
case R_MIPS_GOT_DISP:
got_disp:
value = g;
overflowed_p = mips_elf_overflow_p (value, 16);
break;
@ -3470,6 +3482,11 @@ mips_elf_calculate_relocation (abfd, input_bfd, input_section, info,
break;
case R_MIPS_GOT_PAGE:
/* GOT_PAGE relocations that reference non-local symbols decay
to GOT_DISP. The corresponding GOT_OFST relocation decays to
0. */
if (! (local_p || ! h || h->root.dynindx < 0))
goto got_disp;
value = mips_elf_got_page (abfd, input_bfd, info, symbol + addend, NULL);
if (value == MINUS_ONE)
return bfd_reloc_outofrange;
@ -3479,7 +3496,10 @@ mips_elf_calculate_relocation (abfd, input_bfd, input_section, info,
break;
case R_MIPS_GOT_OFST:
mips_elf_got_page (abfd, input_bfd, info, symbol + addend, &value);
if (local_p || ! h || h->root.dynindx < 0)
mips_elf_got_page (abfd, input_bfd, info, symbol + addend, &value);
else
value = addend;
overflowed_p = mips_elf_overflow_p (value, 16);
break;
@ -5312,6 +5332,44 @@ _bfd_mips_elf_check_relocs (abfd, info, sec, relocs)
}
break;
case R_MIPS_GOT_PAGE:
/* If this is a global, overridable symbol, GOT_PAGE will
decay to GOT_DISP, so we'll need a GOT entry for it. */
if (h == NULL)
break;
else
{
struct mips_elf_link_hash_entry *hmips =
(struct mips_elf_link_hash_entry *) h;
while (hmips->root.root.type == bfd_link_hash_indirect
|| hmips->root.root.type == bfd_link_hash_warning)
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
&& ! (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)
break;
}
/* Fall through. */
case R_MIPS_GOT16:
case R_MIPS_GOT_HI16:
case R_MIPS_GOT_LO16: