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