Blob Blame History Raw
http://sourceware.org/ml/binutils/2008-10/msg00235.html

2008-10-26  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* elflink.c (elf_link_input_bfd): Handle pre-COMDAT g++-3.4 relocations
	in `.gnu.linkonce.r.*' referencing its `.gnu.linkonce.t.*'.

2008-10-26  Jan Kratochvil  <jan.kratochvil@redhat.com>

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

--- ../binutils-2.19.50.0.1.orig/bfd/elflink.c	2008-11-21 16:45:02.000000000 +0000
+++ bfd/elflink.c	2008-11-21 17:08:32.000000000 +0000
@@ -9361,7 +9361,23 @@ elf_link_input_bfd (struct elf_final_lin
 		  if ((sec = *ps) != NULL && elf_discarded_section (sec))
 		    {
 		      BFD_ASSERT (r_symndx != 0);
-		      if (action_discarded & COMPLAIN)
+
+		      /* 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 with its `.gnu.linkonce.t.F' being discarded
+			 means we chose one-only `.gnu.linkonce.t.F' section
+			 from an other file not needing any `.gnu.linkonce.r.F'
+			 and thus `.gnu.linkonce.r.F' could be in fact also
+			 discarded.  */
+		      if ((action_discarded & COMPLAIN)
+		          && !(CONST_STRNEQ (o->name, ".gnu.linkonce.r.")
+			       && CONST_STRNEQ (sec->name, ".gnu.linkonce.t.")
+			       && strcmp (o->name + 16, sec->name + 16) == 0))
 			(*finfo->info->callbacks->einfo)
 			  (_("%X`%s' referenced in section `%A' of %B: "
 			     "defined in discarded section `%A' of %B\n"),
--- /dev/null	2008-11-21 14:50:50.404125628 +0000
+++ ld/testsuite/ld-elf/linkoncerdiff.d	2008-11-21 16:12:11.000000000 +0000
@@ -0,0 +1,5 @@
+#source: linkoncerdiff1.s
+#source: linkoncerdiff2.s
+#notarget: arc* d30v* dlx* openrisc* or32* pj*
+#ld: -r
+#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
--- /dev/null	2008-11-21 14:50:50.404125628 +0000
+++ ld/testsuite/ld-elf/linkoncerdiff1.s	2008-11-21 16:12:11.000000000 +0000
@@ -0,0 +1,7 @@
+	.section	.gnu.linkonce.t.foo, "a", %progbits
+	.globl	symfoo
+symfoo:
+
+	.section	.gnu.linkonce.t.bar, "a", %progbits
+	.globl	symbar
+symbar:
--- /dev/null	2008-11-21 14:50:50.404125628 +0000
+++ ld/testsuite/ld-elf/linkoncerdiff2.s	2008-11-21 16:12:11.000000000 +0000
@@ -0,0 +1,17 @@
+	.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
+	.long	2b
+	.long	symbar