gcc/ChangeLog:
2019-10-21  Egeyar Bagcioglu  <egeyar.bagcio...@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): Add --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 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/ChangeLog:
2019-10-30  Egeyar Bagcioglu  <egeyar.bagcio...@oracle.com>

        * c-c++-common/record-gcc-command-line.c: New test case.


---
 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                                       | 36 +++++++++++++++++++
 11 files changed, 167 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 cc279f4..59d670f 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -394,6 +394,10 @@ Driver Alias(print-sysroot-headers-suffix)
 -profile
 Common Alias(p)
 
+-record-gcc-command-line
+Common Driver 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 e00d437..5caa9e0 100644
--- a/gcc/config/elfos.h
+++ b/gcc/config/elfos.h
@@ -451,6 +451,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 915e961..6da5e1b 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -8061,6 +8061,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 ac0f049..73ca552 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 c45a1df..480263e 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -236,6 +236,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;
 
@@ -409,6 +414,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
@@ -1158,6 +1164,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)}\
  %{fprofile-arcs|fprofile-generate*|coverage:\
    %{!fprofile-update=single:\
      %{pthread:-fprofile-update=prefer-atomic}}}";
@@ -1649,6 +1656,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
@@ -7359,6 +7367,7 @@ driver::main (int argc, char **argv)
   bool early_exit;
 
   set_progname (argv[0]);
+  set_commandline (argc, const_cast <const char **> (argv));
   expand_at_files (&argc, &argv);
   decode_argv (argc, const_cast <const char **> (argv));
   global_initializations ();
@@ -7402,6 +7411,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.  */
 
@@ -10046,6 +10064,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)
+    {
+      fputs (_gcc_argv[0], out);
+      for (int i = 1; i < _gcc_argc; i += 1)
+       {
+         fputc (' ', out);
+         fputs (_gcc_argv[i], out);
+       }
+      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 dc77dba..0ab0e93 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 1f011ed..62e1381 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 9f80658..4d180ec 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 1c7002f..3e1e1ef 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -866,6 +866,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 57365ad..ff86ae8 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"
@@ -7819,6 +7820,41 @@ 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_switches_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)
+    {
+      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);
+    }
+  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

Reply via email to