aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/elf32-nios2.c40
1 files changed, 24 insertions, 16 deletions
diff --git a/bfd/elf32-nios2.c b/bfd/elf32-nios2.c
index bebf423..7f61e2f 100644
--- a/bfd/elf32-nios2.c
+++ b/bfd/elf32-nios2.c
@@ -1878,8 +1878,6 @@ nios2_elf32_install_imm16 (asection *sec, bfd_vma offset, bfd_vma value)
{
bfd_vma word = bfd_get_32 (sec->owner, sec->contents + offset);
- BFD_ASSERT (value <= 0xffff || ((bfd_signed_vma) value) >= -0xffff);
-
bfd_put_32 (sec->owner, word | ((value & 0xffff) << 6),
sec->contents + offset);
}
@@ -2518,7 +2516,7 @@ nios2_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg ATTRIBUTE_U
nios2_elf32_install_imm16 (stub_sec, hsh->stub_offset,
hiadj (sym_value));
nios2_elf32_install_imm16 (stub_sec, hsh->stub_offset + 4,
- (sym_value & 0xffff));
+ sym_value);
stub_sec->size += 12;
break;
default:
@@ -4986,16 +4984,28 @@ nios2_elf32_finish_dynamic_symbol (bfd *output_bfd,
/* Emit the PLT entry. */
if (bfd_link_pic (info))
{
+ bfd_vma br_offset;
+
nios2_elf32_install_data (splt, nios2_so_plt_entry, h->plt.offset,
3);
plt_index = (h->plt.offset - 24) / 12;
got_offset = (plt_index + 3) * 4;
nios2_elf32_install_imm16 (splt, h->plt.offset,
- hiadj(plt_index * 4));
+ hiadj (plt_index * 4));
nios2_elf32_install_imm16 (splt, h->plt.offset + 4,
- (plt_index * 4) & 0xffff);
- nios2_elf32_install_imm16 (splt, h->plt.offset + 8,
- 0xfff4 - h->plt.offset);
+ plt_index * 4);
+ br_offset = -(h->plt.offset + 12);
+ /* If this plt entry is too far away from the start of .plt
+ for the "br" to reach .PLTresolve, bounce through one or
+ more of the previous "br" instructions. */
+ if (br_offset < (bfd_vma) -32768)
+ {
+ br_offset += 32768 / 12 * 12 - 4;
+ while (br_offset < (bfd_vma) -32768)
+ br_offset += 32768 / 12 * 12;
+ }
+ nios2_elf32_install_imm16 (splt, h->plt.offset + 8, br_offset);
+
got_address = (sgotplt->output_section->vma + sgotplt->output_offset
+ got_offset);
@@ -5014,9 +5024,8 @@ nios2_elf32_finish_dynamic_symbol (bfd *output_bfd,
nios2_elf32_install_data (splt, nios2_plt_entry, h->plt.offset, 3);
got_address = (sgotplt->output_section->vma + sgotplt->output_offset
+ got_offset);
- nios2_elf32_install_imm16 (splt, h->plt.offset, hiadj(got_address));
- nios2_elf32_install_imm16 (splt, h->plt.offset + 4,
- got_address & 0xffff);
+ nios2_elf32_install_imm16 (splt, h->plt.offset, hiadj (got_address));
+ nios2_elf32_install_imm16 (splt, h->plt.offset + 4, got_address);
/* Fill in the entry in the global offset table. */
bfd_put_32 (output_bfd,
@@ -5217,8 +5226,8 @@ nios2_elf32_finish_dynamic_sections (bfd *output_bfd,
BFD_ASSERT ((got_pcrel & 0xf) == 0);
nios2_elf32_install_data (splt, nios2_so_plt0_entry, 0, 6);
nios2_elf32_install_imm16 (splt, 4, hiadj (got_pcrel));
- nios2_elf32_install_imm16 (splt, 12, got_pcrel & 0xffff);
- nios2_elf32_install_imm16 (splt, 16, (got_pcrel + 4) & 0xffff);
+ nios2_elf32_install_imm16 (splt, 12, got_pcrel);
+ nios2_elf32_install_imm16 (splt, 16, got_pcrel + 4);
}
else
{
@@ -5240,14 +5249,13 @@ nios2_elf32_finish_dynamic_sections (bfd *output_bfd,
nios2_elf32_install_data (splt, nios2_plt0_entry, res_size, 7);
nios2_elf32_install_imm16 (splt, res_size, hiadj (res_start));
- nios2_elf32_install_imm16 (splt, res_size + 4,
- res_start & 0xffff);
+ nios2_elf32_install_imm16 (splt, res_size + 4, res_start);
nios2_elf32_install_imm16 (splt, res_size + 12,
hiadj (got_address));
nios2_elf32_install_imm16 (splt, res_size + 16,
- (got_address + 4) & 0xffff);
+ got_address + 4);
nios2_elf32_install_imm16 (splt, res_size + 20,
- (got_address + 8) & 0xffff);
+ got_address + 8);
}
}
}