diff options
Diffstat (limited to 'bfd')
-rw-r--r-- | bfd/ChangeLog | 7 | ||||
-rw-r--r-- | bfd/elfnn-aarch64.c | 53 |
2 files changed, 60 insertions, 0 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index d51800e..1a07fba 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,10 @@ +2015-09-09 Jiong Wang <jiong.wang@arm.com> + + * elfnn-aarch64.c (aarch64_tls_transition_without_check): Support three + TLS local dynamic traditional relocations types. + (elfNN_aarch64_tls_relax): Support TLS local dynamic traditional to + local executable relaxation. + 2015-09-03 H.J. Lu <hongjiu.lu@intel.com> * elf64-x86-64.c (elf_x86_64_convert_mov_to_lea): Remove diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c index 3c43924..696fdcc 100644 --- a/bfd/elfnn-aarch64.c +++ b/bfd/elfnn-aarch64.c @@ -213,6 +213,9 @@ || (R_TYPE) == BFD_RELOC_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 \ || (R_TYPE) == BFD_RELOC_AARCH64_TLSIE_LD_GOTTPREL_PREL19 \ || (R_TYPE) == BFD_RELOC_AARCH64_TLSIE_LDNN_GOTTPREL_LO12_NC \ + || (R_TYPE) == BFD_RELOC_AARCH64_TLSLD_ADD_LO12_NC \ + || (R_TYPE) == BFD_RELOC_AARCH64_TLSLD_ADR_PAGE21 \ + || (R_TYPE) == BFD_RELOC_AARCH64_TLSLD_ADR_PREL21 \ || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_ADR_PAGE21 \ || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_ADR_PREL21 \ || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_LD_PREL19 \ @@ -4390,6 +4393,11 @@ aarch64_tls_transition_without_check (bfd_reloc_code_real_type r_type, /* Instructions with these relocations will become NOPs. */ return BFD_RELOC_AARCH64_NONE; + case BFD_RELOC_AARCH64_TLSLD_ADD_LO12_NC: + case BFD_RELOC_AARCH64_TLSLD_ADR_PAGE21: + case BFD_RELOC_AARCH64_TLSLD_ADR_PREL21: + return is_local ? BFD_RELOC_AARCH64_NONE : r_type; + default: break; } @@ -5616,6 +5624,51 @@ elfNN_aarch64_tls_relax (struct elf_aarch64_link_hash_table *globals, } 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 + */ + 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); + bfd_putl32 (0xd53bd040, contents + rel->r_offset + 0); + bfd_putl32 (0x91004000, contents + rel->r_offset + 4); + return bfd_reloc_ok; + } + return bfd_reloc_continue; + + case BFD_RELOC_AARCH64_TLSLD_ADR_PAGE21: + /* LD->LE relaxation (small): + adrp x0, :tlsldm:x => mrs x0, tpidr_el0 + */ + if (is_local) + { + bfd_putl32 (0xd53bd040, contents + rel->r_offset); + 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 + bl __tls_get_addr => nop + */ + 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); + bfd_putl32 (0x91004000, contents + rel->r_offset + 0); + bfd_putl32 (0xd503201f, contents + rel->r_offset + 4); + return bfd_reloc_ok; + } + return bfd_reloc_continue; + default: return bfd_reloc_continue; } |