OSDN Git Service

bfd/
authorJan Kratochvil <jan.kratochvil@redhat.com>
Sun, 11 Jan 2009 21:09:49 +0000 (21:09 +0000)
committerJan Kratochvil <jan.kratochvil@redhat.com>
Sun, 11 Jan 2009 21:09:49 +0000 (21:09 +0000)
* elflink.c (_bfd_elf_section_already_linked): Handle g++-3.4
relocations in `.gnu.linkonce.r.*' referencing its `.gnu.linkonce.t.*'.

ld/testsuite/
* ld-elf/linkoncerdiff.d, ld-elf/linkoncerdiff1.s,
ld-elf/linkoncerdiff2.s: New.

bfd/ChangeLog
bfd/elflink.c
ld/testsuite/ChangeLog
ld/testsuite/ld-elf/linkoncerdiff.d [new file with mode: 0644]
ld/testsuite/ld-elf/linkoncerdiff1.s [new file with mode: 0644]
ld/testsuite/ld-elf/linkoncerdiff2.s [new file with mode: 0644]

index da237ce..477cad0 100644 (file)
@@ -1,3 +1,8 @@
+2009-01-11  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+       * elflink.c (_bfd_elf_section_already_linked): Handle g++-3.4
+       relocations in `.gnu.linkonce.r.*' referencing its `.gnu.linkonce.t.*'.
+
 2009-01-07  Hans-Peter Nilsson  <hp@axis.com>
 
        * elf32-cris.c (cris_elf_relocate_section) <case R_CRIS_32_GD>
index 987de89..29523c4 100644 (file)
@@ -12281,6 +12281,28 @@ _bfd_elf_section_already_linked (bfd *abfd, asection *sec,
            }
        }
 
+  /* Do not complain on unresolved relocations in `.gnu.linkonce.r.F'
+     referencing its discarded `.gnu.linkonce.t.F' counterpart - g++-3.4
+     specific as g++-4.x is using COMDAT groups (without the `.gnu.linkonce'
+     prefix) instead.  `.gnu.linkonce.r.*' were the `.rodata' part of its
+     matching `.gnu.linkonce.t.*'.  If `.gnu.linkonce.r.F' is not discarded
+     but its `.gnu.linkonce.t.F' is discarded means we chose one-only
+     `.gnu.linkonce.t.F' section from a different bfd not requiring any
+     `.gnu.linkonce.r.F'.  Thus `.gnu.linkonce.r.F' should be discarded.
+     The reverse order cannot happen as there is never a bfd with only the
+     `.gnu.linkonce.r.F' section.  The order of sections in a bfd does not
+     matter as here were are looking only for cross-bfd sections.  */
+
+  if ((flags & SEC_GROUP) == 0 && CONST_STRNEQ (name, ".gnu.linkonce.r."))
+    for (l = already_linked_list->entry; l != NULL; l = l->next)
+      if ((l->sec->flags & SEC_GROUP) == 0
+         && CONST_STRNEQ (l->sec->name, ".gnu.linkonce.t."))
+       {
+         if (abfd != l->sec->owner)
+           sec->output_section = bfd_abs_section_ptr;
+         break;
+       }
+
   /* This is the first section with this name.  Record it.  */
   if (! bfd_section_already_linked_table_insert (already_linked_list, sec))
     info->callbacks->einfo (_("%F%P: already_linked_table: %E"));
index f0728e5..1c8b545 100644 (file)
@@ -1,3 +1,8 @@
+2009-01-11  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+       * ld-elf/linkoncerdiff.d, ld-elf/linkoncerdiff1.s,
+       ld-elf/linkoncerdiff2.s: New.
+
 2009-01-07  Hans-Peter Nilsson  <hp@axis.com>
 
        * ld-cris/tls-e-20.d, ld-cris/tls-e-20a.d, ld-cris/tls-e-21.d,
diff --git a/ld/testsuite/ld-elf/linkoncerdiff.d b/ld/testsuite/ld-elf/linkoncerdiff.d
new file mode 100644 (file)
index 0000000..8eec3d2
--- /dev/null
@@ -0,0 +1,6 @@
+#source: linkoncerdiff1.s
+#source: linkoncerdiff2.s
+#ld: -r
+#readelf: -r
+There are no relocations in this file.
+#pass
diff --git a/ld/testsuite/ld-elf/linkoncerdiff1.s b/ld/testsuite/ld-elf/linkoncerdiff1.s
new file mode 100644 (file)
index 0000000..9e8e17e
--- /dev/null
@@ -0,0 +1,7 @@
+       .section        .gnu.linkonce.t.foo, "a", %progbits
+       .globl  symfoo
+symfoo:
+
+       .section        .gnu.linkonce.t.bar, "a", %progbits
+       .globl  symbar
+symbar:
diff --git a/ld/testsuite/ld-elf/linkoncerdiff2.s b/ld/testsuite/ld-elf/linkoncerdiff2.s
new file mode 100644 (file)
index 0000000..1e8c2ba
--- /dev/null
@@ -0,0 +1,22 @@
+       .section        .gnu.linkonce.t.foo, "a", %progbits
+1:
+       .globl  symfoo
+symfoo:
+       .long   0
+
+       .section        .gnu.linkonce.t.bar, "a", %progbits
+2:
+       .globl  symbar
+symbar:
+       .long   0
+
+       .section        .gnu.linkonce.r.foo, "a", %progbits
+       .long   1b
+       .long   symfoo
+/* ld currently incorrectly silently discards this relocation.  Just such
+   relocations are never produced by g++-3.4 so this suppressed error message
+   is not a problem:
+   #error: `.gnu.linkonce.t.bar' referenced in section `.gnu.linkonce.r.foo' of tmpdir/dump1.o: defined in discarded section `.gnu.linkonce.t.bar' of tmpdir/dump1.o
+   */
+       .long   2b
+       .long   symbar