* elfxx-mips.c (mips_elf_calculate_relocation): Take

save_addend argument.  Don't apply the 32-bit mask to a
GPREL32 value if it's to be used in another relocation.  Don't
use forced-check computation of local_p to decide whether to
add gp0 to GPREL16 value.  Don't use only the lowest 16 bits
of the addend of a non-in-place GPREL16 relocation.
(_bfd_mips_elf_relocate_section): Pass use_saved_addend_p to
mips_elf_calculate_relocation().
This commit is contained in:
Alexandre Oliva
2002-10-13 21:22:31 +00:00
parent e1026ffb69
commit bce03d3da8
2 changed files with 34 additions and 9 deletions

View File

@ -1,3 +1,14 @@
2002-10-13 Alexandre Oliva <aoliva@redhat.com>
* elfxx-mips.c (mips_elf_calculate_relocation): Take
save_addend argument. Don't apply the 32-bit mask to a
GPREL32 value if it's to be used in another relocation. Don't
use forced-check computation of local_p to decide whether to
add gp0 to GPREL16 value. Don't use only the lowest 16 bits
of the addend of a non-in-place GPREL16 relocation.
(_bfd_mips_elf_relocate_section): Pass use_saved_addend_p to
mips_elf_calculate_relocation().
2002-10-12 Stephane Carrez <stcarrez@nerim.fr> 2002-10-12 Stephane Carrez <stcarrez@nerim.fr>
* elf32-m68hc11.c (m68hc11_elf_relax_section): Don't treat relocs * elf32-m68hc11.c (m68hc11_elf_relax_section): Don't treat relocs

View File

@ -345,7 +345,7 @@ static bfd_reloc_status_type mips_elf_calculate_relocation
PARAMS ((bfd *, bfd *, asection *, struct bfd_link_info *, PARAMS ((bfd *, bfd *, asection *, struct bfd_link_info *,
const Elf_Internal_Rela *, bfd_vma, reloc_howto_type *, const Elf_Internal_Rela *, bfd_vma, reloc_howto_type *,
Elf_Internal_Sym *, asection **, bfd_vma *, const char **, Elf_Internal_Sym *, asection **, bfd_vma *, const char **,
boolean *)); boolean *, boolean));
static bfd_vma mips_elf_obtain_contents static bfd_vma mips_elf_obtain_contents
PARAMS ((reloc_howto_type *, const Elf_Internal_Rela *, bfd *, bfd_byte *)); PARAMS ((reloc_howto_type *, const Elf_Internal_Rela *, bfd *, bfd_byte *));
static boolean mips_elf_perform_relocation static boolean mips_elf_perform_relocation
@ -2006,7 +2006,7 @@ static bfd_reloc_status_type
mips_elf_calculate_relocation (abfd, input_bfd, input_section, info, mips_elf_calculate_relocation (abfd, input_bfd, input_section, info,
relocation, addend, howto, local_syms, relocation, addend, howto, local_syms,
local_sections, valuep, namep, local_sections, valuep, namep,
require_jalxp) require_jalxp, save_addend)
bfd *abfd; bfd *abfd;
bfd *input_bfd; bfd *input_bfd;
asection *input_section; asection *input_section;
@ -2019,6 +2019,7 @@ mips_elf_calculate_relocation (abfd, input_bfd, input_section, info,
bfd_vma *valuep; bfd_vma *valuep;
const char **namep; const char **namep;
boolean *require_jalxp; boolean *require_jalxp;
boolean save_addend;
{ {
/* The eventual value we will return. */ /* The eventual value we will return. */
bfd_vma value; bfd_vma value;
@ -2043,7 +2044,7 @@ mips_elf_calculate_relocation (abfd, input_bfd, input_section, info,
struct mips_elf_link_hash_entry *h = NULL; struct mips_elf_link_hash_entry *h = NULL;
/* True if the symbol referred to by this relocation is a local /* True if the symbol referred to by this relocation is a local
symbol. */ symbol. */
boolean local_p; boolean local_p, was_local_p;
/* True if the symbol referred to by this relocation is "_gp_disp". */ /* True if the symbol referred to by this relocation is "_gp_disp". */
boolean gp_disp_p = false; boolean gp_disp_p = false;
Elf_Internal_Shdr *symtab_hdr; Elf_Internal_Shdr *symtab_hdr;
@ -2071,6 +2072,7 @@ mips_elf_calculate_relocation (abfd, input_bfd, input_section, info,
symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
local_p = mips_elf_local_relocation_p (input_bfd, relocation, local_p = mips_elf_local_relocation_p (input_bfd, relocation,
local_sections, false); local_sections, false);
was_local_p = local_p;
if (! elf_bad_symtab (input_bfd)) if (! elf_bad_symtab (input_bfd))
extsymoff = symtab_hdr->sh_info; extsymoff = symtab_hdr->sh_info;
else else
@ -2458,10 +2460,19 @@ mips_elf_calculate_relocation (abfd, input_bfd, input_section, info,
order. We don't need to do anything special here; the order. We don't need to do anything special here; the
differences are handled in mips_elf_perform_relocation. */ differences are handled in mips_elf_perform_relocation. */
case R_MIPS_GPREL16: case R_MIPS_GPREL16:
if (local_p) /* Only sign-extend the addend if it was extracted from the
value = mips_elf_sign_extend (addend, 16) + symbol + gp0 - gp; instruction. If the addend was separate, leave it alone,
else otherwise we may lose significant bits. */
value = mips_elf_sign_extend (addend, 16) + symbol - gp; if (howto->partial_inplace)
addend = mips_elf_sign_extend (addend, 16);
value = symbol + addend - gp;
/* If the symbol was local, any earlier relocatable links will
have adjusted its addend with the gp offset, so compensate
for that now. Don't do it for symbols forced local in this
link, though, since they won't have had the gp offset applied
to them before. */
if (was_local_p)
value += gp0;
overflowed_p = mips_elf_overflow_p (value, 16); overflowed_p = mips_elf_overflow_p (value, 16);
break; break;
@ -2494,7 +2505,9 @@ mips_elf_calculate_relocation (abfd, input_bfd, input_section, info,
break; break;
case R_MIPS_GPREL32: case R_MIPS_GPREL32:
value = (addend + symbol + gp0 - gp) & howto->dst_mask; value = (addend + symbol + gp0 - gp);
if (!save_addend)
value &= howto->dst_mask;
break; break;
case R_MIPS_PC16: case R_MIPS_PC16:
@ -5251,7 +5264,8 @@ _bfd_mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
input_section, info, rel, input_section, info, rel,
addend, howto, local_syms, addend, howto, local_syms,
local_sections, &value, local_sections, &value,
&name, &require_jalx)) &name, &require_jalx,
use_saved_addend_p))
{ {
case bfd_reloc_continue: case bfd_reloc_continue:
/* There's nothing to do. */ /* There's nothing to do. */