diff options
author | Marcus Shawcroft <marcus.shawcroft@arm.com> | 2015-02-18 15:37:35 +0000 |
---|---|---|
committer | Marcus Shawcroft <marcus.shawcroft@arm.com> | 2015-02-26 22:59:23 +0000 |
commit | 1ada945d059789e05542ebf573bd9b7eab2a2654 (patch) | |
tree | 164f1baf6f54ca23ddced208db9fa9c499e5c429 /bfd | |
parent | 389b8029b69e2a4cdbc3a23d0ee9d5b3c974bd34 (diff) | |
download | gdb-1ada945d059789e05542ebf573bd9b7eab2a2654.zip gdb-1ada945d059789e05542ebf573bd9b7eab2a2654.tar.gz gdb-1ada945d059789e05542ebf573bd9b7eab2a2654.tar.bz2 |
[AArch64] Add support for :tlsdesc: and TLSDESC_LD_PREL19
Diffstat (limited to 'bfd')
-rw-r--r-- | bfd/ChangeLog | 12 | ||||
-rw-r--r-- | bfd/elfnn-aarch64.c | 58 | ||||
-rw-r--r-- | bfd/elfxx-aarch64.c | 2 |
3 files changed, 68 insertions, 4 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 0103df2..9c40f0b 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,5 +1,17 @@ 2015-02-26 Marcus Shawcroft <marcus.shawcroft@arm.com> + * 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 <marcus.shawcroft@arm.com> + * elfnn-aarch64.c (IS_AARCH64_TLSDESC_RELOC) BFD_RELOC_AARCH64_TLSDESC_ADR_PREL21 move. (aarch64_tls_transition_without_check) (aarch64_reloc_got_type, elfNN_aarch64_final_link_relocate) diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c index ee88b5d..8a66299 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 929eb64..1d661b3 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: |