/* Xilinx MicroBlaze-specific support for 32-bit ELF
- Copyright (C) 2009-2016 Free Software Foundation, Inc.
+ Copyright (C) 2009-2017 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
{
struct elf_link_hash_table elf;
- /* Short-cuts to get to dynamic linker sections. */
- asection *sdynbss;
- asection *srelbss;
-
/* Small local sym to section mapping cache. */
struct sym_cache sym_sec;
dogottls:
sec->has_tls_reloc = 1;
/* Fall through. */
+ case R_MICROBLAZE_GOTOFF_64:
case R_MICROBLAZE_GOT_64:
if (htab->elf.sgot == NULL)
{
return TRUE;
}
-static bfd_boolean
-microblaze_elf_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info)
-{
- struct elf32_mb_link_hash_table *htab;
-
- htab = elf32_mb_hash_table (info);
- if (htab == NULL)
- return FALSE;
-
- if (!htab->elf.sgot && !_bfd_elf_create_got_section (dynobj, info))
- return FALSE;
-
- if (!_bfd_elf_create_dynamic_sections (dynobj, info))
- return FALSE;
-
- htab->sdynbss = bfd_get_linker_section (dynobj, ".dynbss");
- if (!bfd_link_pic (info))
- htab->srelbss = bfd_get_linker_section (dynobj, ".rela.bss");
-
- if (!htab->elf.splt || !htab->elf.srelplt || !htab->sdynbss
- || (!bfd_link_pic (info) && !htab->srelbss))
- abort ();
-
- return TRUE;
-}
-
/* Copy the extra info we tack onto an elf_link_hash_entry. */
static void
struct elf32_mb_link_hash_table *htab;
struct elf32_mb_link_hash_entry * eh;
struct elf32_mb_dyn_relocs *p;
- asection *sdynbss, *s;
+ asection *s, *srel;
unsigned int power_of_two;
- bfd *dynobj;
htab = elf32_mb_hash_table (info);
if (htab == NULL)
/* We must generate a R_MICROBLAZE_COPY reloc to tell the dynamic linker
to copy the initial value out of the dynamic object and into the
runtime process image. */
- dynobj = elf_hash_table (info)->dynobj;
- BFD_ASSERT (dynobj != NULL);
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ {
+ s = htab->elf.sdynrelro;
+ srel = htab->elf.sreldynrelro;
+ }
+ else
+ {
+ s = htab->elf.sdynbss;
+ srel = htab->elf.srelbss;
+ }
if ((h->root.u.def.section->flags & SEC_ALLOC) != 0)
{
- htab->srelbss->size += sizeof (Elf32_External_Rela);
+ srel->size += sizeof (Elf32_External_Rela);
h->needs_copy = 1;
}
if (power_of_two > 3)
power_of_two = 3;
- sdynbss = htab->sdynbss;
/* Apply the required alignment. */
- sdynbss->size = BFD_ALIGN (sdynbss->size, (bfd_size_type) (1 << power_of_two));
- if (power_of_two > bfd_get_section_alignment (dynobj, sdynbss))
+ s->size = BFD_ALIGN (s->size, (bfd_size_type) (1 << power_of_two));
+ if (power_of_two > s->alignment_power)
{
- if (! bfd_set_section_alignment (dynobj, sdynbss, power_of_two))
+ if (!bfd_set_section_alignment (s->owner, s, power_of_two))
return FALSE;
}
/* Define the symbol as being at this point in the section. */
- h->root.u.def.section = sdynbss;
- h->root.u.def.value = sdynbss->size;
+ h->root.u.def.section = s;
+ h->root.u.def.value = s->size;
/* Increment the section size to make room for the symbol. */
- sdynbss->size += h->size;
+ s->size += h->size;
return TRUE;
}
}
else if (s != htab->elf.splt
&& s != htab->elf.sgot
- && s != htab->elf.sgotplt)
+ && s != htab->elf.sgotplt
+ && s != htab->elf.sdynbss
+ && s != htab->elf.sdynrelro)
{
/* It's not one of our sections, so don't allocate space. */
continue;
|| h->dynindx == -1))
{
asection *sec = h->root.u.def.section;
+ bfd_vma value;
+
+ value = h->root.u.def.value;
+ if (sec->output_section != NULL)
+ /* PR 21180: If the output section is NULL, then the symbol is no
+ longer needed, and in theory the GOT entry is redundant. But
+ it is too late to change our minds now... */
+ value += sec->output_section->vma + sec->output_offset;
+
microblaze_elf_output_dynamic_relocation (output_bfd,
srela, srela->reloc_count++,
/* symindex= */ 0,
R_MICROBLAZE_REL, offset,
- h->root.u.def.value
- + sec->output_section->vma
- + sec->output_offset);
+ value);
}
else
{
BFD_ASSERT (h->dynindx != -1);
- s = bfd_get_linker_section (htab->elf.dynobj, ".rela.bss");
- BFD_ASSERT (s != NULL);
-
rela.r_offset = (h->root.u.def.value
+ h->root.u.def.section->output_section->vma
+ h->root.u.def.section->output_offset);
rela.r_info = ELF32_R_INFO (h->dynindx, R_MICROBLAZE_COPY);
rela.r_addend = 0;
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ s = htab->elf.sreldynrelro;
+ else
+ s = htab->elf.srelbss;
loc = s->contents + s->reloc_count++ * sizeof (Elf32_External_Rela);
bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
}
asection *splt;
Elf32_External_Dyn *dyncon, *dynconend;
- splt = htab->elf.splt;
- BFD_ASSERT (splt != NULL && sdyn != NULL);
-
dyncon = (Elf32_External_Dyn *) sdyn->contents;
dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->size);
for (; dyncon < dynconend; dyncon++)
{
Elf_Internal_Dyn dyn;
- const char *name;
+ asection *s;
bfd_boolean size;
bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn);
switch (dyn.d_tag)
{
- case DT_PLTGOT: name = ".got.plt"; size = FALSE; break;
- case DT_PLTRELSZ: name = ".rela.plt"; size = TRUE; break;
- case DT_JMPREL: name = ".rela.plt"; size = FALSE; break;
- case DT_RELA: name = ".rela.dyn"; size = FALSE; break;
- case DT_RELASZ: name = ".rela.dyn"; size = TRUE; break;
- default: name = NULL; size = FALSE; break;
- }
+ case DT_PLTGOT:
+ s = htab->elf.sgotplt;
+ size = FALSE;
+ break;
- if (name != NULL)
- {
- asection *s;
+ case DT_PLTRELSZ:
+ s = htab->elf.srelplt;
+ size = TRUE;
+ break;
- s = bfd_get_section_by_name (output_bfd, name);
- if (s == NULL)
- dyn.d_un.d_val = 0;
- else
- {
- if (! size)
- dyn.d_un.d_ptr = s->vma;
- else
- dyn.d_un.d_val = s->size;
- }
- bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
+ case DT_JMPREL:
+ s = htab->elf.srelplt;
+ size = FALSE;
+ break;
+
+ default:
+ continue;
}
+
+ if (s == NULL)
+ dyn.d_un.d_val = 0;
+ else
+ {
+ if (!size)
+ dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
+ else
+ dyn.d_un.d_val = s->size;
+ }
+ bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
}
+ splt = htab->elf.splt;
+ BFD_ASSERT (splt != NULL && sdyn != NULL);
+
/* Clear the first entry in the procedure linkage table,
and put a nop in the last four bytes. */
if (splt->size > 0)
#define elf_backend_want_got_plt 1
#define elf_backend_plt_readonly 1
#define elf_backend_got_header_size 12
+#define elf_backend_want_dynrelro 1
#define elf_backend_rela_normal 1
+#define elf_backend_dtrel_excludes_plt 1
#define elf_backend_adjust_dynamic_symbol microblaze_elf_adjust_dynamic_symbol
-#define elf_backend_create_dynamic_sections microblaze_elf_create_dynamic_sections
+#define elf_backend_create_dynamic_sections _bfd_elf_create_dynamic_sections
#define elf_backend_finish_dynamic_sections microblaze_elf_finish_dynamic_sections
#define elf_backend_finish_dynamic_symbol microblaze_elf_finish_dynamic_symbol
#define elf_backend_size_dynamic_sections microblaze_elf_size_dynamic_sections