This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils 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]

[RFA] CFI improvements


Hi,
the attached patch adds some new features to the CFI engine:
- register names can start with '%' as requested by GCC guys.
- CIEs are not duplicated anymore but instead reused if possible.
- tc_cfi_init() is moved from main() to dot_cfi_startproc() - otherwise it didn't set correct values on amd64 because the output format wasn't yet known in main().
- .cfi_startproc takes optional parameter 'simple' that disables emitting of architecture-dependent initial instructions.
- testsuite is modified to pass with CIE optimalization.


I hope I haven't introduce any new C89 incompatibility (sorry for that one).

Comments? Approvals?

Michal Ludvig
--
* SuSE CR, s.r.o     * mludvig@suse.cz
* (+420) 296.545.373 * http://www.suse.cz
2003-05-20  Michal Ludvig  <mludvig@suse.cz>

	* as.c (main): Remove tc_cfi_init().
	* dw2gencfi.c (cfi_parse_arg): Allow regnames beginning 
	with '%'.
	(cfi_make_insn): Handle CFA_register.
	(cfi_output_insn): Ditto.
	(dot_cfi): Ditto.
	(cfi_get_label): Add 'simple' modifier to .cfi_startproc.
	(dot_cfi_endproc): Reuse already emitted CIEs.
	* testsuite/gas/cfi/cfi-i386.d: New pattern.
	* testsuite/gas/cfi/cfi-x86-64.d: Ditto.

Index: as.c
===================================================================
RCS file: /cvs/src/src/gas/as.c,v
retrieving revision 1.43
diff -u -p -r1.43 as.c
--- as.c	20 May 2003 07:58:06 -0000	1.43
+++ as.c	20 May 2003 12:04:30 -0000
@@ -837,10 +837,6 @@ main (argc, argv)
   bfd_set_error_program_name (myname);
 #endif
 
-#ifdef TARGET_USE_CFIPOP
-  tc_cfi_init ();
-#endif
-
 #ifdef USE_EMULATIONS
   select_emulation_mode (argc, argv);
 #endif
Index: dw2gencfi.c
===================================================================
RCS file: /cvs/src/src/gas/dw2gencfi.c,v
retrieving revision 1.2
diff -u -p -r1.2 dw2gencfi.c
--- dw2gencfi.c	20 May 2003 11:35:45 -0000	1.2
+++ dw2gencfi.c	20 May 2003 12:04:30 -0000
@@ -23,24 +23,55 @@
 #include "as.h"
 #include "dw2gencfi.h"
 
+struct cie_entry
+{
+  unsigned long offset;
+  size_t size;
+  void *data;
+  struct cie_entry *next;
+};
+
+struct cfi_data
+{
+  enum cfi_insn insn;
+  long param[2];
+  struct cfi_data *next;
+};
+
+struct cfi_info
+{
+  addressT start_address;
+  addressT end_address;
+  addressT last_address;
+  const char *labelname;
+  struct cfi_data *data;
+  struct cfi_info *next;
+};
+
+/* Current open CFI entry.  */
+static struct cfi_info *cfi_info;
+
+/* List of CIEs so that they could be reused.  */
+static struct cie_entry *cie_root;
+
 /* Current target config.  */
 static struct cfi_config current_config;
 
 /* This is the main entry point to the CFI machinery.  */
 static void dot_cfi (int arg);
 
-const pseudo_typeS cfi_pseudo_table[] =
-  {
-    { "cfi_verbose", dot_cfi, CFI_verbose },
-    { "cfi_startproc", dot_cfi, CFI_startproc },
-    { "cfi_endproc", dot_cfi, CFI_endproc },
-    { "cfi_def_cfa", dot_cfi, CFA_def_cfa },
-    { "cfi_def_cfa_register", dot_cfi, CFA_def_cfa_register },
-    { "cfi_def_cfa_offset", dot_cfi, CFA_def_cfa_offset },
-    { "cfi_adjust_cfa_offset", dot_cfi, CFI_adjust_cfa_offset },
-    { "cfi_offset", dot_cfi, CFA_offset },
-    { NULL, NULL, 0 }
-  };
+const pseudo_typeS cfi_pseudo_table[] = {
+  {"cfi_verbose", dot_cfi, CFI_verbose},
+  {"cfi_startproc", dot_cfi, CFI_startproc},
+  {"cfi_endproc", dot_cfi, CFI_endproc},
+  {"cfi_def_cfa", dot_cfi, CFA_def_cfa},
+  {"cfi_def_cfa_register", dot_cfi, CFA_def_cfa_register},
+  {"cfi_def_cfa_offset", dot_cfi, CFA_def_cfa_offset},
+  {"cfi_adjust_cfa_offset", dot_cfi, CFI_adjust_cfa_offset},
+  {"cfi_offset", dot_cfi, CFA_offset},
+  {"cfi_register", dot_cfi, CFA_register},
+  {NULL, NULL, 0}
+};
 
 static const char *
 cfi_insn_str (enum cfi_insn insn)
@@ -90,25 +121,6 @@ cfi_insn_str (enum cfi_insn insn)
   return "CFA_unknown";
 }
 
-struct cfi_data
-{
-  enum cfi_insn insn;
-  long param[2];
-  struct cfi_data *next;
-};
-
-struct cfi_info
-{
-  addressT start_address;
-  addressT end_address;
-  addressT last_address;
-  const char *labelname;
-  struct cfi_data *data;
-  struct cfi_info *next;
-};
-
-static struct cfi_info *cfi_info;
-
 static struct cfi_data *
 alloc_cfi_data (void)
 {
@@ -138,7 +150,9 @@ cfi_parse_arg (long *param, int resolver
       retval = 1;
     }
 #ifdef tc_regname_to_dw2regnum
-  else if (resolvereg && (is_name_beginner (*input_line_pointer)))
+  else if (resolvereg && ((is_name_beginner (*input_line_pointer)) ||
+			  (*input_line_pointer == '%' &&
+			   is_name_beginner (*(++input_line_pointer)))))
     {
       char *name, c, *p;
 
@@ -271,6 +285,21 @@ cfi_make_insn (int arg)
 	}
       break;
 
+    case CFA_register:
+      if (cfi_parse_reg (&param[0]) < 0)
+	{
+	  as_bad (_("first argument to %s is not a register"),
+		  cfi_insn_str (arg));
+	  return;
+	}
+      if (cfi_parse_reg (&param[1]) < 0)
+	{
+	  as_bad (_("second argument to %s is not a register"),
+		  cfi_insn_str (arg));
+	  return;
+	}
+      break;
+
       /* Instructions that take one register argument.  */
     case CFA_def_cfa_register:
       if (cfi_parse_reg (&param[0]) < 0)
@@ -336,20 +365,33 @@ cfi_get_label (void)
 static void
 dot_cfi_startproc (void)
 {
+  char *simple = "simple";
+
   if (cfi_info)
     {
       as_bad (_("previous CFI entry not closed (missing .cfi_endproc)"));
       return;
     }
 
+#if defined(TARGET_USE_CFIPOP)
+  /* Because this file is linked even for architectures that 
+     don't use CFI, we must wrap this call.  */
+  if (current_config.addr_length == 0)
+    tc_cfi_init ();
+#endif
+
   cfi_info = alloc_cfi_info ();
 
   cfi_info->start_address = frag_now_fix ();
   cfi_info->last_address = cfi_info->start_address;
   cfi_info->labelname = S_GET_NAME (cfi_get_label ());
 
+  SKIP_WHITESPACE ();
 #ifdef tc_cfi_frame_initial_instructions
-  tc_cfi_frame_initial_instructions ();
+  if (strncmp (simple, input_line_pointer, strlen (simple)) != 0)
+    tc_cfi_frame_initial_instructions ();
+  else
+    input_line_pointer += strlen (simple);
 #endif
 }
 
@@ -357,6 +399,8 @@ dot_cfi_startproc (void)
   ((insn >= CFA_set_loc && insn <= CFA_advance_loc4)		\
    || insn == CFA_advance_loc)
 
+/* Output CFI instructions to the file.  */
+
 enum data_types
   {
     t_ascii = 0,
@@ -368,8 +412,6 @@ enum data_types
     t_sleb128 = 0x11
   };
 
-/* Output CFI instructions to the file.  */
-
 static int
 output_data (char **p, unsigned long *size, enum data_types type, long value)
 {
@@ -393,7 +435,8 @@ output_data (char **p, unsigned long *si
       ret_size = 8;
       break;
     default:
-      as_warn (_("unknown type %d"), type);
+      /* This should never happen - throw an internal error.  */
+      as_fatal (_("unknown type %d"), type);
       return 0;
     }
 
@@ -434,7 +477,7 @@ output_data (char **p, unsigned long *si
 		value);
       break;
     default:
-      as_warn ("unknown type %d", type);
+      as_fatal (_("unknown type %d"), type);
       return 0;
     }
 
@@ -486,7 +529,8 @@ cfi_output_insn (struct cfi_data *data, 
 
     case CFA_def_cfa:
       if (verbose)
-	printf ("\t# CFA_def_cfa(%ld,%ld)\n", data->param[0], data->param[1]);
+	printf ("\t# CFA_def_cfa(%ld,%ld)\n",
+		data->param[0], data->param[1]);
       output_data (pbuf, buf_size, t_byte, CFA_def_cfa);
       output_data (pbuf, buf_size, t_uleb128, data->param[0]);
       output_data (pbuf, buf_size, t_uleb128, data->param[1]);
@@ -518,6 +562,15 @@ cfi_output_insn (struct cfi_data *data, 
 		   data->param[1] / current_config.data_align);
       break;
 
+    case CFA_register:
+      if (verbose)
+	printf ("\t# %s(%ld,%ld)\n", cfi_insn_str (data->insn),
+		data->param[0], data->param[1]);
+      output_data (pbuf, buf_size, t_byte, CFA_register);
+      output_data (pbuf, buf_size, t_uleb128, data->param[0]);
+      output_data (pbuf, buf_size, t_uleb128, data->param[1]);
+      break;
+
     case CFA_nop:
       if (verbose)
 	printf ("\t# CFA_nop\n");
@@ -538,9 +591,10 @@ static void
 dot_cfi_endproc (void)
 {
   struct cfi_data *data_ptr;
+  struct cie_entry *cie_ptr;
   char *cie_buf, *fde_buf, *pbuf, *where;
-  unsigned long  buf_size, cie_size, fde_size, last_cie_offset;
-  unsigned long	fde_initloc_offset, fde_len_offset;
+  unsigned long buf_size, cie_size, fde_size, last_cie_offset;
+  unsigned long fde_initloc_offset, fde_len_offset, fde_offset;
   void *saved_seg, *cfi_seg;
   expressionS exp;
 
@@ -598,8 +653,51 @@ dot_cfi_endproc (void)
 
   /* OK, we built the CIE. Let's write it to the file...  */
   last_cie_offset = frag_now_fix ();
-  where = (unsigned char *) frag_more (cie_size);
-  memcpy (where, cie_buf, cie_size);
+
+  /* Check if we have already emitted the exactly same CIE. 
+     If yes then use its offset instead and don't put out 
+     the new one.  */
+  cie_ptr = cie_root;
+  while (cie_ptr)
+    {
+      if (cie_ptr->size == cie_size - 4 &&
+	  memcmp (cie_ptr->data, cie_buf + 4, cie_ptr->size) == 0)
+	break;
+      cie_ptr = cie_ptr->next;
+    }
+
+  /* If we have found the same CIE, use it...  */
+  if (cie_ptr)
+    {
+      if (verbose)
+	printf ("# Duplicate CIE found. Previous is at offset %lu\n",
+		cie_ptr->offset);
+      last_cie_offset = cie_ptr->offset;
+    }
+  else
+    {
+      /* Otherwise join this CIE to the list.  */
+      where = (unsigned char *) frag_more (cie_size);
+      memcpy (where, cie_buf, cie_size);
+      if (cie_root)
+	{
+	  cie_ptr = cie_root;
+	  while (cie_ptr->next)
+	    cie_ptr = cie_ptr->next;
+	  cie_ptr->next = calloc (sizeof (struct cie_entry), 1);
+	  cie_ptr = cie_ptr->next;
+	}
+      else
+	{
+	  cie_root = calloc (sizeof (struct cie_entry), 1);
+	  cie_ptr = cie_root;
+	}
+
+      cie_ptr->size = cie_size - 4;
+      cie_ptr->data = calloc (cie_ptr->size, 1);
+      cie_ptr->offset = last_cie_offset;
+      memcpy (cie_ptr->data, cie_buf + 4, cie_ptr->size);
+    }
 
   /* Clean up.  */
   free (cie_buf);
@@ -609,6 +707,9 @@ dot_cfi_endproc (void)
   pbuf = fde_buf;
   buf_size = 1024;
 
+  /* Offset of this FDE in current fragment.  */
+  fde_offset = frag_now_fix ();
+
   if (verbose)
     {
       printf ("# FDE: start=0x%lx, end=0x%lx, delta=%d\n",
@@ -623,10 +724,10 @@ dot_cfi_endproc (void)
   buf_size -= 4;
 
   /* CIE pointer - offset from here.  */
-  output_data (&pbuf, &buf_size, t_long, cie_size + 4);
+  output_data (&pbuf, &buf_size, t_long, fde_offset - last_cie_offset + 4);
 
   /* FDE initial location - this must be set relocatable!  */
-  fde_initloc_offset = pbuf - fde_buf;
+  fde_initloc_offset = pbuf - fde_buf + fde_offset;
   output_data (&pbuf, &buf_size, current_config.addr_length,
 	       cfi_info->start_address);
 
@@ -648,9 +749,6 @@ dot_cfi_endproc (void)
   buf_size = 4;
   output_data (&pbuf, &buf_size, t_long, fde_size - 4);
 
-  /* Adjust initloc offset.  */
-  fde_initloc_offset += frag_now_fix ();
-
   /* Copy FDE to objfile.  */
   where = (unsigned char *) frag_more (fde_size);
   memcpy (where, fde_buf, fde_size);
@@ -691,6 +789,7 @@ dot_cfi (int arg)
     case CFA_def_cfa_register:
     case CFA_def_cfa_offset:
     case CFA_offset:
+    case CFA_register:
     case CFI_adjust_cfa_offset:
       cfi_make_insn (arg);
       break;
Index: testsuite/gas/cfi/cfi-i386.d
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/cfi/cfi-i386.d,v
retrieving revision 1.1
diff -u -p -r1.1 cfi-i386.d
--- testsuite/gas/cfi/cfi-i386.d	20 May 2003 08:01:19 -0000	1.1
+++ testsuite/gas/cfi/cfi-i386.d	20 May 2003 12:04:30 -0000
@@ -1,6 +1,5 @@
 #readelf: -wf
 #name: CFI on i386
-
 The section .eh_frame contains:
 
 00000000 00000010 00000000 CIE
@@ -22,19 +21,7 @@ The section .eh_frame contains:
   DW_CFA_def_cfa_offset: 4
   DW_CFA_nop
 
-0000002c 00000010 00000000 CIE
-  Version:               1
-  Augmentation:          ""
-  Code alignment factor: 1
-  Data alignment factor: -4
-  Return address column: 8
-
-  DW_CFA_def_cfa: r7 ofs 4
-  DW_CFA_offset: r8 at cfa-4
-  DW_CFA_nop
-  DW_CFA_nop
-
-00000040 00000018 00000018 FDE cie=0000002c pc=00000012..0000001f
+0000002c 00000018 00000030 FDE cie=00000000 pc=00000012..0000001f
   DW_CFA_advance_loc: 1 to 00000013
   DW_CFA_def_cfa_offset: 8
   DW_CFA_offset: r6 at cfa-8
@@ -44,56 +31,20 @@ The section .eh_frame contains:
   DW_CFA_def_cfa_reg: r7
   DW_CFA_nop
 
-0000005c 00000010 00000000 CIE
-  Version:               1
-  Augmentation:          ""
-  Code alignment factor: 1
-  Data alignment factor: -4
-  Return address column: 8
-
-  DW_CFA_def_cfa: r7 ofs 4
-  DW_CFA_offset: r8 at cfa-4
-  DW_CFA_nop
-  DW_CFA_nop
-
-00000070 00000014 00000018 FDE cie=0000005c pc=0000001f..0000002f
+00000048 00000014 0000004c FDE cie=00000000 pc=0000001f..0000002f
   DW_CFA_advance_loc: 2 to 00000021
   DW_CFA_def_cfa_reg: r1
   DW_CFA_advance_loc: 13 to 0000002e
   DW_CFA_def_cfa: r7 ofs 4
   DW_CFA_nop
 
-00000088 00000010 00000000 CIE
-  Version:               1
-  Augmentation:          ""
-  Code alignment factor: 1
-  Data alignment factor: -4
-  Return address column: 8
-
-  DW_CFA_def_cfa: r7 ofs 4
-  DW_CFA_offset: r8 at cfa-4
-  DW_CFA_nop
-  DW_CFA_nop
-
-0000009c 00000010 00000018 FDE cie=00000088 pc=0000002f..00000035
+00000060 00000010 00000064 FDE cie=00000000 pc=0000002f..00000035
   DW_CFA_nop
   DW_CFA_nop
   DW_CFA_nop
   DW_CFA_nop
 
-000000b0 00000010 00000000 CIE
-  Version:               1
-  Augmentation:          ""
-  Code alignment factor: 1
-  Data alignment factor: -4
-  Return address column: 8
-
-  DW_CFA_def_cfa: r7 ofs 4
-  DW_CFA_offset: r8 at cfa-4
-  DW_CFA_nop
-  DW_CFA_nop
-
-000000c4 00000010 00000018 FDE cie=000000b0 pc=00000035..00000044
+00000074 00000010 00000078 FDE cie=00000000 pc=00000035..00000044
   DW_CFA_nop
   DW_CFA_nop
   DW_CFA_nop
Index: testsuite/gas/cfi/cfi-x86_64.d
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/cfi/cfi-x86_64.d,v
retrieving revision 1.1
diff -u -p -r1.1 cfi-x86_64.d
--- testsuite/gas/cfi/cfi-x86_64.d	20 May 2003 08:01:19 -0000	1.1
+++ testsuite/gas/cfi/cfi-x86_64.d	20 May 2003 12:04:30 -0000
@@ -26,23 +26,7 @@ The section .eh_frame contains:
   DW_CFA_def_cfa_offset: 8
   DW_CFA_nop
 
-00000038 00000014 00000000 CIE
-  Version:               1
-  Augmentation:          ""
-  Code alignment factor: 1
-  Data alignment factor: -8
-  Return address column: 16
-
-  DW_CFA_def_cfa: r7 ofs 8
-  DW_CFA_offset: r16 at cfa-8
-  DW_CFA_nop
-  DW_CFA_nop
-  DW_CFA_nop
-  DW_CFA_nop
-  DW_CFA_nop
-  DW_CFA_nop
-
-00000050 00000024 0000001c FDE cie=00000038 pc=00000000..0000000f
+00000038 00000024 0000003c FDE cie=00000000 pc=00000000..0000000f
   DW_CFA_advance_loc: 1 to 00000001
   DW_CFA_def_cfa_offset: 16
   DW_CFA_offset: r6 at cfa-16
@@ -55,23 +39,7 @@ The section .eh_frame contains:
   DW_CFA_nop
   DW_CFA_nop
 
-00000078 00000014 00000000 CIE
-  Version:               1
-  Augmentation:          ""
-  Code alignment factor: 1
-  Data alignment factor: -8
-  Return address column: 16
-
-  DW_CFA_def_cfa: r7 ofs 8
-  DW_CFA_offset: r16 at cfa-8
-  DW_CFA_nop
-  DW_CFA_nop
-  DW_CFA_nop
-  DW_CFA_nop
-  DW_CFA_nop
-  DW_CFA_nop
-
-00000090 0000001c 0000001c FDE cie=00000078 pc=00000000..00000013
+00000060 0000001c 00000064 FDE cie=00000000 pc=00000000..00000013
   DW_CFA_advance_loc: 3 to 00000003
   DW_CFA_def_cfa_reg: r12
   DW_CFA_advance_loc: 15 to 00000012
@@ -79,23 +47,7 @@ The section .eh_frame contains:
   DW_CFA_nop
   DW_CFA_nop
 
-000000b0 00000014 00000000 CIE
-  Version:               1
-  Augmentation:          ""
-  Code alignment factor: 1
-  Data alignment factor: -8
-  Return address column: 16
-
-  DW_CFA_def_cfa: r7 ofs 8
-  DW_CFA_offset: r16 at cfa-8
-  DW_CFA_nop
-  DW_CFA_nop
-  DW_CFA_nop
-  DW_CFA_nop
-  DW_CFA_nop
-  DW_CFA_nop
-
-000000c8 0000001c 0000001c FDE cie=000000b0 pc=00000000..00000006
+00000080 0000001c 00000084 FDE cie=00000000 pc=00000000..00000006
   DW_CFA_nop
   DW_CFA_nop
   DW_CFA_nop
@@ -105,23 +57,7 @@ The section .eh_frame contains:
   DW_CFA_nop
   DW_CFA_nop
 
-000000e8 00000014 00000000 CIE
-  Version:               1
-  Augmentation:          ""
-  Code alignment factor: 1
-  Data alignment factor: -8
-  Return address column: 16
-
-  DW_CFA_def_cfa: r7 ofs 8
-  DW_CFA_offset: r16 at cfa-8
-  DW_CFA_nop
-  DW_CFA_nop
-  DW_CFA_nop
-  DW_CFA_nop
-  DW_CFA_nop
-  DW_CFA_nop
-
-00000100 0000001c 0000001c FDE cie=000000e8 pc=00000000..00000012
+000000a0 0000001c 000000a4 FDE cie=00000000 pc=00000000..00000012
   DW_CFA_nop
   DW_CFA_nop
   DW_CFA_nop

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