ld.bfd in -pie mode will 'optimize' away a R_AARCH64_ABS64 relocation against a hidden SHN_ABS symbol by replacing it with a R_AARCH64_RELATIVE relocation, which obviously makes the resulting value in the place dependent on the load offset rather than fixed. Instead, I would expect either the relocation to be preserved as a R_AARCH64_ABS64 relocation to be resolved at load time, or be optimized away completely, since the symbol is hidden and therefore not preemptible and could thus be fully resolved at link time. I don't have a small test case handy (I found this while working on KASLR for arm64 Linux), but the following hunk fixes the problem completely for me: it not only prevents the R_AARCH64_RELATIVE relocation from being emitted, but it fully resolves the relocation and puts the correct 64-bit absolute value in the place in the ELF binary. diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c index 3435a3d67339..d1068f56c4ee 100644 --- a/bfd/elfnn-aarch64.c +++ b/bfd/elfnn-aarch64.c @@ -5191,7 +5191,8 @@ && h->dynindx != -1 && (!bfd_link_pic (info) || !SYMBOLIC_BIND (info, h) - || !h->def_regular)) + || !h->def_regular + || sym->st_shndx == SHN_ABS)) outrel.r_info = ELFNN_R_INFO (h->dynindx, r_type); else { (
Uhm, actually it does not fix it. I will try to come up with a small reproducing test case.
The issue can be reproduced by: abs.s ----- .quad foo, bar abs.lds ------- HIDDEN(foo = ABSOLUTE(0xff00ff11ff22ff33)); bar = ABSOLUTE(0xff44ff55ff66ff77); Build using aarch64-linux-gnu-gcc -pie -nostdlib -o abs -T abs.lds abs.s which produces a binary containing the following relocations Relocation section '.rela.dyn' at offset 0x100c8 contains 2 entries: Offset Info Type Sym. Value Sym. Name + Addend 000000000000 000000000403 R_AARCH64_RELATIV -ff00ee00dd00cd 000000000008 000200000101 R_AARCH64_ABS64 ff44ff55ff66ff77 bar + 0
Thanks for reporting this, will investigate shortly
It seems this to be a generic ld.bfd issue? I see there is relocations generated on x86-64 as well, while I think linker should fully resolve these relocation during static linking as they are absolute value. When using ld.gold, I see no relocations generated for above abs testcase.
As it turns out, this is a known issue (at least to some): https://sourceware.org/ml/binutils/2012-05/msg00019.html SHN_ABS symbols are treated just like other (section relative) symbols, because symbols like __GLOBAL_OFFSET_TABLE__ and __DYNAMIC are erroneously emitted as absolute. So it seems this cannot be fixed without fixing the underlying problem.
See also PR 19818, for the corresponding GNU dynamic loader issue.
I'll note that many of the generic linker issues that prevent this bug being fixed have already been solved, and many targets no longer make symbols like _DYNAMIC absolute. So for example, a user script that does something like .text : { .... } my_end_text = .; will define my_end_text as a section relative symbol rather than absolute as older linkers did, which is likely what most users want. Users who really do want absolute symbols defined from dot now need to write my_end_text = ABSOLUTE (.); Even so, there will no doubt be projects that break..
The master branch has been updated by Renlin Li <renlin@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=0c1ded8dc0be9c61975e04a0b416b064223f7bda commit 0c1ded8dc0be9c61975e04a0b416b064223f7bda Author: Renlin Li <renlin.li@arm.com> Date: Wed Mar 7 09:27:45 2018 +0000 [PR20402][LD][AARCH64]Don't emit RELATIVE relocation for absolute symbols which are resolved at static linking time. For absolute symbols which are forced local or not dynamic, the ABS relocation should be resolved at static linking time. Originally, an RELATIVE/ABS relocation will be generated even for absolution symbols for the dynamic linker to resolve. bfd/ 2018-03-07 Renlin Li <renlin.li@arm.com> PR ld/20402 * elfnn-aarch64.c (elfNN_aarch64_final_link_relocate): Check absolute symbol, and don't emit relocation in specific case. ld/ 2018-03-07 Renlin Li <renlin.li@arm.com> PR ld/20402 * testsuite/ld-aarch64/aarch64-elf.exp: Run new test. * testsuite/ld-aarch64/pr20402.s: New. * testsuite/ld-aarch64/pr20402.d: New.
Can be closed now.
closed