From 1ada945d059789e05542ebf573bd9b7eab2a2654 Mon Sep 17 00:00:00 2001 From: Marcus Shawcroft Date: Wed, 18 Feb 2015 15:37:35 +0000 Subject: [PATCH] [AArch64] Add support for :tlsdesc: and TLSDESC_LD_PREL19 --- bfd/ChangeLog | 12 +++++++++ bfd/elfnn-aarch64.c | 58 ++++++++++++++++++++++++++++++++++++++--- bfd/elfxx-aarch64.c | 2 ++ gas/config/tc-aarch64.c | 4 ++- 4 files changed, 71 insertions(+), 5 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 0103df24148..9c40f0ba15b 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,15 @@ +2015-02-26 Marcus Shawcroft + + * elfnn-aarch64.c (elfNN_aarch64_howto_table): Fix + TLSDESC_LD_PREL19 field width and masks. + (aarch64_tls_transition_without_check) + (aarch64_reloc_got_type, elfNN_aarch64_final_link_relocate) + (elfNN_aarch64_tls_relax, elfNN_aarch64_relocate_section) + (elfNN_aarch64_gc_sweep_hook, elfNN_aarch64_check_relocs): Handle + BFD_RELOC_AARCH64_TLSDESC_LD_PREL19. + * elfxx-aarch64.c (_bfd_aarch64_elf_put_addend) + (_bfd_aarch64_elf_resolve_relocation): Likewise. + 2015-02-26 Marcus Shawcroft * elfnn-aarch64.c (IS_AARCH64_TLSDESC_RELOC) BFD_RELOC_AARCH64_TLSDESC_ADR_PREL21 move. diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c index ee88b5dc28c..8a66299acb0 100644 --- a/bfd/elfnn-aarch64.c +++ b/bfd/elfnn-aarch64.c @@ -1092,15 +1092,15 @@ static reloc_howto_type elfNN_aarch64_howto_table[] = HOWTO (AARCH64_R (TLSDESC_LD_PREL19), /* type */ 2, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ - 21, /* bitsize */ + 19, /* bitsize */ TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ AARCH64_R_STR (TLSDESC_LD_PREL19), /* name */ FALSE, /* partial_inplace */ - 0x1ffffc, /* src_mask */ - 0x1ffffc, /* dst_mask */ + 0x0ffffe0, /* src_mask */ + 0x0ffffe0, /* dst_mask */ TRUE), /* pcrel_offset */ HOWTO (AARCH64_R (TLSDESC_ADR_PREL21), /* type */ @@ -3755,6 +3755,11 @@ aarch64_tls_transition_without_check (bfd_reloc_code_real_type r_type, ? BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0_NC : r_type); + case BFD_RELOC_AARCH64_TLSDESC_LD_PREL19: + return (is_local + ? BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1 + : BFD_RELOC_AARCH64_TLSIE_LD_GOTTPREL_PREL19); + case BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC: case BFD_RELOC_AARCH64_TLSDESC_LDNN_LO12_NC: return (is_local @@ -3809,6 +3814,7 @@ aarch64_reloc_got_type (bfd_reloc_code_real_type r_type) case BFD_RELOC_AARCH64_TLSDESC_CALL: case BFD_RELOC_AARCH64_TLSDESC_LD64_LO12_NC: case BFD_RELOC_AARCH64_TLSDESC_LD32_LO12_NC: + case BFD_RELOC_AARCH64_TLSDESC_LD_PREL19: return GOT_TLSDESC_GD; case BFD_RELOC_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: @@ -4555,6 +4561,7 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto, 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; value = (symbol_tlsdesc_got_offset (input_bfd, h, r_symndx) @@ -4625,11 +4632,51 @@ elfNN_aarch64_tls_relax (struct elf_aarch64_link_hash_table *globals, return bfd_reloc_continue; } - case BFD_RELOC_AARCH64_TLSDESC_ADR_PREL21: BFD_ASSERT (0); break; + case BFD_RELOC_AARCH64_TLSDESC_LD_PREL19: + if (is_local) + { + /* Tiny TLSDESC->LE relaxation: + ldr x1, :tlsdesc:var => movz x0, #:tprel_g1:var + adr x0, :tlsdesc:var => movk x0, #:tprel_g0_nc:var + .tlsdesccall var + blr x1 => nop + */ + BFD_ASSERT (ELFNN_R_TYPE (rel[1].r_info) == AARCH64_R (TLSDESC_ADR_PREL21)); + BFD_ASSERT (ELFNN_R_TYPE (rel[2].r_info) == AARCH64_R (TLSDESC_CALL)); + + rel[1].r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel->r_info), + AARCH64_R (TLSLE_MOVW_TPREL_G0_NC)); + rel[2].r_info = ELFNN_R_INFO (STN_UNDEF, R_AARCH64_NONE); + + bfd_putl32 (0xd2a00000, contents + rel->r_offset); + bfd_putl32 (0xf2800000, contents + rel->r_offset + 4); + bfd_putl32 (INSN_NOP, contents + rel->r_offset + 8); + return bfd_reloc_continue; + } + else + { + /* Tiny TLSDESC->IE relaxation: + ldr x1, :tlsdesc:var => ldr x0, :gottprel:var + adr x0, :tlsdesc:var => nop + .tlsdesccall var + blr x1 => nop + */ + BFD_ASSERT (ELFNN_R_TYPE (rel[1].r_info) == AARCH64_R (TLSDESC_ADR_PREL21)); + BFD_ASSERT (ELFNN_R_TYPE (rel[2].r_info) == AARCH64_R (TLSDESC_CALL)); + + rel[1].r_info = ELFNN_R_INFO (STN_UNDEF, R_AARCH64_NONE); + rel[2].r_info = ELFNN_R_INFO (STN_UNDEF, R_AARCH64_NONE); + + bfd_putl32 (0x58000000, contents + rel->r_offset); + bfd_putl32 (INSN_NOP, contents + rel->r_offset + 4); + bfd_putl32 (INSN_NOP, contents + rel->r_offset + 8); + return bfd_reloc_continue; + } + case BFD_RELOC_AARCH64_TLSGD_ADR_PREL21: if (is_local) { @@ -5106,6 +5153,7 @@ elfNN_aarch64_relocate_section (bfd *output_bfd, case BFD_RELOC_AARCH64_TLSDESC_ADR_PAGE21: case BFD_RELOC_AARCH64_TLSDESC_ADR_PREL21: case BFD_RELOC_AARCH64_TLSDESC_LDNN_LO12_NC: + case BFD_RELOC_AARCH64_TLSDESC_LD_PREL19: if (! symbol_tlsdesc_got_offset_mark_p (input_bfd, h, r_symndx)) { bfd_boolean need_relocs = FALSE; @@ -5476,6 +5524,7 @@ elfNN_aarch64_gc_sweep_hook (bfd *abfd, 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_TLSGD_ADD_LO12_NC: case BFD_RELOC_AARCH64_TLSGD_ADR_PAGE21: case BFD_RELOC_AARCH64_TLSGD_ADR_PREL21: @@ -5947,6 +5996,7 @@ elfNN_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info, 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_TLSGD_ADD_LO12_NC: case BFD_RELOC_AARCH64_TLSGD_ADR_PAGE21: case BFD_RELOC_AARCH64_TLSGD_ADR_PREL21: diff --git a/bfd/elfxx-aarch64.c b/bfd/elfxx-aarch64.c index 929eb648199..1d661b3b763 100644 --- a/bfd/elfxx-aarch64.c +++ b/bfd/elfxx-aarch64.c @@ -241,6 +241,7 @@ _bfd_aarch64_elf_put_addend (bfd *abfd, contents = reencode_tst_branch_ofs_14 (contents, addend); break; + case BFD_RELOC_AARCH64_TLSDESC_LD_PREL19: case BFD_RELOC_AARCH64_LD_LO19_PCREL: case BFD_RELOC_AARCH64_GOT_LD_PREL19: case BFD_RELOC_AARCH64_TLSIE_LD_GOTTPREL_PREL19: @@ -380,6 +381,7 @@ _bfd_aarch64_elf_resolve_relocation (bfd_reloc_code_real_type r_type, break; case BFD_RELOC_AARCH64_TLSDESC_ADR_PREL21: + case BFD_RELOC_AARCH64_TLSDESC_LD_PREL19: case BFD_RELOC_AARCH64_TLSGD_ADR_PREL21: case BFD_RELOC_AARCH64_TLSIE_LD_GOTTPREL_PREL19: case BFD_RELOC_AARCH64_ADR_LO21_PCREL: diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c index ce56dc3b571..1e2b182246a 100644 --- a/gas/config/tc-aarch64.c +++ b/gas/config/tc-aarch64.c @@ -2479,7 +2479,7 @@ static struct reloc_table_entry reloc_table[] = { 0, 0, 0, - 0}, + BFD_RELOC_AARCH64_TLSDESC_LD_PREL19}, /* 12 bit offset into the page containing GOT TLS entry for a symbol */ {"tlsdesc_lo12", 0, @@ -6711,6 +6711,7 @@ md_apply_fix (fixS * fixP, valueT * valP, segT seg) 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_TLSGD_ADD_LO12_NC: case BFD_RELOC_AARCH64_TLSGD_ADR_PAGE21: case BFD_RELOC_AARCH64_TLSGD_ADR_PREL21: @@ -6913,6 +6914,7 @@ aarch64_force_relocation (struct fix *fixp) 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_TLSGD_ADD_LO12_NC: case BFD_RELOC_AARCH64_TLSGD_ADR_PAGE21: case BFD_RELOC_AARCH64_TLSGD_ADR_PREL21: -- 2.30.2