bug-binutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Bug ld/22756] Linker relaxation miscalculates symbol addresses on riscv


From: wilson at gcc dot gnu.org
Subject: [Bug ld/22756] Linker relaxation miscalculates symbol addresses on riscv
Date: Fri, 01 Jun 2018 23:05:55 +0000

https://sourceware.org/bugzilla/show_bug.cgi?id=22756

--- Comment #8 from Jim Wilson <wilson at gcc dot gnu.org> ---
Linker relaxation that deletes code is O(m*n) where m is the number of
relocations and n is the number of symbols.  There have been complaints about
this.  This makes the RISC-V linker slower than other targets that don't have
this feature.  Checking for duplicate symbols makes this O(m*n^2) which is even
worse, so I want to only check for duplicates when necessary.

The only significant difference between my patch and yours is that you are
checking for duplicates unconditionally, where I check for them only when
wrapped symbols are present.  Debugging the run-time differences between your
patch and mine, I see that all of the affected symbols are versioned_hidden. 
This happens in the nondeflt_vers code in elflink.c, where it makes the
sym_hash entry for foo point to the sym_hash entry for address@hidden  This 
would
explain why none of the other ports that delete code during linker relaxation
have seen this problem, as they are almost all embedded targets, and symbol
versioning is not common outside glibc.

Here is the patch I propose to add to fix this

diff --git a/bfd/elfnn-riscv.c b/bfd/elfnn-riscv.c
index b82e655b7b..a0bdee54b2 100644
--- a/bfd/elfnn-riscv.c
+++ b/bfd/elfnn-riscv.c
@@ -2708,9 +2708,12 @@ riscv_relax_delete_bytes (bfd *abfd, asection *sec,
bfd_vma addr, size_t count,
         call to SYMBOL as well. Since both __wrap_SYMBOL and SYMBOL reference
         the same symbol (which is __wrap_SYMBOL), but still exist as two
         different symbols in 'sym_hashes', we don't want to adjust
-        the global symbol __wrap_SYMBOL twice.
-        This check is only relevant when symbols are being wrapped.  */
-      if (link_info->wrap_hash != NULL)
+        the global symbol __wrap_SYMBOL twice.  */
+      /* The same problem occurs with symbols that are versioned_hidden, as
+        foo becomes an alias for address@hidden, and hence they need the same
+        treatment.  */
+      if (link_info->wrap_hash != NULL
+         || sym_hash->versioned == versioned_hidden)
        {
          struct elf_link_hash_entry **cur_sym_hashes;

-- 
You are receiving this mail because:
You are on the CC list for the bug.


reply via email to

[Prev in Thread] Current Thread [Next in Thread]