Bug 20402 - ld.bfd for emits *_RELATIVE relocations against SHN_ABS symbols
Summary: ld.bfd for emits *_RELATIVE relocations against SHN_ABS symbols
Status: RESOLVED FIXED
Alias: None
Product: binutils
Classification: Unclassified
Component: ld (show other bugs)
Version: 2.28
: P2 normal
Target Milestone: ---
Assignee: Jiong Wang
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2016-07-24 13:12 UTC by Ard Biesheuvel
Modified: 2020-04-06 10:57 UTC (History)
7 users (show)

See Also:
Host:
Target: aarch64*, x86-64
Build:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Ard Biesheuvel 2016-07-24 13:12:54 UTC
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
            {
(
Comment 1 Ard Biesheuvel 2016-07-24 13:43:44 UTC
Uhm, actually it does not fix it. I will try to come up with a small reproducing test case.
Comment 2 Ard Biesheuvel 2016-07-24 14:03:25 UTC
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
Comment 3 Jiong Wang 2016-07-25 09:42:18 UTC
Thanks for reporting this, will investigate shortly
Comment 4 Jiong Wang 2017-02-06 14:44:47 UTC
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.
Comment 5 Ard Biesheuvel 2017-02-06 14:54:37 UTC
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.
Comment 6 Maciej W. Rozycki 2017-04-12 00:25:36 UTC
See also PR 19818, for the corresponding GNU dynamic loader issue.
Comment 7 Alan Modra 2018-02-03 01:17:40 UTC
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..
Comment 8 Sourceware Commits 2018-03-07 16:47:49 UTC
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.
Comment 9 Fangrui Song 2020-04-05 20:48:43 UTC
Can be closed now.
Comment 10 Nick Clifton 2020-04-06 10:57:34 UTC
closed