elf/riscv: Fix relaxation with aliases [PR28021]
authorMichael Matz <matz@suse.de>
Mon, 28 Jun 2021 15:57:17 +0000 (17:57 +0200)
committerMichael Matz <matz@suse.de>
Tue, 6 Jul 2021 13:49:03 +0000 (15:49 +0200)
the fix for PR22756 only changed behaviour for hidden aliases,
but the same situation exists for non-hidden aliases: sym_hashes[]
can contain multiple entries pointing to the same symbol structure
leading to relaxation adjustment to be applied twice.

Fix this by testing for duplicates for everything that looks like it
has a version.

PR ld/28021

bfd/
* elfnn-riscv.c (riscv_relax_delete_bytes): Check for any
versioning.

ld/
* testsuite/ld-riscv-elf/relax-twice.ver: New.
* testsuite/ld-riscv-elf/relax-twice-1.s: New.
* testsuite/ld-riscv-elf/relax-twice-2.s: New.
* testsuite/ld-riscv-elf/ld-riscv-elf.exp
(run_relax_twice_test): New, and call it.

bfd/ChangeLog
bfd/elfnn-riscv.c
ld/ChangeLog
ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp
ld/testsuite/ld-riscv-elf/relax-twice-1.s [new file with mode: 0644]
ld/testsuite/ld-riscv-elf/relax-twice-2.s [new file with mode: 0644]
ld/testsuite/ld-riscv-elf/relax-twice.ver [new file with mode: 0644]

index dd7256127161b0dc1fe93c651a4618e1506f9244..7591469681035b17ed7a590a097f0b115969ab81 100644 (file)
@@ -1,3 +1,9 @@
+2021-07-06  Michael Matz  <matz@suse.de>
+
+       PR ld/28021
+       * elfnn-riscv.c (riscv_relax_delete_bytes): Check for any
+       versioning.
+
 2021-07-06  Alan Modra  <amodra@gmail.com>
 
        PR 28055
index 2dfa63513370327f7f9452a3589deb242a0c2bbe..85a99f3d610523b351a13f4cc10ca36d4512a6c1 100644 (file)
@@ -3995,7 +3995,7 @@ riscv_relax_delete_bytes (bfd *abfd, asection *sec, bfd_vma addr, size_t count,
         foo becomes an alias for foo@BAR, and hence they need the same
         treatment.  */
       if (link_info->wrap_hash != NULL
-         || sym_hash->versioned == versioned_hidden)
+         || sym_hash->versioned != unversioned)
        {
          struct elf_link_hash_entry **cur_sym_hashes;
 
index 8ecbb2f8fc2c9f0ffe107ac25ebf11155cf891e2..22e751ed855027848ba60faa648edaa038afc06c 100644 (file)
@@ -1,3 +1,12 @@
+2021-07-06  Michael Matz  <matz@suse.de>
+
+       PR ld/28021
+       * testsuite/ld-riscv-elf/relax-twice.ver: New.
+       * testsuite/ld-riscv-elf/relax-twice-1.s: New.
+       * testsuite/ld-riscv-elf/relax-twice-2.s: New.
+       * testsuite/ld-riscv-elf/ld-riscv-elf.exp
+       (run_relax_twice_test): New, and call it.
+
 2021-07-03  Nick Clifton  <nickc@redhat.com>
 
        * configure: Regenerate.
index 1f6eceb3ae84f1b73f82e352272b7aae68eb39e6..119776117337f0c697b55857fedee16c7b989f7d 100644 (file)
@@ -78,6 +78,46 @@ proc run_dump_test_ifunc { name target output} {
              "$name-$target.$ext"]]
 }
 
+proc run_relax_twice_test {} {
+    global as
+    global ld
+    global nm
+    global nm_output
+    global srcdir
+    global subdir
+    global runtests
+
+    set testname "relax-twice"
+    if ![runtest_file_p $runtests $testname] then {
+       return
+    }
+
+    # assemble and link the two input files with a version script, then
+    # capture output of nm and compare addresses of the two symbols
+    # 'foobar_new' and 'foobar@@New'.  They must be equal.
+    # Bitness doesn't matter so we simply force 64bit.
+    if { ![ld_assemble_flags $as "-march=rv64i" $srcdir/$subdir/relax-twice-1.s tmpdir/relax-twice-1.o ]
+       || ![ld_assemble_flags $as "-march=rv64i" $srcdir/$subdir/relax-twice-2.s tmpdir/relax-twice-2.o]
+       || ![ld_link $ld tmpdir/relax-twice.so "-m[riscv_choose_lp64_emul] -shared --relax --version-script $srcdir/$subdir/relax-twice.ver tmpdir/relax-twice-1.o tmpdir/relax-twice-2.o"] } {
+       fail $testname
+    } elseif { ![ld_nm $nm "" tmpdir/relax-twice.so] } {
+       fail $testname
+    } elseif { ![info exists nm_output(foobar_new)]
+              || ![info exists nm_output(foobar@@New)]} {
+       send_log "bad output from nm\n"
+       verbose "bad output from nm"
+       fail $testname
+    } elseif {$nm_output(foobar_new) != $nm_output(foobar@@New)} {
+       send_log "foobar_new == $nm_output(foobar_new)\n"
+       verbose "foobar_new == $nm_output(foobar_new)"
+       send_log "foobar@@New == $nm_output(foobar@@New)\n"
+       verbose "foobar@@New == $nm_output(foobar@@New)"
+       fail $testname
+    } else {
+       pass $testname
+    }
+}
+
 if [istarget "riscv*-*-*"] {
     run_dump_test "call-relax"
     run_dump_test "pcgp-relax"
@@ -128,6 +168,7 @@ if [istarget "riscv*-*-*"] {
 
     run_dump_test "relro-relax-lui"
     run_dump_test "relro-relax-pcrel"
+    run_relax_twice_test
 
     set abis [list rv32gc ilp32 [riscv_choose_ilp32_emul] rv64gc lp64 [riscv_choose_lp64_emul]]
     foreach { arch abi emul } $abis {
diff --git a/ld/testsuite/ld-riscv-elf/relax-twice-1.s b/ld/testsuite/ld-riscv-elf/relax-twice-1.s
new file mode 100644 (file)
index 0000000..79f1d94
--- /dev/null
@@ -0,0 +1,12 @@
+       .file   "<artificial>"
+       .option pic
+       .text
+       .globl  foobar_new
+       .weak   foobar_new
+       .type   foobar_new, @function
+foobar_new:
+       jr ra
+       .size   foobar_new, .-foobar_new
+       .symver foobar_new, foobar@@New
+
+       .section        .note.GNU-stack,"",@progbits
diff --git a/ld/testsuite/ld-riscv-elf/relax-twice-2.s b/ld/testsuite/ld-riscv-elf/relax-twice-2.s
new file mode 100644 (file)
index 0000000..39b82b5
--- /dev/null
@@ -0,0 +1,44 @@
+       .file   "<artificial>"
+       .option pic
+       .text
+       .section        .rodata.str1.8,"aMS",@progbits,1
+       .align  3
+.LC0:
+       .string "%u"
+       .text
+       .align  1
+       .globl  relaxme
+       .type   relaxme, @function
+relaxme:
+       addi    sp,sp,-32
+       addi    a2,sp,12
+       lla     a1,.LC0
+       li      a0,0
+       sd      ra,24(sp)
+       call    sscanf@plt
+       ld      ra,24(sp)
+       addi    sp,sp,32
+       jr      ra
+       .size   relaxme, .-relaxme
+       .align  1
+       .globl  foobar_new
+       .type   foobar_new, @function
+foobar_new:
+       li      a0,1
+       ret
+       .size   foobar_new, .-foobar_new
+       .symver foobar_new, foobar@@New
+       .align  1
+       .globl  foobar_old
+       .type   foobar_old, @function
+foobar_old:
+       addi    sp,sp,-16
+       sd      ra,8(sp)
+       call    foobar@plt
+       ld      ra,8(sp)
+       snez    a0,a0
+       addi    sp,sp,16
+       jr      ra
+       .size   foobar_old, .-foobar_old
+       .symver foobar_old, foobar@Old
+       .section        .note.GNU-stack,"",@progbits
diff --git a/ld/testsuite/ld-riscv-elf/relax-twice.ver b/ld/testsuite/ld-riscv-elf/relax-twice.ver
new file mode 100644 (file)
index 0000000..a6d80e7
--- /dev/null
@@ -0,0 +1,11 @@
+Old {
+        global:
+                foobar;
+                relaxme;
+        local:
+                *;
+};
+New {
+        global:
+                foobar;
+} Old;