/* 32-bit ELF support for Nios II.
- Copyright (C) 2012-2015 Free Software Foundation, Inc.
+ Copyright (C) 2012-2016 Free Software Foundation, Inc.
Contributed by Nigel Gray (ngray@altera.com).
Contributed by Mentor Graphics, Inc.
{
bfd_vma word = bfd_get_32 (sec->owner, sec->contents + offset);
- BFD_ASSERT(value <= 0xffff);
+ BFD_ASSERT (value <= 0xffff || ((bfd_signed_vma) value) >= -0xffff);
bfd_put_32 (sec->owner, word | ((value & 0xffff) << 6),
sec->contents + offset);
TRUE, FALSE);
if (hsh == NULL)
{
- (*_bfd_error_handler) (_("%B: cannot create stub entry %s"),
- section->owner,
- stub_name);
+ /* xgettext:c-format */
+ _bfd_error_handler (_("%B: cannot create stub entry %s"),
+ section->owner,
+ stub_name);
return NULL;
}
object file when linking. */
static bfd_boolean
-nios2_elf32_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
+nios2_elf32_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
{
+ bfd *obfd = info->output_bfd;
flagword old_flags;
flagword new_flags;
return TRUE;
/* Check if we have the same endianness. */
- if (! _bfd_generic_verify_endian_match (ibfd, obfd))
+ if (! _bfd_generic_verify_endian_match (ibfd, info))
return FALSE;
new_flags = elf_elfheader (ibfd)->e_flags;
case EF_NIOS2_ARCH_R2:
if (bfd_big_endian (ibfd))
{
- (*_bfd_error_handler)
+ _bfd_error_handler
(_("error: %B: Big-endian R2 is not supported."), ibfd);
bfd_set_error (bfd_error_bad_value);
return FALSE;
{
/* So far, the only incompatible flags denote incompatible
architectures. */
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("error: %B: Conflicting CPU architectures %d/%d"),
ibfd, new_flags, old_flags);
bfd_set_error (bfd_error_bad_value);
}
/* Merge Tag_compatibility attributes and any common GNU ones. */
- _bfd_elf_merge_object_attributes (ibfd, obfd);
+ _bfd_elf_merge_object_attributes (ibfd, info);
return TRUE;
}
case bfd_link_hash_defined:
case bfd_link_hash_defweak:
gp_found = TRUE;
- *pgp = lh->u.def.value;
+ {
+ asection *sym_sec = lh->u.def.section;
+ bfd_vma sym_value = lh->u.def.value;
+
+ if (sym_sec->output_section)
+ sym_value = (sym_value + sym_sec->output_offset
+ + sym_sec->output_section->vma);
+ *pgp = sym_value;
+ }
break;
case bfd_link_hash_indirect:
case bfd_link_hash_warning:
struct elf32_nios2_link_hash_entry *eh;
bfd_vma relocation;
bfd_vma gp;
- bfd_vma reloc_address;
bfd_reloc_status_type r = bfd_reloc_ok;
const char *name = NULL;
int r_type;
if (bfd_link_relocatable (info))
continue;
- if (sec && sec->output_section)
- reloc_address = (sec->output_section->vma + sec->output_offset
- + rel->r_offset);
- else
- reloc_address = 0;
-
if (howto)
{
switch (howto->type)
/* Turns an absolute address into a gp-relative address. */
if (!nios2_elf_assign_gp (output_bfd, &gp, info))
{
+ bfd_vma reloc_address;
+
+ if (sec && sec->output_section)
+ reloc_address = (sec->output_section->vma
+ + sec->output_offset
+ + rel->r_offset);
+ else
+ reloc_address = 0;
+
format = _("global pointer relative relocation at address "
"0x%08x when _gp not defined\n");
sprintf (msgbuf, format, reloc_address);
else
{
bfd_vma symbol_address = rel->r_addend + relocation;
- relocation = relocation + rel->r_addend - gp;
+ relocation = symbol_address - gp;
rel->r_addend = 0;
if (((signed) relocation < -32768
|| (signed) relocation > 32767)
|| h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak))
{
+ if (h)
+ name = h->root.root.string;
+ /* xgettext:c-format */
format = _("Unable to reach %s (at 0x%08x) from the "
"global pointer (at 0x%08x) because the "
"offset (%d) is out of the allowed range, "
rel->r_offset, relocation,
rel->r_addend);
}
-
break;
case R_NIOS2_UJMP:
r = nios2_elf32_do_ujmp_relocate (input_bfd, howto,
case R_NIOS2_TLS_LE16:
if (bfd_link_dll (info))
{
- (*_bfd_error_handler)
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%B(%A+0x%lx): R_NIOS2_TLS_LE16 relocation not "
"permitted in shared object"),
input_bfd, input_section,
switch (r)
{
case bfd_reloc_overflow:
- r = info->callbacks->reloc_overflow (info, NULL, name,
- howto->name, (bfd_vma) 0,
- input_bfd, input_section,
- rel->r_offset);
+ (*info->callbacks->reloc_overflow) (info, NULL, name,
+ howto->name, (bfd_vma) 0,
+ input_bfd, input_section,
+ rel->r_offset);
break;
case bfd_reloc_undefined:
- r = info->callbacks->undefined_symbol (info, name, input_bfd,
- input_section,
- rel->r_offset, TRUE);
+ (*info->callbacks->undefined_symbol) (info, name, input_bfd,
+ input_section,
+ rel->r_offset, TRUE);
break;
case bfd_reloc_outofrange:
if (msg)
{
- r = info->callbacks->warning
- (info, msg, name, input_bfd, input_section, rel->r_offset);
+ (*info->callbacks->warning) (info, msg, name, input_bfd,
+ input_section, rel->r_offset);
return FALSE;
}
}
break;
case DT_PLTGOT:
- s = htab->root.sgot;
- BFD_ASSERT (s != NULL);
- dyn.d_un.d_ptr = s->output_section->vma;
+ s = htab->root.sgotplt;
+ dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
break;
case DT_JMPREL:
s = htab->root.srelplt;
- BFD_ASSERT (s != NULL);
- dyn.d_un.d_ptr = s->output_section->vma;
+ dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
break;
case DT_PLTRELSZ:
s = htab->root.srelplt;
- BFD_ASSERT (s != NULL);
dyn.d_un.d_val = s->size;
bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
break;
- case DT_RELASZ:
- /* The procedure linkage table relocs (DT_JMPREL) should
- not be included in the overall relocs (DT_RELA).
- Therefore, we override the DT_RELASZ entry here to
- make it not include the JMPREL relocs. Since the
- linker script arranges for .rela.plt to follow all
- other relocation sections, we don't have to worry
- about changing the DT_RELA entry. */
- s = htab->root.srelplt;
- if (s != NULL)
- dyn.d_un.d_val -= s->size;
- bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
- break;
-
case DT_NIOS2_GP:
- s = htab->root.sgot;
- BFD_ASSERT (s != NULL);
- dyn.d_un.d_ptr = s->output_section->vma + 0x7ff0;
+ s = htab->root.sgotplt;
+ dyn.d_un.d_ptr
+ = s->output_section->vma + s->output_offset + 0x7ff0;
bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
break;
}
+ sgotplt->output_offset);
if (bfd_link_pic (info))
{
- bfd_vma corrected = got_address - (splt->output_section->vma
- + splt->output_offset + 4);
+ bfd_vma got_pcrel = got_address - (splt->output_section->vma
+ + splt->output_offset);
+ /* Both GOT and PLT must be aligned to a 16-byte boundary
+ for the two loads to share the %hiadj part. The 4-byte
+ offset for nextpc is accounted for in the %lo offsets
+ on the loads. */
+ BFD_ASSERT ((got_pcrel & 0xf) == 0);
nios2_elf32_install_data (splt, nios2_so_plt0_entry, 0, 6);
- nios2_elf32_install_imm16 (splt, 4, hiadj (corrected));
- nios2_elf32_install_imm16 (splt, 12, (corrected & 0xffff) + 4);
- nios2_elf32_install_imm16 (splt, 16, (corrected & 0xffff) + 8);
+ 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);
}
else
{
6 | ((res_size - (res_offset + 4)) << 6),
splt->contents + res_offset);
+ /* The GOT must be aligned to a 16-byte boundary for the
+ two loads to share the same %hiadj part. */
+ BFD_ASSERT ((got_address & 0xf) == 0);
+
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,
nios2_elf32_install_imm16 (splt, res_size + 12,
hiadj (got_address));
nios2_elf32_install_imm16 (splt, res_size + 16,
- (got_address & 0xffff) + 4);
+ (got_address + 4) & 0xffff);
nios2_elf32_install_imm16 (splt, res_size + 20,
- (got_address & 0xffff) + 8);
+ (got_address + 8) & 0xffff);
}
}
}
if (h->size == 0)
{
- (*_bfd_error_handler) (_("dynamic variable `%s' is zero size"),
- h->root.root.string);
+ _bfd_error_handler (_("dynamic variable `%s' is zero size"),
+ h->root.root.string);
return TRUE;
}
if (elf_hash_table (info)->dynamic_sections_created)
{
/* Set the contents of the .interp section to the interpreter. */
- if (bfd_link_executable (info))
+ if (bfd_link_executable (info) && !info->nointerp)
{
s = bfd_get_linker_section (dynobj, ".interp");
BFD_ASSERT (s != NULL);
#define elf_backend_plt_readonly 1
#define elf_backend_want_got_plt 1
#define elf_backend_rela_normal 1
+#define elf_backend_dtrel_excludes_plt 1
#define elf_backend_relocate_section nios2_elf32_relocate_section
#define elf_backend_section_flags nios2_elf32_section_flags