This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Rework the handling of assembler sections


Hans-Peter Nilsson <hp@bitrange.com> writes:
> On Wed, 7 Dec 2005, Richard Sandiford wrote:
>> The patch below fixes the testcases for arm-eabi.  Could you check
>> whether it works for you?
>
> It works.  Tested on mmix-knuth-mmixware, cris-axis-elf and
> cris-axis-linux-gnu.  No regressions.

Thanks.  Unfortunately, I don't think the patch is right.  We would
no longer complain about .eh_frame conflicts if we happened to switch
to our internal section after finding a conflicting decl attribute.
(The patch even felt like a hack when I wrote last night, and in the
cold light of day...)

To recap, the changes I made in this area were:

> - The current exception_section and eh_frame_section hooks will
>   switch to the same section every time they were called.  I've
>   therefore replaced them with global variables of the same name.
>
>   eh_frame_section can be null if there's no dedicated section.
>   This selects the code that used to be in collect2_eh_frame_section.

And the problem is that the old code would only create an eh_frame or
exception section when the hooks were first called, whereas the new code
creates them in init_varasm_once.  This causes a new error if a TU did
not ever trigger calls to the old hooks and if that TU used the sections
with incompatible flags.

I hadn't anticipated that such code would exist.  Given that it does
(and that it's in gcc itself) I now think the best fix is to back to
the lazy creation of eh_frame_section and exception_section.
The patch below does this.  The aims were:

  - To fix the bug, and reinstate the behaviour from before the
    section patch.

  - To keep the advantages of the current approach, such as the
    once-per-compilation hashtable lookup.

  - To continue to allow targets to override the sections in their
    init_sections hook.

The two section variables are only used in one place each, as arguments
to switch_section.  One of these uses is inside switch_to_eh_frame_section,
the other in output_function_exception_table.  The patch replaces the latter
with a call to a new function, switch_to_exception_section, which serves
a similar purpose to the old exception_section target hook.

After the patch, switch_to_eh_frame_section will use the section cached
in eh_frame_section, if any, otherwise it will apply the usual default
rules.  (The values cached in eh_frame_section will come either from the
target's init_sections hook or from earlier calls to the function.)
switch_to_exception_section behaves similarly for exception_section.

IMO, this is much cleaner than the patch I posted yesterday,
and diffstat likes it too.  Bootstrapped & regression tested
on i686-pc-linux-gnu.  OK to install?

Richard


	* dwarf2out.c (default_eh_frame_section): Delete, moving handling
	of EH_FRAME_SECTION_NAME into...
	(switch_to_eh_frame_section): ...here.  Try to set eh_frame_section
	if it is still null.
	* except.c (default_exception_section): Delete, moving most
	of the code to...
	(switch_to_exception_section): ...this new function.  Set
	exception_section if it is still null, then switch to it.
	(output_function_exception_table): Use switch_to_exception_section.
	* varasm.c (exception_section, eh_frame_section): Update comments.
	(get_section): Hoist use of SECTION_NAMED.
	(init_varasm_once): Don't set exception_section and eh_frame_section.
	* output.h (default_exception_section): Delete.
	(default_eh_frame_section): Delete.

testsuite/
	* gcc.dg/20051207-1.c,
	* gcc.dg/20051207-2.c,
	* gcc.dg/20051207-3.c: New tests.

Index: gcc/testsuite/gcc.dg/20051207-2.c
===================================================================
--- gcc/testsuite/gcc.dg/20051207-2.c	(revision 0)
+++ gcc/testsuite/gcc.dg/20051207-2.c	(revision 0)
@@ -0,0 +1,5 @@
+/* GCC doesn't generate any .eh_frame data for this TU itself, so it
+   shouldn't warn about "a" conflicting with the built-in idea of
+   .eh_frame, even if it thinks that .eh_frame should be read-write.  */
+/* { dg-require-named-sections "" } */
+const int a __attribute__((section (".eh_frame"))) = 1;
Index: gcc/testsuite/gcc.dg/20051207-1.c
===================================================================
--- gcc/testsuite/gcc.dg/20051207-1.c	(revision 0)
+++ gcc/testsuite/gcc.dg/20051207-1.c	(revision 0)
@@ -0,0 +1,5 @@
+/* GCC doesn't generate any .eh_frame data for this TU itself, so it
+   shouldn't warn about "a" conflicting with the built-in idea of
+   .eh_frame, even if it thinks that .eh_frame should be read-only.  */
+/* { dg-require-named-sections "" } */
+int a __attribute__((section (".eh_frame"))) = 1;
Index: gcc/testsuite/gcc.dg/20051207-3.c
===================================================================
--- gcc/testsuite/gcc.dg/20051207-3.c	(revision 0)
+++ gcc/testsuite/gcc.dg/20051207-3.c	(revision 0)
@@ -0,0 +1,7 @@
+/* GCC doesn't generate any .eh_frame data for this TU itself, so it
+   shouldn't warn about "a" conflicting with the built-in idea of
+   .eh_frame.  The warning therefore belongs on the second decl.  */
+/* { dg-options "-fno-unit-at-a-time" } */
+/* { dg-require-named-sections "" } */
+int a __attribute__((section (".eh_frame"))) = 1;
+const int b __attribute__((section (".eh_frame"))) = 1; /* { dg-error "section type conflict" } */
Index: gcc/dwarf2out.c
===================================================================
--- gcc/dwarf2out.c	(revision 108162)
+++ gcc/dwarf2out.c	(working copy)
@@ -113,42 +113,6 @@ dwarf2out_do_frame (void)
 #define PTR_SIZE (POINTER_SIZE / BITS_PER_UNIT)
 #endif
 
-/* Return the default value of eh_frame_section.  Note that this function
-   must appear outside the DWARF2_DEBUGGING_INFO || DWARF2_UNWIND_INFO
-   macro guards.  */
-
-section *
-default_eh_frame_section (void)
-{
-#ifdef EH_FRAME_SECTION_NAME
-  int flags;
-
-  if (EH_TABLES_CAN_BE_READ_ONLY)
-    {
-      int fde_encoding;
-      int per_encoding;
-      int lsda_encoding;
-
-      fde_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/1, /*global=*/0);
-      per_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/2, /*global=*/1);
-      lsda_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/0, /*global=*/0);
-      flags = (! flag_pic
-	       || ((fde_encoding & 0x70) != DW_EH_PE_absptr
-		   && (fde_encoding & 0x70) != DW_EH_PE_aligned
-		   && (per_encoding & 0x70) != DW_EH_PE_absptr
-		   && (per_encoding & 0x70) != DW_EH_PE_aligned
-		   && (lsda_encoding & 0x70) != DW_EH_PE_absptr
-		   && (lsda_encoding & 0x70) != DW_EH_PE_aligned))
-	      ? 0 : SECTION_WRITE;
-    }
-  else
-    flags = SECTION_WRITE;
-  return get_section (EH_FRAME_SECTION_NAME, flags, NULL);
-#else
-  return NULL;
-#endif
-}
-
 DEF_VEC_P(rtx);
 DEF_VEC_ALLOC_P(rtx,gc);
 
@@ -1993,10 +1957,44 @@ switch_to_eh_frame_section (void)
 {
   tree label;
 
+#ifdef EH_FRAME_SECTION_NAME
+  if (eh_frame_section == 0)
+    {
+      int flags;
+
+      if (EH_TABLES_CAN_BE_READ_ONLY)
+	{
+	  int fde_encoding;
+	  int per_encoding;
+	  int lsda_encoding;
+
+	  fde_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/1,
+						       /*global=*/0);
+	  per_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/2,
+						       /*global=*/1);
+	  lsda_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/0,
+							/*global=*/0);
+	  flags = ((! flag_pic
+		    || ((fde_encoding & 0x70) != DW_EH_PE_absptr
+			&& (fde_encoding & 0x70) != DW_EH_PE_aligned
+			&& (per_encoding & 0x70) != DW_EH_PE_absptr
+			&& (per_encoding & 0x70) != DW_EH_PE_aligned
+			&& (lsda_encoding & 0x70) != DW_EH_PE_absptr
+			&& (lsda_encoding & 0x70) != DW_EH_PE_aligned))
+		   ? 0 : SECTION_WRITE);
+	}
+      else
+	flags = SECTION_WRITE;
+      eh_frame_section = get_section (EH_FRAME_SECTION_NAME, flags, NULL);
+    }
+#endif
+
   if (eh_frame_section)
     switch_to_section (eh_frame_section);
   else
     {
+      /* We have no special eh_frame section.  Put the information in
+	 the data section and emit special labels to guide collect2.  */
       switch_to_section (data_section);
       label = get_file_function_name ('F');
       ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (PTR_SIZE));
Index: gcc/except.c
===================================================================
--- gcc/except.c	(revision 108162)
+++ gcc/except.c	(working copy)
@@ -3425,30 +3425,34 @@ sjlj_output_call_site_table (void)
   call_site_base += n;
 }
 
-/* Return the default value of exception_section.  */
+/* Switch to the section that should be used for exception tables.  */
 
-section *
-default_exception_section (void)
+static void
+switch_to_exception_section (void)
 {
-  if (targetm.have_named_sections)
+  if (exception_section == 0)
     {
-      int flags;
-
-      if (EH_TABLES_CAN_BE_READ_ONLY)
+      if (targetm.have_named_sections)
 	{
-	  int tt_format = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/0, /*global=*/1);
-	  
-	  flags = (! flag_pic
-		   || ((tt_format & 0x70) != DW_EH_PE_absptr
-		       && (tt_format & 0x70) != DW_EH_PE_aligned))
-	    ? 0 : SECTION_WRITE;
+	  int flags;
+
+	  if (EH_TABLES_CAN_BE_READ_ONLY)
+	    {
+	      int tt_format =
+		ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/0, /*global=*/1);
+	      flags = ((! flag_pic
+			|| ((tt_format & 0x70) != DW_EH_PE_absptr
+			    && (tt_format & 0x70) != DW_EH_PE_aligned))
+		       ? 0 : SECTION_WRITE);
+	    }
+	  else
+	    flags = SECTION_WRITE;
+	  exception_section = get_section (".gcc_except_table", flags, NULL);
 	}
       else
-	flags = SECTION_WRITE;
-      return get_section (".gcc_except_table", flags, NULL);
+	exception_section = flag_pic ? data_section : readonly_data_section;
     }
-  else
-    return flag_pic ? data_section : readonly_data_section;
+  switch_to_section (exception_section);
 }
 
 
@@ -3530,7 +3534,7 @@ output_function_exception_table (void)
   /* Note that varasm still thinks we're in the function's code section.
      The ".endp" directive that will immediately follow will take us back.  */
 #else
-  switch_to_section (exception_section);
+  switch_to_exception_section ();
 #endif
 
   have_tt_data = (VEC_length (tree, cfun->eh->ttype_data) > 0
Index: gcc/varasm.c
===================================================================
--- gcc/varasm.c	(revision 108162)
+++ gcc/varasm.c	(working copy)
@@ -155,12 +155,14 @@ static void mark_weak (tree);
 section *init_section;
 section *fini_section;
 
-/* The section that holds the main exception table.  */
+/* The section that holds the main exception table, when known.  The section
+   is set either by the target's init_sections hook or by the first call to
+   switch_to_exception_section.  */
 section *exception_section;
 
-/* The section that holds the DWARF2 frame unwind information.  If it
-   is null, we will place the unwind information in the data section
-   and emit special labels to guide collect2.  */
+/* The section that holds the DWARF2 frame unwind information, when known.
+   The section is set either by the target's init_sections hook or by the
+   first call to switch_to_eh_frame_section.  */
 section *eh_frame_section;
 
 /* asm_out_file's current section.  This is NULL if no section has yet
@@ -230,10 +232,11 @@ get_section (const char *name, unsigned 
   slot = (section **)
     htab_find_slot_with_hash (section_htab, name,
 			      htab_hash_string (name), INSERT);
+  flags |= SECTION_NAMED;
   if (*slot == NULL)
     {
       sect = ggc_alloc (sizeof (struct named_section));
-      sect->named.common.flags = flags | SECTION_NAMED;
+      sect->named.common.flags = flags;
       sect->named.name = ggc_strdup (name);
       sect->named.decl = decl;
       *slot = sect;
@@ -241,7 +244,7 @@ get_section (const char *name, unsigned 
   else
     {
       sect = *slot;
-      if ((sect->common.flags & ~(SECTION_DECLARED | SECTION_NAMED)) != flags
+      if ((sect->common.flags & ~SECTION_DECLARED) != flags
 	  && ((sect->common.flags | flags) & SECTION_OVERRIDE) == 0)
 	{
 	  /* Sanity check user variables for flag changes.  */
@@ -4868,10 +4871,6 @@ init_varasm_once (void)
 
   if (readonly_data_section == NULL)
     readonly_data_section = text_section;
-  if (exception_section == NULL)
-    exception_section = default_exception_section ();
-  if (eh_frame_section == NULL)
-    eh_frame_section = default_eh_frame_section ();
 }
 
 enum tls_model
Index: gcc/output.h
===================================================================
--- gcc/output.h	(revision 108162)
+++ gcc/output.h	(working copy)
@@ -384,12 +384,6 @@ extern int compute_reloc_for_constant (t
 /* Default target function prologue and epilogue assembler output.  */
 extern void default_function_pro_epilogue (FILE *, HOST_WIDE_INT);
 
-/* Return the default value of exception_section.  */
-extern section *default_exception_section (void);
-
-/* Return the default value of eh_frame_section.  */
-extern section *default_eh_frame_section (void);
-
 /* Default target hook that outputs nothing to a stream.  */
 extern void no_asm_to_stream (FILE *);
 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]