Bootstrapped and regtested on x86_64-redhat-linux and
s390x-redhat-linux.  Ok for master (or GCC 13 in case this doesn't fit
stage4 criteria)?



Building C++ template-heavy code with ASan sometimes leads to bogus
"defined in discarded section" linker errors.

The reason is that .rodata.FUNC.cstN sections are not placed into
COMDAT group sections FUNC.  This is important, because ASan puts
references to .LASANPC labels into these sections.  Discarding the
respective .text.FUNC section causes the linker error.

Fix by adding SECTION_LINKONCE to .rodata.FUNC.cstN sections in
mergeable_constant_section () if the current function has an associated
COMDAT group.  This is similar to what switch_to_exception_section ()
is currently doing with .gcc_except_table.FUNC sections.

gcc/ChangeLog:

        * varasm.cc (mergeable_constant_section): Honor COMDAT.

gcc/testsuite/ChangeLog:

        * g++.dg/asan/comdat.C: New test.
---
 gcc/testsuite/g++.dg/asan/comdat.C | 35 ++++++++++++++++++++++++++++++
 gcc/varasm.cc                      |  6 ++++-
 2 files changed, 40 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/asan/comdat.C

diff --git a/gcc/testsuite/g++.dg/asan/comdat.C 
b/gcc/testsuite/g++.dg/asan/comdat.C
new file mode 100644
index 00000000000..cd4f3f830a8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/asan/comdat.C
@@ -0,0 +1,35 @@
+/* Check that we don't emit non-COMDAT rodata.  */
+
+/* { dg-do compile } */
+/* { dg-final { scan-assembler-not 
{\.section\t\.rodata\._ZN1hlsIPKcEERS_RKT_\.cst[48],"[^"]*",@progbits,[48]\n} } 
} */
+
+const char *a;
+
+class b
+{
+public:
+  b ();
+};
+
+class h
+{
+public:
+  template <typename c>
+  h &
+  operator<< (const c &)
+  {
+    d (b ());
+    return *this;
+  }
+
+  void d (b);
+};
+
+h e ();
+
+h
+g ()
+{
+  e () << a << a << a;
+  throw;
+}
diff --git a/gcc/varasm.cc b/gcc/varasm.cc
index c41f17d64f7..f2614f0ee39 100644
--- a/gcc/varasm.cc
+++ b/gcc/varasm.cc
@@ -938,7 +938,11 @@ mergeable_constant_section (machine_mode mode 
ATTRIBUTE_UNUSED,
 
       sprintf (name, "%s.cst%d", prefix, (int) (align / 8));
       flags |= (align / 8) | SECTION_MERGE;
-      return get_section (name, flags, NULL);
+      if (current_function_decl
+         && DECL_COMDAT_GROUP (current_function_decl)
+         && HAVE_COMDAT_GROUP)
+       flags |= SECTION_LINKONCE;
+      return get_section (name, flags, current_function_decl);
     }
   return readonly_data_section;
 }
-- 
2.35.1

Reply via email to