SHT_GROUP Support in binutils

Alan Modra amodra@bigpond.net.au
Mon Jan 7 15:51:00 GMT 2002


On Mon, Jan 07, 2002 at 01:03:14PM -0800, Jessica Han wrote:
> Alan,
>   I've noticed that you added SHT_GROUP support into binutils back in Oct
> 2001. Could you please tell me what else is on your list in this area? Are
> you going to provide complete COMDAT support specified by IA64-ABI?

Yes, although it may be a while before I do so.  I didn't do it at first,
because I wasn't certain of the requirements.  If you want to contribute
some code, please go ahead!

> It seems that gas relies on the assembly file to specify what sections form
> a group and what's the name of the group, are those information going to be
> generated by GCC? If so, do you know if anybody is working in this problem?

I started to make changes to gcc to emit the information, mainly with the
idea of splitting up dwarf debugging info and grouping it with a function's
code and data.  That fails because of an unfortunate choice in the sign
of one of the dwarf offset bytes - see
http://gcc.gnu.org/ml/gcc-bugs/2001-12/msg00314.html

I haven't done anything since then, as it appears gas will need a new
special reloc to handle the subtraction of two syms in dwarf data.
Current diff attached.  Watch out for the dwarf_cie change!  That's just
a temporary hack.

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre
-------------- next part --------------
Index: gcc/configure.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/configure.in,v
retrieving revision 1.573
diff -u -p -r1.573 configure.in
--- configure.in	2002/01/01 23:20:59	1.573
+++ configure.in	2002/01/06 13:03:08
@@ -1604,13 +1604,31 @@ EOF
 fi
 AC_MSG_RESULT($gcc_cv_as_eh_frame)
 
-AC_MSG_CHECKING(assembler section merging support)
+AC_MSG_CHECKING(assembler section group support)
+gcc_cv_as_sht_group=no
 gcc_cv_as_shf_merge=no
-if test x$gcc_cv_gas_major_version != x -a x$gcc_cv_gas_minor_version != x; then
-  if test "$gcc_cv_gas_major_version" -eq 2 -a "$gcc_cv_gas_minor_version" -ge 12 -o "$gcc_cv_gas_major_version" -gt 2 && grep 'obj_format = elf' ../gas/Makefile > /dev/null; then
-    gcc_cv_as_shf_merge=yes
-  fi
-elif test x$gcc_cv_as != x; then
+  if test x$gcc_cv_gas_major_version != x -a x$gcc_cv_gas_minor_version != x; then
+    if test "$gcc_cv_gas_major_version" -eq 2 -a "$gcc_cv_gas_minor_version" -ge 12 -o "$gcc_cv_gas_major_version" -gt 2 && grep 'obj_format = elf' ../gas/Makefile > /dev/null; then
+      gcc_cv_as_sht_group=yes
+      gcc_cv_as_shf_merge=yes
+    fi
+  elif test x$gcc_cv_as != x; then
+	# Check for both SHF_MERGE and SHT_GROUP
+	echo '.section .rodata.str, "aMSG", @progbits, 1, str' > conftest.s
+	if $gcc_cv_as --fatal-warnings -o conftest.o conftest.s > /dev/null 2>&1; then
+		gcc_cv_as_sht_group=yes
+		gcc_cv_as_shf_merge=yes
+	fi
+	rm -f conftest.s conftest.o
+fi
+if test x"$gcc_cv_as_sht_group" = xyes; then
+	AC_DEFINE(HAVE_GAS_SHT_GROUP, 1,
+[Define if your assembler supports section groups.])
+fi
+AC_MSG_RESULT($gcc_cv_as_sht_group)
+
+AC_MSG_CHECKING(assembler section merging support)
+if test $gcc_cv_as_shf_merge=no -a x$gcc_cv_as != x; then
 	# Check if we support SHF_MERGE sections
 	echo '.section .rodata.str, "aMS", @progbits, 1' > conftest.s
 	if $gcc_cv_as --fatal-warnings -o conftest.o conftest.s > /dev/null 2>&1; then
Index: gcc/dwarf2out.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/dwarf2out.c,v
retrieving revision 1.347
diff -u -p -r1.347 dwarf2out.c
--- dwarf2out.c	2002/01/06 03:51:09	1.347
+++ dwarf2out.c	2002/01/06 13:03:19
@@ -119,18 +119,26 @@ unsigned current_funcdef_number = 0;
    guards.  */
 
 void
-default_eh_frame_section ()
+default_eh_frame_section (section, group)
+     const char *section;
+     const char *group;
 {
-#ifdef EH_FRAME_SECTION_NAME
-  named_section_flags (EH_FRAME_SECTION_NAME, SECTION_WRITE);
-#else
-  tree label = get_file_function_name ('F');
+  if (section != NULL)
+    {
+      if (group != NULL)
+	named_section_group_flags (section, SECTION_WRITE, group);
+      else
+	named_section_flags (section, SECTION_WRITE);
+    }
+  else
+    {
+      tree label = get_file_function_name ('F');
 
-  data_section ();
-  ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (PTR_SIZE));
-  ASM_GLOBALIZE_LABEL (asm_out_file, IDENTIFIER_POINTER (label));
-  ASM_OUTPUT_LABEL (asm_out_file, IDENTIFIER_POINTER (label));
-#endif
+      data_section ();
+      ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (PTR_SIZE));
+      ASM_GLOBALIZE_LABEL (asm_out_file, IDENTIFIER_POINTER (label));
+      ASM_OUTPUT_LABEL (asm_out_file, IDENTIFIER_POINTER (label));
+    }
 }
 
 #if defined (DWARF2_DEBUGGING_INFO) || defined (DWARF2_UNWIND_INFO)
@@ -191,6 +199,7 @@ typedef struct dw_fde_struct
   const char *dw_fde_begin;
   const char *dw_fde_current_label;
   const char *dw_fde_end;
+  const char *sec_group;
   dw_cfi_ref dw_fde_cfi;
   unsigned funcdef_number;
   unsigned nothrow : 1;
@@ -317,6 +326,10 @@ static int output_indirect_string	PARAMS
 #define SECTION_ASM_OP	"\t.section\t"
 #endif
 
+#ifndef EH_FRAME_SECTION_NAME
+#define EH_FRAME_SECTION_NAME	NULL
+#endif
+
 #ifndef DEBUG_FRAME_SECTION
 #define DEBUG_FRAME_SECTION	".debug_frame"
 #endif
@@ -1777,6 +1790,7 @@ output_call_frame_info (for_eh)
   int fde_encoding = DW_EH_PE_absptr;
   int per_encoding = DW_EH_PE_absptr;
   int lsda_encoding = DW_EH_PE_absptr;
+  bool ingroup;
 
   /* If we don't have any functions we'll want to unwind out of, don't emit any
      EH unwind information.  */
@@ -1799,7 +1813,7 @@ output_call_frame_info (for_eh)
     app_enable ();
 
   if (for_eh)
-    (*targetm.asm_out.eh_frame_section) ();
+    (*targetm.asm_out.eh_frame_section) (EH_FRAME_SECTION_NAME, NULL);
   else
     named_section_flags (DEBUG_FRAME_SECTION, SECTION_DEBUG);
 
@@ -1921,6 +1935,7 @@ output_call_frame_info (for_eh)
   ASM_OUTPUT_LABEL (asm_out_file, l2);
 
   /* Loop through all of the FDE's.  */
+  ingroup = 0;
   for (i = 0; i < fde_table_in_use; i++)
     {
       fde = &fde_table[i];
@@ -1929,6 +1944,26 @@ output_call_frame_info (for_eh)
       if (for_eh && fde->nothrow && ! fde->uses_eh_lsda)
 	continue;
 
+      if (fde->sec_group != NULL || ingroup)
+	{
+	  const char *name;
+	  char buf[48];
+
+	  name = for_eh ? EH_FRAME_SECTION_NAME : DEBUG_FRAME_SECTION;
+	  ingroup = fde->sec_group != NULL;
+	  if (ingroup && name != NULL)
+	    {
+	      sprintf (buf, "%s%d", name, i);
+	      name = buf;
+	    }
+
+	  if (for_eh)
+	    (*targetm.asm_out.eh_frame_section) (name, fde->sec_group);
+	  else
+	    named_section_group_flags (name, SECTION_DEBUG,
+				       fde->sec_group);
+	}
+
       ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, FDE_LABEL, for_eh + i * 2);
       ASM_GENERATE_INTERNAL_LABEL (l1, FDE_AFTER_SIZE_LABEL, for_eh + i * 2);
       ASM_GENERATE_INTERNAL_LABEL (l2, FDE_END_LABEL, for_eh + i * 2);
@@ -1937,7 +1972,7 @@ output_call_frame_info (for_eh)
       ASM_OUTPUT_LABEL (asm_out_file, l1);
 
       if (for_eh)
-	dw2_asm_output_delta (4, l1, section_start_label, "FDE CIE offset");
+	dw2_asm_output_delta (4, section_start_label, l1, "FDE CIE offset");
       else
 	dw2_asm_output_offset (DWARF_OFFSET_SIZE, section_start_label,
 			       "FDE CIE offset");
@@ -2014,10 +2049,9 @@ output_call_frame_info (for_eh)
       ASM_OUTPUT_LABEL (asm_out_file, l2);
     }
 
-#ifndef EH_FRAME_SECTION_NAME
-  if (for_eh)
+  if (for_eh && EH_FRAME_SECTION_NAME == NULL)
     dw2_asm_output_data (4, 0, "End of Table");
-#endif
+
 #ifdef MIPS_DEBUGGING_INFO
   /* Work around Irix 6 assembler bug whereby labels at the end of a section
      get a value of 0.  Putting .align 0 after the label fixes it.  */
@@ -2089,6 +2123,12 @@ dwarf2out_begin_prologue (line, file)
   fde->funcdef_number = current_funcdef_number;
   fde->nothrow = current_function_nothrow;
   fde->uses_eh_lsda = cfun->uses_eh_lsda;
+  fde->sec_group = NULL;
+  if (targetm.have_section_groups
+      && flag_function_sections
+      && flag_data_sections)
+    fde->sec_group
+      = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
 
   args_size = old_args_size = 0;
 
Index: gcc/output.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/output.h,v
retrieving revision 1.92
diff -u -p -r1.92 output.h
--- output.h	2001/12/17 15:05:22	1.92
+++ output.h	2002/01/06 13:03:28
@@ -495,7 +495,7 @@ extern void default_function_pro_epilogu
 extern void default_exception_section	PARAMS ((void));
 
 /* Tell assembler to switch to the section for the EH frames.  */
-extern void default_eh_frame_section	PARAMS ((void));
+extern void default_eh_frame_section	PARAMS ((const char *, const char *));
 
 /* Default target hook that outputs nothing to a stream.  */
 extern void no_asm_to_stream PARAMS ((FILE *));
@@ -518,13 +518,20 @@ extern unsigned int get_named_section_fl
 extern bool set_named_section_flags	PARAMS ((const char *, unsigned int));
 extern void named_section_flags		PARAMS ((const char *, unsigned int));
 extern bool named_section_first_declaration PARAMS((const char *));
+extern void named_section_group_flags PARAMS ((const char *, unsigned int,
+					       const char *));
 
 union tree_node;
 extern unsigned int default_section_type_flags PARAMS ((union tree_node *,
 							const char *, int));
 
 extern void default_no_named_section PARAMS ((const char *, unsigned int));
+extern void default_no_named_section_group PARAMS ((const char *, unsigned int,
+						    const char *));
 extern void default_elf_asm_named_section PARAMS ((const char *, unsigned int));
+extern void default_elf_asm_named_section_group PARAMS ((const char *,
+							 unsigned int,
+							 const char *));
 extern void default_coff_asm_named_section PARAMS ((const char *,
 						    unsigned int));
 extern void default_pe_asm_named_section PARAMS ((const char *, unsigned int));
Index: gcc/target-def.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/target-def.h,v
retrieving revision 1.16
diff -u -p -r1.16 target-def.h
--- target-def.h	2001/12/17 15:05:22	1.16
+++ target-def.h	2002/01/06 13:03:28
@@ -98,6 +98,13 @@ Foundation, 59 Temple Place - Suite 330,
 #define TARGET_HAVE_NAMED_SECTIONS false
 #endif
 
+#ifdef TARGET_ASM_NAMED_SECTION_GROUP
+#define TARGET_HAVE_SECTION_GROUPS true
+#else
+#define TARGET_ASM_NAMED_SECTION_GROUP default_no_named_section_group
+#define TARGET_HAVE_SECTION_GROUPS false
+#endif
+
 #ifndef TARGET_ASM_EXCEPTION_SECTION
 #define TARGET_ASM_EXCEPTION_SECTION default_exception_section
 #endif
@@ -129,6 +136,7 @@ Foundation, 59 Temple Place - Suite 330,
 			TARGET_ASM_FUNCTION_BEGIN_EPILOGUE,	\
 			TARGET_ASM_FUNCTION_EPILOGUE,		\
 			TARGET_ASM_NAMED_SECTION,		\
+			TARGET_ASM_NAMED_SECTION_GROUP,		\
 			TARGET_ASM_EXCEPTION_SECTION,		\
 			TARGET_ASM_EH_FRAME_SECTION,		\
 			TARGET_ASM_CONSTRUCTOR,			\
@@ -190,5 +198,6 @@ Foundation, 59 Temple Place - Suite 330,
   TARGET_EXPAND_BUILTIN,			\
   TARGET_SECTION_TYPE_FLAGS,			\
   TARGET_HAVE_NAMED_SECTIONS,			\
+  TARGET_HAVE_SECTION_GROUPS,			\
   TARGET_HAVE_CTORS_DTORS			\
 }
Index: gcc/target.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/target.h,v
retrieving revision 1.18
diff -u -p -r1.18 target.h
--- target.h	2001/12/17 15:05:22	1.18
+++ target.h	2002/01/06 13:03:29
@@ -85,11 +85,15 @@ struct gcc_target
        specified by FLAGS.  */
     void (* named_section) PARAMS ((const char *, unsigned int));
 
+    /* As above, but section is a member of a group.  */
+    void (* named_section_group) PARAMS ((const char *, unsigned int,
+					  const char *));
+
     /* Switch to the section that holds the exception table.  */
     void (* exception_section) PARAMS ((void));
 
     /* Switch to the section that holds the exception frames.  */
-    void (* eh_frame_section) PARAMS ((void));
+    void (* eh_frame_section) PARAMS ((const char *, const char *));
 
     /* Output a constructor for a symbol with a given priority.  */
     void (* constructor) PARAMS ((rtx, int));
@@ -176,6 +180,9 @@ struct gcc_target
 
   /* True if arbitrary sections are supported.  */
   bool have_named_sections;
+
+  /* True if section groups are supported.  */
+  bool have_section_groups;
 
   /* True if "native" constructors and destructors are supported,
      false if we're using collect2 for the job.  */
Index: gcc/unwind-dw2-fde.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/unwind-dw2-fde.h,v
retrieving revision 1.5
diff -u -p -r1.5 unwind-dw2-fde.h
--- unwind-dw2-fde.h	2001/11/11 11:25:28	1.5
+++ unwind-dw2-fde.h	2002/01/06 13:03:29
@@ -149,7 +149,7 @@ typedef struct dwarf_fde fde;
 static inline struct dwarf_cie *
 get_cie (struct dwarf_fde *f)
 {
-  return (void *)&f->CIE_delta - f->CIE_delta;
+  return (void *)&f->CIE_delta + f->CIE_delta;
 }
 
 static inline fde *
Index: gcc/varasm.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/varasm.c,v
retrieving revision 1.242
diff -u -p -r1.242 varasm.c
--- varasm.c	2002/01/03 00:51:34	1.242
+++ varasm.c	2002/01/06 13:03:31
@@ -424,6 +424,32 @@ named_section_flags (name, flags)
     }
 }
 
+/* Tell assembler to change to section NAME belonging to group GROUP,
+   with attributes FLAGS.  */
+
+void
+named_section_group_flags (name, flags, group)
+     const char *name;
+     unsigned int flags;
+     const char *group;
+{
+  if (in_section != in_named || strcmp (name, in_named_name) != 0)
+    {
+      if (! set_named_section_flags (name, flags))
+	abort ();
+
+      (* targetm.asm_out.named_section_group) (name, flags, group);
+
+      if (flags & SECTION_FORGET)
+	in_section = no_section;
+      else
+	{
+	  in_named_name = ggc_strdup (name);
+	  in_section = in_named;
+	}
+    }
+}
+
 /* Tell assembler to change to section NAME for DECL.
    If DECL is NULL, just switch to section NAME.
    If NAME is NULL, get the name from DECL.
@@ -451,8 +477,18 @@ named_section (decl, name, reloc)
       error_with_decl (decl, "%s causes a section type conflict");
       flags = get_named_section_flags (name);
     }
+
+  if (targetm.have_section_groups
+      && flag_function_sections && flag_data_sections
+      && current_function_decl)
+    {
+      const char *group;
 
-  named_section_flags (name, flags);
+      group = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
+      named_section_group_flags (name, flags, group);
+    }
+  else
+    named_section_flags (name, flags);
 }
 
 /* If required, set DECL_SECTION_NAME to a unique name.  */
@@ -5112,7 +5148,8 @@ default_section_type_flags (decl, name, 
 }
 
 /* Output assembly to switch to section NAME with attribute FLAGS.
-   Four variants for common object file formats.  */
+   Four main variants for common object file formats, with section
+   group support thrown in for ELF.  */
 
 void
 default_no_named_section (name, flags)
@@ -5125,9 +5162,20 @@ default_no_named_section (name, flags)
 }
 
 void
-default_elf_asm_named_section (name, flags)
+default_no_named_section_group (name, flags, group)
+     const char *name ATTRIBUTE_UNUSED;
+     unsigned int flags ATTRIBUTE_UNUSED;
+     const char *group ATTRIBUTE_UNUSED;
+{
+  /* As per above.  */
+  abort ();
+}
+
+void
+default_elf_asm_named_section_group (name, flags, group)
      const char *name;
      unsigned int flags;
+     const char *group;
 {
   char flagchars[10], *f = flagchars;
   const char *type;
@@ -5150,6 +5198,8 @@ default_elf_asm_named_section (name, fla
     *f++ = 'M';
   if (flags & SECTION_STRINGS)
     *f++ = 'S';
+  if (group != NULL)
+    *f++ = 'G';
   *f = '\0';
 
   if (flags & SECTION_BSS)
@@ -5157,12 +5207,21 @@ default_elf_asm_named_section (name, fla
   else
     type = "progbits";
 
+  fprintf (asm_out_file, "\t.section\t%s,\"%s\",@%s",
+	   name, flagchars, type);
   if (flags & SECTION_ENTSIZE)
-    fprintf (asm_out_file, "\t.section\t%s,\"%s\",@%s,%d\n",
-	     name, flagchars, type, flags & SECTION_ENTSIZE);
-  else
-    fprintf (asm_out_file, "\t.section\t%s,\"%s\",@%s\n",
-	     name, flagchars, type);
+    fprintf (asm_out_file, ",%d", flags & SECTION_ENTSIZE);
+  if (group != NULL)
+    fprintf (asm_out_file, ",%s", group);
+  putc ('\n', asm_out_file);
+}
+
+void
+default_elf_asm_named_section (name, flags)
+     const char *name;
+     unsigned int flags;
+{
+  default_elf_asm_named_section_group (name, flags, NULL);
 }
 
 void
Index: gcc/config/elfos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/elfos.h,v
retrieving revision 1.45
diff -u -p -r1.45 elfos.h
--- elfos.h	2001/12/18 10:42:32	1.45
+++ elfos.h	2002/01/06 13:03:33
@@ -322,6 +322,11 @@ const_section ()						\
 /* Switch into a generic section.  */
 #define TARGET_ASM_NAMED_SECTION  default_elf_asm_named_section
 
+#ifdef HAVE_GAS_SHT_GROUP
+/* Switch into a generic section belonging to a group.  */
+#define TARGET_ASM_NAMED_SECTION_GROUP  default_elf_asm_named_section_group
+#endif
+
 /* A C statement or statements to switch to the appropriate
    section for output of RTX in mode MODE.  RTX is some kind
    of constant in RTL.  The argument MODE is redundant except
Index: gcc/doc/tm.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/tm.texi,v
retrieving revision 1.86
diff -u -p -r1.86 tm.texi
--- tm.texi	2002/01/03 00:51:35	1.86
+++ tm.texi	2002/01/06 13:03:49
@@ -5799,6 +5799,19 @@ precede any Objective-C object definitio
 
 @deftypefn {Target Hook} bool TARGET_HAVE_NAMED_SECTIONS
 This flag is true if the target supports @code{TARGET_ASM_NAMED_SECTION}.
+@end deftypefn
+
+@deftypefn {Target Hook} void TARGET_ASM_NAMED_SECTION_GROUP (const char *@var{name}, unsigned int @var{flags}, const char *@var{group})
+Output assembly directives to switch to section @var{name}, and if doing
+so for the first time, define section @var{name} to be a member of group
+@var{group}.  The section should have attributes as specified by
+@var{flags}, which is a bit mask of the @code{SECTION_*} flags defined
+in @file{output.h}.
+@end deftypefn
+
+@deftypefn {Target Hook} bool TARGET_HAVE_SECTION_GROUPS
+This flag is true if the target supports
+@code{TARGET_ASM_NAMED_SECTION_GROUPS}.
 @end deftypefn
 
 @deftypefn {Target Hook} {unsigned int} TARGET_SECTION_TYPE_FLAGS (tree @var{decl}, const char *@var{name}, int @var{reloc})


More information about the Binutils mailing list