[PATCH v2 2/3] Introduce the gcc option --record-gcc-command-line

Egeyar Bagcioglu egeyar.bagcioglu@oracle.com
Tue Mar 3 16:41:00 GMT 2020


gcc:
2020-02-27  Egeyar Bagcioglu  <egeyar.bagcioglu@oracle.com>

	* common.opt (--record-gcc-command-line): New option.
	* config/elfos.h (TARGET_ASM_RECORD_GCC_COMMAND_LINE): Define as
	elf_record_gcc_command_line.
	* doc/tm.texi: Regenerate.
	* doc/tm.texi.in (TARGET_ASM_RECORD_GCC_COMMAND_LINE): Introduce.
	(TARGET_ASM_RECORD_GCC_COMMAND_LINE_SECTION): Likewise.
	* gcc.c (_gcc_argc): New static variable.
	(_gcc_argv): Likewise.
	(record_gcc_command_line_spec_function): New function.
	(cc1_options): Handle --record-gcc-command-line.
	(static_spec_functions): Add record_gcc_command_line_spec_function
	with pseudo name record-gcc-command-line.
	(driver::main): Call set_commandline.
	(driver::set_commandline): Declare.
	* gcc.h (driver::set_commandline): Declare.
	* target.def (record_gcc_command_line): A new hook.
	(record_gcc_command_line_section): A new hookpod.
	* target.h (elf_record_gcc_command_line): Declare.
	* toplev.c (init_asm_output): Check for gcc_command_line_file and
	call record_gcc_command_line if necessary.
	* varasm.c: Include "version.h".
	(elf_record_gcc_command_line): Define.

gcc/testsuite:
2020-02-27  Egeyar Bagcioglu  <egeyar.bagcioglu@oracle.com>

	* c-c++-common/record-gcc-command-line.c: New.
---
 gcc/common.opt                                     |  4 +++
 gcc/config/elfos.h                                 |  5 +++
 gcc/doc/tm.texi                                    | 22 ++++++++++++
 gcc/doc/tm.texi.in                                 |  4 +++
 gcc/gcc.c                                          | 41 ++++++++++++++++++++++
 gcc/gcc.h                                          |  1 +
 gcc/target.def                                     | 30 ++++++++++++++++
 gcc/target.h                                       |  3 ++
 .../c-c++-common/record-gcc-command-line.c         |  8 +++++
 gcc/toplev.c                                       | 13 +++++++
 gcc/varasm.c                                       | 40 +++++++++++++++++++++
 11 files changed, 171 insertions(+)
 create mode 100644 gcc/testsuite/c-c++-common/record-gcc-command-line.c

diff --git a/gcc/common.opt b/gcc/common.opt
index fa9da50..1bacded 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -391,6 +391,10 @@ Driver Alias(print-sysroot-headers-suffix)
 -profile
 Common Alias(p)
 
+-record-gcc-command-line
+Common NoDriverArg Separate Var(gcc_command_line_file)
+Record the command line making this gcc call in the produced object file.
+
 -save-temps
 Driver Alias(save-temps)
 
diff --git a/gcc/config/elfos.h b/gcc/config/elfos.h
index 74a3eaf..1d5f447 100644
--- a/gcc/config/elfos.h
+++ b/gcc/config/elfos.h
@@ -462,6 +462,11 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #undef  TARGET_ASM_RECORD_GCC_SWITCHES
 #define TARGET_ASM_RECORD_GCC_SWITCHES elf_record_gcc_switches
 
+/* Allow the use of the --record-gcc-command-line switch via the
+   elf_record_gcc_command_line function defined in varasm.c.  */
+#undef  TARGET_ASM_RECORD_GCC_COMMAND_LINE
+#define TARGET_ASM_RECORD_GCC_COMMAND_LINE elf_record_gcc_command_line
+
 /* A C statement (sans semicolon) to output to the stdio stream STREAM
    any text necessary for declaring the name of an external symbol
    named NAME which is referenced in this compilation but not defined.
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 19985ad..0a8ef03 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -8113,6 +8113,28 @@ ELF implementation of the @code{TARGET_ASM_RECORD_GCC_SWITCHES} target
 hook.
 @end deftypevr
 
+@deftypefn {Target Hook} int TARGET_ASM_RECORD_GCC_COMMAND_LINE ()
+Provides the target with the ability to record the command line that
+has been passed to the compiler driver. The @var{gcc_command_line_file}
+variable specifies the intermediate file that holds the command line.
+
+The return value must be zero.  Other return values may be supported
+in the future.
+
+By default this hook is set to NULL, but an example implementation,
+@var{elf_record_gcc_command_line}, is provided for ELF based targets.
+it records the command line as ASCII text inside a new, mergable string
+section in the assembler output file.  The name of the new section is
+provided by the @code{TARGET_ASM_RECORD_GCC_COMMAND_LINE_SECTION}
+target hook.
+@end deftypefn
+
+@deftypevr {Target Hook} {const char *} TARGET_ASM_RECORD_GCC_COMMAND_LINE_SECTION
+This is the name of the section that will be created by the example
+ELF implementation of the @code{TARGET_ASM_RECORD_GCC_COMMAND_LINE}
+target hook.
+@end deftypevr
+
 @need 2000
 @node Data Output
 @subsection Output of Data
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index 1a16150..174840b 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -5192,6 +5192,10 @@ It must not be modified by command-line option processing.
 
 @hook TARGET_ASM_RECORD_GCC_SWITCHES_SECTION
 
+@hook TARGET_ASM_RECORD_GCC_COMMAND_LINE
+
+@hook TARGET_ASM_RECORD_GCC_COMMAND_LINE_SECTION
+
 @need 2000
 @node Data Output
 @subsection Output of Data
diff --git a/gcc/gcc.c b/gcc/gcc.c
index 9f790db..3a9d6bf 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -235,6 +235,11 @@ static int verbose_only_flag;
 
 static int print_subprocess_help;
 
+/* argc and argv used to call gcc. Necessary for
+   --record-gcc-command-line option.  */
+static int _gcc_argc;
+static const char **_gcc_argv;
+
 /* Linker suffix passed to -fuse-ld=... */
 static const char *use_ld;
 
@@ -408,6 +413,7 @@ static const char *replace_extension_spec_func (int, const char **);
 static const char *greater_than_spec_func (int, const char **);
 static const char *debug_level_greater_than_spec_func (int, const char **);
 static const char *find_fortran_preinclude_file (int, const char **);
+static const char *record_gcc_command_line_spec_function (int, const char **);
 static char *convert_white_space (char *);
 
 /* The Specs Language
@@ -1157,6 +1163,7 @@ static const char *cc1_options =
  %{!fsyntax-only:%{S:%W{o*}%{!o*:-o %b.s}}}\
  %{fsyntax-only:-o %j} %{-param*}\
  %{coverage:-fprofile-arcs -ftest-coverage}\
+ %{-record-gcc-command-line:--record-gcc-command-line %:record-gcc-command-line(%g.cmdline) %<-record-gcc-command-line}\
  %{fprofile-arcs|fprofile-generate*|coverage:\
    %{!fprofile-update=single:\
      %{pthread:-fprofile-update=prefer-atomic}}}";
@@ -1648,6 +1655,7 @@ static const struct spec_function static_spec_functions[] =
   { "gt",			greater_than_spec_func },
   { "debug-level-gt",		debug_level_greater_than_spec_func },
   { "fortran-preinclude-file",	find_fortran_preinclude_file},
+  { "record-gcc-command-line",	record_gcc_command_line_spec_function},
 #ifdef EXTRA_SPEC_FUNCTIONS
   EXTRA_SPEC_FUNCTIONS
 #endif
@@ -7387,6 +7395,7 @@ driver::main (int argc, char **argv)
 
   set_progname (argv[0]);
   expand_at_files (&argc, &argv);
+  set_commandline (argc, const_cast <const char **> (argv));
   decode_argv (argc, const_cast <const char **> (argv));
   global_initializations ();
   build_multilib_strings ();
@@ -7430,6 +7439,15 @@ driver::set_progname (const char *argv0) const
   xmalloc_set_program_name (progname);
 }
 
+/* Keep command line for --record-gcc-command-line.  */
+
+void
+driver::set_commandline (int argc, const char **argv) const
+{
+  _gcc_argc = argc;
+  _gcc_argv = argv;
+}
+
 /* Expand any @ files within the command-line args,
    setting at_file_supplied if any were expanded.  */
 
@@ -10070,6 +10088,29 @@ find_fortran_preinclude_file (int argc, const char **argv)
   return result;
 }
 
+/* The option --record-gcc-command-line saves the command line options given to
+   gcc into the created object file. Those options are passed to the backends via
+   an intermediate file whose name is generated while the spec is evaluated. This
+   function takes that filename as an argument, writes to it, and returns it as a
+   single string.  */
+
+static const char *
+record_gcc_command_line_spec_function(int argc ATTRIBUTE_UNUSED, const char **argv)
+{
+  const char *filename = argv[0];
+  FILE *out = fopen (filename, "w");
+  if (!out)
+    error ("cannot open %s: %m", filename);
+
+  fprintf (out, "%s", _gcc_argv[0]);
+  for (int i = 1; i < _gcc_argc; i += 1)
+    {
+      fprintf (out, " %s", _gcc_argv[i]);
+    }
+
+  fclose (out);
+  return filename;
+}
 
 /* Insert backslash before spaces in ORIG (usually a file path), to 
    avoid being broken by spec parser.
diff --git a/gcc/gcc.h b/gcc/gcc.h
index 70d8f08..cde77fb 100644
--- a/gcc/gcc.h
+++ b/gcc/gcc.h
@@ -37,6 +37,7 @@ class driver
 
  private:
   void set_progname (const char *argv0) const;
+  void set_commandline (int argc, const char **argv) const;
   void expand_at_files (int *argc, char ***argv) const;
   void decode_argv (int argc, const char **argv);
   void global_initializations ();
diff --git a/gcc/target.def b/gcc/target.def
index b5e82ff..4608119 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -801,6 +801,36 @@ ELF implementation of the @code{TARGET_ASM_RECORD_GCC_SWITCHES} target\n\
 hook.",
  const char *, ".GCC.command.line")
 
+/* Output a record of the command line that have been passed to gcc.  */
+DEFHOOK
+(record_gcc_command_line,
+ "Provides the target with the ability to record the command line that\n\
+has been passed to the compiler driver. The @var{gcc_command_line_file}\n\
+variable specifies the intermediate file that holds the command line.\n\
+\n\
+The return value must be zero.  Other return values may be supported\n\
+in the future.\n\
+\n\
+By default this hook is set to NULL, but an example implementation,\n\
+@var{elf_record_gcc_command_line}, is provided for ELF based targets.\n\
+it records the command line as ASCII text inside a new, mergable string\n\
+section in the assembler output file.  The name of the new section is\n\
+provided by the @code{TARGET_ASM_RECORD_GCC_COMMAND_LINE_SECTION}\n\
+target hook.",
+ int, (),
+ NULL)
+
+/* The name of the section that the example ELF implementation of
+   record_gcc_switches will use to store the information.  Target
+   specific versions of record_gcc_switches may or may not use
+   this information.  */
+DEFHOOKPOD
+(record_gcc_command_line_section,
+ "This is the name of the section that will be created by the example\n\
+ELF implementation of the @code{TARGET_ASM_RECORD_GCC_COMMAND_LINE}\n\
+target hook.",
+ const char *, ".GCC.command.line")
+
 /* Output the definition of a section anchor.  */
 DEFHOOK
 (output_anchor,
diff --git a/gcc/target.h b/gcc/target.h
index 2f47c57..66f7064 100644
--- a/gcc/target.h
+++ b/gcc/target.h
@@ -101,6 +101,9 @@ typedef int (* print_switch_fn_type) (print_switch_type, const char *);
 /* An example implementation for ELF targets.  Defined in varasm.c  */
 extern int elf_record_gcc_switches (print_switch_type type, const char *);
 
+/* An example implementation for ELF targets.  Defined in varasm.c  */
+extern int elf_record_gcc_command_line ();
+
 /* Some places still assume that all pointer or address modes are the
    standard Pmode and ptr_mode.  These optimizations become invalid if
    the target actually supports multiple different modes.  For now,
diff --git a/gcc/testsuite/c-c++-common/record-gcc-command-line.c b/gcc/testsuite/c-c++-common/record-gcc-command-line.c
new file mode 100644
index 0000000..2fdce4f
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/record-gcc-command-line.c
@@ -0,0 +1,8 @@
+/* Test the option "--record-gcc-command-line".
+   { dg-do compile }
+   { dg-require-target-object-format "elf" }
+   { dg-options "-O2 -g --record-gcc-command-line" } */
+
+int main () { return 0; }
+
+/* { dg-final { scan-assembler "-O2 -g --record-gcc-command-line"} }  */
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 4c8be50..d588a3d 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -868,6 +868,19 @@ init_asm_output (const char *name)
     {
       targetm.asm_out.file_start ();
 
+      if (gcc_command_line_file)
+	{
+	  if (targetm.asm_out.record_gcc_command_line)
+	    {
+	      /* Record the command line.  */
+	      targetm.asm_out.record_gcc_command_line ();
+	    }
+	  else
+	    inform (UNKNOWN_LOCATION,
+		    "--record-gcc-command-line is not supported by "
+		    "the current target");
+	}
+
       if (flag_record_gcc_switches)
 	{
 	  if (targetm.asm_out.record_gcc_switches)
diff --git a/gcc/varasm.c b/gcc/varasm.c
index dc6da6c..9c8e477 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -43,6 +43,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "fold-const.h"
 #include "stor-layout.h"
 #include "varasm.h"
+#include "version.h"
 #include "flags.h"
 #include "stmt.h"
 #include "expr.h"
@@ -7844,6 +7845,45 @@ elf_record_gcc_switches (print_switch_type type, const char * name)
   return 0;
 }
 
+/* This function provides a possible implementation of the
+   TARGET_ASM_RECORD_GCC_COMMAND_LINE target hook for ELF targets.  When
+   triggered by --record-gcc-command-line it creates a new mergeable
+   string section in the assembler output file called
+   TARGET_ASM_RECORD_GCC_COMMAND_LINE_SECTION which contains the command line
+   in ASCII format.  */
+
+int
+elf_record_gcc_command_line ()
+{
+  char cmdline[256];
+  section *sec;
+  sec = get_section (targetm.asm_out.record_gcc_command_line_section,
+		     SECTION_DEBUG | SECTION_MERGE
+		     | SECTION_STRINGS | (SECTION_ENTSIZE & 1),
+		     NULL);
+  switch_to_section (sec);
+
+  ASM_OUTPUT_ASCII (asm_out_file, version_string, strlen(version_string));
+
+  FILE *out_stream = fopen (gcc_command_line_file, "r");
+  if (!out_stream)
+    error ("cannot open %s: %m", gcc_command_line_file);
+
+  ASM_OUTPUT_ASCII (asm_out_file, " : ", 3);
+  ssize_t cmdline_length;
+  while ((cmdline_length = fread (cmdline, 1, 256, out_stream)))
+    ASM_OUTPUT_ASCII (asm_out_file, cmdline, cmdline_length);
+
+  fclose (out_stream);
+
+  /* End the line.  */
+  cmdline[0] = 0;
+  ASM_OUTPUT_ASCII (asm_out_file, cmdline, 1);
+
+  /* The return value is currently ignored by the caller, but must be 0.  */
+  return 0;
+}
+
 /* Emit text to declare externally defined symbols. It is needed to
    properly support non-default visibility.  */
 void
-- 
1.8.3.1



More information about the Gcc-patches mailing list