For C++ functions that are emitted to a comdat section (template instantiations and the like), the corresponding exception handling information is presently being emitted to the non-comdat .gcc_except_table section. This means that you can end up with multiple copies of the exception tables in the executable from different objects, even though the linker can remove all but one copy of the function it goes with.

We do have a test case for this, but I don't know how to mash it into the Dejagnu framework. My hand-testing involved comparing the before/after output of readelf to see the new exception table sections in the group, and verifying that the size of the executable is smaller with the patch than without it.

Otherwise, I bootstrapped and regression tested on x86_64, and also tested on mipsisa32r2-sde-elf since I had an existing build tree for that set up. This patch has also been present in our local source base for a while so it's been well-tested in that context. OK for mainline?

-Sandra


2012-08-04  Paul Brook  <p...@codesourcery.com>
            Sandra Loosemore  <san...@codesourcery.com>

        gcc/
        * except.c (switch_to_exception_section): Place tables for
        DECL_ONE_ONLY functions in comdat groups.

Index: gcc/except.c
===================================================================
--- gcc/except.c	(revision 190149)
+++ gcc/except.c	(working copy)
@@ -2777,11 +2777,16 @@ switch_to_exception_section (const char 
 	    flags = SECTION_WRITE;
 
 #ifdef HAVE_LD_EH_GC_SECTIONS
-	  if (flag_function_sections)
+	  if (flag_function_sections
+	      || (DECL_ONE_ONLY (current_function_decl) && HAVE_COMDAT_GROUP))
 	    {
 	      char *section_name = XNEWVEC (char, strlen (fnname) + 32);
+	      /* The EH table must match the code section, so only mark
+		 it linkonce if we have COMDAT groups to tie them together.  */
+	      if (DECL_ONE_ONLY (current_function_decl) && HAVE_COMDAT_GROUP)
+		flags |= SECTION_LINKONCE;
 	      sprintf (section_name, ".gcc_except_table.%s", fnname);
-	      s = get_section (section_name, flags, NULL);
+	      s = get_section (section_name, flags, current_function_decl);
 	      free (section_name);
 	    }
 	  else

Reply via email to