aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'bfd/elfxx-mips.c')
-rw-r--r--bfd/elfxx-mips.c49
1 files changed, 34 insertions, 15 deletions
diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c
index 6ca4f063af2..2b2f615934a 100644
--- a/bfd/elfxx-mips.c
+++ b/bfd/elfxx-mips.c
@@ -496,6 +496,7 @@ static struct mips_got_info *mips_elf_got_for_ibfd
static bfd *reldyn_sorting_bfd;
/* Nonzero if ABFD is using the N32 ABI. */
+
#define ABI_N32_P(abfd) \
((elf_elfheader (abfd)->e_flags & EF_MIPS_ABI2) != 0)
@@ -2129,7 +2130,7 @@ mips_elf_bfd2got_entry_eq (entry1, entry2)
return e1->bfd == e2->bfd;
}
-/* In a multi-got link, determine the GOT to be used for IBFD. G must
+/* In a multi-got link, determine the GOT to be used for IBDF. G must
be the master GOT data. */
static struct mips_got_info *
@@ -3315,6 +3316,12 @@ mips_elf_calculate_relocation (abfd, input_bfd, input_section, info,
value &= howto->dst_mask;
break;
+ case R_MIPS_GNU_REL16_S2:
+ value = symbol + mips_elf_sign_extend (addend << 2, 18) - p;
+ overflowed_p = mips_elf_overflow_p (value, 18);
+ value = (value >> 2) & howto->dst_mask;
+ break;
+
case R_MIPS_GNU_REL_HI16:
/* Instead of subtracting 'p' here, we should be subtracting the
equivalent value for the LO part of the reloc, since the value
@@ -3443,10 +3450,8 @@ mips_elf_calculate_relocation (abfd, input_bfd, input_section, info,
break;
case R_MIPS_PC16:
- case R_MIPS_GNU_REL16_S2:
- value = mips_elf_sign_extend (addend << 2, 18) + symbol - p;
- overflowed_p = mips_elf_overflow_p (value, 18);
- value = (value >> 2) & howto->dst_mask;
+ value = mips_elf_sign_extend (addend, 16) + symbol - p;
+ overflowed_p = mips_elf_overflow_p (value, 16);
break;
case R_MIPS_GOT_HI16:
@@ -3832,7 +3837,6 @@ mips_elf_create_dynamic_relocation (output_bfd, info, rel, h, sec,
else
{
long indx;
- bfd_vma section_offset;
/* We must now calculate the dynamic symbol table index to use
in the relocation. */
@@ -3862,15 +3866,18 @@ mips_elf_create_dynamic_relocation (output_bfd, info, rel, h, sec,
abort ();
}
- /* Figure out how far the target of the relocation is from
- the beginning of its section. */
- section_offset = symbol - sec->output_section->vma;
- /* The relocation we're building is section-relative.
- Therefore, the original addend must be adjusted by the
- section offset. */
- *addendp += section_offset;
- /* Now, the relocation is just against the section. */
- symbol = sec->output_section->vma;
+ /* Instead of generating a relocation using the section
+ symbol, we may as well make it a fully relative
+ relocation. We want to avoid generating relocations to
+ local symbols because we used to generate them
+ incorrectly, without adding the original symbol value,
+ which is mandated by the ABI for section symbols. In
+ order to give dynamic loaders and applications time to
+ phase out the incorrect use, we refrain from emitting
+ section-relative relocations. It's not like they're
+ useful, after all. This should be a bit more efficient
+ as well. */
+ indx = 0;
}
/* If the relocation was previously an absolute relocation and
@@ -3884,6 +3891,18 @@ mips_elf_create_dynamic_relocation (output_bfd, info, rel, h, sec,
know where the shared library will wind up at load-time. */
outrel[0].r_info = ELF_R_INFO (output_bfd, (unsigned long) indx,
R_MIPS_REL32);
+ /* For strict adherence to the ABI specification, we should
+ generate a R_MIPS_64 relocation record by itself before the
+ _REL32/_64 record as well, such that the addend is read in as
+ a 64-bit value (REL32 is a 32-bit relocation, after all).
+ However, since none of the existing ELF64 MIPS dynamic
+ loaders seems to care, we don't waste space with these
+ artificial relocations. If this turns out to not be true,
+ mips_elf_allocate_dynamic_relocation() should be tweaked so
+ as to make room for a pair of dynamic relocations per
+ invocation if ABI_64_P, and here we should generate an
+ additional relocation record with R_MIPS_64 by itself for a
+ NULL symbol before this relocation record. */
outrel[1].r_info = ELF_R_INFO (output_bfd, (unsigned long) 0,
ABI_64_P (output_bfd)
? R_MIPS_64