This is the mail archive of the
mailing list for the binutils project.
[AArch64] Don't generate GOT entry for large model TLS LE relocation
- From: Jiong Wang <jiong dot wang at foss dot arm dot com>
- To: "binutils at sourceware dot org" <binutils at sourceware dot org>
- Date: Wed, 23 Dec 2015 16:55:40 +0000
- Subject: [AArch64] Don't generate GOT entry for large model TLS LE relocation
- Authentication-results: sourceware.org; auth=none
This patch revert the following commit
Author: Renlin Li <email@example.com>
Date: Fri Oct 2 17:02:53 2015 +0100
[BFD][AARCH64]Create GOT section for TLSLE_MOVW_TPREL_G(1, 1_NC, 2).
2015-10-02 Renlin Li <firstname.lastname@example.org>
* elfnn-aarch64.c (elfNN_aarch64_check_relocs): Create GOT section
for TLSLE_MOVW_TPREL_G(1, 1_NC, 2) relocation.
We shouldn't generate GOT entries for TLS Local Executable relocation
types as they don't need GOT.
This commit was trying to fix the following problem:
1. In large code model, the instruction sequences for TLS traditional
general dynamic will be:
movz a0, #:tlsgd_g1:var R_AARCH64_TLSGD_MOVW_G1
movk a0, #:tlsgd_g0_nc:var R_AARCH64_TLSGD_MOVW_G0_NC
add a0, gp, a0
bl __tls_get_addr R_AARCH64_CALL26
While in large code model, GOT section might be very far from text
section that is out of the addressing range of our pc-relative
instructions, so need to initialize gp register by loading the
address from literal pool, then the full instruction sequences will
become the following:
ldr x1, .Lgot
adr x2, .Lgot
add x1, x2, x1
movz x0, #:tlsgd_g1:var
movk x0, #:tlsgd_g0_nc:var
add x0, x1, x0
.dword _GLOBAL_OFFSET_TABLE_ - . // R_AARCH64_PREL64 _GOT_
2. When TLS relaxation happen, all GD relocations will be turned into
LE relocation types which don't need GOT support, but the PREL64
relocation for literal pool is still referencing the special
symbol _GLOBAL_OFFSET_TABLE_ which is defined by linker to the
start address of .got section. We can't remove it, and we can't
remove the symbol, as gp may needed in other places across this
object, or even gp is only used in above TLS sequences, it will be
impossible to remove the literal pool entry and the symbol under
current BFD linker intrastructure.
So if TLS GD -> LE relaxation happen, and if there is no
relocation types which require GOT support, then .got section
won't be generated, that this symbol will not be defined, we will
end up with a undefined symbol static linking error.
The correct approach to fix this is not by cheating linker that large
model LE relocation require GOT support, but we should always generate
.got section if a relocation has referenced the special symbol
_GLOBAL_OFFSET_TABLE_ during check_relocs. This can fix all
situations where _GLOBAL_OFFSET_TABLE_ are referenced.
This is also the approach ppc is using.
build & check-ld ok. OK for trunk and 2.26?
2015-12-23 Jiong Wang <email@example.com>
* elfnn-aarch64.c (elfNN_aarch64_check_relocs): Require .got section
is a relocation referenced _GLOBAL_OFFSET_TABLE_, meanwhile don't
generate GOT entry for large model TLS LE relocation types.
diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c
index 59c51cc42e08f78d28221aeecf0f72e86fdd7d16..ae3de56ffe0277dfe8e324ca82fcfc20707cd0e1 100644
@@ -7053,6 +7053,22 @@ elfNN_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info,
if (h != NULL)
+ /* If a relocation refers to _GLOBAL_OFFSET_TABLE_, create the .got.
+ This shows up in particular in an R_AARCH64_PREL64 in large model
+ when calculatin the pc-relative address to .got section which is
+ used for initialize gp register. */
+ if (h->root.root.string
+ && strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)
+ if (htab->root.dynobj == NULL)
+ htab->root.dynobj = abfd;
+ if (! aarch64_elf_create_got_section (htab->root.dynobj, info))
+ return FALSE;
+ BFD_ASSERT (h == htab->root.hgot);
/* Create the ifunc sections for static executables. If we
never see an indirect function symbol nor we are building
a static executable, those sections will be empty and
@@ -7213,9 +7229,6 @@ elfNN_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info,
- case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1:
- case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1_NC:
- case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G2: