[V1,6/9] gas: scfidw2gen: new functionality to prepapre for SCFI

Message ID 20231026191337.3872149-7-indu.bhagat@oracle.com
State New
Headers
Series Synthesize CFI for hand-written asm |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_binutils_build--master-arm fail Testing failed
linaro-tcwg-bot/tcwg_binutils_build--master-aarch64 fail Testing failed
linaro-tcwg-bot/tcwg_binutils_check--master-aarch64 pending Build did not complete; will be retriggered
linaro-tcwg-bot/tcwg_binutils_check--master-arm pending Build did not complete; will be retriggered

Commit Message

Indu Bhagat Oct. 26, 2023, 7:13 p.m. UTC
  [Changes from the RFC patch set]
  - scfidw2gen.c now defines its own set of handlers.  For many of those
    CFI directives, we simply warn ("Warning: --scfi=all ignores some
    user-specified CFI directives") and return.
  - The above-mentioned warning is issued only once per file.
  - The advantage of adding new set of handlers in scfidwgen.c is that
    dw2gencfi now does not need to add a condition for each handler to
    simply return if --scfi is in effect (the latter was the approach in
    the RFC patch set.)
[End of changes]

Define a new set of handlers for CFI directives for the purpose of SCFI.
The SCFI machinery ignores many of the user-specified CFI direcives when
--scfi=all is in effect.  The following CFI directives, however, are not
ignored:
      - .cfi_sections  (To be handled).
      - .cfi_label
      - .cfi_signal_frame

Since the option --scfi=inline still needs to be worked out, the
implementation in scfidw2gen may need to be adjusted later.

gas/
	* Makefile.am: Add new files to GAS_CFILES and HFILES.
	* Makefile.in: Likewise.
	* gas/read.c (scfi_pop_insert): New define.
	(pobegin): Use the SCFI handlers.
	* scfidw2gen.c: New file.
	* scfidw2gen.h: New file.
---
 gas/Makefile.am  |   2 +
 gas/Makefile.in  |   9 +-
 gas/read.c       |  17 ++-
 gas/scfidw2gen.c | 325 +++++++++++++++++++++++++++++++++++++++++++++++
 gas/scfidw2gen.h |  37 ++++++
 5 files changed, 385 insertions(+), 5 deletions(-)
 create mode 100644 gas/scfidw2gen.c
 create mode 100644 gas/scfidw2gen.h
  

Patch

diff --git a/gas/Makefile.am b/gas/Makefile.am
index 0e98ca3ec85..e174305ca62 100644
--- a/gas/Makefile.am
+++ b/gas/Makefile.am
@@ -93,6 +93,7 @@  GAS_CFILES = \
 	read.c \
 	remap.c \
 	sb.c \
+	scfidw2gen.c \
 	sframe-opt.c \
 	stabs.c \
 	subsegs.c \
@@ -128,6 +129,7 @@  HFILES = \
 	output-file.h \
 	read.h \
 	sb.h \
+	scfidw2gen.h \
 	subsegs.h \
 	symbols.h \
 	tc.h \
diff --git a/gas/Makefile.in b/gas/Makefile.in
index fae3a47c144..87428bc46b8 100644
--- a/gas/Makefile.in
+++ b/gas/Makefile.in
@@ -170,9 +170,9 @@  am__objects_1 = app.$(OBJEXT) as.$(OBJEXT) atof-generic.$(OBJEXT) \
 	hash.$(OBJEXT) input-file.$(OBJEXT) input-scrub.$(OBJEXT) \
 	listing.$(OBJEXT) literal.$(OBJEXT) macro.$(OBJEXT) \
 	messages.$(OBJEXT) output-file.$(OBJEXT) read.$(OBJEXT) \
-	remap.$(OBJEXT) sb.$(OBJEXT) sframe-opt.$(OBJEXT) \
-	stabs.$(OBJEXT) subsegs.$(OBJEXT) symbols.$(OBJEXT) \
-	write.$(OBJEXT)
+	remap.$(OBJEXT) sb.$(OBJEXT) scfidw2gen.$(OBJEXT) \
+	sframe-opt.$(OBJEXT) stabs.$(OBJEXT) subsegs.$(OBJEXT) \
+	symbols.$(OBJEXT) write.$(OBJEXT)
 am_as_new_OBJECTS = $(am__objects_1)
 am__dirstamp = $(am__leading_dot)dirstamp
 as_new_OBJECTS = $(am_as_new_OBJECTS)
@@ -581,6 +581,7 @@  GAS_CFILES = \
 	read.c \
 	remap.c \
 	sb.c \
+	scfidw2gen.c \
 	sframe-opt.c \
 	stabs.c \
 	subsegs.c \
@@ -615,6 +616,7 @@  HFILES = \
 	output-file.h \
 	read.h \
 	sb.h \
+	scfidw2gen.h \
 	subsegs.h \
 	symbols.h \
 	tc.h \
@@ -1337,6 +1339,7 @@  distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/read.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/remap.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sb.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/scfidw2gen.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sframe-opt.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stabs.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/subsegs.Po@am__quote@
diff --git a/gas/read.c b/gas/read.c
index 826156db3fe..9068072493a 100644
--- a/gas/read.c
+++ b/gas/read.c
@@ -38,6 +38,7 @@ 
 #include "obstack.h"
 #include "ecoff.h"
 #include "dw2gencfi.h"
+#include "scfidw2gen.h"
 #include "codeview.h"
 #include "wchar.h"
 #include "filenames.h"
@@ -587,6 +588,10 @@  pop_insert (const pseudo_typeS *table)
 #define cfi_pop_insert()	pop_insert(cfi_pseudo_table)
 #endif
 
+#ifndef scfi_pop_insert
+#define scfi_pop_insert()	pop_insert(scfi_pseudo_table)
+#endif
+
 static void
 pobegin (void)
 {
@@ -607,8 +612,16 @@  pobegin (void)
   pop_insert (potable);
 
   /* Now CFI ones.  */
-  pop_table_name = "cfi";
-  cfi_pop_insert ();
+  if (flag_synth_cfi)
+    {
+      pop_table_name = "scfi";
+      scfi_pop_insert ();
+    }
+  else
+    {
+      pop_table_name = "cfi";
+      cfi_pop_insert ();
+    }
 }
 
 static void
diff --git a/gas/scfidw2gen.c b/gas/scfidw2gen.c
new file mode 100644
index 00000000000..613ef919a1e
--- /dev/null
+++ b/gas/scfidw2gen.c
@@ -0,0 +1,325 @@ 
+/* scfidw2gen.c - Support for emission of synthesized Dwarf2 CFI.
+   Copyright (C) 2003-2023 Free Software Foundation, Inc.
+
+   This file is part of GAS, the GNU Assembler.
+
+   GAS is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GAS is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GAS; see the file COPYING.  If not, write to the Free
+   Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
+   02110-1301, USA.  */
+
+#include "as.h"
+#include "ginsn.h"
+#include "scfi.h"
+#include "dw2gencfi.h"
+#include "subsegs.h"
+#include "scfidw2gen.h"
+
+#if defined (TARGET_USE_SCFI) && defined (TARGET_USE_GINSN)
+
+static int scfi_ignore_warn_once = 0;
+
+static void dot_scfi_sections (int);
+static void dot_scfi_ignore (int);
+static void dot_scfi (int);
+
+const pseudo_typeS scfi_pseudo_table[] =
+  {
+    { "cfi_sections", dot_scfi_sections, 0 }, /* No ignore.  */
+    { "cfi_startproc", dot_scfi_ignore, 0 },
+    { "cfi_endproc", dot_scfi_ignore, 0 },
+    { "cfi_fde_data", dot_scfi_ignore, 0 },
+    { "cfi_def_cfa", dot_scfi_ignore, 0 },
+    { "cfi_def_cfa_register", dot_scfi_ignore, 0 },
+    { "cfi_def_cfa_offset", dot_scfi_ignore, 0 },
+    { "cfi_adjust_cfa_offset", dot_scfi_ignore, 0 },
+    { "cfi_offset", dot_scfi_ignore, 0 },
+    { "cfi_rel_offset", dot_scfi_ignore, 0 },
+    { "cfi_register", dot_scfi_ignore, 0 },
+    { "cfi_return_column", dot_scfi_ignore, 0 },
+    { "cfi_restore", dot_scfi_ignore, 0 },
+    { "cfi_undefined", dot_scfi_ignore, 0 },
+    { "cfi_same_value", dot_scfi_ignore, 0 },
+    { "cfi_remember_state", dot_scfi_ignore, 0 },
+    { "cfi_restore_state", dot_scfi_ignore, 0 },
+    { "cfi_window_save", dot_scfi_ignore, 0 },
+    { "cfi_negate_ra_state", dot_scfi_ignore, 0 },
+    { "cfi_escape", dot_scfi_ignore, 0 },
+    { "cfi_signal_frame", dot_scfi, CFI_signal_frame }, /* No ignore.  */
+    { "cfi_personality", dot_scfi_ignore, 0 },
+    { "cfi_personality_id", dot_scfi_ignore, 0 },
+    { "cfi_lsda", dot_scfi_ignore, 0 },
+    { "cfi_val_encoded_addr", dot_scfi_ignore, 0 },
+    { "cfi_inline_lsda", dot_scfi_ignore, 0 },
+    { "cfi_label", dot_scfi, CFI_label }, /* No ignore.  */
+    { "cfi_val_offset", dot_scfi_ignore, 0 },
+    { NULL, NULL, 0 }
+  };
+
+static void
+dot_scfi_ignore (int ignored ATTRIBUTE_UNUSED)
+{
+  gas_assert (flag_synth_cfi);
+
+  if (scfi_ignore_warn_once == 0)
+    {
+      as_warn (_("--scfi=all ignores some user-specified CFI directives"));
+      scfi_ignore_warn_once = 1;
+    }
+  ignore_rest_of_line ();
+}
+
+static void
+dot_scfi_sections (int ignored ATTRIBUTE_UNUSED)
+{
+  /* To be implemented.  */
+  return;
+}
+
+static void
+scfi_process_cfi_label (void)
+{
+  char *name;
+  ginsnS *ginsn;
+
+  name = read_symbol_name ();
+  if (name == NULL)
+    return;
+
+  /* Add a new ginsn.  */
+  ginsn = ginsn_new_phantom (symbol_temp_new_now ());
+  frch_ginsn_data_append (ginsn);
+
+  scfi_op_add_cfi_label (ginsn, name);
+  /* TODO.  */
+  // free (name);
+
+  demand_empty_rest_of_line ();
+}
+
+static void
+scfi_process_cfi_signal_frame (void)
+{
+  ginsnS *ginsn;
+
+  ginsn = ginsn_new_phantom (symbol_temp_new_now ());
+  frch_ginsn_data_append (ginsn);
+
+  scfi_op_add_signal_frame (ginsn);
+}
+
+static void
+dot_scfi (int arg)
+{
+  switch (arg)
+    {
+      case CFI_label:
+	scfi_process_cfi_label ();
+	break;
+      case CFI_signal_frame:
+	scfi_process_cfi_signal_frame ();
+	break;
+      default:
+	abort ();
+    }
+}
+
+void
+scfi_dot_cfi_startproc (symbolS *start_sym)
+{
+  if (frchain_now->frch_cfi_data != NULL)
+    {
+      as_bad (_("previous CFI entry not closed (missing .cfi_endproc)"));
+      return;
+    }
+
+  cfi_new_fde (start_sym);
+
+  cfi_set_sections ();
+
+  frchain_now->frch_cfi_data->cur_cfa_offset = 0;
+
+  /* By default, SCFI machinery assumes .cfi_startproc is used without
+     parameter simple.  */
+  tc_cfi_frame_initial_instructions ();
+
+  if ((all_cfi_sections & CFI_EMIT_target) != 0)
+    tc_cfi_startproc ();
+}
+
+void
+scfi_dot_cfi_endproc (symbolS *end_sym)
+{
+  struct fde_entry *fde_last;
+
+  if (frchain_now->frch_cfi_data == NULL)
+    {
+      as_bad (_(".cfi_endproc without corresponding .cfi_startproc"));
+      return;
+    }
+
+  fde_last = frchain_now->frch_cfi_data->cur_fde_data;
+  cfi_set_last_fde (fde_last);
+
+  cfi_end_fde (end_sym);
+
+  if ((all_cfi_sections & CFI_EMIT_target) != 0)
+    tc_cfi_endproc (fde_last);
+}
+
+void
+scfi_dot_cfi (int arg, unsigned reg1, unsigned reg2, offsetT offset,
+	      const char *name, symbolS *advloc)
+{
+  if (frchain_now->frch_cfi_data == NULL)
+    {
+      as_bad (_("CFI instruction used without previous .cfi_startproc"));
+      return;
+    }
+
+  /* If the last address was not at the current PC, advance to current.  */
+  if (frchain_now->frch_cfi_data->last_address != advloc)
+    cfi_add_advance_loc (advloc);
+
+  switch (arg)
+    {
+    case DW_CFA_offset:
+      cfi_add_CFA_offset (reg1, offset);
+      break;
+
+    case DW_CFA_val_offset:
+      cfi_add_CFA_val_offset (reg1, offset);
+      break;
+
+    case CFI_rel_offset:
+      cfi_add_CFA_offset (reg1,
+			  offset - frchain_now->frch_cfi_data->cur_cfa_offset);
+      break;
+
+    case DW_CFA_def_cfa:
+      cfi_add_CFA_def_cfa (reg1, offset);
+      break;
+
+    case DW_CFA_register:
+      cfi_add_CFA_register (reg1, reg2);
+      break;
+
+    case DW_CFA_def_cfa_register:
+      cfi_add_CFA_def_cfa_register (reg1);
+      break;
+
+    case DW_CFA_def_cfa_offset:
+      cfi_add_CFA_def_cfa_offset (offset);
+      break;
+
+    case CFI_adjust_cfa_offset:
+      cfi_add_CFA_def_cfa_offset (frchain_now->frch_cfi_data->cur_cfa_offset
+				  + offset);
+      break;
+
+    case DW_CFA_restore:
+      cfi_add_CFA_restore (reg1);
+      break;
+
+    case DW_CFA_remember_state:
+      cfi_add_CFA_remember_state ();
+      break;
+
+    case DW_CFA_restore_state:
+      cfi_add_CFA_restore_state ();
+      break;
+
+    case CFI_label:
+      cfi_add_label (name);
+      break;
+
+    case CFI_signal_frame:
+      frchain_now->frch_cfi_data->cur_fde_data->signal_frame = 1;
+      break;
+
+/*
+    case DW_CFA_undefined:
+      for (;;)
+	{
+	  reg1 = cfi_parse_reg ();
+	  cfi_add_CFA_undefined (reg1);
+	  SKIP_WHITESPACE ();
+	  if (*input_line_pointer != ',')
+	    break;
+	  ++input_line_pointer;
+	}
+      break;
+
+    case DW_CFA_same_value:
+      reg1 = cfi_parse_reg ();
+      cfi_add_CFA_same_value (reg1);
+      break;
+
+    case CFI_return_column:
+      reg1 = cfi_parse_reg ();
+      cfi_set_return_column (reg1);
+      break;
+
+    case DW_CFA_GNU_window_save:
+      cfi_add_CFA_insn (DW_CFA_GNU_window_save);
+      break;
+
+*/
+    default:
+      abort ();
+    }
+}
+
+#else
+
+static void
+dot_scfi_dummy (int ignored ATTRIBUTE_UNUSED)
+{
+  as_bad (_("SCFI is not supported for this target"));
+  ignore_rest_of_line ();
+}
+
+const pseudo_typeS scfi_pseudo_table[] =
+  {
+    { "cfi_sections", dot_scfi_dummy, 0 },
+    { "cfi_startproc", dot_scfi_dummy, 0 },
+    { "cfi_endproc", dot_scfi_dummy, 0 },
+    { "cfi_fde_data", dot_scfi_dummy, 0 },
+    { "cfi_def_cfa", dot_scfi_dummy, 0 },
+    { "cfi_def_cfa_register", dot_scfi_dummy, 0 },
+    { "cfi_def_cfa_offset", dot_scfi_dummy, 0 },
+    { "cfi_adjust_cfa_offset", dot_scfi_dummy, 0 },
+    { "cfi_offset", dot_scfi_dummy, 0 },
+    { "cfi_rel_offset", dot_scfi_dummy, 0 },
+    { "cfi_register", dot_scfi_dummy, 0 },
+    { "cfi_return_column", dot_scfi_dummy, 0 },
+    { "cfi_restore", dot_scfi_dummy, 0 },
+    { "cfi_undefined", dot_scfi_dummy, 0 },
+    { "cfi_same_value", dot_scfi_dummy, 0 },
+    { "cfi_remember_state", dot_scfi_dummy, 0 },
+    { "cfi_restore_state", dot_scfi_dummy, 0 },
+    { "cfi_window_save", dot_scfi_dummy, 0 },
+    { "cfi_negate_ra_state", dot_scfi_dummy, 0 },
+    { "cfi_escape", dot_scfi_dummy, 0 },
+    { "cfi_signal_frame", dot_scfi_dummy, 0 },
+    { "cfi_personality", dot_scfi_dummy, 0 },
+    { "cfi_personality_id", dot_scfi_dummy, 0 },
+    { "cfi_lsda", dot_scfi_dummy, 0 },
+    { "cfi_val_encoded_addr", dot_scfi_dummy, 0 },
+    { "cfi_inline_lsda", dot_scfi_dummy, 0 },
+    { "cfi_label", dot_scfi_dummy, 0 },
+    { "cfi_val_offset", dot_scfi_dummy, 0 },
+    { NULL, NULL, 0 }
+  };
+
+#endif
diff --git a/gas/scfidw2gen.h b/gas/scfidw2gen.h
new file mode 100644
index 00000000000..c3d6f80b3db
--- /dev/null
+++ b/gas/scfidw2gen.h
@@ -0,0 +1,37 @@ 
+/* scfidw2gen.h - Support for emitting synthesized Dwarf2 CFI.
+   Copyright (C) 2003-2023 Free Software Foundation, Inc.
+
+   This file is part of GAS, the GNU Assembler.
+
+   GAS is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GAS is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GAS; see the file COPYING.  If not, write to the Free
+   Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
+   02110-1301, USA.  */
+
+#ifndef SCFIDW2GEN_H
+#define SCFIDW2GEN_H
+
+#include "as.h"
+#include "dwarf2.h"
+
+extern int all_cfi_sections;
+
+extern const pseudo_typeS scfi_pseudo_table[];
+
+void scfi_dot_cfi_startproc (symbolS *start_sym);
+void scfi_dot_cfi_endproc (symbolS *end_sym);
+void scfi_dot_cfi (int arg, unsigned reg1, unsigned reg2, offsetT offset,
+		   const char *name, symbolS *advloc);
+
+#endif
+