From 235f5ef4a6b8fbdcfaea8b629f7c6a9792a789de Mon Sep 17 00:00:00 2001 From: Michael Matz Date: Mon, 28 Jun 2021 17:57:17 +0200 Subject: elf/riscv: Fix relaxation with aliases [PR28021] 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 | 6 ++++ bfd/elfnn-riscv.c | 2 +- ld/ChangeLog | 9 ++++++ ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp | 41 ++++++++++++++++++++++++++++ ld/testsuite/ld-riscv-elf/relax-twice-1.s | 12 ++++++++ ld/testsuite/ld-riscv-elf/relax-twice-2.s | 44 ++++++++++++++++++++++++++++++ ld/testsuite/ld-riscv-elf/relax-twice.ver | 11 ++++++++ 7 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 ld/testsuite/ld-riscv-elf/relax-twice-1.s create mode 100644 ld/testsuite/ld-riscv-elf/relax-twice-2.s create mode 100644 ld/testsuite/ld-riscv-elf/relax-twice.ver diff --git a/bfd/ChangeLog b/bfd/ChangeLog index dd72561..7591469 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,9 @@ +2021-07-06 Michael Matz + + PR ld/28021 + * elfnn-riscv.c (riscv_relax_delete_bytes): Check for any + versioning. + 2021-07-06 Alan Modra PR 28055 diff --git a/bfd/elfnn-riscv.c b/bfd/elfnn-riscv.c index 2dfa635..85a99f3 100644 --- a/bfd/elfnn-riscv.c +++ b/bfd/elfnn-riscv.c @@ -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; diff --git a/ld/ChangeLog b/ld/ChangeLog index 8ecbb2f..22e751e 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,12 @@ +2021-07-06 Michael Matz + + 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 * configure: Regenerate. diff --git a/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp b/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp index 1f6eceb..1197761 100644 --- a/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp +++ b/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp @@ -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 index 0000000..79f1d94 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/relax-twice-1.s @@ -0,0 +1,12 @@ + .file "" + .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 index 0000000..39b82b5 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/relax-twice-2.s @@ -0,0 +1,44 @@ + .file "" + .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 index 0000000..a6d80e7 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/relax-twice.ver @@ -0,0 +1,11 @@ +Old { + global: + foobar; + relaxme; + local: + *; +}; +New { + global: + foobar; +} Old; -- cgit v1.1