xtensa: fix localized symbol refcounting with --gc-sections
authorMax Filippov <jcmvbkbc@gmail.com>
Thu, 14 May 2015 02:22:55 +0000 (05:22 +0300)
committerMax Filippov <jcmvbkbc@gmail.com>
Thu, 14 May 2015 04:07:27 +0000 (07:07 +0300)
elf_xtensa_gc_sweep_hook doesn't correctly unreference symbols that were
made local, that results in link failure with the following message:

  BFD (GNU Binutils) 2.24 internal error, aborting at elf32-xtensa.c line
  3372 in elf_xtensa_finish_dynamic_sections

elf_xtensa_gc_sweep_hook determines symbol reference type (PLT or GOT) by
relocation type. Relocation types are not changed when symbol becomes
local, but its PLT references are added to GOT references and
plt.refcount is set to 0. Such symbol cannot be unreferences in the
elf_xtensa_gc_sweep_hook and its extra references make calculated GOT
relocations section size not match number of GOT relocations.

Fix it by treating PLT reference as GOT reference when plt.refcount is
not positive.

2015-05-14  Max Filippov  <jcmvbkbc@gmail.com>
bfd/
* elf32-xtensa.c (elf_xtensa_gc_sweep_hook): Treat PLT reference
as GOT reference when plt.refcount is not positive.

bfd/ChangeLog
bfd/elf32-xtensa.c

index 398476b613855643c3c72f3490c08effc0a88483..24f08d948ed03b65543af409e26d627b6be14efd 100644 (file)
@@ -1,3 +1,8 @@
+2015-05-14  Max Filippov  <jcmvbkbc@gmail.com>
+
+       * elf32-xtensa.c (elf_xtensa_gc_sweep_hook): Treat PLT reference
+       as GOT reference when plt.refcount is not positive.
+
 2015-05-12  H.J. Lu  <hongjiu.lu@intel.com>
 
        * elf32-i386.c (elf_i386_allocate_dynrelocs): Allocate space
index 53af1c6ee287676574e9705bba86211bb150bf45..25236707dae46e7190c646de1601fb1f6ff088fc 100644 (file)
@@ -1360,10 +1360,14 @@ elf_xtensa_gc_sweep_hook (bfd *abfd,
        {
          if (is_plt)
            {
+             /* If the symbol has been localized its plt.refcount got moved
+                to got.refcount.  Handle it as GOT.  */
              if (h->plt.refcount > 0)
                h->plt.refcount--;
+             else
+               is_got = TRUE;
            }
-         else if (is_got)
+         if (is_got)
            {
              if (h->got.refcount > 0)
                h->got.refcount--;