/* AArch64-specific support for NN-bit ELF.
- Copyright (C) 2009-2015 Free Software Foundation, Inc.
+ Copyright (C) 2009-2016 Free Software Foundation, Inc.
Contributed by ARM Ltd.
This file is part of BFD, the Binary File Descriptor library.
|| IS_AARCH64_TLSDESC_RELOC ((R_TYPE)))
#define IS_AARCH64_TLS_RELAX_RELOC(R_TYPE) \
- ((R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_ADD_LO12_NC \
+ ((R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_ADD \
+ || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_ADD_LO12_NC \
|| (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_ADR_PAGE21 \
|| (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_ADR_PREL21 \
|| (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_CALL \
|| (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_LD_PREL19 \
|| (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_LDNN_LO12_NC \
+ || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_LDR \
+ || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_OFF_G0_NC \
+ || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_OFF_G1 \
+ || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_LDR \
|| (R_TYPE) == BFD_RELOC_AARCH64_TLSGD_ADR_PAGE21 \
|| (R_TYPE) == BFD_RELOC_AARCH64_TLSGD_ADR_PREL21 \
|| (R_TYPE) == BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC \
12, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
+ complain_overflow_unsigned, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
AARCH64_R_STR (TLSDESC_OFF_G1), /* name */
FALSE, /* partial_inplace */
bfd_boolean via_plt_p;
if (st_type != STT_FUNC
- && (sym_sec != bfd_abs_section_ptr))
+ && (sym_sec == input_sec))
return stub_type;
globals = elf_aarch64_hash_table (info);
goto error_ret_free_internal;
}
- stub_entry->target_value = sym_value;
+ stub_entry->target_value = sym_value + irela->r_addend;
stub_entry->target_section = sym_sec;
stub_entry->stub_type = stub_type;
stub_entry->h = hash;
? BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1
: BFD_RELOC_AARCH64_TLSIE_LD_GOTTPREL_PREL19);
+ case BFD_RELOC_AARCH64_TLSDESC_LDR:
+ return (is_local
+ ? BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0_NC
+ : BFD_RELOC_AARCH64_NONE);
+
+ case BFD_RELOC_AARCH64_TLSDESC_OFF_G0_NC:
+ return (is_local
+ ? BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1_NC
+ : BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC);
+
+ case BFD_RELOC_AARCH64_TLSDESC_OFF_G1:
+ return (is_local
+ ? BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G2
+ : BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G1);
+
case BFD_RELOC_AARCH64_TLSDESC_LDNN_LO12_NC:
case BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC:
return (is_local
? BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_HI12
: BFD_RELOC_AARCH64_TLSIE_LD_GOTTPREL_PREL19);
+ case BFD_RELOC_AARCH64_TLSDESC_ADD:
case BFD_RELOC_AARCH64_TLSDESC_ADD_LO12_NC:
case BFD_RELOC_AARCH64_TLSDESC_CALL:
/* Instructions with these relocations will become NOPs. */
case BFD_RELOC_AARCH64_TLSLD_ADR_PREL21:
return GOT_TLS_GD;
+ case BFD_RELOC_AARCH64_TLSDESC_ADD:
case BFD_RELOC_AARCH64_TLSDESC_ADD_LO12_NC:
case BFD_RELOC_AARCH64_TLSDESC_ADR_PAGE21:
case BFD_RELOC_AARCH64_TLSDESC_ADR_PREL21:
case BFD_RELOC_AARCH64_TLSDESC_LD32_LO12_NC:
case BFD_RELOC_AARCH64_TLSDESC_LD64_LO12_NC:
case BFD_RELOC_AARCH64_TLSDESC_LD_PREL19:
+ case BFD_RELOC_AARCH64_TLSDESC_LDR:
+ case BFD_RELOC_AARCH64_TLSDESC_OFF_G0_NC:
+ case BFD_RELOC_AARCH64_TLSDESC_OFF_G1:
return GOT_TLSDESC_GD;
case BFD_RELOC_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
switch (bfd_r_type)
{
case BFD_RELOC_AARCH64_NONE:
+ case BFD_RELOC_AARCH64_TLSDESC_ADD:
case BFD_RELOC_AARCH64_TLSDESC_CALL:
+ case BFD_RELOC_AARCH64_TLSDESC_LDR:
*unresolved_reloc_p = FALSE;
return bfd_reloc_ok;
/* Check if a stub has to be inserted because the destination
is too far away. */
struct elf_aarch64_stub_hash_entry *stub_entry = NULL;
- if (! aarch64_valid_branch_p (value, place))
+
+ /* If the branch destination is directed to plt stub, "value" will be
+ the final destination, otherwise we should plus signed_addend, it may
+ contain non-zero value, for example call to local function symbol
+ which are turned into "sec_sym + sec_off", and sec_off is kept in
+ signed_addend. */
+ if (! aarch64_valid_branch_p (via_plt_p ? value : value + signed_addend,
+ place))
/* The target is out of reach, so redirect the branch to
the local stub for this function. */
stub_entry = elfNN_aarch64_get_stub_entry (input_section, sym_sec, h,
rel, globals);
if (stub_entry != NULL)
- value = (stub_entry->stub_offset
- + stub_entry->stub_sec->output_offset
- + stub_entry->stub_sec->output_section->vma);
+ {
+ value = (stub_entry->stub_offset
+ + stub_entry->stub_sec->output_offset
+ + stub_entry->stub_sec->output_section->vma);
+
+ /* We have redirected the destination to stub entry address,
+ so ignore any addend record in the original rela entry. */
+ signed_addend = 0;
+ }
}
value = _bfd_aarch64_elf_resolve_relocation (bfd_r_type, place, value,
signed_addend, weak_undef_p);
*unresolved_reloc_p = FALSE;
break;
- case BFD_RELOC_AARCH64_TLSDESC_ADD:
case BFD_RELOC_AARCH64_TLSDESC_ADD_LO12_NC:
case BFD_RELOC_AARCH64_TLSDESC_ADR_PAGE21:
case BFD_RELOC_AARCH64_TLSDESC_ADR_PREL21:
case BFD_RELOC_AARCH64_TLSDESC_LD32_LO12_NC:
case BFD_RELOC_AARCH64_TLSDESC_LD64_LO12_NC:
- case BFD_RELOC_AARCH64_TLSDESC_LDR:
case BFD_RELOC_AARCH64_TLSDESC_LD_PREL19:
if (globals->root.sgot == NULL)
return bfd_reloc_notsupported;
*unresolved_reloc_p = FALSE;
break;
+ case BFD_RELOC_AARCH64_TLSDESC_OFF_G0_NC:
+ case BFD_RELOC_AARCH64_TLSDESC_OFF_G1:
+ if (globals->root.sgot == NULL)
+ return bfd_reloc_notsupported;
+
+ value = (symbol_tlsdesc_got_offset (input_bfd, h, r_symndx)
+ + globals->root.sgotplt->output_section->vma
+ + globals->root.sgotplt->output_offset
+ + globals->sgotplt_jump_table_size);
+
+ value -= (globals->root.sgot->output_section->vma
+ + globals->root.sgot->output_offset);
+
+ value = _bfd_aarch64_elf_resolve_relocation (bfd_r_type, place, value,
+ 0, weak_undef_p);
+ *unresolved_reloc_p = FALSE;
+ break;
+
default:
return bfd_reloc_notsupported;
}
return bfd_reloc_continue;
}
+ case BFD_RELOC_AARCH64_TLSDESC_ADD:
case BFD_RELOC_AARCH64_TLSDESC_ADD_LO12_NC:
case BFD_RELOC_AARCH64_TLSDESC_CALL:
/* GD->IE/LE relaxation:
bfd_putl32 (INSN_NOP, contents + rel->r_offset);
return bfd_reloc_ok;
+ case BFD_RELOC_AARCH64_TLSDESC_LDR:
+ if (is_local)
+ {
+ /* GD->LE relaxation:
+ ldr xd, [gp, xn] => movk x0, #:tprel_g0_nc:var
+ */
+ bfd_putl32 (0xf2800000, contents + rel->r_offset);
+ return bfd_reloc_continue;
+ }
+ else
+ {
+ /* GD->IE relaxation:
+ ldr xd, [gp, xn] => ldr x0, [gp, xn]
+ */
+ insn = bfd_getl32 (contents + rel->r_offset);
+ insn &= 0xffffffe0;
+ bfd_putl32 (insn, contents + rel->r_offset);
+ return bfd_reloc_ok;
+ }
+
+ case BFD_RELOC_AARCH64_TLSDESC_OFF_G0_NC:
+ /* GD->LE relaxation:
+ movk xd, #:tlsdesc_off_g0_nc:var => movk x0, #:tprel_g1_nc:var, lsl #16
+ GD->IE relaxation:
+ movk xd, #:tlsdesc_off_g0_nc:var => movk xd, #:gottprel_g0_nc:var
+ */
+ if (is_local)
+ bfd_putl32 (0xf2a00000, contents + rel->r_offset);
+ return bfd_reloc_continue;
+
+ case BFD_RELOC_AARCH64_TLSDESC_OFF_G1:
+ if (is_local)
+ {
+ /* GD->LE relaxation:
+ movz xd, #:tlsdesc_off_g1:var => movz x0, #:tprel_g2:var, lsl #32
+ */
+ bfd_putl32 (0xd2c00000, contents + rel->r_offset);
+ return bfd_reloc_continue;
+ }
+ else
+ {
+ /* GD->IE relaxation:
+ movz xd, #:tlsdesc_off_g1:var => movz xd, #:gottprel_g1:var, lsl #16
+ */
+ insn = bfd_getl32 (contents + rel->r_offset);
+ bfd_putl32 (0xd2a00000 | (insn & 0x1f), contents + rel->r_offset);
+ return bfd_reloc_continue;
+ }
+
case BFD_RELOC_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
/* IE->LE relaxation:
adrp xd, :gottprel:var => movz xd, :tprel_g1:var
case BFD_RELOC_AARCH64_TLSDESC_ADR_PREL21:
case BFD_RELOC_AARCH64_TLSDESC_LDNN_LO12_NC:
case BFD_RELOC_AARCH64_TLSDESC_LD_PREL19:
+ case BFD_RELOC_AARCH64_TLSDESC_OFF_G0_NC:
+ case BFD_RELOC_AARCH64_TLSDESC_OFF_G1:
if (! symbol_tlsdesc_got_offset_mark_p (input_bfd, h, r_symndx))
{
bfd_boolean need_relocs = FALSE;
case BFD_RELOC_AARCH64_TLSDESC_LD32_LO12_NC:
case BFD_RELOC_AARCH64_TLSDESC_LD64_LO12_NC:
case BFD_RELOC_AARCH64_TLSDESC_LD_PREL19:
+ case BFD_RELOC_AARCH64_TLSDESC_OFF_G0_NC:
+ case BFD_RELOC_AARCH64_TLSDESC_OFF_G1:
case BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC:
case BFD_RELOC_AARCH64_TLSGD_ADR_PAGE21:
case BFD_RELOC_AARCH64_TLSGD_ADR_PREL21:
case BFD_RELOC_AARCH64_TLSDESC_LD32_LO12_NC:
case BFD_RELOC_AARCH64_TLSDESC_LD64_LO12_NC:
case BFD_RELOC_AARCH64_TLSDESC_LD_PREL19:
+ case BFD_RELOC_AARCH64_TLSDESC_OFF_G0_NC:
+ case BFD_RELOC_AARCH64_TLSDESC_OFF_G1:
case BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC:
case BFD_RELOC_AARCH64_TLSGD_ADR_PAGE21:
case BFD_RELOC_AARCH64_TLSGD_ADR_PREL21:
#define elf_backend_obj_attrs_section ".ARM.attributes"
#include "elfNN-target.h"
+
+/* CloudABI support. */
+
+#undef TARGET_LITTLE_SYM
+#define TARGET_LITTLE_SYM aarch64_elfNN_le_cloudabi_vec
+#undef TARGET_LITTLE_NAME
+#define TARGET_LITTLE_NAME "elfNN-littleaarch64-cloudabi"
+#undef TARGET_BIG_SYM
+#define TARGET_BIG_SYM aarch64_elfNN_be_cloudabi_vec
+#undef TARGET_BIG_NAME
+#define TARGET_BIG_NAME "elfNN-bigaarch64-cloudabi"
+
+#undef ELF_OSABI
+#define ELF_OSABI ELFOSABI_CLOUDABI
+
+#undef elfNN_bed
+#define elfNN_bed elfNN_aarch64_cloudabi_bed
+
+#include "elfNN-target.h"