summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Kratochvil <jan.kratochvil@redhat.com>2009-01-11 21:09:49 +0000
committerJan Kratochvil <jan.kratochvil@redhat.com>2009-01-11 21:09:49 +0000
commit80c29487db33cf7e597402790cdf62785e7a89cb (patch)
tree04d3162299f1d83d746dff927c8ff7e8e66b9522
parent5f61c20e05b3752fb9ab5b2aeea6adc8bf515db5 (diff)
downloadbinutils-80c29487db33cf7e597402790cdf62785e7a89cb.tar.gz
binutils-80c29487db33cf7e597402790cdf62785e7a89cb.tar.bz2
binutils-80c29487db33cf7e597402790cdf62785e7a89cb.zip
bfd/
* 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.
-rw-r--r--bfd/ChangeLog5
-rw-r--r--bfd/elflink.c22
-rw-r--r--ld/testsuite/ChangeLog5
-rw-r--r--ld/testsuite/ld-elf/linkoncerdiff.d6
-rw-r--r--ld/testsuite/ld-elf/linkoncerdiff1.s7
-rw-r--r--ld/testsuite/ld-elf/linkoncerdiff2.s22
6 files changed, 67 insertions, 0 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index da237ce608d..477cad0938b 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -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>
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 987de895b26..29523c4614e 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -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"));
diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog
index f0728e50d75..1c8b545660c 100644
--- a/ld/testsuite/ChangeLog
+++ b/ld/testsuite/ChangeLog
@@ -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
index 00000000000..8eec3d2ca27
--- /dev/null
+++ b/ld/testsuite/ld-elf/linkoncerdiff.d
@@ -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
index 00000000000..9e8e17eca14
--- /dev/null
+++ b/ld/testsuite/ld-elf/linkoncerdiff1.s
@@ -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
index 00000000000..1e8c2baefd0
--- /dev/null
+++ b/ld/testsuite/ld-elf/linkoncerdiff2.s
@@ -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