[V4,07/14] gas: add new command line option --scfi[=all,none]

Message ID 20240103071526.3846985-8-indu.bhagat@oracle.com
State Unresolved
Headers
Series Synthesize CFI for hand-written asm |

Checks

Context Check Description
snail/binutils-gdb-check warning Git am fail log

Commit Message

Indu Bhagat Jan. 3, 2024, 7:15 a.m. UTC
  [Changes from V3 to V4]
  - Code restructuring so that --scfi=[all,none] is available for ELF
    targets only
[End of changes from V3 to V4]

[No changes from V2]

When the command line option --scfi (default is --scfi=all) is passed to
the GNU assembler, it will synthesize DWARF call frame information (CFI)
for the input assembly.

The option --scfi=all will also ignore many of the existing .cfi_*
directives, if already contained in the provided input file.  Only the
following CFI directives will not be ignored:
  - .cfi_sections,
  - .cfi_label,
  - .cfi_signal_frame

To use SCFI, a target will need to:
    - define TARGET_USE_SCFI and TARGET_USE_GINSN, and other necessary
    definitions,
    - provide means to help GAS understand the target specific instruction
    semantics by creating ginsns.

The --scfi=[all,none] may see more options added in future.  For
example, --scfi=inline, for dealing with inline asm may be added in the
future.  In this option, the GNU assembler will consume (and not ignore)
the compiler generated CFI for the code surrounding the inline asm.

Also document the option.

gas/
        * as.c (show_usage): Add support for --scfi.
        (parse_args): Likewise.
        * as.h (enum synth_cfi_type): Define new type.
        * doc/as.texi: Document the new option.
---
 gas/as.c        | 24 ++++++++++++++++++++++--
 gas/as.h        |  8 ++++++++
 gas/doc/as.texi | 12 ++++++++++++
 3 files changed, 42 insertions(+), 2 deletions(-)
  

Patch

diff --git a/gas/as.c b/gas/as.c
index 6839c841588..953b9bc0b99 100644
--- a/gas/as.c
+++ b/gas/as.c
@@ -321,6 +321,11 @@  Options:\n\
                           generate GNU Build notes if none are present in the input\n"));
   fprintf (stream, _("\
   --gsframe               generate SFrame stack trace information\n"));
+# if defined (TARGET_USE_SCFI) && defined (TARGET_USE_GINSN)
+  fprintf (stream, _("\
+  --scfi=[all,none]       (default: all)\n\
+                          Synthesize DWARF CFI for hand-written asm\n"));
+# endif
 #endif /* OBJ_ELF */
 
   fprintf (stream, _("\
@@ -511,7 +516,8 @@  parse_args (int * pargc, char *** pargv)
       OPTION_NOCOMPRESS_DEBUG,
       OPTION_NO_PAD_SECTIONS,
       OPTION_MULTIBYTE_HANDLING,  /* = STD_BASE + 40 */
-      OPTION_SFRAME
+      OPTION_SFRAME,
+      OPTION_SCFI
     /* When you add options here, check that they do
        not collide with OPTION_MD_BASE.  See as.h.  */
     };
@@ -543,7 +549,10 @@  parse_args (int * pargc, char *** pargv)
     ,{"sectname-subst", no_argument, NULL, OPTION_SECTNAME_SUBST}
     ,{"generate-missing-build-notes", required_argument, NULL, OPTION_ELF_BUILD_NOTES}
     ,{"gsframe", no_argument, NULL, OPTION_SFRAME}
-#endif
+# if defined (TARGET_USE_SCFI) && defined (TARGET_USE_GINSN)
+    ,{"scfi", optional_argument, NULL, OPTION_SCFI}
+# endif
+#endif /* OBJ_ELF || OBJ_MAYBE_ELF.  */
     ,{"fatal-warnings", no_argument, NULL, OPTION_WARN_FATAL}
     ,{"gdwarf-2", no_argument, NULL, OPTION_GDWARF_2}
     ,{"gdwarf-3", no_argument, NULL, OPTION_GDWARF_3}
@@ -982,6 +991,17 @@  This program has absolutely no warranty.\n"));
 	  flag_execstack = 0;
 	  break;
 
+# if defined (TARGET_USE_SCFI) && defined (TARGET_USE_GINSN)
+	case OPTION_SCFI:
+	  if (!optarg || strcasecmp (optarg, "all") == 0)
+	    flag_synth_cfi = SYNTH_CFI_ALL;
+	  else if (strcasecmp (optarg, "none") == 0)
+	    flag_synth_cfi = SYNTH_CFI_NONE;
+	  else
+	    as_fatal (_("Invalid --scfi= option: `%s'"), optarg);
+	  break;
+# endif
+
 	case OPTION_SIZE_CHECK:
 	  if (strcasecmp (optarg, "error") == 0)
 	    flag_allow_nonconst_size = false;
diff --git a/gas/as.h b/gas/as.h
index 46dd0d0776d..378653e2200 100644
--- a/gas/as.h
+++ b/gas/as.h
@@ -324,6 +324,14 @@  COMMON int flag_fatal_warnings; /* --fatal-warnings */
    are detected.  */
 COMMON unsigned char flag_always_generate_output; /* -Z */
 
+enum synth_cfi_type
+{
+  SYNTH_CFI_NONE = 0,
+  SYNTH_CFI_ALL,
+};
+
+COMMON enum synth_cfi_type flag_synth_cfi;
+
 /* This is true if the assembler should output time and space usage.  */
 COMMON unsigned char flag_print_statistics;
 
diff --git a/gas/doc/as.texi b/gas/doc/as.texi
index 52571d95dd2..cfc1078c36b 100644
--- a/gas/doc/as.texi
+++ b/gas/doc/as.texi
@@ -255,6 +255,7 @@  gcc(1), ld(1), and the Info entries for @file{binutils} and @file{ld}.
  [@b{--multibyte-handling=[allow|warn|warn-sym-only]}]
  [@b{--no-pad-sections}]
  [@b{-o} @var{objfile}] [@b{-R}]
+ [@b{--scfi=[all,none]}]
  [@b{--sectname-subst}]
  [@b{--size-check=[error|warning]}]
  [@b{--statistics}]
@@ -932,6 +933,17 @@  Ignored.  Supported for compatibility with tools that apss the same option to
 both the assembler and the linker.
 
 @ifset ELF
+@item --scfi=none
+@itemx --scfi=all
+These options control whether the assembler should synthesize CFI for
+hand-written input.  If the input already contains some synthesizable CFI
+directives, the assembler ignores them and emits a warning.  Note that
+@code{--scfi=all} is not intended to be used for compiler-generated code,
+including inline assembly.
+
+The input asm must begin with the @code{.type} directive, and should ideally be
+closed off using a @code{.size} directive.
+
 @item --sectname-subst
 Honor substitution sequences in section names.
 @ifclear man