]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
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>
Wed, 7 Jul 2021 16:04:18 +0000 (18:04 +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.

(cherry picked from commit 235f5ef4a6b8fbdcfaea8b629f7c6a9792a789de)

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 39c7fd73f9220ed3836f92d75bf6cea7d8695e5c..5a1efd7425c94fb027f873d12c5bc3805f972bec 100644 (file)
@@ -1,3 +1,9 @@
+2021-07-07  Michael Matz  <matz@suse.de>
+
+       PR ld/28021
+       * elfnn-riscv.c (riscv_relax_delete_bytes): Check for any
+       versioning.
+
 2021-07-07  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR ld/18028
index f206708a9f356eb119589228c8c68a048ed2c89c..a02f1af02bd34a0885bd9c9b6e5f02cff0f41d56 100644 (file)
@@ -3993,7 +3993,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 b7d9656d5d47df2e9a0588d917c4deb84ef64187..fa8cd35d22f9f02c40596d0ae2dddfb9e4ada3c5 100644 (file)
@@ -1,3 +1,12 @@
+2021-07-07  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-07  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR ld/18028
index 1f1245af7074299c310ba90793735cc6a7d60a0b..c1418aa407689d7309dd3e1e1822969e996ecf82 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"
@@ -127,6 +167,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;