/* The number of bytes in the subsequent PLT etries. */
bfd_size_type plt_entry_size;
- /* Short-cuts to get to dynamic linker sections. */
- asection *sdynbss;
- asection *srelbss;
-
/* Small local sym cache. */
struct sym_cache sym_cache;
else
{
/* GD->IE relaxation
- ADD x0, #:tlsgd_lo12:var => ldr x0, [x0, #:gottprel_lo12:var]
+ ADD x0, #:tlsgd_lo12:var => ldr R0, [x0, #:gottprel_lo12:var]
BL __tls_get_addr => mrs x1, tpidr_el0
R_AARCH64_CALL26
- NOP => add x0, x1, x0
- */
+ NOP => add R0, R1, R0
+
+ Where R is x for lp64 mode, and w for ilp32 mode. */
BFD_ASSERT (ELFNN_R_TYPE (rel[1].r_info) == AARCH64_R (CALL26));
/* Remove the relocation on the BL instruction. */
rel[1].r_info = ELFNN_R_INFO (STN_UNDEF, R_AARCH64_NONE);
- bfd_putl32 (0xf9400000, contents + rel->r_offset);
-
/* We choose to fixup the BL and NOP instructions using the
offset from the second relocation to allow flexibility in
scheduling instructions between the ADD and BL. */
- bfd_putl32 (0xd53bd041, contents + rel[1].r_offset);
+#if ARCH_SIZE == 32
+ bfd_putl32 (0xb9400000, contents + rel->r_offset);
+ bfd_putl32 (0x0b000020, contents + rel[1].r_offset + 4);
+#else
+ bfd_putl32 (0xf9400000, contents + rel->r_offset);
bfd_putl32 (0x8b000020, contents + rel[1].r_offset + 4);
+#endif
+ bfd_putl32 (0xd53bd041, contents + rel[1].r_offset);
return bfd_reloc_continue;
}
case BFD_RELOC_AARCH64_TLSLD_ADR_PREL21:
/* LD->LE relaxation (tiny):
adr x0, :tlsldm:x => mrs x0, tpidr_el0
- bl __tls_get_addr => add x0, x0, TCB_SIZE
- */
+ bl __tls_get_addr => add R0, R0, TCB_SIZE
+
+ Where R is x for lp64 mode, and w for ilp32 mode. */
if (is_local)
{
BFD_ASSERT (rel->r_offset + 4 == rel[1].r_offset);
/* No need of CALL26 relocation for tls_get_addr. */
rel[1].r_info = ELFNN_R_INFO (STN_UNDEF, R_AARCH64_NONE);
bfd_putl32 (0xd53bd040, contents + rel->r_offset + 0);
+#if ARCH_SIZE == 64
bfd_putl32 (0x91004000, contents + rel->r_offset + 4);
+#else
+ bfd_putl32 (0x11002000, contents + rel->r_offset + 4);
+#endif
return bfd_reloc_ok;
}
return bfd_reloc_continue;
case BFD_RELOC_AARCH64_TLSLD_ADD_LO12_NC:
/* LD->LE relaxation (small):
- add x0, #:tlsldm_lo12:x => add x0, x0, TCB_SIZE
+ add x0, #:tlsldm_lo12:x => add R0, R0, TCB_SIZE
bl __tls_get_addr => nop
- */
+
+ Where R is x for lp64 mode, and w for ilp32 mode. */
if (is_local)
{
BFD_ASSERT (rel->r_offset + 4 == rel[1].r_offset);
BFD_ASSERT (ELFNN_R_TYPE (rel[1].r_info) == AARCH64_R (CALL26));
/* No need of CALL26 relocation for tls_get_addr. */
rel[1].r_info = ELFNN_R_INFO (STN_UNDEF, R_AARCH64_NONE);
+#if ARCH_SIZE == 64
bfd_putl32 (0x91004000, contents + rel->r_offset + 0);
- bfd_putl32 (0xd503201f, contents + rel->r_offset + 4);
+#else
+ bfd_putl32 (0x11002000, contents + rel->r_offset + 0);
+#endif
+ bfd_putl32 (INSN_NOP, contents + rel->r_offset + 4);
return bfd_reloc_ok;
}
return bfd_reloc_continue;
struct elf_link_hash_entry *h)
{
struct elf_aarch64_link_hash_table *htab;
- asection *s;
+ asection *s, *srel;
/* If this is a function, put it in the procedure linkage table. We
will fill in the contents of the procedure linkage table later,
/* We must generate a R_AARCH64_COPY reloc to tell the dynamic linker
to copy the initial value out of the dynamic object and into the
runtime process image. */
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ {
+ s = htab->root.sdynrelro;
+ srel = htab->root.sreldynrelro;
+ }
+ else
+ {
+ s = htab->root.sdynbss;
+ srel = htab->root.srelbss;
+ }
if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0)
{
- htab->srelbss->size += RELOC_SIZE (htab);
+ srel->size += RELOC_SIZE (htab);
h->needs_copy = 1;
}
- s = htab->sdynbss;
-
return _bfd_elf_adjust_dynamic_copy (info, h, s);
}
struct elf_link_hash_table *htab = elf_hash_table (info);
/* This function may be called more than once. */
- s = bfd_get_linker_section (abfd, ".got");
- if (s != NULL)
+ if (htab->sgot != NULL)
return TRUE;
flags = bed->dynamic_sec_flags;
elfNN_aarch64_create_dynamic_sections (bfd *dynobj,
struct bfd_link_info *info)
{
- struct elf_aarch64_link_hash_table *htab;
-
/* We need to create .got section. */
if (!aarch64_elf_create_got_section (dynobj, info))
return FALSE;
- if (!_bfd_elf_create_dynamic_sections (dynobj, info))
- return FALSE;
-
- htab = elf_aarch64_hash_table (info);
- htab->sdynbss = bfd_get_linker_section (dynobj, ".dynbss");
- if (!bfd_link_pic (info))
- htab->srelbss = bfd_get_linker_section (dynobj, ".rela.bss");
-
- if (!htab->sdynbss || (!bfd_link_pic (info) && !htab->srelbss))
- abort ();
-
- return TRUE;
+ return _bfd_elf_create_dynamic_sections (dynobj, info);
}
|| s == htab->root.sgot
|| s == htab->root.sgotplt
|| s == htab->root.iplt
- || s == htab->root.igotplt || s == htab->sdynbss)
+ || s == htab->root.igotplt
+ || s == htab->root.sdynbss
+ || s == htab->root.sdynrelro)
{
/* Strip this section if we don't need it; see the
comment below. */
if (h->needs_copy)
{
Elf_Internal_Rela rela;
+ asection *s;
bfd_byte *loc;
/* This symbol needs a copy reloc. Set it up. */
if (h->dynindx == -1
|| (h->root.type != bfd_link_hash_defined
&& h->root.type != bfd_link_hash_defweak)
- || htab->srelbss == NULL)
+ || htab->root.srelbss == NULL)
abort ();
rela.r_offset = (h->root.u.def.value
+ h->root.u.def.section->output_offset);
rela.r_info = ELFNN_R_INFO (h->dynindx, AARCH64_R (COPY));
rela.r_addend = 0;
- loc = htab->srelbss->contents;
- loc += htab->srelbss->reloc_count++ * RELOC_SIZE (htab);
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ s = htab->root.sreldynrelro;
+ else
+ s = htab->root.srelbss;
+ loc = s->contents + s->reloc_count++ * RELOC_SIZE (htab);
bfd_elfNN_swap_reloca_out (output_bfd, &rela, loc);
}
dyn.d_un.d_val = s->size;
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. */
- if (htab->root.srelplt != NULL)
- {
- s = htab->root.srelplt;
- dyn.d_un.d_val -= s->size;
- }
- break;
-
case DT_TLSDESC_PLT:
s = htab->root.splt;
dyn.d_un.d_ptr = s->output_section->vma + s->output_offset
#define elf_backend_plt_readonly 1
#define elf_backend_want_got_plt 1
#define elf_backend_want_plt_sym 0
+#define elf_backend_want_dynrelro 1
#define elf_backend_may_use_rel_p 0
#define elf_backend_may_use_rela_p 1
#define elf_backend_default_use_rela_p 1
#define elf_backend_rela_normal 1
+#define elf_backend_dtrel_excludes_plt 1
#define elf_backend_got_header_size (GOT_ENTRY_SIZE * 3)
#define elf_backend_default_execstack 0
#define elf_backend_extern_protected_data 1