public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Add patch for debugging compiler ICEs.
@ 2014-08-04 17:03 Maxim Ostapenko
  2014-08-12 16:14 ` [PING][PATCH] " Maxim Ostapenko
  2014-08-19 13:58 ` Fwd: [PATCH] " Maxim Ostapenko
  0 siblings, 2 replies; 24+ messages in thread
From: Maxim Ostapenko @ 2014-08-04 17:03 UTC (permalink / raw)
  To: GCC Patches
  Cc: Jeff Law, Jakub Jelinek, tsaunders, Yury Gribov, Slava Garbuzov

[-- Attachment #1: Type: text/plain, Size: 1072 bytes --]

Hi,

A years ago there was a discussion 
(https://gcc.gnu.org/ml/gcc-patches/2004-01/msg02437.html) about 
debugging compiler ICEs that resulted in a patch from Jakub, which dumps 
useful information into temporary file, but for some reasons this patch 
wasn't applied to trunk.

This is the resurrected patch with added GCC version information into 
generated repro file.

I've updated the patch that I've posted earlier 
(https://gcc.gnu.org/ml/gcc-patches/2014-07/msg01649.html ) according to 
recent upstream discussion 
(https://gcc.gnu.org/ml/gcc-patches/2014-08/msg00020.html).

The debugging functionality is disabled by default and can be enabled 
with adding -freport-bug into compile options. It can be also enabled by 
default with
--with-spec during GCC build.

There are several directions in which this can be improved e.g:

1) more user-friendly ways to report bugs (autosubmitting to Bugzilla, etc.)

2) generate repro in case of segfault.

but having basic functionality (autogenerating reprocase in temprorary 
file) already seems quite useful.

-Maxim

[-- Attachment #2: ICE.diff --]
[-- Type: text/x-patch, Size: 14866 bytes --]

2014-08-04  Jakub Jelinek  <jakub@redhat.com>
	      Max Ostapenko  <m.ostapenko@partner.samsung.com>

	* common.opt: New option.
	* doc/invoke.texi: Describe new option.
	* diagnostic.c (diagnostic_action_after_output): Exit with
	ICE_EXIT_CODE instead of FATAL_EXIT_CODE.
	* gcc.c (execute): Don't free first string early, but at the end
	of the function.  Call retry_ice if compiler exited with
	ICE_EXIT_CODE.
	(main): Factor out common code.
	(print_configuration): New function.
	(try_fork): Likewise.
	(redirect_stdout_stderr): Likewise.
	(files_equal_p): Likewise.
	(check_repro): Likewise.
	(run_attempt): Likewise.
	(do_report_bug): Likewise.
	(append_text): Likewise.
	(try_generate_repro): Likewise

diff --git a/gcc/common.opt b/gcc/common.opt
index 0c4f86b..aa79250 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1120,6 +1120,11 @@ fdump-noaddr
 Common Report Var(flag_dump_noaddr)
 Suppress output of addresses in debugging dumps
 
+freport-bug
+Common Driver Var(flag_report_bug)
+Collect and dump debug information into temporary file if ICE in C/C++
+compiler occured.
+
 fdump-passes
 Common Var(flag_dump_passes) Init(0)
 Dump optimization passes
diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
index 0cc7593..67b8c5b 100644
--- a/gcc/diagnostic.c
+++ b/gcc/diagnostic.c
@@ -492,7 +492,7 @@ diagnostic_action_after_output (diagnostic_context *context,
 	real_abort ();
       diagnostic_finish (context);
       fnotice (stderr, "compilation terminated.\n");
-      exit (FATAL_EXIT_CODE);
+      exit (ICE_EXIT_CODE);
 
     default:
       gcc_unreachable ();
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 4f327df..dafb573 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -6271,6 +6271,11 @@ feasible to use diff on debugging dumps for compiler invocations with
 different compiler binaries and/or different
 text / bss / data / heap / stack / dso start locations.
 
+@item -freport-bug
+@opindex freport-bug
+Collect and dump debug information into temporary file if ICE in C/C++
+compiler occured.
+
 @item -fdump-unnumbered
 @opindex fdump-unnumbered
 When doing debugging dumps, suppress instruction numbers and address output.
diff --git a/gcc/gcc.c b/gcc/gcc.c
index 44d0416..f7a56d1 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -43,6 +43,13 @@ compilation is specified by a string called a "spec".  */
 #include "params.h"
 #include "vec.h"
 #include "filenames.h"
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#if !(defined (__MSDOS__) || defined (OS2) || defined (VMS))
+#define RETRY_ICE_SUPPORTED
+#endif
 
 /* By default there is no special suffix for target executables.  */
 /* FIXME: when autoconf is fixed, remove the host check - dj */
@@ -253,6 +260,9 @@ static void init_gcc_specs (struct obstack *, const char *, const char *,
 static const char *convert_filename (const char *, int, int);
 #endif
 
+#ifdef RETRY_ICE_SUPPORTED
+static void try_generate_repro (const char *prog, const char **argv);
+#endif
 static const char *getenv_spec_function (int, const char **);
 static const char *if_exists_spec_function (int, const char **);
 static const char *if_exists_else_spec_function (int, const char **);
@@ -2849,7 +2859,7 @@ execute (void)
 	    }
 	}
 
-      if (string != commands[i].prog)
+      if (i && string != commands[i].prog)
 	free (CONST_CAST (char *, string));
     }
 
@@ -2902,6 +2912,17 @@ execute (void)
 	else if (WIFEXITED (status)
 		 && WEXITSTATUS (status) >= MIN_FATAL_STATUS)
 	  {
+#ifdef RETRY_ICE_SUPPORTED
+	    /* For ICEs in cc1, cc1obj, cc1plus see if it is
+	       reproducible or not.  */
+	    const char *p;
+	    if (flag_report_bug
+		&& WEXITSTATUS (status) == ICE_EXIT_CODE
+		&& i == 0
+		&& (p = strrchr (commands[0].argv[0], DIR_SEPARATOR))
+		&& ! strncmp (p + 1, "cc1", 3))
+	      try_generate_repro (commands[0].prog, commands[0].argv);
+#endif
 	    if (WEXITSTATUS (status) > greatest_status)
 	      greatest_status = WEXITSTATUS (status);
 	    ret_code = -1;
@@ -2959,6 +2980,9 @@ execute (void)
 	  }
       }
 
+   if (commands[0].argv[0] != commands[0].prog)
+     free (CONST_CAST (char *, commands[0].argv[0]));
+
     return ret_code;
   }
 }
@@ -6150,6 +6174,342 @@ give_switch (int switchnum, int omit_first_word)
   switches[switchnum].validated = true;
 }
 \f
+static void
+print_configuration (void)
+{
+  int n;
+  const char *thrmod;
+
+  fnotice (stderr, "Target: %s\n", spec_machine);
+  fnotice (stderr, "Configured with: %s\n", configuration_arguments);
+
+#ifdef THREAD_MODEL_SPEC
+  /* We could have defined THREAD_MODEL_SPEC to "%*" by default,
+  but there's no point in doing all this processing just to get
+  thread_model back.  */
+  obstack_init (&obstack);
+  do_spec_1 (THREAD_MODEL_SPEC, 0, thread_model);
+  obstack_1grow (&obstack, '\0');
+  thrmod = XOBFINISH (&obstack, const char *);
+#else
+  thrmod = thread_model;
+#endif
+
+  fnotice (stderr, "Thread model: %s\n", thrmod);
+
+  /* compiler_version is truncated at the first space when initialized
+  from version string, so truncate version_string at the first space
+  before comparing.  */
+  for (n = 0; version_string[n]; n++)
+    if (version_string[n] == ' ')
+      break;
+
+  if (! strncmp (version_string, compiler_version, n)
+      && compiler_version[n] == 0)
+    fnotice (stderr, "gcc version %s %s\n\n", version_string,
+             pkgversion_string);
+  else
+    fnotice (stderr, "gcc driver version %s %sexecuting gcc version %s\n\n",
+             version_string, pkgversion_string, compiler_version);
+}
+
+#ifdef RETRY_ICE_SUPPORTED
+#define RETRY_ICE_ATTEMPTS 3
+
+static int
+try_fork ()
+{
+  int pid, retries, sleep_interval;
+  sleep_interval = 1;
+  pid = -1;
+  for (retries = 0; retries < 4; retries++)
+    {
+      pid = fork ();
+      if (pid >= 0)
+        break;
+      sleep (sleep_interval);
+      sleep_interval *= 2;
+    }
+  return pid;
+}
+
+
+static void
+redirect_stdout_stderr (const char *out_temp, const char *err_temp,
+                        int append)
+{
+  int fd;
+  fd = open (out_temp, append ? O_RDWR | O_APPEND : O_RDWR);
+
+  if (fd < 0)
+    exit (-1);
+
+  close (STDOUT_FILENO);
+  dup (fd);
+  close (fd);
+
+  fd = open (err_temp, append ? O_RDWR | O_APPEND : O_RDWR);
+
+  if (fd < 0)
+    exit (-1);
+
+  close (STDERR_FILENO);
+  dup (fd);
+  close (fd);
+}
+
+static int
+files_equal_p (char *file1, char *file2, char *buf, const int bufsize)
+{
+  struct stat st1, st2;
+  size_t n, len;
+  int fd1, fd2;
+
+  fd1 = open (file1, O_RDONLY);
+  fd2 = open (file2, O_RDONLY);
+
+  if (fd1 < 0 || fd2 < 0)
+    goto error;
+
+  if (fstat (fd1, &st1) < 0 || fstat (fd2, &st2) < 0)
+    goto error;
+
+  if (st1.st_size != st2.st_size)
+    goto error;
+
+  for (n = st1.st_size; n; n -= len)
+    {
+      len = n;
+      if ((int) len > bufsize / 2)
+        len = bufsize / 2;
+
+      if (read (fd1, buf, len) != (int) len
+          || read (fd2, buf + bufsize / 2, len) != (int) len)
+        {
+          goto error;
+        }
+
+      if (memcmp (buf, buf + bufsize / 2, len) != 0)
+        goto error;
+    }
+
+  close (fd1);
+  close (fd2);
+
+  return 1;
+
+error:
+  close (fd1);
+  close (fd2);
+  return 0;
+}
+
+static int
+check_repro (char **temp_stdout_files, char **temp_stderr_files)
+{
+  int i;
+  const int ice_bufsize = 8192;
+  char *ice_buf = XNEWVEC (char, ice_bufsize);
+  for (i = 0; i < RETRY_ICE_ATTEMPTS - 2; ++i)
+    {
+     if (!files_equal_p (temp_stdout_files[i], temp_stdout_files[i + 1],
+                        ice_buf, ice_bufsize)
+         || !files_equal_p (temp_stderr_files[i], temp_stderr_files[i + 1],
+                          ice_buf, ice_bufsize))
+        {
+          fnotice (stderr, "The bug is not reproducible, so it is"
+                   " likely a hardware or OS problem.\n");
+          break;
+        }
+    }
+  free (ice_buf);
+  return i == RETRY_ICE_ATTEMPTS - 2;
+}
+
+enum attempt_status {
+  ATTEMPT_STATUS_FAIL_TO_RUN,
+  ATTEMPT_STATUS_SUCCESS,
+  ATTEMPT_STATUS_ICE
+};
+
+static enum attempt_status
+run_attempt (const char *prog, const char **new_argv, const char *out_temp,
+             const char *err_temp, int emit_system_info, int append)
+{
+  int status;
+  int pid = try_fork ();
+  if (pid < 0)
+    return ATTEMPT_STATUS_FAIL_TO_RUN;
+  else if (pid == 0)
+    {
+      redirect_stdout_stderr (out_temp, err_temp, append);
+
+      if (emit_system_info)
+        print_configuration ();
+
+      if (prog == new_argv[0])
+        execvp (prog, CONST_CAST2 (char *const *, const char **, new_argv));
+      else
+        execv (new_argv[0], CONST_CAST2 (char *const *, const char **,
+               new_argv));
+      exit (-1);
+    }
+
+  if (waitpid (pid, &status, 0) < 0)
+    return ATTEMPT_STATUS_FAIL_TO_RUN;
+
+  switch (WEXITSTATUS (status))
+    {
+      case ICE_EXIT_CODE:
+        return ATTEMPT_STATUS_ICE;
+
+      case SUCCESS_EXIT_CODE:
+        return ATTEMPT_STATUS_SUCCESS;
+
+      default:
+        return ATTEMPT_STATUS_FAIL_TO_RUN;
+    }
+}
+
+static void
+do_report_bug (const char *prog, const char **new_argv,
+                            const int nargs, char **out_file, char **err_file)
+{
+  int i, status;
+  int fd = open (*out_file, O_RDWR | O_APPEND);
+  if (fd < 0)
+    return;
+  write (fd, "\n//", 3);
+  for (i = 0; i < nargs; i++)
+    {
+      write (fd, " ", 1);
+      write (fd, new_argv[i], strlen (new_argv[i]));
+    }
+  write (fd, "\n\n", 2);
+  close (fd);
+  new_argv[nargs] = "-E";
+  new_argv[nargs + 1] = NULL;
+
+  status = run_attempt (prog, new_argv, *out_file, *err_file, 0, 1);
+
+  if (status == ATTEMPT_STATUS_SUCCESS)
+    {
+      fnotice (stderr, "Preprocessed source stored into %s file,"
+               " please attach this to your bugreport.\n",
+               *out_file);
+      /* Make sure it is not deleted.  */
+      free (*out_file);
+      *out_file = NULL;
+    }
+}
+
+static void
+append_text (char *file, const char *str)
+{
+  int fd = open (file, O_RDWR | O_APPEND);
+  if (fd < 0)
+    return;
+
+  write (fd, str, strlen (str));
+  close (fd);
+}
+
+static void
+try_generate_repro (const char *prog, const char **argv)
+{
+  int i, nargs, out_arg = -1, quiet = 0, attempt;
+  const char **new_argv;
+  char *temp_files[RETRY_ICE_ATTEMPTS * 2];
+  char **temp_stdout_files = &temp_files[0];
+  char **temp_stderr_files = &temp_files[RETRY_ICE_ATTEMPTS];
+
+  if (gcc_input_filename == NULL || ! strcmp (gcc_input_filename, "-"))
+    return;
+
+  for (nargs = 0; argv[nargs] != NULL; ++nargs)
+    /* Only retry compiler ICEs, not preprocessor ones.  */
+    if (! strcmp (argv[nargs], "-E"))
+      return;
+    else if (argv[nargs][0] == '-' && argv[nargs][1] == 'o')
+      {
+        if (out_arg == -1)
+          out_arg = nargs;
+        else
+          return;
+      }
+    /* If the compiler is going to output any time information,
+       it might varry between invocations.  */
+    else if (! strcmp (argv[nargs], "-quiet"))
+      quiet = 1;
+    else if (! strcmp (argv[nargs], "-ftime-report"))
+      return;
+
+  if (out_arg == -1 || !quiet)
+    return;
+
+  memset (temp_files, '\0', sizeof (temp_files));
+  new_argv = XALLOCAVEC (const char *, nargs + 4);
+  memcpy (new_argv, argv, (nargs + 1) * sizeof (const char *));
+  new_argv[nargs++] = "-frandom-seed=0";
+  new_argv[nargs++] = "-fdump-noaddr";
+  new_argv[nargs] = NULL;
+  if (new_argv[out_arg][2] == '\0')
+    new_argv[out_arg + 1] = "-";
+  else
+    new_argv[out_arg] = "-o-";
+
+  int status;
+  for (attempt = 0; attempt < RETRY_ICE_ATTEMPTS; ++attempt)
+    {
+      int emit_system_info = 0;
+      int append = 0;
+      temp_stdout_files[attempt] = make_temp_file (".out");
+      temp_stderr_files[attempt] = make_temp_file (".err");
+
+      if (attempt == RETRY_ICE_ATTEMPTS - 1)
+        {
+          append = 1;
+          emit_system_info = 1;
+        }
+
+      if (emit_system_info)
+        append_text (temp_stderr_files[attempt], "/*\n");
+
+      /* Fork a subprocess; wait and retry if it fails.  */
+      status = run_attempt (prog, new_argv, temp_stdout_files[attempt],
+                            temp_stderr_files[attempt], emit_system_info,
+                            append);
+
+      if (emit_system_info)
+        append_text (temp_stderr_files[attempt], "*/\n");
+
+      if (status != ATTEMPT_STATUS_ICE)
+        {
+          fnotice (stderr, "The bug is not reproducible, so it is"
+                   " likely a hardware or OS problem.\n");
+          goto out;
+        }
+    }
+
+  if (!check_repro (temp_stdout_files, temp_stderr_files))
+    goto out;
+
+  /* In final attempt we append cc1 options and preprocesssed code to last
+     generated .err file with configuration and backtrace.  */
+  do_report_bug (prog, new_argv, nargs,
+                              &temp_stderr_files[RETRY_ICE_ATTEMPTS - 1],
+                              &temp_stdout_files[RETRY_ICE_ATTEMPTS - 1]);
+
+out:
+  for (i = 0; i < RETRY_ICE_ATTEMPTS * 2; i++)
+    if (temp_files[i])
+      {
+        unlink (temp_stdout_files[i]);
+        free (temp_stdout_files[i]);
+      }
+}
+#endif
+
 /* Search for a file named NAME trying various prefixes including the
    user's -B prefix and some standard ones.
    Return the absolute file name found.  If nothing is found, return NAME.  */
@@ -6919,43 +7279,9 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
 
   if (verbose_flag)
     {
-      int n;
-      const char *thrmod;
-
-      fnotice (stderr, "Target: %s\n", spec_machine);
-      fnotice (stderr, "Configured with: %s\n", configuration_arguments);
-
-#ifdef THREAD_MODEL_SPEC
-      /* We could have defined THREAD_MODEL_SPEC to "%*" by default,
-	 but there's no point in doing all this processing just to get
-	 thread_model back.  */
-      obstack_init (&obstack);
-      do_spec_1 (THREAD_MODEL_SPEC, 0, thread_model);
-      obstack_1grow (&obstack, '\0');
-      thrmod = XOBFINISH (&obstack, const char *);
-#else
-      thrmod = thread_model;
-#endif
-
-      fnotice (stderr, "Thread model: %s\n", thrmod);
-
-      /* compiler_version is truncated at the first space when initialized
-	 from version string, so truncate version_string at the first space
-	 before comparing.  */
-      for (n = 0; version_string[n]; n++)
-	if (version_string[n] == ' ')
-	  break;
-
-      if (! strncmp (version_string, compiler_version, n)
-	  && compiler_version[n] == 0)
-	fnotice (stderr, "gcc version %s %s\n", version_string,
-		 pkgversion_string);
-      else
-	fnotice (stderr, "gcc driver version %s %sexecuting gcc version %s\n",
-		 version_string, pkgversion_string, compiler_version);
-
+      print_configuration ();
       if (n_infiles == 0)
-	return (0);
+        return (0);
     }
 
   if (n_infiles == added_libraries)

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PING][PATCH] Add patch for debugging compiler ICEs.
  2014-08-04 17:03 [PATCH] Add patch for debugging compiler ICEs Maxim Ostapenko
@ 2014-08-12 16:14 ` Maxim Ostapenko
  2014-08-19 13:58 ` Fwd: [PATCH] " Maxim Ostapenko
  1 sibling, 0 replies; 24+ messages in thread
From: Maxim Ostapenko @ 2014-08-12 16:14 UTC (permalink / raw)
  To: Jeff Law, GCC Patches
  Cc: tsaunders, Yury Gribov, Slava Garbuzov, Maxim Ostapenko

[-- Attachment #1: Type: text/plain, Size: 1593 bytes --]

Ping.

-Maxim
-------- Original Message --------
Subject: 	[PATCH] Add patch for debugging compiler ICEs.
Date: 	Mon, 04 Aug 2014 21:03:22 +0400
From: 	Maxim Ostapenko <m.ostapenko@partner.samsung.com>
To: 	GCC Patches <gcc-patches@gcc.gnu.org>
CC: 	Jeff Law <law@redhat.com>, Jakub Jelinek <jakub@redhat.com>, 
tsaunders@mozilla.com, Yury Gribov <y.gribov@samsung.com>, Slava 
Garbuzov <v.garbuzov@samsung.com>


On 08/04/2014 09:03 PM, Maxim Ostapenko wrote:
> Hi,
>
> A years ago there was a discussion 
> (https://gcc.gnu.org/ml/gcc-patches/2004-01/msg02437.html) about 
> debugging compiler ICEs that resulted in a patch from Jakub, which 
> dumps useful information into temporary file, but for some reasons 
> this patch wasn't applied to trunk.
>
> This is the resurrected patch with added GCC version information into 
> generated repro file.
>
> I've updated the patch that I've posted earlier 
> (https://gcc.gnu.org/ml/gcc-patches/2014-07/msg01649.html ) according 
> to recent upstream discussion 
> (https://gcc.gnu.org/ml/gcc-patches/2014-08/msg00020.html).
>
> The debugging functionality is disabled by default and can be enabled 
> with adding -freport-bug into compile options. It can be also enabled 
> by default with
> --with-spec during GCC build.
>
> There are several directions in which this can be improved e.g:
>
> 1) more user-friendly ways to report bugs (autosubmitting to Bugzilla, 
> etc.)
>
> 2) generate repro in case of segfault.
>
> but having basic functionality (autogenerating reprocase in temprorary 
> file) already seems quite useful.
>
> -Maxim





[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: ICE.diff --]
[-- Type: text/x-patch; name="ICE.diff", Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 24+ messages in thread

* Fwd: [PATCH] Add patch for debugging compiler ICEs.
  2014-08-04 17:03 [PATCH] Add patch for debugging compiler ICEs Maxim Ostapenko
  2014-08-12 16:14 ` [PING][PATCH] " Maxim Ostapenko
@ 2014-08-19 13:58 ` Maxim Ostapenko
  2014-08-28  7:31   ` [Ping v2][PATCH] " Maxim Ostapenko
  1 sibling, 1 reply; 24+ messages in thread
From: Maxim Ostapenko @ 2014-08-19 13:58 UTC (permalink / raw)
  To: Jeff Law, GCC Patches
  Cc: tsaunders, Yury Gribov, Slava Garbuzov, Maxim Ostapenko

[-- Attachment #1: Type: text/plain, Size: 1479 bytes --]

Ping.

-Maxim
-------- Original Message --------
Subject: 	[PATCH] Add patch for debugging compiler ICEs.
Date: 	Mon, 04 Aug 2014 21:03:22 +0400
From: 	Maxim Ostapenko <m.ostapenko@partner.samsung.com>
To: 	GCC Patches <gcc-patches@gcc.gnu.org>
CC: 	Jeff Law <law@redhat.com>, Jakub Jelinek <jakub@redhat.com>, 
tsaunders@mozilla.com, Yury Gribov <y.gribov@samsung.com>, Slava 
Garbuzov <v.garbuzov@samsung.com>



Hi,

A years ago there was a discussion
(https://gcc.gnu.org/ml/gcc-patches/2004-01/msg02437.html) about
debugging compiler ICEs that resulted in a patch from Jakub, which dumps
useful information into temporary file, but for some reasons this patch
wasn't applied to trunk.

This is the resurrected patch with added GCC version information into
generated repro file.

I've updated the patch that I've posted earlier
(https://gcc.gnu.org/ml/gcc-patches/2014-07/msg01649.html ) according to
recent upstream discussion
(https://gcc.gnu.org/ml/gcc-patches/2014-08/msg00020.html).

The debugging functionality is disabled by default and can be enabled
with adding -freport-bug into compile options. It can be also enabled by
default with
--with-spec during GCC build.

There are several directions in which this can be improved e.g:

1) more user-friendly ways to report bugs (autosubmitting to Bugzilla, etc.)

2) generate repro in case of segfault.

but having basic functionality (autogenerating reprocase in temprorary
file) already seems quite useful.

-Maxim




[-- Attachment #2: ICE.diff --]
[-- Type: text/x-patch, Size: 14867 bytes --]

2014-08-04  Jakub Jelinek  <jakub@redhat.com>
	      Max Ostapenko  <m.ostapenko@partner.samsung.com>

	* common.opt: New option.
	* doc/invoke.texi: Describe new option.
	* diagnostic.c (diagnostic_action_after_output): Exit with
	ICE_EXIT_CODE instead of FATAL_EXIT_CODE.
	* gcc.c (execute): Don't free first string early, but at the end
	of the function.  Call retry_ice if compiler exited with
	ICE_EXIT_CODE.
	(main): Factor out common code.
	(print_configuration): New function.
	(try_fork): Likewise.
	(redirect_stdout_stderr): Likewise.
	(files_equal_p): Likewise.
	(check_repro): Likewise.
	(run_attempt): Likewise.
	(do_report_bug): Likewise.
	(append_text): Likewise.
	(try_generate_repro): Likewise

diff --git a/gcc/common.opt b/gcc/common.opt
index 0c4f86b..aa79250 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1120,6 +1120,11 @@ fdump-noaddr
 Common Report Var(flag_dump_noaddr)
 Suppress output of addresses in debugging dumps
 
+freport-bug
+Common Driver Var(flag_report_bug)
+Collect and dump debug information into temporary file if ICE in C/C++
+compiler occured.
+
 fdump-passes
 Common Var(flag_dump_passes) Init(0)
 Dump optimization passes
diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
index 0cc7593..67b8c5b 100644
--- a/gcc/diagnostic.c
+++ b/gcc/diagnostic.c
@@ -492,7 +492,7 @@ diagnostic_action_after_output (diagnostic_context *context,
 	real_abort ();
       diagnostic_finish (context);
       fnotice (stderr, "compilation terminated.\n");
-      exit (FATAL_EXIT_CODE);
+      exit (ICE_EXIT_CODE);
 
     default:
       gcc_unreachable ();
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 4f327df..dafb573 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -6271,6 +6271,11 @@ feasible to use diff on debugging dumps for compiler invocations with
 different compiler binaries and/or different
 text / bss / data / heap / stack / dso start locations.
 
+@item -freport-bug
+@opindex freport-bug
+Collect and dump debug information into temporary file if ICE in C/C++
+compiler occured.
+
 @item -fdump-unnumbered
 @opindex fdump-unnumbered
 When doing debugging dumps, suppress instruction numbers and address output.
diff --git a/gcc/gcc.c b/gcc/gcc.c
index 44d0416..f7a56d1 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -43,6 +43,13 @@ compilation is specified by a string called a "spec".  */
 #include "params.h"
 #include "vec.h"
 #include "filenames.h"
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#if !(defined (__MSDOS__) || defined (OS2) || defined (VMS))
+#define RETRY_ICE_SUPPORTED
+#endif
 
 /* By default there is no special suffix for target executables.  */
 /* FIXME: when autoconf is fixed, remove the host check - dj */
@@ -253,6 +260,9 @@ static void init_gcc_specs (struct obstack *, const char *, const char *,
 static const char *convert_filename (const char *, int, int);
 #endif
 
+#ifdef RETRY_ICE_SUPPORTED
+static void try_generate_repro (const char *prog, const char **argv);
+#endif
 static const char *getenv_spec_function (int, const char **);
 static const char *if_exists_spec_function (int, const char **);
 static const char *if_exists_else_spec_function (int, const char **);
@@ -2849,7 +2859,7 @@ execute (void)
 	    }
 	}
 
-      if (string != commands[i].prog)
+      if (i && string != commands[i].prog)
 	free (CONST_CAST (char *, string));
     }
 
@@ -2902,6 +2912,17 @@ execute (void)
 	else if (WIFEXITED (status)
 		 && WEXITSTATUS (status) >= MIN_FATAL_STATUS)
 	  {
+#ifdef RETRY_ICE_SUPPORTED
+	    /* For ICEs in cc1, cc1obj, cc1plus see if it is
+	       reproducible or not.  */
+	    const char *p;
+	    if (flag_report_bug
+		&& WEXITSTATUS (status) == ICE_EXIT_CODE
+		&& i == 0
+		&& (p = strrchr (commands[0].argv[0], DIR_SEPARATOR))
+		&& ! strncmp (p + 1, "cc1", 3))
+	      try_generate_repro (commands[0].prog, commands[0].argv);
+#endif
 	    if (WEXITSTATUS (status) > greatest_status)
 	      greatest_status = WEXITSTATUS (status);
 	    ret_code = -1;
@@ -2959,6 +2980,9 @@ execute (void)
 	  }
       }
 
+   if (commands[0].argv[0] != commands[0].prog)
+     free (CONST_CAST (char *, commands[0].argv[0]));
+
     return ret_code;
   }
 }
@@ -6150,6 +6174,342 @@ give_switch (int switchnum, int omit_first_word)
   switches[switchnum].validated = true;
 }
 \f
+static void
+print_configuration (void)
+{
+  int n;
+  const char *thrmod;
+
+  fnotice (stderr, "Target: %s\n", spec_machine);
+  fnotice (stderr, "Configured with: %s\n", configuration_arguments);
+
+#ifdef THREAD_MODEL_SPEC
+  /* We could have defined THREAD_MODEL_SPEC to "%*" by default,
+  but there's no point in doing all this processing just to get
+  thread_model back.  */
+  obstack_init (&obstack);
+  do_spec_1 (THREAD_MODEL_SPEC, 0, thread_model);
+  obstack_1grow (&obstack, '\0');
+  thrmod = XOBFINISH (&obstack, const char *);
+#else
+  thrmod = thread_model;
+#endif
+
+  fnotice (stderr, "Thread model: %s\n", thrmod);
+
+  /* compiler_version is truncated at the first space when initialized
+  from version string, so truncate version_string at the first space
+  before comparing.  */
+  for (n = 0; version_string[n]; n++)
+    if (version_string[n] == ' ')
+      break;
+
+  if (! strncmp (version_string, compiler_version, n)
+      && compiler_version[n] == 0)
+    fnotice (stderr, "gcc version %s %s\n\n", version_string,
+             pkgversion_string);
+  else
+    fnotice (stderr, "gcc driver version %s %sexecuting gcc version %s\n\n",
+             version_string, pkgversion_string, compiler_version);
+}
+
+#ifdef RETRY_ICE_SUPPORTED
+#define RETRY_ICE_ATTEMPTS 3
+
+static int
+try_fork ()
+{
+  int pid, retries, sleep_interval;
+  sleep_interval = 1;
+  pid = -1;
+  for (retries = 0; retries < 4; retries++)
+    {
+      pid = fork ();
+      if (pid >= 0)
+        break;
+      sleep (sleep_interval);
+      sleep_interval *= 2;
+    }
+  return pid;
+}
+
+
+static void
+redirect_stdout_stderr (const char *out_temp, const char *err_temp,
+                        int append)
+{
+  int fd;
+  fd = open (out_temp, append ? O_RDWR | O_APPEND : O_RDWR);
+
+  if (fd < 0)
+    exit (-1);
+
+  close (STDOUT_FILENO);
+  dup (fd);
+  close (fd);
+
+  fd = open (err_temp, append ? O_RDWR | O_APPEND : O_RDWR);
+
+  if (fd < 0)
+    exit (-1);
+
+  close (STDERR_FILENO);
+  dup (fd);
+  close (fd);
+}
+
+static int
+files_equal_p (char *file1, char *file2, char *buf, const int bufsize)
+{
+  struct stat st1, st2;
+  size_t n, len;
+  int fd1, fd2;
+
+  fd1 = open (file1, O_RDONLY);
+  fd2 = open (file2, O_RDONLY);
+
+  if (fd1 < 0 || fd2 < 0)
+    goto error;
+
+  if (fstat (fd1, &st1) < 0 || fstat (fd2, &st2) < 0)
+    goto error;
+
+  if (st1.st_size != st2.st_size)
+    goto error;
+
+  for (n = st1.st_size; n; n -= len)
+    {
+      len = n;
+      if ((int) len > bufsize / 2)
+        len = bufsize / 2;
+
+      if (read (fd1, buf, len) != (int) len
+          || read (fd2, buf + bufsize / 2, len) != (int) len)
+        {
+          goto error;
+        }
+
+      if (memcmp (buf, buf + bufsize / 2, len) != 0)
+        goto error;
+    }
+
+  close (fd1);
+  close (fd2);
+
+  return 1;
+
+error:
+  close (fd1);
+  close (fd2);
+  return 0;
+}
+
+static int
+check_repro (char **temp_stdout_files, char **temp_stderr_files)
+{
+  int i;
+  const int ice_bufsize = 8192;
+  char *ice_buf = XNEWVEC (char, ice_bufsize);
+  for (i = 0; i < RETRY_ICE_ATTEMPTS - 2; ++i)
+    {
+     if (!files_equal_p (temp_stdout_files[i], temp_stdout_files[i + 1],
+                        ice_buf, ice_bufsize)
+         || !files_equal_p (temp_stderr_files[i], temp_stderr_files[i + 1],
+                          ice_buf, ice_bufsize))
+        {
+          fnotice (stderr, "The bug is not reproducible, so it is"
+                   " likely a hardware or OS problem.\n");
+          break;
+        }
+    }
+  free (ice_buf);
+  return i == RETRY_ICE_ATTEMPTS - 2;
+}
+
+enum attempt_status {
+  ATTEMPT_STATUS_FAIL_TO_RUN,
+  ATTEMPT_STATUS_SUCCESS,
+  ATTEMPT_STATUS_ICE
+};
+
+static enum attempt_status
+run_attempt (const char *prog, const char **new_argv, const char *out_temp,
+             const char *err_temp, int emit_system_info, int append)
+{
+  int status;
+  int pid = try_fork ();
+  if (pid < 0)
+    return ATTEMPT_STATUS_FAIL_TO_RUN;
+  else if (pid == 0)
+    {
+      redirect_stdout_stderr (out_temp, err_temp, append);
+
+      if (emit_system_info)
+        print_configuration ();
+
+      if (prog == new_argv[0])
+        execvp (prog, CONST_CAST2 (char *const *, const char **, new_argv));
+      else
+        execv (new_argv[0], CONST_CAST2 (char *const *, const char **,
+               new_argv));
+      exit (-1);
+    }
+
+  if (waitpid (pid, &status, 0) < 0)
+    return ATTEMPT_STATUS_FAIL_TO_RUN;
+
+  switch (WEXITSTATUS (status))
+    {
+      case ICE_EXIT_CODE:
+        return ATTEMPT_STATUS_ICE;
+
+      case SUCCESS_EXIT_CODE:
+        return ATTEMPT_STATUS_SUCCESS;
+
+      default:
+        return ATTEMPT_STATUS_FAIL_TO_RUN;
+    }
+}
+
+static void
+do_report_bug (const char *prog, const char **new_argv,
+                            const int nargs, char **out_file, char **err_file)
+{
+  int i, status;
+  int fd = open (*out_file, O_RDWR | O_APPEND);
+  if (fd < 0)
+    return;
+  write (fd, "\n//", 3);
+  for (i = 0; i < nargs; i++)
+    {
+      write (fd, " ", 1);
+      write (fd, new_argv[i], strlen (new_argv[i]));
+    }
+  write (fd, "\n\n", 2);
+  close (fd);
+  new_argv[nargs] = "-E";
+  new_argv[nargs + 1] = NULL;
+
+  status = run_attempt (prog, new_argv, *out_file, *err_file, 0, 1);
+
+  if (status == ATTEMPT_STATUS_SUCCESS)
+    {
+      fnotice (stderr, "Preprocessed source stored into %s file,"
+               " please attach this to your bugreport.\n",
+               *out_file);
+      /* Make sure it is not deleted.  */
+      free (*out_file);
+      *out_file = NULL;
+    }
+}
+
+static void
+append_text (char *file, const char *str)
+{
+  int fd = open (file, O_RDWR | O_APPEND);
+  if (fd < 0)
+    return;
+
+  write (fd, str, strlen (str));
+  close (fd);
+}
+
+static void
+try_generate_repro (const char *prog, const char **argv)
+{
+  int i, nargs, out_arg = -1, quiet = 0, attempt;
+  const char **new_argv;
+  char *temp_files[RETRY_ICE_ATTEMPTS * 2];
+  char **temp_stdout_files = &temp_files[0];
+  char **temp_stderr_files = &temp_files[RETRY_ICE_ATTEMPTS];
+
+  if (gcc_input_filename == NULL || ! strcmp (gcc_input_filename, "-"))
+    return;
+
+  for (nargs = 0; argv[nargs] != NULL; ++nargs)
+    /* Only retry compiler ICEs, not preprocessor ones.  */
+    if (! strcmp (argv[nargs], "-E"))
+      return;
+    else if (argv[nargs][0] == '-' && argv[nargs][1] == 'o')
+      {
+        if (out_arg == -1)
+          out_arg = nargs;
+        else
+          return;
+      }
+    /* If the compiler is going to output any time information,
+       it might varry between invocations.  */
+    else if (! strcmp (argv[nargs], "-quiet"))
+      quiet = 1;
+    else if (! strcmp (argv[nargs], "-ftime-report"))
+      return;
+
+  if (out_arg == -1 || !quiet)
+    return;
+
+  memset (temp_files, '\0', sizeof (temp_files));
+  new_argv = XALLOCAVEC (const char *, nargs + 4);
+  memcpy (new_argv, argv, (nargs + 1) * sizeof (const char *));
+  new_argv[nargs++] = "-frandom-seed=0";
+  new_argv[nargs++] = "-fdump-noaddr";
+  new_argv[nargs] = NULL;
+  if (new_argv[out_arg][2] == '\0')
+    new_argv[out_arg + 1] = "-";
+  else
+    new_argv[out_arg] = "-o-";
+
+  int status;
+  for (attempt = 0; attempt < RETRY_ICE_ATTEMPTS; ++attempt)
+    {
+      int emit_system_info = 0;
+      int append = 0;
+      temp_stdout_files[attempt] = make_temp_file (".out");
+      temp_stderr_files[attempt] = make_temp_file (".err");
+
+      if (attempt == RETRY_ICE_ATTEMPTS - 1)
+        {
+          append = 1;
+          emit_system_info = 1;
+        }
+
+      if (emit_system_info)
+        append_text (temp_stderr_files[attempt], "/*\n");
+
+      /* Fork a subprocess; wait and retry if it fails.  */
+      status = run_attempt (prog, new_argv, temp_stdout_files[attempt],
+                            temp_stderr_files[attempt], emit_system_info,
+                            append);
+
+      if (emit_system_info)
+        append_text (temp_stderr_files[attempt], "*/\n");
+
+      if (status != ATTEMPT_STATUS_ICE)
+        {
+          fnotice (stderr, "The bug is not reproducible, so it is"
+                   " likely a hardware or OS problem.\n");
+          goto out;
+        }
+    }
+
+  if (!check_repro (temp_stdout_files, temp_stderr_files))
+    goto out;
+
+  /* In final attempt we append cc1 options and preprocesssed code to last
+     generated .err file with configuration and backtrace.  */
+  do_report_bug (prog, new_argv, nargs,
+                              &temp_stderr_files[RETRY_ICE_ATTEMPTS - 1],
+                              &temp_stdout_files[RETRY_ICE_ATTEMPTS - 1]);
+
+out:
+  for (i = 0; i < RETRY_ICE_ATTEMPTS * 2; i++)
+    if (temp_files[i])
+      {
+        unlink (temp_stdout_files[i]);
+        free (temp_stdout_files[i]);
+      }
+}
+#endif
+
 /* Search for a file named NAME trying various prefixes including the
    user's -B prefix and some standard ones.
    Return the absolute file name found.  If nothing is found, return NAME.  */
@@ -6919,43 +7279,9 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
 
   if (verbose_flag)
     {
-      int n;
-      const char *thrmod;
-
-      fnotice (stderr, "Target: %s\n", spec_machine);
-      fnotice (stderr, "Configured with: %s\n", configuration_arguments);
-
-#ifdef THREAD_MODEL_SPEC
-      /* We could have defined THREAD_MODEL_SPEC to "%*" by default,
-	 but there's no point in doing all this processing just to get
-	 thread_model back.  */
-      obstack_init (&obstack);
-      do_spec_1 (THREAD_MODEL_SPEC, 0, thread_model);
-      obstack_1grow (&obstack, '\0');
-      thrmod = XOBFINISH (&obstack, const char *);
-#else
-      thrmod = thread_model;
-#endif
-
-      fnotice (stderr, "Thread model: %s\n", thrmod);
-
-      /* compiler_version is truncated at the first space when initialized
-	 from version string, so truncate version_string at the first space
-	 before comparing.  */
-      for (n = 0; version_string[n]; n++)
-	if (version_string[n] == ' ')
-	  break;
-
-      if (! strncmp (version_string, compiler_version, n)
-	  && compiler_version[n] == 0)
-	fnotice (stderr, "gcc version %s %s\n", version_string,
-		 pkgversion_string);
-      else
-	fnotice (stderr, "gcc driver version %s %sexecuting gcc version %s\n",
-		 version_string, pkgversion_string, compiler_version);
-
+      print_configuration ();
       if (n_infiles == 0)
-	return (0);
+        return (0);
     }
 
   if (n_infiles == added_libraries)


^ permalink raw reply	[flat|nested] 24+ messages in thread

* [Ping v2][PATCH] Add patch for debugging compiler ICEs.
  2014-08-19 13:58 ` Fwd: [PATCH] " Maxim Ostapenko
@ 2014-08-28  7:31   ` Maxim Ostapenko
  2014-09-05 14:16     ` [Ping v3][PATCH] " Maxim Ostapenko
  2014-09-09 22:51     ` [Ping v2][PATCH] " Joseph S. Myers
  0 siblings, 2 replies; 24+ messages in thread
From: Maxim Ostapenko @ 2014-08-28  7:31 UTC (permalink / raw)
  To: GCC Patches, Jeff Law, joseph
  Cc: Yury Gribov, Slava Garbuzov, Maxim Ostapenko

[-- Attachment #1: Type: text/plain, Size: 1945 bytes --]

Ping. Add Joseph S. Myers as driver maintainer.

-Maxim
-------- Original Message --------
Subject: 	Fwd: [PATCH] Add patch for debugging compiler ICEs.
Date: 	Tue, 19 Aug 2014 17:57:51 +0400
From: 	Maxim Ostapenko <m.ostapenko@partner.samsung.com>
To: 	Jeff Law <law@redhat.com>, GCC Patches <gcc-patches@gcc.gnu.org>
CC: 	tsaunders@mozilla.com, Yury Gribov <y.gribov@samsung.com>, Slava 
Garbuzov <v.garbuzov@samsung.com>, Maxim Ostapenko <chefmax7@gmail.com>



Ping.

-Maxim
-------- Original Message --------
Subject: 	[PATCH] Add patch for debugging compiler ICEs.
Date: 	Mon, 04 Aug 2014 21:03:22 +0400
From: 	Maxim Ostapenko <m.ostapenko@partner.samsung.com>
To: 	GCC Patches <gcc-patches@gcc.gnu.org>
CC: 	Jeff Law <law@redhat.com>, Jakub Jelinek <jakub@redhat.com>,
tsaunders@mozilla.com, Yury Gribov <y.gribov@samsung.com>, Slava
Garbuzov <v.garbuzov@samsung.com>



Hi,

A years ago there was a discussion
(https://gcc.gnu.org/ml/gcc-patches/2004-01/msg02437.html) about
debugging compiler ICEs that resulted in a patch from Jakub, which dumps
useful information into temporary file, but for some reasons this patch
wasn't applied to trunk.

This is the resurrected patch with added GCC version information into
generated repro file.

I've updated the patch that I've posted earlier
(https://gcc.gnu.org/ml/gcc-patches/2014-07/msg01649.html ) according to
recent upstream discussion
(https://gcc.gnu.org/ml/gcc-patches/2014-08/msg00020.html).

The debugging functionality is disabled by default and can be enabled
with adding -freport-bug into compile options. It can be also enabled by
default with
--with-spec during GCC build.

There are several directions in which this can be improved e.g:

1) more user-friendly ways to report bugs (autosubmitting to Bugzilla, etc.)

2) generate repro in case of segfault.

but having basic functionality (autogenerating reprocase in temprorary
file) already seems quite useful.

-Maxim







[-- Attachment #2: ICE.diff --]
[-- Type: text/x-patch, Size: 14868 bytes --]

2014-08-04  Jakub Jelinek  <jakub@redhat.com>
	      Max Ostapenko  <m.ostapenko@partner.samsung.com>

	* common.opt: New option.
	* doc/invoke.texi: Describe new option.
	* diagnostic.c (diagnostic_action_after_output): Exit with
	ICE_EXIT_CODE instead of FATAL_EXIT_CODE.
	* gcc.c (execute): Don't free first string early, but at the end
	of the function.  Call retry_ice if compiler exited with
	ICE_EXIT_CODE.
	(main): Factor out common code.
	(print_configuration): New function.
	(try_fork): Likewise.
	(redirect_stdout_stderr): Likewise.
	(files_equal_p): Likewise.
	(check_repro): Likewise.
	(run_attempt): Likewise.
	(do_report_bug): Likewise.
	(append_text): Likewise.
	(try_generate_repro): Likewise

diff --git a/gcc/common.opt b/gcc/common.opt
index 0c4f86b..aa79250 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1120,6 +1120,11 @@ fdump-noaddr
 Common Report Var(flag_dump_noaddr)
 Suppress output of addresses in debugging dumps
 
+freport-bug
+Common Driver Var(flag_report_bug)
+Collect and dump debug information into temporary file if ICE in C/C++
+compiler occured.
+
 fdump-passes
 Common Var(flag_dump_passes) Init(0)
 Dump optimization passes
diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
index 0cc7593..67b8c5b 100644
--- a/gcc/diagnostic.c
+++ b/gcc/diagnostic.c
@@ -492,7 +492,7 @@ diagnostic_action_after_output (diagnostic_context *context,
 	real_abort ();
       diagnostic_finish (context);
       fnotice (stderr, "compilation terminated.\n");
-      exit (FATAL_EXIT_CODE);
+      exit (ICE_EXIT_CODE);
 
     default:
       gcc_unreachable ();
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 4f327df..dafb573 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -6271,6 +6271,11 @@ feasible to use diff on debugging dumps for compiler invocations with
 different compiler binaries and/or different
 text / bss / data / heap / stack / dso start locations.
 
+@item -freport-bug
+@opindex freport-bug
+Collect and dump debug information into temporary file if ICE in C/C++
+compiler occured.
+
 @item -fdump-unnumbered
 @opindex fdump-unnumbered
 When doing debugging dumps, suppress instruction numbers and address output.
diff --git a/gcc/gcc.c b/gcc/gcc.c
index 44d0416..f7a56d1 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -43,6 +43,13 @@ compilation is specified by a string called a "spec".  */
 #include "params.h"
 #include "vec.h"
 #include "filenames.h"
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#if !(defined (__MSDOS__) || defined (OS2) || defined (VMS))
+#define RETRY_ICE_SUPPORTED
+#endif
 
 /* By default there is no special suffix for target executables.  */
 /* FIXME: when autoconf is fixed, remove the host check - dj */
@@ -253,6 +260,9 @@ static void init_gcc_specs (struct obstack *, const char *, const char *,
 static const char *convert_filename (const char *, int, int);
 #endif
 
+#ifdef RETRY_ICE_SUPPORTED
+static void try_generate_repro (const char *prog, const char **argv);
+#endif
 static const char *getenv_spec_function (int, const char **);
 static const char *if_exists_spec_function (int, const char **);
 static const char *if_exists_else_spec_function (int, const char **);
@@ -2849,7 +2859,7 @@ execute (void)
 	    }
 	}
 
-      if (string != commands[i].prog)
+      if (i && string != commands[i].prog)
 	free (CONST_CAST (char *, string));
     }
 
@@ -2902,6 +2912,17 @@ execute (void)
 	else if (WIFEXITED (status)
 		 && WEXITSTATUS (status) >= MIN_FATAL_STATUS)
 	  {
+#ifdef RETRY_ICE_SUPPORTED
+	    /* For ICEs in cc1, cc1obj, cc1plus see if it is
+	       reproducible or not.  */
+	    const char *p;
+	    if (flag_report_bug
+		&& WEXITSTATUS (status) == ICE_EXIT_CODE
+		&& i == 0
+		&& (p = strrchr (commands[0].argv[0], DIR_SEPARATOR))
+		&& ! strncmp (p + 1, "cc1", 3))
+	      try_generate_repro (commands[0].prog, commands[0].argv);
+#endif
 	    if (WEXITSTATUS (status) > greatest_status)
 	      greatest_status = WEXITSTATUS (status);
 	    ret_code = -1;
@@ -2959,6 +2980,9 @@ execute (void)
 	  }
       }
 
+   if (commands[0].argv[0] != commands[0].prog)
+     free (CONST_CAST (char *, commands[0].argv[0]));
+
     return ret_code;
   }
 }
@@ -6150,6 +6174,342 @@ give_switch (int switchnum, int omit_first_word)
   switches[switchnum].validated = true;
 }
 \f
+static void
+print_configuration (void)
+{
+  int n;
+  const char *thrmod;
+
+  fnotice (stderr, "Target: %s\n", spec_machine);
+  fnotice (stderr, "Configured with: %s\n", configuration_arguments);
+
+#ifdef THREAD_MODEL_SPEC
+  /* We could have defined THREAD_MODEL_SPEC to "%*" by default,
+  but there's no point in doing all this processing just to get
+  thread_model back.  */
+  obstack_init (&obstack);
+  do_spec_1 (THREAD_MODEL_SPEC, 0, thread_model);
+  obstack_1grow (&obstack, '\0');
+  thrmod = XOBFINISH (&obstack, const char *);
+#else
+  thrmod = thread_model;
+#endif
+
+  fnotice (stderr, "Thread model: %s\n", thrmod);
+
+  /* compiler_version is truncated at the first space when initialized
+  from version string, so truncate version_string at the first space
+  before comparing.  */
+  for (n = 0; version_string[n]; n++)
+    if (version_string[n] == ' ')
+      break;
+
+  if (! strncmp (version_string, compiler_version, n)
+      && compiler_version[n] == 0)
+    fnotice (stderr, "gcc version %s %s\n\n", version_string,
+             pkgversion_string);
+  else
+    fnotice (stderr, "gcc driver version %s %sexecuting gcc version %s\n\n",
+             version_string, pkgversion_string, compiler_version);
+}
+
+#ifdef RETRY_ICE_SUPPORTED
+#define RETRY_ICE_ATTEMPTS 3
+
+static int
+try_fork ()
+{
+  int pid, retries, sleep_interval;
+  sleep_interval = 1;
+  pid = -1;
+  for (retries = 0; retries < 4; retries++)
+    {
+      pid = fork ();
+      if (pid >= 0)
+        break;
+      sleep (sleep_interval);
+      sleep_interval *= 2;
+    }
+  return pid;
+}
+
+
+static void
+redirect_stdout_stderr (const char *out_temp, const char *err_temp,
+                        int append)
+{
+  int fd;
+  fd = open (out_temp, append ? O_RDWR | O_APPEND : O_RDWR);
+
+  if (fd < 0)
+    exit (-1);
+
+  close (STDOUT_FILENO);
+  dup (fd);
+  close (fd);
+
+  fd = open (err_temp, append ? O_RDWR | O_APPEND : O_RDWR);
+
+  if (fd < 0)
+    exit (-1);
+
+  close (STDERR_FILENO);
+  dup (fd);
+  close (fd);
+}
+
+static int
+files_equal_p (char *file1, char *file2, char *buf, const int bufsize)
+{
+  struct stat st1, st2;
+  size_t n, len;
+  int fd1, fd2;
+
+  fd1 = open (file1, O_RDONLY);
+  fd2 = open (file2, O_RDONLY);
+
+  if (fd1 < 0 || fd2 < 0)
+    goto error;
+
+  if (fstat (fd1, &st1) < 0 || fstat (fd2, &st2) < 0)
+    goto error;
+
+  if (st1.st_size != st2.st_size)
+    goto error;
+
+  for (n = st1.st_size; n; n -= len)
+    {
+      len = n;
+      if ((int) len > bufsize / 2)
+        len = bufsize / 2;
+
+      if (read (fd1, buf, len) != (int) len
+          || read (fd2, buf + bufsize / 2, len) != (int) len)
+        {
+          goto error;
+        }
+
+      if (memcmp (buf, buf + bufsize / 2, len) != 0)
+        goto error;
+    }
+
+  close (fd1);
+  close (fd2);
+
+  return 1;
+
+error:
+  close (fd1);
+  close (fd2);
+  return 0;
+}
+
+static int
+check_repro (char **temp_stdout_files, char **temp_stderr_files)
+{
+  int i;
+  const int ice_bufsize = 8192;
+  char *ice_buf = XNEWVEC (char, ice_bufsize);
+  for (i = 0; i < RETRY_ICE_ATTEMPTS - 2; ++i)
+    {
+     if (!files_equal_p (temp_stdout_files[i], temp_stdout_files[i + 1],
+                        ice_buf, ice_bufsize)
+         || !files_equal_p (temp_stderr_files[i], temp_stderr_files[i + 1],
+                          ice_buf, ice_bufsize))
+        {
+          fnotice (stderr, "The bug is not reproducible, so it is"
+                   " likely a hardware or OS problem.\n");
+          break;
+        }
+    }
+  free (ice_buf);
+  return i == RETRY_ICE_ATTEMPTS - 2;
+}
+
+enum attempt_status {
+  ATTEMPT_STATUS_FAIL_TO_RUN,
+  ATTEMPT_STATUS_SUCCESS,
+  ATTEMPT_STATUS_ICE
+};
+
+static enum attempt_status
+run_attempt (const char *prog, const char **new_argv, const char *out_temp,
+             const char *err_temp, int emit_system_info, int append)
+{
+  int status;
+  int pid = try_fork ();
+  if (pid < 0)
+    return ATTEMPT_STATUS_FAIL_TO_RUN;
+  else if (pid == 0)
+    {
+      redirect_stdout_stderr (out_temp, err_temp, append);
+
+      if (emit_system_info)
+        print_configuration ();
+
+      if (prog == new_argv[0])
+        execvp (prog, CONST_CAST2 (char *const *, const char **, new_argv));
+      else
+        execv (new_argv[0], CONST_CAST2 (char *const *, const char **,
+               new_argv));
+      exit (-1);
+    }
+
+  if (waitpid (pid, &status, 0) < 0)
+    return ATTEMPT_STATUS_FAIL_TO_RUN;
+
+  switch (WEXITSTATUS (status))
+    {
+      case ICE_EXIT_CODE:
+        return ATTEMPT_STATUS_ICE;
+
+      case SUCCESS_EXIT_CODE:
+        return ATTEMPT_STATUS_SUCCESS;
+
+      default:
+        return ATTEMPT_STATUS_FAIL_TO_RUN;
+    }
+}
+
+static void
+do_report_bug (const char *prog, const char **new_argv,
+                            const int nargs, char **out_file, char **err_file)
+{
+  int i, status;
+  int fd = open (*out_file, O_RDWR | O_APPEND);
+  if (fd < 0)
+    return;
+  write (fd, "\n//", 3);
+  for (i = 0; i < nargs; i++)
+    {
+      write (fd, " ", 1);
+      write (fd, new_argv[i], strlen (new_argv[i]));
+    }
+  write (fd, "\n\n", 2);
+  close (fd);
+  new_argv[nargs] = "-E";
+  new_argv[nargs + 1] = NULL;
+
+  status = run_attempt (prog, new_argv, *out_file, *err_file, 0, 1);
+
+  if (status == ATTEMPT_STATUS_SUCCESS)
+    {
+      fnotice (stderr, "Preprocessed source stored into %s file,"
+               " please attach this to your bugreport.\n",
+               *out_file);
+      /* Make sure it is not deleted.  */
+      free (*out_file);
+      *out_file = NULL;
+    }
+}
+
+static void
+append_text (char *file, const char *str)
+{
+  int fd = open (file, O_RDWR | O_APPEND);
+  if (fd < 0)
+    return;
+
+  write (fd, str, strlen (str));
+  close (fd);
+}
+
+static void
+try_generate_repro (const char *prog, const char **argv)
+{
+  int i, nargs, out_arg = -1, quiet = 0, attempt;
+  const char **new_argv;
+  char *temp_files[RETRY_ICE_ATTEMPTS * 2];
+  char **temp_stdout_files = &temp_files[0];
+  char **temp_stderr_files = &temp_files[RETRY_ICE_ATTEMPTS];
+
+  if (gcc_input_filename == NULL || ! strcmp (gcc_input_filename, "-"))
+    return;
+
+  for (nargs = 0; argv[nargs] != NULL; ++nargs)
+    /* Only retry compiler ICEs, not preprocessor ones.  */
+    if (! strcmp (argv[nargs], "-E"))
+      return;
+    else if (argv[nargs][0] == '-' && argv[nargs][1] == 'o')
+      {
+        if (out_arg == -1)
+          out_arg = nargs;
+        else
+          return;
+      }
+    /* If the compiler is going to output any time information,
+       it might varry between invocations.  */
+    else if (! strcmp (argv[nargs], "-quiet"))
+      quiet = 1;
+    else if (! strcmp (argv[nargs], "-ftime-report"))
+      return;
+
+  if (out_arg == -1 || !quiet)
+    return;
+
+  memset (temp_files, '\0', sizeof (temp_files));
+  new_argv = XALLOCAVEC (const char *, nargs + 4);
+  memcpy (new_argv, argv, (nargs + 1) * sizeof (const char *));
+  new_argv[nargs++] = "-frandom-seed=0";
+  new_argv[nargs++] = "-fdump-noaddr";
+  new_argv[nargs] = NULL;
+  if (new_argv[out_arg][2] == '\0')
+    new_argv[out_arg + 1] = "-";
+  else
+    new_argv[out_arg] = "-o-";
+
+  int status;
+  for (attempt = 0; attempt < RETRY_ICE_ATTEMPTS; ++attempt)
+    {
+      int emit_system_info = 0;
+      int append = 0;
+      temp_stdout_files[attempt] = make_temp_file (".out");
+      temp_stderr_files[attempt] = make_temp_file (".err");
+
+      if (attempt == RETRY_ICE_ATTEMPTS - 1)
+        {
+          append = 1;
+          emit_system_info = 1;
+        }
+
+      if (emit_system_info)
+        append_text (temp_stderr_files[attempt], "/*\n");
+
+      /* Fork a subprocess; wait and retry if it fails.  */
+      status = run_attempt (prog, new_argv, temp_stdout_files[attempt],
+                            temp_stderr_files[attempt], emit_system_info,
+                            append);
+
+      if (emit_system_info)
+        append_text (temp_stderr_files[attempt], "*/\n");
+
+      if (status != ATTEMPT_STATUS_ICE)
+        {
+          fnotice (stderr, "The bug is not reproducible, so it is"
+                   " likely a hardware or OS problem.\n");
+          goto out;
+        }
+    }
+
+  if (!check_repro (temp_stdout_files, temp_stderr_files))
+    goto out;
+
+  /* In final attempt we append cc1 options and preprocesssed code to last
+     generated .err file with configuration and backtrace.  */
+  do_report_bug (prog, new_argv, nargs,
+                              &temp_stderr_files[RETRY_ICE_ATTEMPTS - 1],
+                              &temp_stdout_files[RETRY_ICE_ATTEMPTS - 1]);
+
+out:
+  for (i = 0; i < RETRY_ICE_ATTEMPTS * 2; i++)
+    if (temp_files[i])
+      {
+        unlink (temp_stdout_files[i]);
+        free (temp_stdout_files[i]);
+      }
+}
+#endif
+
 /* Search for a file named NAME trying various prefixes including the
    user's -B prefix and some standard ones.
    Return the absolute file name found.  If nothing is found, return NAME.  */
@@ -6919,43 +7279,9 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
 
   if (verbose_flag)
     {
-      int n;
-      const char *thrmod;
-
-      fnotice (stderr, "Target: %s\n", spec_machine);
-      fnotice (stderr, "Configured with: %s\n", configuration_arguments);
-
-#ifdef THREAD_MODEL_SPEC
-      /* We could have defined THREAD_MODEL_SPEC to "%*" by default,
-	 but there's no point in doing all this processing just to get
-	 thread_model back.  */
-      obstack_init (&obstack);
-      do_spec_1 (THREAD_MODEL_SPEC, 0, thread_model);
-      obstack_1grow (&obstack, '\0');
-      thrmod = XOBFINISH (&obstack, const char *);
-#else
-      thrmod = thread_model;
-#endif
-
-      fnotice (stderr, "Thread model: %s\n", thrmod);
-
-      /* compiler_version is truncated at the first space when initialized
-	 from version string, so truncate version_string at the first space
-	 before comparing.  */
-      for (n = 0; version_string[n]; n++)
-	if (version_string[n] == ' ')
-	  break;
-
-      if (! strncmp (version_string, compiler_version, n)
-	  && compiler_version[n] == 0)
-	fnotice (stderr, "gcc version %s %s\n", version_string,
-		 pkgversion_string);
-      else
-	fnotice (stderr, "gcc driver version %s %sexecuting gcc version %s\n",
-		 version_string, pkgversion_string, compiler_version);
-
+      print_configuration ();
       if (n_infiles == 0)
-	return (0);
+        return (0);
     }
 
   if (n_infiles == added_libraries)



^ permalink raw reply	[flat|nested] 24+ messages in thread

* [Ping v3][PATCH] Add patch for debugging compiler ICEs.
  2014-08-28  7:31   ` [Ping v2][PATCH] " Maxim Ostapenko
@ 2014-09-05 14:16     ` Maxim Ostapenko
  2014-09-09 22:51     ` [Ping v2][PATCH] " Joseph S. Myers
  1 sibling, 0 replies; 24+ messages in thread
From: Maxim Ostapenko @ 2014-09-05 14:16 UTC (permalink / raw)
  To: GCC Patches, Jeff Law, joseph
  Cc: Yury Gribov, Slava Garbuzov, Maxim Ostapenko

[-- Attachment #1: Type: text/plain, Size: 2148 bytes --]

Ping.

-Maxim
On 08/28/2014 11:31 AM, Maxim Ostapenko wrote:
> Ping. Add Joseph S. Myers as driver maintainer.
>
> -Maxim
> -------- Original Message --------
> Subject:     Fwd: [PATCH] Add patch for debugging compiler ICEs.
> Date:     Tue, 19 Aug 2014 17:57:51 +0400
> From:     Maxim Ostapenko <m.ostapenko@partner.samsung.com>
> To:     Jeff Law <law@redhat.com>, GCC Patches <gcc-patches@gcc.gnu.org>
> CC:     tsaunders@mozilla.com, Yury Gribov <y.gribov@samsung.com>, 
> Slava Garbuzov <v.garbuzov@samsung.com>, Maxim Ostapenko 
> <chefmax7@gmail.com>
>
>
>
> Ping.
>
> -Maxim
> -------- Original Message --------
> Subject:     [PATCH] Add patch for debugging compiler ICEs.
> Date:     Mon, 04 Aug 2014 21:03:22 +0400
> From:     Maxim Ostapenko <m.ostapenko@partner.samsung.com>
> To:     GCC Patches <gcc-patches@gcc.gnu.org>
> CC:     Jeff Law <law@redhat.com>, Jakub Jelinek <jakub@redhat.com>,
> tsaunders@mozilla.com, Yury Gribov <y.gribov@samsung.com>, Slava
> Garbuzov <v.garbuzov@samsung.com>
>
>
>
> Hi,
>
> A years ago there was a discussion
> (https://gcc.gnu.org/ml/gcc-patches/2004-01/msg02437.html) about
> debugging compiler ICEs that resulted in a patch from Jakub, which dumps
> useful information into temporary file, but for some reasons this patch
> wasn't applied to trunk.
>
> This is the resurrected patch with added GCC version information into
> generated repro file.
>
> I've updated the patch that I've posted earlier
> (https://gcc.gnu.org/ml/gcc-patches/2014-07/msg01649.html ) according to
> recent upstream discussion
> (https://gcc.gnu.org/ml/gcc-patches/2014-08/msg00020.html).
>
> The debugging functionality is disabled by default and can be enabled
> with adding -freport-bug into compile options. It can be also enabled by
> default with
> --with-spec during GCC build.
>
> There are several directions in which this can be improved e.g:
>
> 1) more user-friendly ways to report bugs (autosubmitting to Bugzilla, 
> etc.)
>
> 2) generate repro in case of segfault.
>
> but having basic functionality (autogenerating reprocase in temprorary
> file) already seems quite useful.
>
> -Maxim
>
>
>
>
>
>


[-- Attachment #2: ICE.diff --]
[-- Type: text/x-patch, Size: 14372 bytes --]

2014-08-04  Jakub Jelinek  <jakub@redhat.com>
	      Max Ostapenko  <m.ostapenko@partner.samsung.com>

	* common.opt: New option.
	* doc/invoke.texi: Describe new option.
	* diagnostic.c (diagnostic_action_after_output): Exit with
	ICE_EXIT_CODE instead of FATAL_EXIT_CODE.
	* gcc.c (execute): Don't free first string early, but at the end
	of the function.  Call retry_ice if compiler exited with
	ICE_EXIT_CODE.
	(main): Factor out common code.
	(print_configuration): New function.
	(try_fork): Likewise.
	(redirect_stdout_stderr): Likewise.
	(files_equal_p): Likewise.
	(check_repro): Likewise.
	(run_attempt): Likewise.
	(do_report_bug): Likewise.
	(append_text): Likewise.
	(try_generate_repro): Likewise

diff --git a/gcc/common.opt b/gcc/common.opt
index f7021102..1133e61 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1120,6 +1120,11 @@ fdump-noaddr
 Common Report Var(flag_dump_noaddr)
 Suppress output of addresses in debugging dumps
 
+freport-bug
+Common Driver Var(flag_report_bug)
+Collect and dump debug information into temporary file if ICE in C/C++
+compiler occured.
+
 fdump-passes
 Common Var(flag_dump_passes) Init(0)
 Dump optimization passes
diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
index 73666d6..60ed607 100644
--- a/gcc/diagnostic.c
+++ b/gcc/diagnostic.c
@@ -494,7 +494,7 @@ diagnostic_action_after_output (diagnostic_context *context,
 	real_abort ();
       diagnostic_finish (context);
       fnotice (stderr, "compilation terminated.\n");
-      exit (FATAL_EXIT_CODE);
+      exit (ICE_EXIT_CODE);
 
     default:
       gcc_unreachable ();
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index d15d4a9..f41a1d8 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -6316,6 +6316,11 @@ feasible to use diff on debugging dumps for compiler invocations with
 different compiler binaries and/or different
 text / bss / data / heap / stack / dso start locations.
 
+@item -freport-bug
+@opindex freport-bug
+Collect and dump debug information into temporary file if ICE in C/C++
+compiler occured.
+
 @item -fdump-unnumbered
 @opindex fdump-unnumbered
 When doing debugging dumps, suppress instruction numbers and address output.
diff --git a/gcc/gcc.c b/gcc/gcc.c
index 44d0416..e0c403d 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -43,6 +43,13 @@ compilation is specified by a string called a "spec".  */
 #include "params.h"
 #include "vec.h"
 #include "filenames.h"
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#if !(defined (__MSDOS__) || defined (OS2) || defined (VMS))
+#define RETRY_ICE_SUPPORTED
+#endif
 
 /* By default there is no special suffix for target executables.  */
 /* FIXME: when autoconf is fixed, remove the host check - dj */
@@ -253,6 +260,9 @@ static void init_gcc_specs (struct obstack *, const char *, const char *,
 static const char *convert_filename (const char *, int, int);
 #endif
 
+#ifdef RETRY_ICE_SUPPORTED
+static void try_generate_repro (const char *prog, const char **argv);
+#endif
 static const char *getenv_spec_function (int, const char **);
 static const char *if_exists_spec_function (int, const char **);
 static const char *if_exists_else_spec_function (int, const char **);
@@ -2849,7 +2859,7 @@ execute (void)
 	    }
 	}
 
-      if (string != commands[i].prog)
+      if (i && string != commands[i].prog)
 	free (CONST_CAST (char *, string));
     }
 
@@ -2902,6 +2912,17 @@ execute (void)
 	else if (WIFEXITED (status)
 		 && WEXITSTATUS (status) >= MIN_FATAL_STATUS)
 	  {
+#ifdef RETRY_ICE_SUPPORTED
+	    /* For ICEs in cc1, cc1obj, cc1plus see if it is
+	       reproducible or not.  */
+	    const char *p;
+	    if (flag_report_bug
+		&& WEXITSTATUS (status) == ICE_EXIT_CODE
+		&& i == 0
+		&& (p = strrchr (commands[0].argv[0], DIR_SEPARATOR))
+		&& ! strncmp (p + 1, "cc1", 3))
+	      try_generate_repro (commands[0].prog, commands[0].argv);
+#endif
 	    if (WEXITSTATUS (status) > greatest_status)
 	      greatest_status = WEXITSTATUS (status);
 	    ret_code = -1;
@@ -2959,6 +2980,9 @@ execute (void)
 	  }
       }
 
+   if (commands[0].argv[0] != commands[0].prog)
+     free (CONST_CAST (char *, commands[0].argv[0]));
+
     return ret_code;
   }
 }
@@ -6150,6 +6174,342 @@ give_switch (int switchnum, int omit_first_word)
   switches[switchnum].validated = true;
 }
 \f
+static void
+print_configuration (void)
+{
+  int n;
+  const char *thrmod;
+
+  fnotice (stderr, "Target: %s\n", spec_machine);
+  fnotice (stderr, "Configured with: %s\n", configuration_arguments);
+
+#ifdef THREAD_MODEL_SPEC
+  /* We could have defined THREAD_MODEL_SPEC to "%*" by default,
+  but there's no point in doing all this processing just to get
+  thread_model back.  */
+  obstack_init (&obstack);
+  do_spec_1 (THREAD_MODEL_SPEC, 0, thread_model);
+  obstack_1grow (&obstack, '\0');
+  thrmod = XOBFINISH (&obstack, const char *);
+#else
+  thrmod = thread_model;
+#endif
+
+  fnotice (stderr, "Thread model: %s\n", thrmod);
+
+  /* compiler_version is truncated at the first space when initialized
+  from version string, so truncate version_string at the first space
+  before comparing.  */
+  for (n = 0; version_string[n]; n++)
+    if (version_string[n] == ' ')
+      break;
+
+  if (! strncmp (version_string, compiler_version, n)
+      && compiler_version[n] == 0)
+    fnotice (stderr, "gcc version %s %s\n\n", version_string,
+	     pkgversion_string);
+  else
+    fnotice (stderr, "gcc driver version %s %sexecuting gcc version %s\n\n",
+	     version_string, pkgversion_string, compiler_version);
+}
+
+#ifdef RETRY_ICE_SUPPORTED
+#define RETRY_ICE_ATTEMPTS 3
+
+static int
+try_fork ()
+{
+  int pid, retries, sleep_interval;
+  sleep_interval = 1;
+  pid = -1;
+  for (retries = 0; retries < 4; retries++)
+    {
+      pid = fork ();
+      if (pid >= 0)
+	break;
+      sleep (sleep_interval);
+      sleep_interval *= 2;
+    }
+  return pid;
+}
+
+
+static void
+redirect_stdout_stderr (const char *out_temp, const char *err_temp,
+                        int append)
+{
+  int fd;
+  fd = open (out_temp, append ? O_RDWR | O_APPEND : O_RDWR);
+
+  if (fd < 0)
+    exit (-1);
+
+  close (STDOUT_FILENO);
+  dup (fd);
+  close (fd);
+
+  fd = open (err_temp, append ? O_RDWR | O_APPEND : O_RDWR);
+
+  if (fd < 0)
+    exit (-1);
+
+  close (STDERR_FILENO);
+  dup (fd);
+  close (fd);
+}
+
+static int
+files_equal_p (char *file1, char *file2, char *buf, const int bufsize)
+{
+  struct stat st1, st2;
+  size_t n, len;
+  int fd1, fd2;
+
+  fd1 = open (file1, O_RDONLY);
+  fd2 = open (file2, O_RDONLY);
+
+  if (fd1 < 0 || fd2 < 0)
+    goto error;
+
+  if (fstat (fd1, &st1) < 0 || fstat (fd2, &st2) < 0)
+    goto error;
+
+  if (st1.st_size != st2.st_size)
+    goto error;
+
+  for (n = st1.st_size; n; n -= len)
+    {
+      len = n;
+      if ((int) len > bufsize / 2)
+        len = bufsize / 2;
+
+      if (read (fd1, buf, len) != (int) len
+	  || read (fd2, buf + bufsize / 2, len) != (int) len)
+	{
+	  goto error;
+	}
+
+      if (memcmp (buf, buf + bufsize / 2, len) != 0)
+	goto error;
+    }
+
+  close (fd1);
+  close (fd2);
+
+  return 1;
+
+error:
+  close (fd1);
+  close (fd2);
+  return 0;
+}
+
+static int
+check_repro (char **temp_stdout_files, char **temp_stderr_files)
+{
+  int i;
+  const int ice_bufsize = 8192;
+  char *ice_buf = XNEWVEC (char, ice_bufsize);
+  for (i = 0; i < RETRY_ICE_ATTEMPTS - 2; ++i)
+    {
+     if (!files_equal_p (temp_stdout_files[i], temp_stdout_files[i + 1],
+			 ice_buf, ice_bufsize)
+         || !files_equal_p (temp_stderr_files[i], temp_stderr_files[i + 1],
+			    ice_buf, ice_bufsize))
+	{
+	  fnotice (stderr, "The bug is not reproducible, so it is"
+		   " likely a hardware or OS problem.\n");
+	  break;
+	}
+    }
+  free (ice_buf);
+  return i == RETRY_ICE_ATTEMPTS - 2;
+}
+
+enum attempt_status {
+  ATTEMPT_STATUS_FAIL_TO_RUN,
+  ATTEMPT_STATUS_SUCCESS,
+  ATTEMPT_STATUS_ICE
+};
+
+static enum attempt_status
+run_attempt (const char *prog, const char **new_argv, const char *out_temp,
+             const char *err_temp, int emit_system_info, int append)
+{
+  int status;
+  int pid = try_fork ();
+  if (pid < 0)
+    return ATTEMPT_STATUS_FAIL_TO_RUN;
+  else if (pid == 0)
+    {
+      redirect_stdout_stderr (out_temp, err_temp, append);
+
+      if (emit_system_info)
+	print_configuration ();
+
+      if (prog == new_argv[0])
+	execvp (prog, CONST_CAST2 (char *const *, const char **, new_argv));
+      else
+	execv (new_argv[0], CONST_CAST2 (char *const *, const char **,
+	       new_argv));
+      exit (-1);
+    }
+
+  if (waitpid (pid, &status, 0) < 0)
+    return ATTEMPT_STATUS_FAIL_TO_RUN;
+
+  switch (WEXITSTATUS (status))
+    {
+      case ICE_EXIT_CODE:
+	return ATTEMPT_STATUS_ICE;
+
+      case SUCCESS_EXIT_CODE:
+	return ATTEMPT_STATUS_SUCCESS;
+
+      default:
+	return ATTEMPT_STATUS_FAIL_TO_RUN;
+    }
+}
+
+static void
+do_report_bug (const char *prog, const char **new_argv,
+	       const int nargs, char **out_file, char **err_file)
+{
+  int i, status;
+  int fd = open (*out_file, O_RDWR | O_APPEND);
+  if (fd < 0)
+    return;
+  write (fd, "\n//", 3);
+  for (i = 0; i < nargs; i++)
+    {
+      write (fd, " ", 1);
+      write (fd, new_argv[i], strlen (new_argv[i]));
+    }
+  write (fd, "\n\n", 2);
+  close (fd);
+  new_argv[nargs] = "-E";
+  new_argv[nargs + 1] = NULL;
+
+  status = run_attempt (prog, new_argv, *out_file, *err_file, 0, 1);
+
+  if (status == ATTEMPT_STATUS_SUCCESS)
+    {
+      fnotice (stderr, "Preprocessed source stored into %s file,"
+	       " please attach this to your bugreport.\n",
+               *out_file);
+      /* Make sure it is not deleted.  */
+      free (*out_file);
+      *out_file = NULL;
+    }
+}
+
+static void
+append_text (char *file, const char *str)
+{
+  int fd = open (file, O_RDWR | O_APPEND);
+  if (fd < 0)
+    return;
+
+  write (fd, str, strlen (str));
+  close (fd);
+}
+
+static void
+try_generate_repro (const char *prog, const char **argv)
+{
+  int i, nargs, out_arg = -1, quiet = 0, attempt;
+  const char **new_argv;
+  char *temp_files[RETRY_ICE_ATTEMPTS * 2];
+  char **temp_stdout_files = &temp_files[0];
+  char **temp_stderr_files = &temp_files[RETRY_ICE_ATTEMPTS];
+
+  if (gcc_input_filename == NULL || ! strcmp (gcc_input_filename, "-"))
+    return;
+
+  for (nargs = 0; argv[nargs] != NULL; ++nargs)
+    /* Only retry compiler ICEs, not preprocessor ones.  */
+    if (! strcmp (argv[nargs], "-E"))
+      return;
+    else if (argv[nargs][0] == '-' && argv[nargs][1] == 'o')
+      {
+	if (out_arg == -1)
+	  out_arg = nargs;
+	else
+	  return;
+      }
+    /* If the compiler is going to output any time information,
+       it might varry between invocations.  */
+    else if (! strcmp (argv[nargs], "-quiet"))
+      quiet = 1;
+    else if (! strcmp (argv[nargs], "-ftime-report"))
+      return;
+
+  if (out_arg == -1 || !quiet)
+    return;
+
+  memset (temp_files, '\0', sizeof (temp_files));
+  new_argv = XALLOCAVEC (const char *, nargs + 4);
+  memcpy (new_argv, argv, (nargs + 1) * sizeof (const char *));
+  new_argv[nargs++] = "-frandom-seed=0";
+  new_argv[nargs++] = "-fdump-noaddr";
+  new_argv[nargs] = NULL;
+  if (new_argv[out_arg][2] == '\0')
+    new_argv[out_arg + 1] = "-";
+  else
+    new_argv[out_arg] = "-o-";
+
+  int status;
+  for (attempt = 0; attempt < RETRY_ICE_ATTEMPTS; ++attempt)
+    {
+      int emit_system_info = 0;
+      int append = 0;
+      temp_stdout_files[attempt] = make_temp_file (".out");
+      temp_stderr_files[attempt] = make_temp_file (".err");
+
+      if (attempt == RETRY_ICE_ATTEMPTS - 1)
+	{
+	  append = 1;
+	  emit_system_info = 1;
+	}
+
+      if (emit_system_info)
+	append_text (temp_stderr_files[attempt], "/*\n");
+
+      /* Fork a subprocess; wait and retry if it fails.  */
+      status = run_attempt (prog, new_argv, temp_stdout_files[attempt],
+			    temp_stderr_files[attempt], emit_system_info,
+			    append);
+
+      if (emit_system_info)
+	append_text (temp_stderr_files[attempt], "*/\n");
+
+      if (status != ATTEMPT_STATUS_ICE)
+	{
+	  fnotice (stderr, "The bug is not reproducible, so it is"
+		   " likely a hardware or OS problem.\n");
+	  goto out;
+	}
+    }
+
+  if (!check_repro (temp_stdout_files, temp_stderr_files))
+    goto out;
+
+  /* In final attempt we append cc1 options and preprocesssed code to last
+     generated .err file with configuration and backtrace.  */
+  do_report_bug (prog, new_argv, nargs,
+		 &temp_stderr_files[RETRY_ICE_ATTEMPTS - 1],
+		 &temp_stdout_files[RETRY_ICE_ATTEMPTS - 1]);
+
+out:
+  for (i = 0; i < RETRY_ICE_ATTEMPTS * 2; i++)
+    if (temp_files[i])
+      {
+	unlink (temp_stdout_files[i]);
+	free (temp_stdout_files[i]);
+      }
+}
+#endif
+
 /* Search for a file named NAME trying various prefixes including the
    user's -B prefix and some standard ones.
    Return the absolute file name found.  If nothing is found, return NAME.  */
@@ -6919,41 +7279,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
 
   if (verbose_flag)
     {
-      int n;
-      const char *thrmod;
-
-      fnotice (stderr, "Target: %s\n", spec_machine);
-      fnotice (stderr, "Configured with: %s\n", configuration_arguments);
-
-#ifdef THREAD_MODEL_SPEC
-      /* We could have defined THREAD_MODEL_SPEC to "%*" by default,
-	 but there's no point in doing all this processing just to get
-	 thread_model back.  */
-      obstack_init (&obstack);
-      do_spec_1 (THREAD_MODEL_SPEC, 0, thread_model);
-      obstack_1grow (&obstack, '\0');
-      thrmod = XOBFINISH (&obstack, const char *);
-#else
-      thrmod = thread_model;
-#endif
-
-      fnotice (stderr, "Thread model: %s\n", thrmod);
-
-      /* compiler_version is truncated at the first space when initialized
-	 from version string, so truncate version_string at the first space
-	 before comparing.  */
-      for (n = 0; version_string[n]; n++)
-	if (version_string[n] == ' ')
-	  break;
-
-      if (! strncmp (version_string, compiler_version, n)
-	  && compiler_version[n] == 0)
-	fnotice (stderr, "gcc version %s %s\n", version_string,
-		 pkgversion_string);
-      else
-	fnotice (stderr, "gcc driver version %s %sexecuting gcc version %s\n",
-		 version_string, pkgversion_string, compiler_version);
-
+      print_configuration ();
       if (n_infiles == 0)
 	return (0);
     }

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [Ping v2][PATCH] Add patch for debugging compiler ICEs.
  2014-08-28  7:31   ` [Ping v2][PATCH] " Maxim Ostapenko
  2014-09-05 14:16     ` [Ping v3][PATCH] " Maxim Ostapenko
@ 2014-09-09 22:51     ` Joseph S. Myers
  2014-09-10  4:57       ` Jakub Jelinek
  1 sibling, 1 reply; 24+ messages in thread
From: Joseph S. Myers @ 2014-09-09 22:51 UTC (permalink / raw)
  To: Maxim Ostapenko
  Cc: GCC Patches, Jeff Law, Yury Gribov, Slava Garbuzov, Maxim Ostapenko

On Thu, 28 Aug 2014, Maxim Ostapenko wrote:

> diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
> index 0cc7593..67b8c5b 100644
> --- a/gcc/diagnostic.c
> +++ b/gcc/diagnostic.c
> @@ -492,7 +492,7 @@ diagnostic_action_after_output (diagnostic_context *context,
>  	real_abort ();
>        diagnostic_finish (context);
>        fnotice (stderr, "compilation terminated.\n");
> -      exit (FATAL_EXIT_CODE);
> +      exit (ICE_EXIT_CODE);

Why?  This is the case for fatal_error.  FATAL_EXIT_CODE seems right for 
this, and ICE_EXIT_CODE wrong.

> diff --git a/gcc/gcc.c b/gcc/gcc.c
> index 44d0416..f7a56d1 100644
> --- a/gcc/gcc.c
> +++ b/gcc/gcc.c
> @@ -43,6 +43,13 @@ compilation is specified by a string called a "spec".  */
>  #include "params.h"
>  #include "vec.h"
>  #include "filenames.h"
> +#ifdef HAVE_UNISTD_H
> +#include <unistd.h>
> +#endif

No, unistd.h is already included in system.h, so no other (host-side) 
source files need to include it directly.

> +#if !(defined (__MSDOS__) || defined (OS2) || defined (VMS))
> +#define RETRY_ICE_SUPPORTED
> +#endif

I don't think it's a good idea to have this sort of host conditional in 
random source files if it can be avoided.  And feature tests (e.g. 
HAVE_FORK) are better than tests for particular systems.

In any case, it would be better to use libiberty's pexecute interface for 
running subprocesses, as used elsewhere in GCC, rather than using POSIX 
interfaces directly, unless there's a clear reason (which needs explaining 
in the patch submission) why it's unsuitable.  Hopefully that would 
eliminate the need for this conditional.

> +static void
> +print_configuration (void)

All the new functions need comments above them giving the semantics of the 
function and any arguments and return values.

> +static int
> +files_equal_p (char *file1, char *file2, char *buf, const int bufsize)
> +{
> +  struct stat st1, st2;
> +  size_t n, len;

> +  for (n = st1.st_size; n; n -= len)

This assignment would silently truncate a large file size on 32-bit 
platforms.  A variable that can store file sizes should be off_t not 
size_t (then you need to be careful about any mixing of signed and 
unsigned types).

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [Ping v2][PATCH] Add patch for debugging compiler ICEs.
  2014-09-09 22:51     ` [Ping v2][PATCH] " Joseph S. Myers
@ 2014-09-10  4:57       ` Jakub Jelinek
  2014-09-10 16:37         ` Joseph S. Myers
  0 siblings, 1 reply; 24+ messages in thread
From: Jakub Jelinek @ 2014-09-10  4:57 UTC (permalink / raw)
  To: Joseph S. Myers
  Cc: Maxim Ostapenko, GCC Patches, Jeff Law, Yury Gribov,
	Slava Garbuzov, Maxim Ostapenko

On Tue, Sep 09, 2014 at 10:51:23PM +0000, Joseph S. Myers wrote:
> On Thu, 28 Aug 2014, Maxim Ostapenko wrote:
> 
> > diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
> > index 0cc7593..67b8c5b 100644
> > --- a/gcc/diagnostic.c
> > +++ b/gcc/diagnostic.c
> > @@ -492,7 +492,7 @@ diagnostic_action_after_output (diagnostic_context *context,
> >  	real_abort ();
> >        diagnostic_finish (context);
> >        fnotice (stderr, "compilation terminated.\n");
> > -      exit (FATAL_EXIT_CODE);
> > +      exit (ICE_EXIT_CODE);
> 
> Why?  This is the case for fatal_error.  FATAL_EXIT_CODE seems right for 
> this, and ICE_EXIT_CODE wrong.

So that the driver can understand the difference between an ICE and other
fatal errors (e.g. sorry etc.).
Users are typically using the driver and for them it matters what exit code
is returned from the driver, not from cc1/cc1plus etc.

	Jakub

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [Ping v2][PATCH] Add patch for debugging compiler ICEs.
  2014-09-10  4:57       ` Jakub Jelinek
@ 2014-09-10 16:37         ` Joseph S. Myers
  2014-09-11 16:18           ` [PATCH 1/2] Extend libiberty to allow append stdout and stderr to existing files Maxim Ostapenko
  2014-09-11 16:20           ` [PATCH 2/2] Add patch for debugging compiler ICEs Maxim Ostapenko
  0 siblings, 2 replies; 24+ messages in thread
From: Joseph S. Myers @ 2014-09-10 16:37 UTC (permalink / raw)
  To: Jakub Jelinek
  Cc: Maxim Ostapenko, GCC Patches, Jeff Law, Yury Gribov,
	Slava Garbuzov, Maxim Ostapenko

On Wed, 10 Sep 2014, Jakub Jelinek wrote:

> On Tue, Sep 09, 2014 at 10:51:23PM +0000, Joseph S. Myers wrote:
> > On Thu, 28 Aug 2014, Maxim Ostapenko wrote:
> > 
> > > diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
> > > index 0cc7593..67b8c5b 100644
> > > --- a/gcc/diagnostic.c
> > > +++ b/gcc/diagnostic.c
> > > @@ -492,7 +492,7 @@ diagnostic_action_after_output (diagnostic_context *context,
> > >  	real_abort ();
> > >        diagnostic_finish (context);
> > >        fnotice (stderr, "compilation terminated.\n");
> > > -      exit (FATAL_EXIT_CODE);
> > > +      exit (ICE_EXIT_CODE);
> > 
> > Why?  This is the case for fatal_error.  FATAL_EXIT_CODE seems right for 
> > this, and ICE_EXIT_CODE wrong.
> 
> So that the driver can understand the difference between an ICE and other
> fatal errors (e.g. sorry etc.).
> Users are typically using the driver and for them it matters what exit code
> is returned from the driver, not from cc1/cc1plus etc.

Well, I think the next revision of the patch submission needs more 
explanation in this area.  What exit codes do cc1 and the driver now 
return for (normal error, fatal error, ICE), and what do they return after 
the patch, and how does the change to the fatal_error case avoid incorrect 
changes if either cc1 or the driver called fatal_error (as opposed to 
either cc1 or the driver having an ICE)?  Maybe that explanation should be 
in the form of a comment on this exit call, explaining why the 
counterintuitive use of ICE_EXIT_CODE in the DK_FATAL case is correct.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH 1/2] Extend libiberty to allow append stdout and stderr to existing files.
  2014-09-10 16:37         ` Joseph S. Myers
@ 2014-09-11 16:18           ` Maxim Ostapenko
  2014-09-11 16:33             ` Ian Lance Taylor
  2014-09-11 16:20           ` [PATCH 2/2] Add patch for debugging compiler ICEs Maxim Ostapenko
  1 sibling, 1 reply; 24+ messages in thread
From: Maxim Ostapenko @ 2014-09-11 16:18 UTC (permalink / raw)
  To: Joseph S. Myers, Jakub Jelinek
  Cc: GCC Patches, Jeff Law, Yury Gribov, Slava Garbuzov,
	Maxim Ostapenko, ian, dj

[-- Attachment #1: Type: text/plain, Size: 274 bytes --]

Working on ICE debugging patch, I've noted that libiberty interface 
doesn't allow to append stdout and stderr to existing files.

This small patch provides two new flags for pex_run and extends 
open_write interface to handle the issue.

Does this patch look sane?

-Maxim

[-- Attachment #2: libiberty_allow_append-2.diff --]
[-- Type: text/x-patch, Size: 6171 bytes --]

libiberty/ChangeLog:

2014-09-11  Max Ostapenko  <m.ostapenko@partner.samsung.com>

	* pex-common.h (struct pex_funcs): Add new parameter for open_write field.
	* pex-unix.c (pex_unix_open_write): Add support for new parameter.
	* pex-djgpp.c (pex_djgpp_open_write): Likewise.
	* pex-win32.c (pex_win32_open_write): Likewise.
	* pex-common.c (pex_run_in_environment): Likewise.


include/ChangeLog:

2014-09-11  Max Ostapenko  <m.ostapenko@partner.samsung.com>

	* libiberty.h (PEX_STDOUT_APPEND): New flag.
	(PEX_STDERR_APPEND): Likewise.

diff --git a/include/libiberty.h b/include/libiberty.h
index 56b8b43..bcc1f9a 100644
--- a/include/libiberty.h
+++ b/include/libiberty.h
@@ -445,6 +445,11 @@ extern struct pex_obj *pex_init (int flags, const char *pname,
    on Unix.  */
 #define PEX_BINARY_ERROR	0x80
 
+/* Append stdout to existing file instead of truncating it.  */
+#define PEX_STDOUT_APPEND	0x100
+
+/* Thes same as PEX_STDOUT_APPEND, but for STDERR.  */
+#define PEX_STDERR_APPEND	0x200
 
 /* Execute one program.  Returns NULL on success.  On error returns an
    error string (typically just the name of a system call); the error
diff --git a/libiberty/pex-common.c b/libiberty/pex-common.c
index 6fd3fde..146010a 100644
--- a/libiberty/pex-common.c
+++ b/libiberty/pex-common.c
@@ -267,7 +267,8 @@ pex_run_in_environment (struct pex_obj *obj, int flags, const char *executable,
   if (out < 0)
     {
       out = obj->funcs->open_write (obj, outname,
-				    (flags & PEX_BINARY_OUTPUT) != 0);
+				    (flags & PEX_BINARY_OUTPUT) != 0,
+				    (flags & PEX_STDOUT_APPEND) != 0);
       if (out < 0)
 	{
 	  *err = errno;
@@ -319,8 +320,9 @@ pex_run_in_environment (struct pex_obj *obj, int flags, const char *executable,
     }
   else
     {
-      errdes = obj->funcs->open_write (obj, errname, 
-				       (flags & PEX_BINARY_ERROR) != 0);
+      errdes = obj->funcs->open_write (obj, errname,
+				       (flags & PEX_BINARY_ERROR) != 0,
+				       (flags & PEX_STDERR_APPEND) != 0);
       if (errdes < 0)
 	{
 	  *err = errno;
diff --git a/libiberty/pex-common.h b/libiberty/pex-common.h
index af338e6..b6db248 100644
--- a/libiberty/pex-common.h
+++ b/libiberty/pex-common.h
@@ -104,7 +104,7 @@ struct pex_funcs
   /* Open file NAME for writing.  If BINARY is non-zero, open in
      binary mode.  Return >= 0 on success, -1 on error.  */
   int (*open_write) (struct pex_obj *, const char */* name */,
-                     int /* binary */);
+                     int /* binary */, int /* append */);
   /* Execute a child process.  FLAGS, EXECUTABLE, ARGV, ERR are from
      pex_run.  IN, OUT, ERRDES, TOCLOSE are all descriptors, from
      open_read, open_write, or pipe, or they are one of STDIN_FILE_NO,
diff --git a/libiberty/pex-djgpp.c b/libiberty/pex-djgpp.c
index 0721139..b014ffa 100644
--- a/libiberty/pex-djgpp.c
+++ b/libiberty/pex-djgpp.c
@@ -43,7 +43,7 @@ extern int errno;
 #endif
 
 static int pex_djgpp_open_read (struct pex_obj *, const char *, int);
-static int pex_djgpp_open_write (struct pex_obj *, const char *, int);
+static int pex_djgpp_open_write (struct pex_obj *, const char *, int, int);
 static pid_t pex_djgpp_exec_child (struct pex_obj *, int, const char *,
 				  char * const *, char * const *,
 				  int, int, int, int,
@@ -90,10 +90,12 @@ pex_djgpp_open_read (struct pex_obj *obj ATTRIBUTE_UNUSED,
 
 static int
 pex_djgpp_open_write (struct pex_obj *obj ATTRIBUTE_UNUSED,
-		      const char *name, int binary)
+		      const char *name, int binary, int append)
 {
   /* Note that we can't use O_EXCL here because gcc may have already
      created the temporary file via make_temp_file.  */
+  if (append)
+    return -1;
   return open (name,
 	       (O_WRONLY | O_CREAT | O_TRUNC
 		| (binary ? O_BINARY : O_TEXT)),
diff --git a/libiberty/pex-unix.c b/libiberty/pex-unix.c
index addf8ee..0715115 100644
--- a/libiberty/pex-unix.c
+++ b/libiberty/pex-unix.c
@@ -301,7 +301,7 @@ pex_wait (struct pex_obj *obj, pid_t pid, int *status, struct pex_time *time)
 static void pex_child_error (struct pex_obj *, const char *, const char *, int)
      ATTRIBUTE_NORETURN;
 static int pex_unix_open_read (struct pex_obj *, const char *, int);
-static int pex_unix_open_write (struct pex_obj *, const char *, int);
+static int pex_unix_open_write (struct pex_obj *, const char *, int, int);
 static pid_t pex_unix_exec_child (struct pex_obj *, int, const char *,
 				 char * const *, char * const *,
 				 int, int, int, int,
@@ -350,11 +350,12 @@ pex_unix_open_read (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name,
 
 static int
 pex_unix_open_write (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name,
-		     int binary ATTRIBUTE_UNUSED)
+		     int binary ATTRIBUTE_UNUSED, int append)
 {
   /* Note that we can't use O_EXCL here because gcc may have already
      created the temporary file via make_temp_file.  */
-  return open (name, O_WRONLY | O_CREAT | O_TRUNC, PUBLIC_MODE);
+  return open (name, O_WRONLY | O_CREAT
+		     | (append ? O_APPEND : O_TRUNC), PUBLIC_MODE);
 }
 
 /* Close a file.  */
diff --git a/libiberty/pex-win32.c b/libiberty/pex-win32.c
index 8b9d4f0..66d2f11 100644
--- a/libiberty/pex-win32.c
+++ b/libiberty/pex-win32.c
@@ -78,7 +78,7 @@ backslashify (char *s)
 }
 
 static int pex_win32_open_read (struct pex_obj *, const char *, int);
-static int pex_win32_open_write (struct pex_obj *, const char *, int);
+static int pex_win32_open_write (struct pex_obj *, const char *, int, int);
 static pid_t pex_win32_exec_child (struct pex_obj *, int, const char *,
 				  char * const *, char * const *,
                                   int, int, int, int,
@@ -126,10 +126,12 @@ pex_win32_open_read (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name,
 
 static int
 pex_win32_open_write (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name,
-		      int binary)
+		      int binary, int append)
 {
   /* Note that we can't use O_EXCL here because gcc may have already
      created the temporary file via make_temp_file.  */
+  if (append)
+    return -1;
   return _open (name,
 		(_O_WRONLY | _O_CREAT | _O_TRUNC
 		 | (binary ? _O_BINARY : _O_TEXT)),

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH 2/2] Add patch for debugging compiler ICEs.
  2014-09-10 16:37         ` Joseph S. Myers
  2014-09-11 16:18           ` [PATCH 1/2] Extend libiberty to allow append stdout and stderr to existing files Maxim Ostapenko
@ 2014-09-11 16:20           ` Maxim Ostapenko
  2014-09-18 15:37             ` [PING] " Maxim Ostapenko
  2014-09-18 22:17             ` Joseph S. Myers
  1 sibling, 2 replies; 24+ messages in thread
From: Maxim Ostapenko @ 2014-09-11 16:20 UTC (permalink / raw)
  To: Joseph S. Myers, Jakub Jelinek
  Cc: GCC Patches, Jeff Law, Yury Gribov, Slava Garbuzov,
	Maxim Ostapenko, ian, dj

[-- Attachment #1: Type: text/plain, Size: 2783 bytes --]

Hi, Joseph,

Thanks for your review! I've added comments for new functions and 
replaced POSIX subprocess interfaces with libiberty's ones.

In general, when cc1 or cc1plus ICE-es, we try to reproduce the bug by 
running compiler 3 times and comparing stderr and stdout on each attempt 
with respective ones that were gotten as the result of previous compiler 
run (we use temporary dump files to do this). If these files are 
identical, we add GCC configuration (e.g. target, configure options and 
version), compiler command line and preprocessed source code into last 
dump file, containing backtrace. Following Jakub's approach, we trigger 
ICE_EXIT_CODE instead of FATAL_EXIT_CODE in case of DK_FATAL error to 
differ ICEs from other fatal errors, so try_generate_repro routine will 
be able to run even if fatal_error occurred in compiler.

We've noticed that on rare occasion a particularly severe segfault can 
cause GCC to abort without ICE-ing. These (hopefully rare) errors will 
be missed by our patch, because SIGSEGV handler is not able to catch the 
signal due to corrupted stack. It could make sense to allocate separate 
stack for SIGSEGV handler to resolve this situation.

-Maxim
On 09/10/2014 08:37 PM, Joseph S. Myers wrote:
> On Wed, 10 Sep 2014, Jakub Jelinek wrote:
>
>> On Tue, Sep 09, 2014 at 10:51:23PM +0000, Joseph S. Myers wrote:
>>> On Thu, 28 Aug 2014, Maxim Ostapenko wrote:
>>>
>>>> diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
>>>> index 0cc7593..67b8c5b 100644
>>>> --- a/gcc/diagnostic.c
>>>> +++ b/gcc/diagnostic.c
>>>> @@ -492,7 +492,7 @@ diagnostic_action_after_output (diagnostic_context *context,
>>>>   	real_abort ();
>>>>         diagnostic_finish (context);
>>>>         fnotice (stderr, "compilation terminated.\n");
>>>> -      exit (FATAL_EXIT_CODE);
>>>> +      exit (ICE_EXIT_CODE);
>>> Why?  This is the case for fatal_error.  FATAL_EXIT_CODE seems right for
>>> this, and ICE_EXIT_CODE wrong.
>> So that the driver can understand the difference between an ICE and other
>> fatal errors (e.g. sorry etc.).
>> Users are typically using the driver and for them it matters what exit code
>> is returned from the driver, not from cc1/cc1plus etc.
> Well, I think the next revision of the patch submission needs more
> explanation in this area.  What exit codes do cc1 and the driver now
> return for (normal error, fatal error, ICE), and what do they return after
> the patch, and how does the change to the fatal_error case avoid incorrect
> changes if either cc1 or the driver called fatal_error (as opposed to
> either cc1 or the driver having an ICE)?  Maybe that explanation should be
> in the form of a comment on this exit call, explaining why the
> counterintuitive use of ICE_EXIT_CODE in the DK_FATAL case is correct.
>


[-- Attachment #2: ICE.diff --]
[-- Type: text/x-patch, Size: 14720 bytes --]

2014-09-04  Jakub Jelinek  <jakub@redhat.com>
	    Max Ostapenko  <m.ostapenko@partner.samsung.com>

	* common.opt: New option.
	* doc/invoke.texi: Describe new option.
	* diagnostic.c (diagnostic_action_after_output): Exit with
	ICE_EXIT_CODE instead of FATAL_EXIT_CODE.
	* gcc.c (execute): Don't free first string early, but at the end
	of the function.  Call retry_ice if compiler exited with
	ICE_EXIT_CODE.
	(main): Factor out common code.
	(print_configuration): New function.
	(try_fork): Likewise.
	(redirect_stdout_stderr): Likewise.
	(files_equal_p): Likewise.
	(check_repro): Likewise.
	(run_attempt): Likewise.
	(do_report_bug): Likewise.
	(append_text): Likewise.
	(try_generate_repro): Likewise

diff --git a/gcc/common.opt b/gcc/common.opt
index 7d78803..ce71f09 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1120,6 +1120,11 @@ fdump-noaddr
 Common Report Var(flag_dump_noaddr)
 Suppress output of addresses in debugging dumps
 
+freport-bug
+Common Driver Var(flag_report_bug)
+Collect and dump debug information into temporary file if ICE in C/C++
+compiler occured.
+
 fdump-passes
 Common Var(flag_dump_passes) Init(0)
 Dump optimization passes
diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
index 73666d6..dbc928b 100644
--- a/gcc/diagnostic.c
+++ b/gcc/diagnostic.c
@@ -494,7 +494,10 @@ diagnostic_action_after_output (diagnostic_context *context,
 	real_abort ();
       diagnostic_finish (context);
       fnotice (stderr, "compilation terminated.\n");
-      exit (FATAL_EXIT_CODE);
+      /* Exit with ICE_EXIT_CODE rather then FATAL_EXIT_CODE so the driver
+         understands the difference between an ICE and other fatal errors
+         (DK_SORRY and DK_ERROR).  */
+      exit (ICE_EXIT_CODE);
 
     default:
       gcc_unreachable ();
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 863b382..565421c 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -6336,6 +6336,11 @@ feasible to use diff on debugging dumps for compiler invocations with
 different compiler binaries and/or different
 text / bss / data / heap / stack / dso start locations.
 
+@item -freport-bug
+@opindex freport-bug
+Collect and dump debug information into temporary file if ICE in C/C++
+compiler occured.
+
 @item -fdump-unnumbered
 @opindex fdump-unnumbered
 When doing debugging dumps, suppress instruction numbers and address output.
diff --git a/gcc/gcc.c b/gcc/gcc.c
index c550d9d..e32ff47 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -253,6 +253,7 @@ static void init_gcc_specs (struct obstack *, const char *, const char *,
 static const char *convert_filename (const char *, int, int);
 #endif
 
+static void try_generate_repro (const char *prog, const char **argv);
 static const char *getenv_spec_function (int, const char **);
 static const char *if_exists_spec_function (int, const char **);
 static const char *if_exists_else_spec_function (int, const char **);
@@ -2856,7 +2857,7 @@ execute (void)
 	    }
 	}
 
-      if (string != commands[i].prog)
+      if (i && string != commands[i].prog)
 	free (CONST_CAST (char *, string));
     }
 
@@ -2909,6 +2910,15 @@ execute (void)
 	else if (WIFEXITED (status)
 		 && WEXITSTATUS (status) >= MIN_FATAL_STATUS)
 	  {
+	    /* For ICEs in cc1, cc1obj, cc1plus see if it is
+	       reproducible or not.  */
+	    const char *p;
+	    if (flag_report_bug
+		&& WEXITSTATUS (status) == ICE_EXIT_CODE
+		&& i == 0
+		&& (p = strrchr (commands[0].argv[0], DIR_SEPARATOR))
+		&& ! strncmp (p + 1, "cc1", 3))
+	      try_generate_repro (commands[0].prog, commands[0].argv);
 	    if (WEXITSTATUS (status) > greatest_status)
 	      greatest_status = WEXITSTATUS (status);
 	    ret_code = -1;
@@ -2966,6 +2976,9 @@ execute (void)
 	  }
       }
 
+   if (commands[0].argv[0] != commands[0].prog)
+     free (CONST_CAST (char *, commands[0].argv[0]));
+
     return ret_code;
   }
 }
@@ -6157,6 +6170,338 @@ give_switch (int switchnum, int omit_first_word)
   switches[switchnum].validated = true;
 }
 \f
+/* Print GCC configuration (e.g. version, thread model, target,
+   configuration_arguments) to a given FILE.  */
+
+static void
+print_configuration (FILE *file)
+{
+  int n;
+  const char *thrmod;
+
+  fnotice (file, "Target: %s\n", spec_machine);
+  fnotice (file, "Configured with: %s\n", configuration_arguments);
+
+#ifdef THREAD_MODEL_SPEC
+  /* We could have defined THREAD_MODEL_SPEC to "%*" by default,
+  but there's no point in doing all this processing just to get
+  thread_model back.  */
+  obstack_init (&obstack);
+  do_spec_1 (THREAD_MODEL_SPEC, 0, thread_model);
+  obstack_1grow (&obstack, '\0');
+  thrmod = XOBFINISH (&obstack, const char *);
+#else
+  thrmod = thread_model;
+#endif
+
+  fnotice (file, "Thread model: %s\n", thrmod);
+
+  /* compiler_version is truncated at the first space when initialized
+  from version string, so truncate version_string at the first space
+  before comparing.  */
+  for (n = 0; version_string[n]; n++)
+    if (version_string[n] == ' ')
+      break;
+
+  if (! strncmp (version_string, compiler_version, n)
+      && compiler_version[n] == 0)
+    fnotice (file, "gcc version %s %s\n\n", version_string,
+	     pkgversion_string);
+  else
+    fnotice (file, "gcc driver version %s %sexecuting gcc version %s\n\n",
+	     version_string, pkgversion_string, compiler_version);
+
+}
+
+#define RETRY_ICE_ATTEMPTS 3
+
+/* Returns true if FILE1 and FILE2 contain equivalent data, 0 otherwise.  */
+
+static bool
+files_equal_p (char *file1, char *file2)
+{
+  struct stat st1, st2;
+  off_t n, len;
+  int fd1, fd2;
+  const int bufsize = 8192;
+  char *buf = XNEWVEC (char, bufsize);
+
+  fd1 = open (file1, O_RDONLY);
+  fd2 = open (file2, O_RDONLY);
+
+  if (fd1 < 0 || fd2 < 0)
+    goto error;
+
+  if (fstat (fd1, &st1) < 0 || fstat (fd2, &st2) < 0)
+    goto error;
+
+  if (st1.st_size != st2.st_size)
+    goto error;
+
+  for (n = st1.st_size; n; n -= len)
+    {
+      len = n;
+      if ((int) len > bufsize / 2)
+	len = bufsize / 2;
+
+      if (read (fd1, buf, len) != (int) len
+	  || read (fd2, buf + bufsize / 2, len) != (int) len)
+	{
+	  goto error;
+	}
+
+      if (memcmp (buf, buf + bufsize / 2, len) != 0)
+	goto error;
+    }
+
+  free (buf);
+  close (fd1);
+  close (fd2);
+
+  return 1;
+
+error:
+  free (buf);
+  close (fd1);
+  close (fd2);
+  return 0;
+}
+
+/* Check that compiler's output doesn't differ across runs.
+   TEMP_STDOUT_FILES and TEMP_STDERR_FILES are arrays of files, containing
+   stdout and stderr for each compiler run.  Return true if all of
+   TEMP_STDOUT_FILES and TEMP_STDERR_FILES are equivalent.  */
+
+static bool
+check_repro (char **temp_stdout_files, char **temp_stderr_files)
+{
+  int i;
+  for (i = 0; i < RETRY_ICE_ATTEMPTS - 2; ++i)
+    {
+     if (!files_equal_p (temp_stdout_files[i], temp_stdout_files[i + 1])
+	 || !files_equal_p (temp_stderr_files[i], temp_stderr_files[i + 1]))
+       {
+	 fnotice (stderr, "The bug is not reproducible, so it is"
+		  " likely a hardware or OS problem.\n");
+	 break;
+       }
+    }
+  return i == RETRY_ICE_ATTEMPTS - 2;
+}
+
+enum attempt_status {
+  ATTEMPT_STATUS_FAIL_TO_RUN,
+  ATTEMPT_STATUS_SUCCESS,
+  ATTEMPT_STATUS_ICE
+};
+
+
+/* Run compiler with arguments NEW_ARGV to reproduce the ICE, storing stdout
+   to OUT_TEMP and stderr to ERR_TEMP.  If APPEND is TRUE, append to OUT_TEMP
+   and ERR_TEMP instead of truncating.  If EMIT_SYSTEM_INFO is TRUE, also write
+   GCC configuration into to ERR_TEMP.  Return ATTEMPT_STATUS_FAIL_TO_RUN if
+   compiler failed to run, ATTEMPT_STATUS_ICE if compiled ICE-ed and
+   ATTEMPT_STATUS_SUCCESS otherwise.  */
+
+static enum attempt_status
+run_attempt (const char **new_argv, const char *out_temp,
+	     const char *err_temp, int emit_system_info, int append)
+{
+
+  if (emit_system_info)
+    {
+      FILE *file_out = fopen (err_temp, "a");
+      print_configuration (file_out);
+      fclose (file_out);
+    }
+
+  int exit_status;
+  const char *errmsg;
+  struct pex_obj *pex;
+  int err;
+  int pex_flags = PEX_USE_PIPES | PEX_LAST;
+  enum attempt_status status = ATTEMPT_STATUS_FAIL_TO_RUN;
+
+  if (append)
+    pex_flags |= PEX_STDOUT_APPEND | PEX_STDERR_APPEND;
+
+  pex = pex_init (PEX_USE_PIPES, new_argv[0], NULL);
+  if (!pex)
+    fatal_error ("pex_init failed: %m");
+
+  errmsg = pex_run (pex, pex_flags, new_argv[0],
+		    CONST_CAST2 (char *const *, const char **, &new_argv[1]), out_temp,
+		    err_temp, &err);
+
+  if (!pex_get_status (pex, 1, &exit_status))
+    goto out;
+
+  switch (WEXITSTATUS (exit_status))
+    {
+      case ICE_EXIT_CODE:
+	status = ATTEMPT_STATUS_ICE;
+	break;
+
+      case SUCCESS_EXIT_CODE:
+	status = ATTEMPT_STATUS_SUCCESS;
+	break;
+
+      default:
+	;
+    }
+
+out:
+  pex_free (pex);
+  return status;
+}
+
+/* This routine adds preprocessed source code into the given ERR_FILE.
+   To do this, it adds "-E" to NEW_ARGV and execute RUN_ATTEMPT routine to
+   add information in report file.  RUN_ATTEMPT should return
+   ATTEMPT_STATUS_SUCCESS, in other case we cannot generate the report.  */
+
+static void
+do_report_bug (const char **new_argv, const int nargs,
+	       char **out_file, char **err_file)
+{
+  int i, status;
+  int fd = open (*out_file, O_RDWR | O_APPEND);
+  if (fd < 0)
+    return;
+  write (fd, "\n//", 3);
+  for (i = 0; i < nargs; i++)
+    {
+      write (fd, " ", 1);
+      write (fd, new_argv[i], strlen (new_argv[i]));
+    }
+  write (fd, "\n\n", 2);
+  close (fd);
+  new_argv[nargs] = "-E";
+  new_argv[nargs + 1] = NULL;
+
+  status = run_attempt (new_argv, *out_file, *err_file, 0, 1);
+
+  if (status == ATTEMPT_STATUS_SUCCESS)
+    {
+      fnotice (stderr, "Preprocessed source stored into %s file,"
+	       " please attach this to your bugreport.\n", *out_file);
+      /* Make sure it is not deleted.  */
+      free (*out_file);
+      *out_file = NULL;
+    }
+}
+
+/* Append string STR to file FILE.  */
+
+static void
+append_text (char *file, const char *str)
+{
+  int fd = open (file, O_RDWR | O_APPEND);
+  if (fd < 0)
+    return;
+
+  write (fd, str, strlen (str));
+  close (fd);
+}
+
+/* Try to reproduce ICE.  If bug is reproducible, generate report .err file
+   containing GCC configuration, backtrace, compiler's command line options
+   and preprocessed source code.  */
+
+static void
+try_generate_repro (const char *prog, const char **argv)
+{
+  int i, nargs, out_arg = -1, quiet = 0, attempt;
+  const char **new_argv;
+  char *temp_files[RETRY_ICE_ATTEMPTS * 2];
+  char **temp_stdout_files = &temp_files[0];
+  char **temp_stderr_files = &temp_files[RETRY_ICE_ATTEMPTS];
+
+  if (gcc_input_filename == NULL || ! strcmp (gcc_input_filename, "-"))
+    return;
+
+  for (nargs = 0; argv[nargs] != NULL; ++nargs)
+    /* Only retry compiler ICEs, not preprocessor ones.  */
+    if (! strcmp (argv[nargs], "-E"))
+      return;
+    else if (argv[nargs][0] == '-' && argv[nargs][1] == 'o')
+      {
+	if (out_arg == -1)
+	  out_arg = nargs;
+	else
+	  return;
+      }
+    /* If the compiler is going to output any time information,
+       it might varry between invocations.  */
+    else if (! strcmp (argv[nargs], "-quiet"))
+      quiet = 1;
+    else if (! strcmp (argv[nargs], "-ftime-report"))
+      return;
+
+  if (out_arg == -1 || !quiet)
+    return;
+
+  memset (temp_files, '\0', sizeof (temp_files));
+  new_argv = XALLOCAVEC (const char *, nargs + 4);
+  memcpy (new_argv, argv, (nargs + 1) * sizeof (const char *));
+  new_argv[nargs++] = "-frandom-seed=0";
+  new_argv[nargs++] = "-fdump-noaddr";
+  new_argv[nargs] = NULL;
+  if (new_argv[out_arg][2] == '\0')
+    new_argv[out_arg + 1] = "-";
+  else
+    new_argv[out_arg] = "-o-";
+
+  int status;
+  for (attempt = 0; attempt < RETRY_ICE_ATTEMPTS; ++attempt)
+    {
+      int emit_system_info = 0;
+      int append = 0;
+      temp_stdout_files[attempt] = make_temp_file (".out");
+      temp_stderr_files[attempt] = make_temp_file (".err");
+
+      if (attempt == RETRY_ICE_ATTEMPTS - 1)
+	{
+	  append = 1;
+	  emit_system_info = 1;
+	}
+
+      if (emit_system_info)
+	append_text (temp_stderr_files[attempt], "/*\n");
+
+      status = run_attempt (new_argv, temp_stdout_files[attempt],
+			    temp_stderr_files[attempt], emit_system_info,
+			    append);
+
+      if (emit_system_info)
+	append_text (temp_stderr_files[attempt], "*/\n");
+
+      if (status != ATTEMPT_STATUS_ICE)
+	{
+	  fnotice (stderr, "The bug is not reproducible, so it is"
+		   " likely a hardware or OS problem.\n");
+	  goto out;
+	}
+    }
+
+  if (!check_repro (temp_stdout_files, temp_stderr_files))
+    goto out;
+
+  /* In final attempt we append compiler options and preprocesssed code to last
+     generated .err file with configuration and backtrace.  */
+  do_report_bug (new_argv, nargs,
+		 &temp_stderr_files[RETRY_ICE_ATTEMPTS - 1],
+		 &temp_stdout_files[RETRY_ICE_ATTEMPTS - 1]);
+
+out:
+  for (i = 0; i < RETRY_ICE_ATTEMPTS * 2; i++)
+    if (temp_files[i])
+      {
+	unlink (temp_stdout_files[i]);
+	free (temp_stdout_files[i]);
+      }
+}
+
 /* Search for a file named NAME trying various prefixes including the
    user's -B prefix and some standard ones.
    Return the absolute file name found.  If nothing is found, return NAME.  */
@@ -6926,41 +7271,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
 
   if (verbose_flag)
     {
-      int n;
-      const char *thrmod;
-
-      fnotice (stderr, "Target: %s\n", spec_machine);
-      fnotice (stderr, "Configured with: %s\n", configuration_arguments);
-
-#ifdef THREAD_MODEL_SPEC
-      /* We could have defined THREAD_MODEL_SPEC to "%*" by default,
-	 but there's no point in doing all this processing just to get
-	 thread_model back.  */
-      obstack_init (&obstack);
-      do_spec_1 (THREAD_MODEL_SPEC, 0, thread_model);
-      obstack_1grow (&obstack, '\0');
-      thrmod = XOBFINISH (&obstack, const char *);
-#else
-      thrmod = thread_model;
-#endif
-
-      fnotice (stderr, "Thread model: %s\n", thrmod);
-
-      /* compiler_version is truncated at the first space when initialized
-	 from version string, so truncate version_string at the first space
-	 before comparing.  */
-      for (n = 0; version_string[n]; n++)
-	if (version_string[n] == ' ')
-	  break;
-
-      if (! strncmp (version_string, compiler_version, n)
-	  && compiler_version[n] == 0)
-	fnotice (stderr, "gcc version %s %s\n", version_string,
-		 pkgversion_string);
-      else
-	fnotice (stderr, "gcc driver version %s %sexecuting gcc version %s\n",
-		 version_string, pkgversion_string, compiler_version);
-
+      print_configuration (stderr);
       if (n_infiles == 0)
 	return (0);
     }

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 1/2] Extend libiberty to allow append stdout and stderr to existing files.
  2014-09-11 16:18           ` [PATCH 1/2] Extend libiberty to allow append stdout and stderr to existing files Maxim Ostapenko
@ 2014-09-11 16:33             ` Ian Lance Taylor
  0 siblings, 0 replies; 24+ messages in thread
From: Ian Lance Taylor @ 2014-09-11 16:33 UTC (permalink / raw)
  To: Maxim Ostapenko
  Cc: Joseph S. Myers, Jakub Jelinek, GCC Patches, Jeff Law,
	Yury Gribov, Slava Garbuzov, Maxim Ostapenko, Ian Lance Taylor,
	DJ Delorie

On Thu, Sep 11, 2014 at 9:18 AM, Maxim Ostapenko
<m.ostapenko@partner.samsung.com> wrote:
>
> Working on ICE debugging patch, I've noted that libiberty interface doesn't
> allow to append stdout and stderr to existing files.
>
> This small patch provides two new flags for pex_run and extends open_write
> interface to handle the issue.
>
> Does this patch look sane?

I'm not sure why you want to do this, but the patch looks sane.

Ian

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PING] [PATCH 2/2] Add patch for debugging compiler ICEs.
  2014-09-11 16:20           ` [PATCH 2/2] Add patch for debugging compiler ICEs Maxim Ostapenko
@ 2014-09-18 15:37             ` Maxim Ostapenko
  2014-09-18 22:17             ` Joseph S. Myers
  1 sibling, 0 replies; 24+ messages in thread
From: Maxim Ostapenko @ 2014-09-18 15:37 UTC (permalink / raw)
  To: Joseph S. Myers, Jakub Jelinek
  Cc: GCC Patches, Jeff Law, Yury Gribov, Slava Garbuzov, Maxim Ostapenko

[-- Attachment #1: Type: text/plain, Size: 2953 bytes --]

Ping.
On 09/11/2014 08:20 PM, Maxim Ostapenko wrote:
> Hi, Joseph,
>
> Thanks for your review! I've added comments for new functions and 
> replaced POSIX subprocess interfaces with libiberty's ones.
>
> In general, when cc1 or cc1plus ICE-es, we try to reproduce the bug by 
> running compiler 3 times and comparing stderr and stdout on each 
> attempt with respective ones that were gotten as the result of 
> previous compiler run (we use temporary dump files to do this). If 
> these files are identical, we add GCC configuration (e.g. target, 
> configure options and version), compiler command line and preprocessed 
> source code into last dump file, containing backtrace. Following 
> Jakub's approach, we trigger ICE_EXIT_CODE instead of FATAL_EXIT_CODE 
> in case of DK_FATAL error to differ ICEs from other fatal errors, so 
> try_generate_repro routine will be able to run even if fatal_error 
> occurred in compiler.
>
> We've noticed that on rare occasion a particularly severe segfault can 
> cause GCC to abort without ICE-ing. These (hopefully rare) errors will 
> be missed by our patch, because SIGSEGV handler is not able to catch 
> the signal due to corrupted stack. It could make sense to allocate 
> separate stack for SIGSEGV handler to resolve this situation.
>
> -Maxim
> On 09/10/2014 08:37 PM, Joseph S. Myers wrote:
>> On Wed, 10 Sep 2014, Jakub Jelinek wrote:
>>
>>> On Tue, Sep 09, 2014 at 10:51:23PM +0000, Joseph S. Myers wrote:
>>>> On Thu, 28 Aug 2014, Maxim Ostapenko wrote:
>>>>
>>>>> diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
>>>>> index 0cc7593..67b8c5b 100644
>>>>> --- a/gcc/diagnostic.c
>>>>> +++ b/gcc/diagnostic.c
>>>>> @@ -492,7 +492,7 @@ diagnostic_action_after_output 
>>>>> (diagnostic_context *context,
>>>>>       real_abort ();
>>>>>         diagnostic_finish (context);
>>>>>         fnotice (stderr, "compilation terminated.\n");
>>>>> -      exit (FATAL_EXIT_CODE);
>>>>> +      exit (ICE_EXIT_CODE);
>>>> Why?  This is the case for fatal_error.  FATAL_EXIT_CODE seems 
>>>> right for
>>>> this, and ICE_EXIT_CODE wrong.
>>> So that the driver can understand the difference between an ICE and 
>>> other
>>> fatal errors (e.g. sorry etc.).
>>> Users are typically using the driver and for them it matters what 
>>> exit code
>>> is returned from the driver, not from cc1/cc1plus etc.
>> Well, I think the next revision of the patch submission needs more
>> explanation in this area.  What exit codes do cc1 and the driver now
>> return for (normal error, fatal error, ICE), and what do they return 
>> after
>> the patch, and how does the change to the fatal_error case avoid 
>> incorrect
>> changes if either cc1 or the driver called fatal_error (as opposed to
>> either cc1 or the driver having an ICE)?  Maybe that explanation 
>> should be
>> in the form of a comment on this exit call, explaining why the
>> counterintuitive use of ICE_EXIT_CODE in the DK_FATAL case is correct.
>>
>


[-- Attachment #2: ICE.diff --]
[-- Type: text/x-patch, Size: 14720 bytes --]

2014-09-04  Jakub Jelinek  <jakub@redhat.com>
	    Max Ostapenko  <m.ostapenko@partner.samsung.com>

	* common.opt: New option.
	* doc/invoke.texi: Describe new option.
	* diagnostic.c (diagnostic_action_after_output): Exit with
	ICE_EXIT_CODE instead of FATAL_EXIT_CODE.
	* gcc.c (execute): Don't free first string early, but at the end
	of the function.  Call retry_ice if compiler exited with
	ICE_EXIT_CODE.
	(main): Factor out common code.
	(print_configuration): New function.
	(try_fork): Likewise.
	(redirect_stdout_stderr): Likewise.
	(files_equal_p): Likewise.
	(check_repro): Likewise.
	(run_attempt): Likewise.
	(do_report_bug): Likewise.
	(append_text): Likewise.
	(try_generate_repro): Likewise

diff --git a/gcc/common.opt b/gcc/common.opt
index 7d78803..ce71f09 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1120,6 +1120,11 @@ fdump-noaddr
 Common Report Var(flag_dump_noaddr)
 Suppress output of addresses in debugging dumps
 
+freport-bug
+Common Driver Var(flag_report_bug)
+Collect and dump debug information into temporary file if ICE in C/C++
+compiler occured.
+
 fdump-passes
 Common Var(flag_dump_passes) Init(0)
 Dump optimization passes
diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
index 73666d6..dbc928b 100644
--- a/gcc/diagnostic.c
+++ b/gcc/diagnostic.c
@@ -494,7 +494,10 @@ diagnostic_action_after_output (diagnostic_context *context,
 	real_abort ();
       diagnostic_finish (context);
       fnotice (stderr, "compilation terminated.\n");
-      exit (FATAL_EXIT_CODE);
+      /* Exit with ICE_EXIT_CODE rather then FATAL_EXIT_CODE so the driver
+         understands the difference between an ICE and other fatal errors
+         (DK_SORRY and DK_ERROR).  */
+      exit (ICE_EXIT_CODE);
 
     default:
       gcc_unreachable ();
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 863b382..565421c 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -6336,6 +6336,11 @@ feasible to use diff on debugging dumps for compiler invocations with
 different compiler binaries and/or different
 text / bss / data / heap / stack / dso start locations.
 
+@item -freport-bug
+@opindex freport-bug
+Collect and dump debug information into temporary file if ICE in C/C++
+compiler occured.
+
 @item -fdump-unnumbered
 @opindex fdump-unnumbered
 When doing debugging dumps, suppress instruction numbers and address output.
diff --git a/gcc/gcc.c b/gcc/gcc.c
index c550d9d..e32ff47 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -253,6 +253,7 @@ static void init_gcc_specs (struct obstack *, const char *, const char *,
 static const char *convert_filename (const char *, int, int);
 #endif
 
+static void try_generate_repro (const char *prog, const char **argv);
 static const char *getenv_spec_function (int, const char **);
 static const char *if_exists_spec_function (int, const char **);
 static const char *if_exists_else_spec_function (int, const char **);
@@ -2856,7 +2857,7 @@ execute (void)
 	    }
 	}
 
-      if (string != commands[i].prog)
+      if (i && string != commands[i].prog)
 	free (CONST_CAST (char *, string));
     }
 
@@ -2909,6 +2910,15 @@ execute (void)
 	else if (WIFEXITED (status)
 		 && WEXITSTATUS (status) >= MIN_FATAL_STATUS)
 	  {
+	    /* For ICEs in cc1, cc1obj, cc1plus see if it is
+	       reproducible or not.  */
+	    const char *p;
+	    if (flag_report_bug
+		&& WEXITSTATUS (status) == ICE_EXIT_CODE
+		&& i == 0
+		&& (p = strrchr (commands[0].argv[0], DIR_SEPARATOR))
+		&& ! strncmp (p + 1, "cc1", 3))
+	      try_generate_repro (commands[0].prog, commands[0].argv);
 	    if (WEXITSTATUS (status) > greatest_status)
 	      greatest_status = WEXITSTATUS (status);
 	    ret_code = -1;
@@ -2966,6 +2976,9 @@ execute (void)
 	  }
       }
 
+   if (commands[0].argv[0] != commands[0].prog)
+     free (CONST_CAST (char *, commands[0].argv[0]));
+
     return ret_code;
   }
 }
@@ -6157,6 +6170,338 @@ give_switch (int switchnum, int omit_first_word)
   switches[switchnum].validated = true;
 }
 \f
+/* Print GCC configuration (e.g. version, thread model, target,
+   configuration_arguments) to a given FILE.  */
+
+static void
+print_configuration (FILE *file)
+{
+  int n;
+  const char *thrmod;
+
+  fnotice (file, "Target: %s\n", spec_machine);
+  fnotice (file, "Configured with: %s\n", configuration_arguments);
+
+#ifdef THREAD_MODEL_SPEC
+  /* We could have defined THREAD_MODEL_SPEC to "%*" by default,
+  but there's no point in doing all this processing just to get
+  thread_model back.  */
+  obstack_init (&obstack);
+  do_spec_1 (THREAD_MODEL_SPEC, 0, thread_model);
+  obstack_1grow (&obstack, '\0');
+  thrmod = XOBFINISH (&obstack, const char *);
+#else
+  thrmod = thread_model;
+#endif
+
+  fnotice (file, "Thread model: %s\n", thrmod);
+
+  /* compiler_version is truncated at the first space when initialized
+  from version string, so truncate version_string at the first space
+  before comparing.  */
+  for (n = 0; version_string[n]; n++)
+    if (version_string[n] == ' ')
+      break;
+
+  if (! strncmp (version_string, compiler_version, n)
+      && compiler_version[n] == 0)
+    fnotice (file, "gcc version %s %s\n\n", version_string,
+	     pkgversion_string);
+  else
+    fnotice (file, "gcc driver version %s %sexecuting gcc version %s\n\n",
+	     version_string, pkgversion_string, compiler_version);
+
+}
+
+#define RETRY_ICE_ATTEMPTS 3
+
+/* Returns true if FILE1 and FILE2 contain equivalent data, 0 otherwise.  */
+
+static bool
+files_equal_p (char *file1, char *file2)
+{
+  struct stat st1, st2;
+  off_t n, len;
+  int fd1, fd2;
+  const int bufsize = 8192;
+  char *buf = XNEWVEC (char, bufsize);
+
+  fd1 = open (file1, O_RDONLY);
+  fd2 = open (file2, O_RDONLY);
+
+  if (fd1 < 0 || fd2 < 0)
+    goto error;
+
+  if (fstat (fd1, &st1) < 0 || fstat (fd2, &st2) < 0)
+    goto error;
+
+  if (st1.st_size != st2.st_size)
+    goto error;
+
+  for (n = st1.st_size; n; n -= len)
+    {
+      len = n;
+      if ((int) len > bufsize / 2)
+	len = bufsize / 2;
+
+      if (read (fd1, buf, len) != (int) len
+	  || read (fd2, buf + bufsize / 2, len) != (int) len)
+	{
+	  goto error;
+	}
+
+      if (memcmp (buf, buf + bufsize / 2, len) != 0)
+	goto error;
+    }
+
+  free (buf);
+  close (fd1);
+  close (fd2);
+
+  return 1;
+
+error:
+  free (buf);
+  close (fd1);
+  close (fd2);
+  return 0;
+}
+
+/* Check that compiler's output doesn't differ across runs.
+   TEMP_STDOUT_FILES and TEMP_STDERR_FILES are arrays of files, containing
+   stdout and stderr for each compiler run.  Return true if all of
+   TEMP_STDOUT_FILES and TEMP_STDERR_FILES are equivalent.  */
+
+static bool
+check_repro (char **temp_stdout_files, char **temp_stderr_files)
+{
+  int i;
+  for (i = 0; i < RETRY_ICE_ATTEMPTS - 2; ++i)
+    {
+     if (!files_equal_p (temp_stdout_files[i], temp_stdout_files[i + 1])
+	 || !files_equal_p (temp_stderr_files[i], temp_stderr_files[i + 1]))
+       {
+	 fnotice (stderr, "The bug is not reproducible, so it is"
+		  " likely a hardware or OS problem.\n");
+	 break;
+       }
+    }
+  return i == RETRY_ICE_ATTEMPTS - 2;
+}
+
+enum attempt_status {
+  ATTEMPT_STATUS_FAIL_TO_RUN,
+  ATTEMPT_STATUS_SUCCESS,
+  ATTEMPT_STATUS_ICE
+};
+
+
+/* Run compiler with arguments NEW_ARGV to reproduce the ICE, storing stdout
+   to OUT_TEMP and stderr to ERR_TEMP.  If APPEND is TRUE, append to OUT_TEMP
+   and ERR_TEMP instead of truncating.  If EMIT_SYSTEM_INFO is TRUE, also write
+   GCC configuration into to ERR_TEMP.  Return ATTEMPT_STATUS_FAIL_TO_RUN if
+   compiler failed to run, ATTEMPT_STATUS_ICE if compiled ICE-ed and
+   ATTEMPT_STATUS_SUCCESS otherwise.  */
+
+static enum attempt_status
+run_attempt (const char **new_argv, const char *out_temp,
+	     const char *err_temp, int emit_system_info, int append)
+{
+
+  if (emit_system_info)
+    {
+      FILE *file_out = fopen (err_temp, "a");
+      print_configuration (file_out);
+      fclose (file_out);
+    }
+
+  int exit_status;
+  const char *errmsg;
+  struct pex_obj *pex;
+  int err;
+  int pex_flags = PEX_USE_PIPES | PEX_LAST;
+  enum attempt_status status = ATTEMPT_STATUS_FAIL_TO_RUN;
+
+  if (append)
+    pex_flags |= PEX_STDOUT_APPEND | PEX_STDERR_APPEND;
+
+  pex = pex_init (PEX_USE_PIPES, new_argv[0], NULL);
+  if (!pex)
+    fatal_error ("pex_init failed: %m");
+
+  errmsg = pex_run (pex, pex_flags, new_argv[0],
+		    CONST_CAST2 (char *const *, const char **, &new_argv[1]), out_temp,
+		    err_temp, &err);
+
+  if (!pex_get_status (pex, 1, &exit_status))
+    goto out;
+
+  switch (WEXITSTATUS (exit_status))
+    {
+      case ICE_EXIT_CODE:
+	status = ATTEMPT_STATUS_ICE;
+	break;
+
+      case SUCCESS_EXIT_CODE:
+	status = ATTEMPT_STATUS_SUCCESS;
+	break;
+
+      default:
+	;
+    }
+
+out:
+  pex_free (pex);
+  return status;
+}
+
+/* This routine adds preprocessed source code into the given ERR_FILE.
+   To do this, it adds "-E" to NEW_ARGV and execute RUN_ATTEMPT routine to
+   add information in report file.  RUN_ATTEMPT should return
+   ATTEMPT_STATUS_SUCCESS, in other case we cannot generate the report.  */
+
+static void
+do_report_bug (const char **new_argv, const int nargs,
+	       char **out_file, char **err_file)
+{
+  int i, status;
+  int fd = open (*out_file, O_RDWR | O_APPEND);
+  if (fd < 0)
+    return;
+  write (fd, "\n//", 3);
+  for (i = 0; i < nargs; i++)
+    {
+      write (fd, " ", 1);
+      write (fd, new_argv[i], strlen (new_argv[i]));
+    }
+  write (fd, "\n\n", 2);
+  close (fd);
+  new_argv[nargs] = "-E";
+  new_argv[nargs + 1] = NULL;
+
+  status = run_attempt (new_argv, *out_file, *err_file, 0, 1);
+
+  if (status == ATTEMPT_STATUS_SUCCESS)
+    {
+      fnotice (stderr, "Preprocessed source stored into %s file,"
+	       " please attach this to your bugreport.\n", *out_file);
+      /* Make sure it is not deleted.  */
+      free (*out_file);
+      *out_file = NULL;
+    }
+}
+
+/* Append string STR to file FILE.  */
+
+static void
+append_text (char *file, const char *str)
+{
+  int fd = open (file, O_RDWR | O_APPEND);
+  if (fd < 0)
+    return;
+
+  write (fd, str, strlen (str));
+  close (fd);
+}
+
+/* Try to reproduce ICE.  If bug is reproducible, generate report .err file
+   containing GCC configuration, backtrace, compiler's command line options
+   and preprocessed source code.  */
+
+static void
+try_generate_repro (const char *prog, const char **argv)
+{
+  int i, nargs, out_arg = -1, quiet = 0, attempt;
+  const char **new_argv;
+  char *temp_files[RETRY_ICE_ATTEMPTS * 2];
+  char **temp_stdout_files = &temp_files[0];
+  char **temp_stderr_files = &temp_files[RETRY_ICE_ATTEMPTS];
+
+  if (gcc_input_filename == NULL || ! strcmp (gcc_input_filename, "-"))
+    return;
+
+  for (nargs = 0; argv[nargs] != NULL; ++nargs)
+    /* Only retry compiler ICEs, not preprocessor ones.  */
+    if (! strcmp (argv[nargs], "-E"))
+      return;
+    else if (argv[nargs][0] == '-' && argv[nargs][1] == 'o')
+      {
+	if (out_arg == -1)
+	  out_arg = nargs;
+	else
+	  return;
+      }
+    /* If the compiler is going to output any time information,
+       it might varry between invocations.  */
+    else if (! strcmp (argv[nargs], "-quiet"))
+      quiet = 1;
+    else if (! strcmp (argv[nargs], "-ftime-report"))
+      return;
+
+  if (out_arg == -1 || !quiet)
+    return;
+
+  memset (temp_files, '\0', sizeof (temp_files));
+  new_argv = XALLOCAVEC (const char *, nargs + 4);
+  memcpy (new_argv, argv, (nargs + 1) * sizeof (const char *));
+  new_argv[nargs++] = "-frandom-seed=0";
+  new_argv[nargs++] = "-fdump-noaddr";
+  new_argv[nargs] = NULL;
+  if (new_argv[out_arg][2] == '\0')
+    new_argv[out_arg + 1] = "-";
+  else
+    new_argv[out_arg] = "-o-";
+
+  int status;
+  for (attempt = 0; attempt < RETRY_ICE_ATTEMPTS; ++attempt)
+    {
+      int emit_system_info = 0;
+      int append = 0;
+      temp_stdout_files[attempt] = make_temp_file (".out");
+      temp_stderr_files[attempt] = make_temp_file (".err");
+
+      if (attempt == RETRY_ICE_ATTEMPTS - 1)
+	{
+	  append = 1;
+	  emit_system_info = 1;
+	}
+
+      if (emit_system_info)
+	append_text (temp_stderr_files[attempt], "/*\n");
+
+      status = run_attempt (new_argv, temp_stdout_files[attempt],
+			    temp_stderr_files[attempt], emit_system_info,
+			    append);
+
+      if (emit_system_info)
+	append_text (temp_stderr_files[attempt], "*/\n");
+
+      if (status != ATTEMPT_STATUS_ICE)
+	{
+	  fnotice (stderr, "The bug is not reproducible, so it is"
+		   " likely a hardware or OS problem.\n");
+	  goto out;
+	}
+    }
+
+  if (!check_repro (temp_stdout_files, temp_stderr_files))
+    goto out;
+
+  /* In final attempt we append compiler options and preprocesssed code to last
+     generated .err file with configuration and backtrace.  */
+  do_report_bug (new_argv, nargs,
+		 &temp_stderr_files[RETRY_ICE_ATTEMPTS - 1],
+		 &temp_stdout_files[RETRY_ICE_ATTEMPTS - 1]);
+
+out:
+  for (i = 0; i < RETRY_ICE_ATTEMPTS * 2; i++)
+    if (temp_files[i])
+      {
+	unlink (temp_stdout_files[i]);
+	free (temp_stdout_files[i]);
+      }
+}
+
 /* Search for a file named NAME trying various prefixes including the
    user's -B prefix and some standard ones.
    Return the absolute file name found.  If nothing is found, return NAME.  */
@@ -6926,41 +7271,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
 
   if (verbose_flag)
     {
-      int n;
-      const char *thrmod;
-
-      fnotice (stderr, "Target: %s\n", spec_machine);
-      fnotice (stderr, "Configured with: %s\n", configuration_arguments);
-
-#ifdef THREAD_MODEL_SPEC
-      /* We could have defined THREAD_MODEL_SPEC to "%*" by default,
-	 but there's no point in doing all this processing just to get
-	 thread_model back.  */
-      obstack_init (&obstack);
-      do_spec_1 (THREAD_MODEL_SPEC, 0, thread_model);
-      obstack_1grow (&obstack, '\0');
-      thrmod = XOBFINISH (&obstack, const char *);
-#else
-      thrmod = thread_model;
-#endif
-
-      fnotice (stderr, "Thread model: %s\n", thrmod);
-
-      /* compiler_version is truncated at the first space when initialized
-	 from version string, so truncate version_string at the first space
-	 before comparing.  */
-      for (n = 0; version_string[n]; n++)
-	if (version_string[n] == ' ')
-	  break;
-
-      if (! strncmp (version_string, compiler_version, n)
-	  && compiler_version[n] == 0)
-	fnotice (stderr, "gcc version %s %s\n", version_string,
-		 pkgversion_string);
-      else
-	fnotice (stderr, "gcc driver version %s %sexecuting gcc version %s\n",
-		 version_string, pkgversion_string, compiler_version);
-
+      print_configuration (stderr);
       if (n_infiles == 0)
 	return (0);
     }

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/2] Add patch for debugging compiler ICEs.
  2014-09-11 16:20           ` [PATCH 2/2] Add patch for debugging compiler ICEs Maxim Ostapenko
  2014-09-18 15:37             ` [PING] " Maxim Ostapenko
@ 2014-09-18 22:17             ` Joseph S. Myers
  2014-09-19  3:33               ` Yury Gribov
  2014-09-23  7:15               ` Maxim Ostapenko
  1 sibling, 2 replies; 24+ messages in thread
From: Joseph S. Myers @ 2014-09-18 22:17 UTC (permalink / raw)
  To: Maxim Ostapenko
  Cc: Jakub Jelinek, GCC Patches, Jeff Law, Yury Gribov,
	Slava Garbuzov, Maxim Ostapenko, ian, dj

On Thu, 11 Sep 2014, Maxim Ostapenko wrote:

> In general, when cc1 or cc1plus ICE-es, we try to reproduce the bug by running
> compiler 3 times and comparing stderr and stdout on each attempt with
> respective ones that were gotten as the result of previous compiler run (we
> use temporary dump files to do this). If these files are identical, we add GCC
> configuration (e.g. target, configure options and version), compiler command
> line and preprocessed source code into last dump file, containing backtrace.
> Following Jakub's approach, we trigger ICE_EXIT_CODE instead of
> FATAL_EXIT_CODE in case of DK_FATAL error to differ ICEs from other fatal
> errors, so try_generate_repro routine will be able to run even if fatal_error
> occurred in compiler.

I still don't understand what's going on here with exit codes.

Suppose cc1 calls fatal_error (not for an ICE, not -Wfatal-errors - a 
normal DK_FATAL arising from a call to fatal_error).  What exit code does 
it exit with?  What path leads to that exit code?  How does the driver 
distinguish this from an ICE?

Suppose cc1 calls internal_error.  What exit code does it exit with?  What 
path leads to that exit code?  How does the driver distinguish this from a 
call to fatal_error?

What about the above exit codes was different before the patch, that means 
the driver ICE detection can only work given the diagnostic.c changes?

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/2] Add patch for debugging compiler ICEs.
  2014-09-18 22:17             ` Joseph S. Myers
@ 2014-09-19  3:33               ` Yury Gribov
  2014-09-23  7:15               ` Maxim Ostapenko
  1 sibling, 0 replies; 24+ messages in thread
From: Yury Gribov @ 2014-09-19  3:33 UTC (permalink / raw)
  To: Joseph S. Myers, Maxim Ostapenko
  Cc: Jakub Jelinek, GCC Patches, Jeff Law, Slava Garbuzov,
	Maxim Ostapenko, ian, dj

On 09/19/2014 02:16 AM, Joseph S. Myers wrote:
> On Thu, 11 Sep 2014, Maxim Ostapenko wrote:
>
>> In general, when cc1 or cc1plus ICE-es, we try to reproduce the bug by running
>> compiler 3 times and comparing stderr and stdout on each attempt with
>> respective ones that were gotten as the result of previous compiler run (we
>> use temporary dump files to do this). If these files are identical, we add GCC
>> configuration (e.g. target, configure options and version), compiler command
>> line and preprocessed source code into last dump file, containing backtrace.
>> Following Jakub's approach, we trigger ICE_EXIT_CODE instead of
>> FATAL_EXIT_CODE in case of DK_FATAL error to differ ICEs from other fatal
>> errors, so try_generate_repro routine will be able to run even if fatal_error
>> occurred in compiler.
>
> I still don't understand what's going on here with exit codes.

I'd second this, internal_error already exits with ICE_EXIT_CODE via 
DK_ICE. Forcing fatal errors to return ICE_EXIT_CODE as well seems 
unnecessary.

-Y

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/2] Add patch for debugging compiler ICEs.
  2014-09-18 22:17             ` Joseph S. Myers
  2014-09-19  3:33               ` Yury Gribov
@ 2014-09-23  7:15               ` Maxim Ostapenko
  2014-09-25 19:05                 ` Jeff Law
  1 sibling, 1 reply; 24+ messages in thread
From: Maxim Ostapenko @ 2014-09-23  7:15 UTC (permalink / raw)
  To: Joseph S. Myers
  Cc: Jakub Jelinek, GCC Patches, Jeff Law, Yury Gribov,
	Slava Garbuzov, Maxim Ostapenko, ian, dj, Yuri Gribov

[-- Attachment #1: Type: text/plain, Size: 1639 bytes --]


On 09/19/2014 02:16 AM, Joseph S. Myers wrote:
> On Thu, 11 Sep 2014, Maxim Ostapenko wrote:
>
>> In general, when cc1 or cc1plus ICE-es, we try to reproduce the bug by running
>> compiler 3 times and comparing stderr and stdout on each attempt with
>> respective ones that were gotten as the result of previous compiler run (we
>> use temporary dump files to do this). If these files are identical, we add GCC
>> configuration (e.g. target, configure options and version), compiler command
>> line and preprocessed source code into last dump file, containing backtrace.
>> Following Jakub's approach, we trigger ICE_EXIT_CODE instead of
>> FATAL_EXIT_CODE in case of DK_FATAL error to differ ICEs from other fatal
>> errors, so try_generate_repro routine will be able to run even if fatal_error
>> occurred in compiler.
> I still don't understand what's going on here with exit codes.
>
> Suppose cc1 calls fatal_error (not for an ICE, not -Wfatal-errors - a
> normal DK_FATAL arising from a call to fatal_error).  What exit code does
> it exit with?  What path leads to that exit code?  How does the driver
> distinguish this from an ICE?
>
> Suppose cc1 calls internal_error.  What exit code does it exit with?  What
> path leads to that exit code?  How does the driver distinguish this from a
> call to fatal_error?
Hm, this line is indeed redundant, thanks. Removed the line.
> What about the above exit codes was different before the patch, that means
> the driver ICE detection can only work given the diagnostic.c changes?
>
The new patch version seems to work fine on some current ICEs in GCC 5.0 
(pr55843 and pr58987).

-Maxim

[-- Attachment #2: ICE.diff --]
[-- Type: text/x-patch, Size: 19580 bytes --]

2014-09-04  Jakub Jelinek  <jakub@redhat.com>
	    Max Ostapenko  <m.ostapenko@partner.samsung.com>

	* common.opt: New option.
	* doc/invoke.texi: Describe new option.
	* gcc.c (execute): Don't free first string early, but at the end
	of the function.  Call retry_ice if compiler exited with
	ICE_EXIT_CODE.
	(main): Factor out common code.
	(print_configuration): New function.
	(files_equal_p): Likewise.
	(check_repro): Likewise.
	(run_attempt): Likewise.
	(do_report_bug): Likewise.
	(append_text): Likewise.
	(try_generate_repro): Likewise

diff --git a/gcc/common.opt b/gcc/common.opt
index 634a72b..b4f0ed4 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1120,6 +1120,11 @@ fdump-noaddr
 Common Report Var(flag_dump_noaddr)
 Suppress output of addresses in debugging dumps
 
+freport-bug
+Common Driver Var(flag_report_bug)
+Collect and dump debug information into temporary file if ICE in C/C++
+compiler occured.
+
 fdump-passes
 Common Var(flag_dump_passes) Init(0)
 Dump optimization passes
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index eae4ab1..2be8475 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -6344,6 +6344,11 @@ feasible to use diff on debugging dumps for compiler invocations with
 different compiler binaries and/or different
 text / bss / data / heap / stack / dso start locations.
 
+@item -freport-bug
+@opindex freport-bug
+Collect and dump debug information into temporary file if ICE in C/C++
+compiler occured.
+
 @item -fdump-unnumbered
 @opindex fdump-unnumbered
 When doing debugging dumps, suppress instruction numbers and address output.
diff --git a/gcc/gcc.c b/gcc/gcc.c
index c550d9d..e32ff47 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -253,6 +253,7 @@ static void init_gcc_specs (struct obstack *, const char *, const char *,
 static const char *convert_filename (const char *, int, int);
 #endif
 
+static void try_generate_repro (const char *prog, const char **argv);
 static const char *getenv_spec_function (int, const char **);
 static const char *if_exists_spec_function (int, const char **);
 static const char *if_exists_else_spec_function (int, const char **);
@@ -2856,7 +2857,7 @@ execute (void)
 	    }
 	}
 
-      if (string != commands[i].prog)
+      if (i && string != commands[i].prog)
 	free (CONST_CAST (char *, string));
     }
 
@@ -2909,6 +2910,15 @@ execute (void)
 	else if (WIFEXITED (status)
 		 && WEXITSTATUS (status) >= MIN_FATAL_STATUS)
 	  {
+	    /* For ICEs in cc1, cc1obj, cc1plus see if it is
+	       reproducible or not.  */
+	    const char *p;
+	    if (flag_report_bug
+		&& WEXITSTATUS (status) == ICE_EXIT_CODE
+		&& i == 0
+		&& (p = strrchr (commands[0].argv[0], DIR_SEPARATOR))
+		&& ! strncmp (p + 1, "cc1", 3))
+	      try_generate_repro (commands[0].prog, commands[0].argv);
 	    if (WEXITSTATUS (status) > greatest_status)
 	      greatest_status = WEXITSTATUS (status);
 	    ret_code = -1;
@@ -2966,6 +2976,9 @@ execute (void)
 	  }
       }
 
+   if (commands[0].argv[0] != commands[0].prog)
+     free (CONST_CAST (char *, commands[0].argv[0]));
+
     return ret_code;
   }
 }
@@ -6157,6 +6170,338 @@ give_switch (int switchnum, int omit_first_word)
   switches[switchnum].validated = true;
 }
 \f
+/* Print GCC configuration (e.g. version, thread model, target,
+   configuration_arguments) to a given FILE.  */
+
+static void
+print_configuration (FILE *file)
+{
+  int n;
+  const char *thrmod;
+
+  fnotice (file, "Target: %s\n", spec_machine);
+  fnotice (file, "Configured with: %s\n", configuration_arguments);
+
+#ifdef THREAD_MODEL_SPEC
+  /* We could have defined THREAD_MODEL_SPEC to "%*" by default,
+  but there's no point in doing all this processing just to get
+  thread_model back.  */
+  obstack_init (&obstack);
+  do_spec_1 (THREAD_MODEL_SPEC, 0, thread_model);
+  obstack_1grow (&obstack, '\0');
+  thrmod = XOBFINISH (&obstack, const char *);
+#else
+  thrmod = thread_model;
+#endif
+
+  fnotice (file, "Thread model: %s\n", thrmod);
+
+  /* compiler_version is truncated at the first space when initialized
+  from version string, so truncate version_string at the first space
+  before comparing.  */
+  for (n = 0; version_string[n]; n++)
+    if (version_string[n] == ' ')
+      break;
+
+  if (! strncmp (version_string, compiler_version, n)
+      && compiler_version[n] == 0)
+    fnotice (file, "gcc version %s %s\n\n", version_string,
+	     pkgversion_string);
+  else
+    fnotice (file, "gcc driver version %s %sexecuting gcc version %s\n\n",
+	     version_string, pkgversion_string, compiler_version);
+
+}
+
+#define RETRY_ICE_ATTEMPTS 3
+
+/* Returns true if FILE1 and FILE2 contain equivalent data, 0 otherwise.  */
+
+static bool
+files_equal_p (char *file1, char *file2)
+{
+  struct stat st1, st2;
+  off_t n, len;
+  int fd1, fd2;
+  const int bufsize = 8192;
+  char *buf = XNEWVEC (char, bufsize);
+
+  fd1 = open (file1, O_RDONLY);
+  fd2 = open (file2, O_RDONLY);
+
+  if (fd1 < 0 || fd2 < 0)
+    goto error;
+
+  if (fstat (fd1, &st1) < 0 || fstat (fd2, &st2) < 0)
+    goto error;
+
+  if (st1.st_size != st2.st_size)
+    goto error;
+
+  for (n = st1.st_size; n; n -= len)
+    {
+      len = n;
+      if ((int) len > bufsize / 2)
+	len = bufsize / 2;
+
+      if (read (fd1, buf, len) != (int) len
+	  || read (fd2, buf + bufsize / 2, len) != (int) len)
+	{
+	  goto error;
+	}
+
+      if (memcmp (buf, buf + bufsize / 2, len) != 0)
+	goto error;
+    }
+
+  free (buf);
+  close (fd1);
+  close (fd2);
+
+  return 1;
+
+error:
+  free (buf);
+  close (fd1);
+  close (fd2);
+  return 0;
+}
+
+/* Check that compiler's output doesn't differ across runs.
+   TEMP_STDOUT_FILES and TEMP_STDERR_FILES are arrays of files, containing
+   stdout and stderr for each compiler run.  Return true if all of
+   TEMP_STDOUT_FILES and TEMP_STDERR_FILES are equivalent.  */
+
+static bool
+check_repro (char **temp_stdout_files, char **temp_stderr_files)
+{
+  int i;
+  for (i = 0; i < RETRY_ICE_ATTEMPTS - 2; ++i)
+    {
+     if (!files_equal_p (temp_stdout_files[i], temp_stdout_files[i + 1])
+	 || !files_equal_p (temp_stderr_files[i], temp_stderr_files[i + 1]))
+       {
+	 fnotice (stderr, "The bug is not reproducible, so it is"
+		  " likely a hardware or OS problem.\n");
+	 break;
+       }
+    }
+  return i == RETRY_ICE_ATTEMPTS - 2;
+}
+
+enum attempt_status {
+  ATTEMPT_STATUS_FAIL_TO_RUN,
+  ATTEMPT_STATUS_SUCCESS,
+  ATTEMPT_STATUS_ICE
+};
+
+
+/* Run compiler with arguments NEW_ARGV to reproduce the ICE, storing stdout
+   to OUT_TEMP and stderr to ERR_TEMP.  If APPEND is TRUE, append to OUT_TEMP
+   and ERR_TEMP instead of truncating.  If EMIT_SYSTEM_INFO is TRUE, also write
+   GCC configuration into to ERR_TEMP.  Return ATTEMPT_STATUS_FAIL_TO_RUN if
+   compiler failed to run, ATTEMPT_STATUS_ICE if compiled ICE-ed and
+   ATTEMPT_STATUS_SUCCESS otherwise.  */
+
+static enum attempt_status
+run_attempt (const char **new_argv, const char *out_temp,
+	     const char *err_temp, int emit_system_info, int append)
+{
+
+  if (emit_system_info)
+    {
+      FILE *file_out = fopen (err_temp, "a");
+      print_configuration (file_out);
+      fclose (file_out);
+    }
+
+  int exit_status;
+  const char *errmsg;
+  struct pex_obj *pex;
+  int err;
+  int pex_flags = PEX_USE_PIPES | PEX_LAST;
+  enum attempt_status status = ATTEMPT_STATUS_FAIL_TO_RUN;
+
+  if (append)
+    pex_flags |= PEX_STDOUT_APPEND | PEX_STDERR_APPEND;
+
+  pex = pex_init (PEX_USE_PIPES, new_argv[0], NULL);
+  if (!pex)
+    fatal_error ("pex_init failed: %m");
+
+  errmsg = pex_run (pex, pex_flags, new_argv[0],
+		    CONST_CAST2 (char *const *, const char **, &new_argv[1]), out_temp,
+		    err_temp, &err);
+
+  if (!pex_get_status (pex, 1, &exit_status))
+    goto out;
+
+  switch (WEXITSTATUS (exit_status))
+    {
+      case ICE_EXIT_CODE:
+	status = ATTEMPT_STATUS_ICE;
+	break;
+
+      case SUCCESS_EXIT_CODE:
+	status = ATTEMPT_STATUS_SUCCESS;
+	break;
+
+      default:
+	;
+    }
+
+out:
+  pex_free (pex);
+  return status;
+}
+
+/* This routine adds preprocessed source code into the given ERR_FILE.
+   To do this, it adds "-E" to NEW_ARGV and execute RUN_ATTEMPT routine to
+   add information in report file.  RUN_ATTEMPT should return
+   ATTEMPT_STATUS_SUCCESS, in other case we cannot generate the report.  */
+
+static void
+do_report_bug (const char **new_argv, const int nargs,
+	       char **out_file, char **err_file)
+{
+  int i, status;
+  int fd = open (*out_file, O_RDWR | O_APPEND);
+  if (fd < 0)
+    return;
+  write (fd, "\n//", 3);
+  for (i = 0; i < nargs; i++)
+    {
+      write (fd, " ", 1);
+      write (fd, new_argv[i], strlen (new_argv[i]));
+    }
+  write (fd, "\n\n", 2);
+  close (fd);
+  new_argv[nargs] = "-E";
+  new_argv[nargs + 1] = NULL;
+
+  status = run_attempt (new_argv, *out_file, *err_file, 0, 1);
+
+  if (status == ATTEMPT_STATUS_SUCCESS)
+    {
+      fnotice (stderr, "Preprocessed source stored into %s file,"
+	       " please attach this to your bugreport.\n", *out_file);
+      /* Make sure it is not deleted.  */
+      free (*out_file);
+      *out_file = NULL;
+    }
+}
+
+/* Append string STR to file FILE.  */
+
+static void
+append_text (char *file, const char *str)
+{
+  int fd = open (file, O_RDWR | O_APPEND);
+  if (fd < 0)
+    return;
+
+  write (fd, str, strlen (str));
+  close (fd);
+}
+
+/* Try to reproduce ICE.  If bug is reproducible, generate report .err file
+   containing GCC configuration, backtrace, compiler's command line options
+   and preprocessed source code.  */
+
+static void
+try_generate_repro (const char *prog, const char **argv)
+{
+  int i, nargs, out_arg = -1, quiet = 0, attempt;
+  const char **new_argv;
+  char *temp_files[RETRY_ICE_ATTEMPTS * 2];
+  char **temp_stdout_files = &temp_files[0];
+  char **temp_stderr_files = &temp_files[RETRY_ICE_ATTEMPTS];
+
+  if (gcc_input_filename == NULL || ! strcmp (gcc_input_filename, "-"))
+    return;
+
+  for (nargs = 0; argv[nargs] != NULL; ++nargs)
+    /* Only retry compiler ICEs, not preprocessor ones.  */
+    if (! strcmp (argv[nargs], "-E"))
+      return;
+    else if (argv[nargs][0] == '-' && argv[nargs][1] == 'o')
+      {
+	if (out_arg == -1)
+	  out_arg = nargs;
+	else
+	  return;
+      }
+    /* If the compiler is going to output any time information,
+       it might varry between invocations.  */
+    else if (! strcmp (argv[nargs], "-quiet"))
+      quiet = 1;
+    else if (! strcmp (argv[nargs], "-ftime-report"))
+      return;
+
+  if (out_arg == -1 || !quiet)
+    return;
+
+  memset (temp_files, '\0', sizeof (temp_files));
+  new_argv = XALLOCAVEC (const char *, nargs + 4);
+  memcpy (new_argv, argv, (nargs + 1) * sizeof (const char *));
+  new_argv[nargs++] = "-frandom-seed=0";
+  new_argv[nargs++] = "-fdump-noaddr";
+  new_argv[nargs] = NULL;
+  if (new_argv[out_arg][2] == '\0')
+    new_argv[out_arg + 1] = "-";
+  else
+    new_argv[out_arg] = "-o-";
+
+  int status;
+  for (attempt = 0; attempt < RETRY_ICE_ATTEMPTS; ++attempt)
+    {
+      int emit_system_info = 0;
+      int append = 0;
+      temp_stdout_files[attempt] = make_temp_file (".out");
+      temp_stderr_files[attempt] = make_temp_file (".err");
+
+      if (attempt == RETRY_ICE_ATTEMPTS - 1)
+	{
+	  append = 1;
+	  emit_system_info = 1;
+	}
+
+      if (emit_system_info)
+	append_text (temp_stderr_files[attempt], "/*\n");
+
+      status = run_attempt (new_argv, temp_stdout_files[attempt],
+			    temp_stderr_files[attempt], emit_system_info,
+			    append);
+
+      if (emit_system_info)
+	append_text (temp_stderr_files[attempt], "*/\n");
+
+      if (status != ATTEMPT_STATUS_ICE)
+	{
+	  fnotice (stderr, "The bug is not reproducible, so it is"
+		   " likely a hardware or OS problem.\n");
+	  goto out;
+	}
+    }
+
+  if (!check_repro (temp_stdout_files, temp_stderr_files))
+    goto out;
+
+  /* In final attempt we append compiler options and preprocesssed code to last
+     generated .err file with configuration and backtrace.  */
+  do_report_bug (new_argv, nargs,
+		 &temp_stderr_files[RETRY_ICE_ATTEMPTS - 1],
+		 &temp_stdout_files[RETRY_ICE_ATTEMPTS - 1]);
+
+out:
+  for (i = 0; i < RETRY_ICE_ATTEMPTS * 2; i++)
+    if (temp_files[i])
+      {
+	unlink (temp_stdout_files[i]);
+	free (temp_stdout_files[i]);
+      }
+}
+
 /* Search for a file named NAME trying various prefixes including the
    user's -B prefix and some standard ones.
    Return the absolute file name found.  If nothing is found, return NAME.  */
@@ -6926,41 +7271,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
 
   if (verbose_flag)
     {
-      int n;
-      const char *thrmod;
-
-      fnotice (stderr, "Target: %s\n", spec_machine);
-      fnotice (stderr, "Configured with: %s\n", configuration_arguments);
-
-#ifdef THREAD_MODEL_SPEC
-      /* We could have defined THREAD_MODEL_SPEC to "%*" by default,
-	 but there's no point in doing all this processing just to get
-	 thread_model back.  */
-      obstack_init (&obstack);
-      do_spec_1 (THREAD_MODEL_SPEC, 0, thread_model);
-      obstack_1grow (&obstack, '\0');
-      thrmod = XOBFINISH (&obstack, const char *);
-#else
-      thrmod = thread_model;
-#endif
-
-      fnotice (stderr, "Thread model: %s\n", thrmod);
-
-      /* compiler_version is truncated at the first space when initialized
-	 from version string, so truncate version_string at the first space
-	 before comparing.  */
-      for (n = 0; version_string[n]; n++)
-	if (version_string[n] == ' ')
-	  break;
-
-      if (! strncmp (version_string, compiler_version, n)
-	  && compiler_version[n] == 0)
-	fnotice (stderr, "gcc version %s %s\n", version_string,
-		 pkgversion_string);
-      else
-	fnotice (stderr, "gcc driver version %s %sexecuting gcc version %s\n",
-		 version_string, pkgversion_string, compiler_version);
-
+      print_configuration (stderr);
       if (n_infiles == 0)
 	return (0);
     }
diff --git a/include/libiberty.h b/include/libiberty.h
index 56b8b43..bcc1f9a 100644
--- a/include/libiberty.h
+++ b/include/libiberty.h
@@ -445,6 +445,11 @@ extern struct pex_obj *pex_init (int flags, const char *pname,
    on Unix.  */
 #define PEX_BINARY_ERROR	0x80
 
+/* Append stdout to existing file instead of truncating it.  */
+#define PEX_STDOUT_APPEND	0x100
+
+/* Thes same as PEX_STDOUT_APPEND, but for STDERR.  */
+#define PEX_STDERR_APPEND	0x200
 
 /* Execute one program.  Returns NULL on success.  On error returns an
    error string (typically just the name of a system call); the error
diff --git a/libiberty/pex-common.c b/libiberty/pex-common.c
index 6fd3fde..146010a 100644
--- a/libiberty/pex-common.c
+++ b/libiberty/pex-common.c
@@ -267,7 +267,8 @@ pex_run_in_environment (struct pex_obj *obj, int flags, const char *executable,
   if (out < 0)
     {
       out = obj->funcs->open_write (obj, outname,
-				    (flags & PEX_BINARY_OUTPUT) != 0);
+				    (flags & PEX_BINARY_OUTPUT) != 0,
+				    (flags & PEX_STDOUT_APPEND) != 0);
       if (out < 0)
 	{
 	  *err = errno;
@@ -319,8 +320,9 @@ pex_run_in_environment (struct pex_obj *obj, int flags, const char *executable,
     }
   else
     {
-      errdes = obj->funcs->open_write (obj, errname, 
-				       (flags & PEX_BINARY_ERROR) != 0);
+      errdes = obj->funcs->open_write (obj, errname,
+				       (flags & PEX_BINARY_ERROR) != 0,
+				       (flags & PEX_STDERR_APPEND) != 0);
       if (errdes < 0)
 	{
 	  *err = errno;
diff --git a/libiberty/pex-common.h b/libiberty/pex-common.h
index af338e6..b6db248 100644
--- a/libiberty/pex-common.h
+++ b/libiberty/pex-common.h
@@ -104,7 +104,7 @@ struct pex_funcs
   /* Open file NAME for writing.  If BINARY is non-zero, open in
      binary mode.  Return >= 0 on success, -1 on error.  */
   int (*open_write) (struct pex_obj *, const char */* name */,
-                     int /* binary */);
+                     int /* binary */, int /* append */);
   /* Execute a child process.  FLAGS, EXECUTABLE, ARGV, ERR are from
      pex_run.  IN, OUT, ERRDES, TOCLOSE are all descriptors, from
      open_read, open_write, or pipe, or they are one of STDIN_FILE_NO,
diff --git a/libiberty/pex-djgpp.c b/libiberty/pex-djgpp.c
index 0721139..b014ffa 100644
--- a/libiberty/pex-djgpp.c
+++ b/libiberty/pex-djgpp.c
@@ -43,7 +43,7 @@ extern int errno;
 #endif
 
 static int pex_djgpp_open_read (struct pex_obj *, const char *, int);
-static int pex_djgpp_open_write (struct pex_obj *, const char *, int);
+static int pex_djgpp_open_write (struct pex_obj *, const char *, int, int);
 static pid_t pex_djgpp_exec_child (struct pex_obj *, int, const char *,
 				  char * const *, char * const *,
 				  int, int, int, int,
@@ -90,10 +90,12 @@ pex_djgpp_open_read (struct pex_obj *obj ATTRIBUTE_UNUSED,
 
 static int
 pex_djgpp_open_write (struct pex_obj *obj ATTRIBUTE_UNUSED,
-		      const char *name, int binary)
+		      const char *name, int binary, int append)
 {
   /* Note that we can't use O_EXCL here because gcc may have already
      created the temporary file via make_temp_file.  */
+  if (append)
+    return -1;
   return open (name,
 	       (O_WRONLY | O_CREAT | O_TRUNC
 		| (binary ? O_BINARY : O_TEXT)),
diff --git a/libiberty/pex-unix.c b/libiberty/pex-unix.c
index addf8ee..0715115 100644
--- a/libiberty/pex-unix.c
+++ b/libiberty/pex-unix.c
@@ -301,7 +301,7 @@ pex_wait (struct pex_obj *obj, pid_t pid, int *status, struct pex_time *time)
 static void pex_child_error (struct pex_obj *, const char *, const char *, int)
      ATTRIBUTE_NORETURN;
 static int pex_unix_open_read (struct pex_obj *, const char *, int);
-static int pex_unix_open_write (struct pex_obj *, const char *, int);
+static int pex_unix_open_write (struct pex_obj *, const char *, int, int);
 static pid_t pex_unix_exec_child (struct pex_obj *, int, const char *,
 				 char * const *, char * const *,
 				 int, int, int, int,
@@ -350,11 +350,12 @@ pex_unix_open_read (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name,
 
 static int
 pex_unix_open_write (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name,
-		     int binary ATTRIBUTE_UNUSED)
+		     int binary ATTRIBUTE_UNUSED, int append)
 {
   /* Note that we can't use O_EXCL here because gcc may have already
      created the temporary file via make_temp_file.  */
-  return open (name, O_WRONLY | O_CREAT | O_TRUNC, PUBLIC_MODE);
+  return open (name, O_WRONLY | O_CREAT
+		     | (append ? O_APPEND : O_TRUNC), PUBLIC_MODE);
 }
 
 /* Close a file.  */
diff --git a/libiberty/pex-win32.c b/libiberty/pex-win32.c
index 8b9d4f0..66d2f11 100644
--- a/libiberty/pex-win32.c
+++ b/libiberty/pex-win32.c
@@ -78,7 +78,7 @@ backslashify (char *s)
 }
 
 static int pex_win32_open_read (struct pex_obj *, const char *, int);
-static int pex_win32_open_write (struct pex_obj *, const char *, int);
+static int pex_win32_open_write (struct pex_obj *, const char *, int, int);
 static pid_t pex_win32_exec_child (struct pex_obj *, int, const char *,
 				  char * const *, char * const *,
                                   int, int, int, int,
@@ -126,10 +126,12 @@ pex_win32_open_read (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name,
 
 static int
 pex_win32_open_write (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name,
-		      int binary)
+		      int binary, int append)
 {
   /* Note that we can't use O_EXCL here because gcc may have already
      created the temporary file via make_temp_file.  */
+  if (append)
+    return -1;
   return _open (name,
 		(_O_WRONLY | _O_CREAT | _O_TRUNC
 		 | (binary ? _O_BINARY : _O_TEXT)),

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/2] Add patch for debugging compiler ICEs.
  2014-09-23  7:15               ` Maxim Ostapenko
@ 2014-09-25 19:05                 ` Jeff Law
  2014-09-26  8:04                   ` Maxim Ostapenko
  0 siblings, 1 reply; 24+ messages in thread
From: Jeff Law @ 2014-09-25 19:05 UTC (permalink / raw)
  To: Maxim Ostapenko, Joseph S. Myers
  Cc: Jakub Jelinek, GCC Patches, Yury Gribov, Slava Garbuzov,
	Maxim Ostapenko, ian, dj, Yuri Gribov

On 09/23/14 01:14, Maxim Ostapenko wrote:
>
>
> 2014-09-04  Jakub Jelinek<jakub@redhat.com>
> 	    Max Ostapenko<m.ostapenko@partner.samsung.com>
>
> 	* common.opt: New option.
> 	* doc/invoke.texi: Describe new option.
> 	* gcc.c (execute): Don't free first string early, but at the end
> 	of the function.  Call retry_ice if compiler exited with
> 	ICE_EXIT_CODE.
> 	(main): Factor out common code.
> 	(print_configuration): New function.
> 	(files_equal_p): Likewise.
> 	(check_repro): Likewise.
> 	(run_attempt): Likewise.
> 	(do_report_bug): Likewise.
> 	(append_text): Likewise.
> 	(try_generate_repro): Likewise
Approved.  Please install.

Thanks for your patience,
Jeff

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/2] Add patch for debugging compiler ICEs.
  2014-09-25 19:05                 ` Jeff Law
@ 2014-09-26  8:04                   ` Maxim Ostapenko
  2014-09-26 13:11                     ` Rainer Orth
                                       ` (2 more replies)
  0 siblings, 3 replies; 24+ messages in thread
From: Maxim Ostapenko @ 2014-09-26  8:04 UTC (permalink / raw)
  To: Jeff Law, Joseph S. Myers
  Cc: Jakub Jelinek, GCC Patches, Yury Gribov, Slava Garbuzov,
	Maxim Ostapenko, ian, dj, Yuri Gribov

Thank you all for your help!

Done in r215633.

-Maxim
On 09/25/2014 11:05 PM, Jeff Law wrote:
> On 09/23/14 01:14, Maxim Ostapenko wrote:
>>
>>
>> 2014-09-04  Jakub Jelinek<jakub@redhat.com>
>>         Max Ostapenko<m.ostapenko@partner.samsung.com>
>>
>>     * common.opt: New option.
>>     * doc/invoke.texi: Describe new option.
>>     * gcc.c (execute): Don't free first string early, but at the end
>>     of the function.  Call retry_ice if compiler exited with
>>     ICE_EXIT_CODE.
>>     (main): Factor out common code.
>>     (print_configuration): New function.
>>     (files_equal_p): Likewise.
>>     (check_repro): Likewise.
>>     (run_attempt): Likewise.
>>     (do_report_bug): Likewise.
>>     (append_text): Likewise.
>>     (try_generate_repro): Likewise
> Approved.  Please install.
>
> Thanks for your patience,
> Jeff
>
>

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/2] Add patch for debugging compiler ICEs.
  2014-09-26  8:04                   ` Maxim Ostapenko
@ 2014-09-26 13:11                     ` Rainer Orth
  2014-09-26 13:24                     ` Thomas Schwinge
  2015-01-23  1:42                     ` H.J. Lu
  2 siblings, 0 replies; 24+ messages in thread
From: Rainer Orth @ 2014-09-26 13:11 UTC (permalink / raw)
  To: Maxim Ostapenko
  Cc: Jeff Law, Joseph S. Myers, Jakub Jelinek, GCC Patches,
	Yury Gribov, Slava Garbuzov, Maxim Ostapenko, ian, dj,
	Yuri Gribov

Hi Maxim,

> Thank you all for your help!
>
> Done in r215633.

unfortuntely, the applied patch cannot have been tested properly and
breaks native i386-pc-solaris2.11 (and every other) bootstrap:

/vol/gcc/src/hg/trunk/local/gcc/gcc.c: In function 'attempt_status run_attempt(const char**, const char*, const char*, int, int)':
/vol/gcc/src/hg/trunk/local/gcc/gcc.c:6319:15: error: variable 'errmsg' set but not used [-Werror=unused-but-set-variable]
   const char *errmsg;
               ^
/vol/gcc/src/hg/trunk/local/gcc/gcc.c: At global scope:
/vol/gcc/src/hg/trunk/local/gcc/gcc.c:6412:33: error: unused parameter 'prog' [-Werror=unused-parameter]
 try_generate_repro (const char *prog, const char **argv)
                                 ^
Removing the errmsg variable and the prog parameter name fixes this.
I'm not sure if the errmsg is intentionally unused, though.

	Rainer

-- 
-----------------------------------------------------------------------------
Rainer Orth, Center for Biotechnology, Bielefeld University

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/2] Add patch for debugging compiler ICEs.
  2014-09-26  8:04                   ` Maxim Ostapenko
  2014-09-26 13:11                     ` Rainer Orth
@ 2014-09-26 13:24                     ` Thomas Schwinge
  2014-09-26 13:32                       ` Maxim Ostapenko
  2014-09-26 16:18                       ` Jeff Law
  2015-01-23  1:42                     ` H.J. Lu
  2 siblings, 2 replies; 24+ messages in thread
From: Thomas Schwinge @ 2014-09-26 13:24 UTC (permalink / raw)
  To: Maxim Ostapenko, Jeff Law, Joseph S. Myers
  Cc: Jakub Jelinek, GCC Patches, Yury Gribov, Slava Garbuzov,
	Maxim Ostapenko, ian, dj, Yuri Gribov

[-- Attachment #1: Type: text/plain, Size: 4189 bytes --]

Hi!

On Fri, 26 Sep 2014 12:04:45 +0400, Maxim Ostapenko <m.ostapenko@partner.samsung.com> wrote:
> Thank you all for your help!
> 
> Done in r215633.
> 
> -Maxim
> On 09/25/2014 11:05 PM, Jeff Law wrote:
> > On 09/23/14 01:14, Maxim Ostapenko wrote:
> >>
> >>
> >> 2014-09-04  Jakub Jelinek<jakub@redhat.com>
> >>         Max Ostapenko<m.ostapenko@partner.samsung.com>
> >>
> >>     * common.opt: New option.
> >>     * doc/invoke.texi: Describe new option.
> >>     * gcc.c (execute): Don't free first string early, but at the end
> >>     of the function.  Call retry_ice if compiler exited with
> >>     ICE_EXIT_CODE.
> >>     (main): Factor out common code.
> >>     (print_configuration): New function.
> >>     (files_equal_p): Likewise.
> >>     (check_repro): Likewise.
> >>     (run_attempt): Likewise.
> >>     (do_report_bug): Likewise.
> >>     (append_text): Likewise.
> >>     (try_generate_repro): Likewise
> > Approved.  Please install.
> >
> > Thanks for your patience,
> > Jeff

This is causing compiler warnings, respectively bootstrap errors:

    [...]
    ../../master/gcc/gcc.c: In function 'attempt_status run_attempt(const char**, const char*, const char*, int, int)':
    ../../master/gcc/gcc.c:6319:15: error: variable 'errmsg' set but not used [-Werror=unused-but-set-variable]
       const char *errmsg;
                   ^
    ../../master/gcc/gcc.c: At global scope:
    ../../master/gcc/gcc.c:6412:33: error: unused parameter 'prog' [-Werror=unused-parameter]
     try_generate_repro (const char *prog, const char **argv)
                                     ^
    cc1plus: all warnings being treated as errors
    Makefile:1040: recipe for target 'gcc.o' failed
    make[3]: *** [gcc.o] Error 1
    make[3]: Leaving directory '/media/erich/home/thomas/tmp/gcc/hurd/master.build/gcc'
    Makefile:4285: recipe for target 'all-stage2-gcc' failed
    make[2]: *** [all-stage2-gcc] Error 2
    make[2]: Leaving directory '/media/erich/home/thomas/tmp/gcc/hurd/master.build'
    Makefile:21561: recipe for target 'stage2-bubble' failed
    make[1]: *** [stage2-bubble] Error 2
    make[1]: Leaving directory '/media/erich/home/thomas/tmp/gcc/hurd/master.build'
    Makefile:892: recipe for target 'all' failed
    make: *** [all] Error 2

OK to fix as follows?  Only compile-tested, did not test the new
-freport-bug functionality.

diff --git gcc/gcc.c gcc/gcc.c
index e32ff47..47c4e28 100644
--- gcc/gcc.c
+++ gcc/gcc.c
@@ -253,7 +253,7 @@ static void init_gcc_specs (struct obstack *, const char *, const char *,
 static const char *convert_filename (const char *, int, int);
 #endif
 
-static void try_generate_repro (const char *prog, const char **argv);
+static void try_generate_repro (const char **argv);
 static const char *getenv_spec_function (int, const char **);
 static const char *if_exists_spec_function (int, const char **);
 static const char *if_exists_else_spec_function (int, const char **);
@@ -2918,7 +2918,7 @@ execute (void)
 		&& i == 0
 		&& (p = strrchr (commands[0].argv[0], DIR_SEPARATOR))
 		&& ! strncmp (p + 1, "cc1", 3))
-	      try_generate_repro (commands[0].prog, commands[0].argv);
+	      try_generate_repro (commands[0].argv);
 	    if (WEXITSTATUS (status) > greatest_status)
 	      greatest_status = WEXITSTATUS (status);
 	    ret_code = -1;
@@ -6332,6 +6332,16 @@ run_attempt (const char **new_argv, const char *out_temp,
   errmsg = pex_run (pex, pex_flags, new_argv[0],
 		    CONST_CAST2 (char *const *, const char **, &new_argv[1]), out_temp,
 		    err_temp, &err);
+  if (errmsg != NULL)
+    {
+      if (err == 0)
+	fatal_error (errmsg);
+      else
+	{
+	  errno = err;
+	  pfatal_with_name (errmsg);
+	}
+    }
 
   if (!pex_get_status (pex, 1, &exit_status))
     goto out;
@@ -6409,7 +6419,7 @@ append_text (char *file, const char *str)
    and preprocessed source code.  */
 
 static void
-try_generate_repro (const char *prog, const char **argv)
+try_generate_repro (const char **argv)
 {
   int i, nargs, out_arg = -1, quiet = 0, attempt;
   const char **new_argv;



Grüße,
 Thomas

[-- Attachment #2: Type: application/pgp-signature, Size: 472 bytes --]

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/2] Add patch for debugging compiler ICEs.
  2014-09-26 13:24                     ` Thomas Schwinge
@ 2014-09-26 13:32                       ` Maxim Ostapenko
  2014-09-26 16:18                       ` Jeff Law
  1 sibling, 0 replies; 24+ messages in thread
From: Maxim Ostapenko @ 2014-09-26 13:32 UTC (permalink / raw)
  To: Thomas Schwinge, Jeff Law, Joseph S. Myers
  Cc: Jakub Jelinek, GCC Patches, Yury Gribov, Slava Garbuzov,
	Maxim Ostapenko, ian, dj, Yuri Gribov

Ugh, sorry. Thanks for fixing this.

On 09/26/2014 05:23 PM, Thomas Schwinge wrote:
> Hi!
>
> On Fri, 26 Sep 2014 12:04:45 +0400, Maxim Ostapenko <m.ostapenko@partner.samsung.com> wrote:
>> Thank you all for your help!
>>
>> Done in r215633.
>>
>> -Maxim
>> On 09/25/2014 11:05 PM, Jeff Law wrote:
>>> On 09/23/14 01:14, Maxim Ostapenko wrote:
>>>>
>>>> 2014-09-04  Jakub Jelinek<jakub@redhat.com>
>>>>          Max Ostapenko<m.ostapenko@partner.samsung.com>
>>>>
>>>>      * common.opt: New option.
>>>>      * doc/invoke.texi: Describe new option.
>>>>      * gcc.c (execute): Don't free first string early, but at the end
>>>>      of the function.  Call retry_ice if compiler exited with
>>>>      ICE_EXIT_CODE.
>>>>      (main): Factor out common code.
>>>>      (print_configuration): New function.
>>>>      (files_equal_p): Likewise.
>>>>      (check_repro): Likewise.
>>>>      (run_attempt): Likewise.
>>>>      (do_report_bug): Likewise.
>>>>      (append_text): Likewise.
>>>>      (try_generate_repro): Likewise
>>> Approved.  Please install.
>>>
>>> Thanks for your patience,
>>> Jeff
> This is causing compiler warnings, respectively bootstrap errors:
>
>      [...]
>      ../../master/gcc/gcc.c: In function 'attempt_status run_attempt(const char**, const char*, const char*, int, int)':
>      ../../master/gcc/gcc.c:6319:15: error: variable 'errmsg' set but not used [-Werror=unused-but-set-variable]
>         const char *errmsg;
>                     ^
>      ../../master/gcc/gcc.c: At global scope:
>      ../../master/gcc/gcc.c:6412:33: error: unused parameter 'prog' [-Werror=unused-parameter]
>       try_generate_repro (const char *prog, const char **argv)
>                                       ^
>      cc1plus: all warnings being treated as errors
>      Makefile:1040: recipe for target 'gcc.o' failed
>      make[3]: *** [gcc.o] Error 1
>      make[3]: Leaving directory '/media/erich/home/thomas/tmp/gcc/hurd/master.build/gcc'
>      Makefile:4285: recipe for target 'all-stage2-gcc' failed
>      make[2]: *** [all-stage2-gcc] Error 2
>      make[2]: Leaving directory '/media/erich/home/thomas/tmp/gcc/hurd/master.build'
>      Makefile:21561: recipe for target 'stage2-bubble' failed
>      make[1]: *** [stage2-bubble] Error 2
>      make[1]: Leaving directory '/media/erich/home/thomas/tmp/gcc/hurd/master.build'
>      Makefile:892: recipe for target 'all' failed
>      make: *** [all] Error 2
>
> OK to fix as follows?  Only compile-tested, did not test the new
> -freport-bug functionality.

This works fine on pr55843 and pr58987.

> diff --git gcc/gcc.c gcc/gcc.c
> index e32ff47..47c4e28 100644
> --- gcc/gcc.c
> +++ gcc/gcc.c
> @@ -253,7 +253,7 @@ static void init_gcc_specs (struct obstack *, const char *, const char *,
>   static const char *convert_filename (const char *, int, int);
>   #endif
>   
> -static void try_generate_repro (const char *prog, const char **argv);
> +static void try_generate_repro (const char **argv);
>   static const char *getenv_spec_function (int, const char **);
>   static const char *if_exists_spec_function (int, const char **);
>   static const char *if_exists_else_spec_function (int, const char **);
> @@ -2918,7 +2918,7 @@ execute (void)
>   		&& i == 0
>   		&& (p = strrchr (commands[0].argv[0], DIR_SEPARATOR))
>   		&& ! strncmp (p + 1, "cc1", 3))
> -	      try_generate_repro (commands[0].prog, commands[0].argv);
> +	      try_generate_repro (commands[0].argv);
>   	    if (WEXITSTATUS (status) > greatest_status)
>   	      greatest_status = WEXITSTATUS (status);
>   	    ret_code = -1;
> @@ -6332,6 +6332,16 @@ run_attempt (const char **new_argv, const char *out_temp,
>     errmsg = pex_run (pex, pex_flags, new_argv[0],
>   		    CONST_CAST2 (char *const *, const char **, &new_argv[1]), out_temp,
>   		    err_temp, &err);
> +  if (errmsg != NULL)
> +    {
> +      if (err == 0)
> +	fatal_error (errmsg);
> +      else
> +	{
> +	  errno = err;
> +	  pfatal_with_name (errmsg);
> +	}
> +    }
>   
>     if (!pex_get_status (pex, 1, &exit_status))
>       goto out;
> @@ -6409,7 +6419,7 @@ append_text (char *file, const char *str)
>      and preprocessed source code.  */
>   
>   static void
> -try_generate_repro (const char *prog, const char **argv)
> +try_generate_repro (const char **argv)
>   {
>     int i, nargs, out_arg = -1, quiet = 0, attempt;
>     const char **new_argv;
>
>
>
> Grüße,
>   Thomas
-Maxim

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/2] Add patch for debugging compiler ICEs.
  2014-09-26 13:24                     ` Thomas Schwinge
  2014-09-26 13:32                       ` Maxim Ostapenko
@ 2014-09-26 16:18                       ` Jeff Law
  2014-09-26 16:31                         ` Thomas Schwinge
  1 sibling, 1 reply; 24+ messages in thread
From: Jeff Law @ 2014-09-26 16:18 UTC (permalink / raw)
  To: Thomas Schwinge, Maxim Ostapenko, Joseph S. Myers
  Cc: Jakub Jelinek, GCC Patches, Yury Gribov, Slava Garbuzov,
	Maxim Ostapenko, ian, dj, Yuri Gribov

On 09/26/14 07:23, Thomas Schwinge wrote:
> Hi!
>
> On Fri, 26 Sep 2014 12:04:45 +0400, Maxim Ostapenko <m.ostapenko@partner.samsung.com> wrote:
>> Thank you all for your help!
>>
>> Done in r215633.
>>
>> -Maxim
>> On 09/25/2014 11:05 PM, Jeff Law wrote:
>>> On 09/23/14 01:14, Maxim Ostapenko wrote:
>>>>
>>>>
>>>> 2014-09-04  Jakub Jelinek<jakub@redhat.com>
>>>>          Max Ostapenko<m.ostapenko@partner.samsung.com>
>>>>
>>>>      * common.opt: New option.
>>>>      * doc/invoke.texi: Describe new option.
>>>>      * gcc.c (execute): Don't free first string early, but at the end
>>>>      of the function.  Call retry_ice if compiler exited with
>>>>      ICE_EXIT_CODE.
>>>>      (main): Factor out common code.
>>>>      (print_configuration): New function.
>>>>      (files_equal_p): Likewise.
>>>>      (check_repro): Likewise.
>>>>      (run_attempt): Likewise.
>>>>      (do_report_bug): Likewise.
>>>>      (append_text): Likewise.
>>>>      (try_generate_repro): Likewise
>>> Approved.  Please install.
>>>
>>> Thanks for your patience,
>>> Jeff
>
> This is causing compiler warnings, respectively bootstrap errors:
>
>      [...]
>      ../../master/gcc/gcc.c: In function 'attempt_status run_attempt(const char**, const char*, const char*, int, int)':
>      ../../master/gcc/gcc.c:6319:15: error: variable 'errmsg' set but not used [-Werror=unused-but-set-variable]
>         const char *errmsg;
>                     ^
>      ../../master/gcc/gcc.c: At global scope:
>      ../../master/gcc/gcc.c:6412:33: error: unused parameter 'prog' [-Werror=unused-parameter]
>       try_generate_repro (const char *prog, const char **argv)
>                                       ^
>      cc1plus: all warnings being treated as errors
>      Makefile:1040: recipe for target 'gcc.o' failed
>      make[3]: *** [gcc.o] Error 1
>      make[3]: Leaving directory '/media/erich/home/thomas/tmp/gcc/hurd/master.build/gcc'
>      Makefile:4285: recipe for target 'all-stage2-gcc' failed
>      make[2]: *** [all-stage2-gcc] Error 2
>      make[2]: Leaving directory '/media/erich/home/thomas/tmp/gcc/hurd/master.build'
>      Makefile:21561: recipe for target 'stage2-bubble' failed
>      make[1]: *** [stage2-bubble] Error 2
>      make[1]: Leaving directory '/media/erich/home/thomas/tmp/gcc/hurd/master.build'
>      Makefile:892: recipe for target 'all' failed
>      make: *** [all] Error 2
>
> OK to fix as follows?  Only compile-tested, did not test the new
> -freport-bug functionality.
[ ... ]
Please construct a ChangeLog and commit.  Thanks.

jeff

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/2] Add patch for debugging compiler ICEs.
  2014-09-26 16:18                       ` Jeff Law
@ 2014-09-26 16:31                         ` Thomas Schwinge
  2014-09-26 16:32                           ` Jeff Law
  0 siblings, 1 reply; 24+ messages in thread
From: Thomas Schwinge @ 2014-09-26 16:31 UTC (permalink / raw)
  To: Jeff Law, Maxim Ostapenko, Joseph S. Myers
  Cc: Jakub Jelinek, GCC Patches, Yury Gribov, Slava Garbuzov,
	Maxim Ostapenko, ian, dj, Yuri Gribov

[-- Attachment #1: Type: text/plain, Size: 645 bytes --]

Hi!

On Fri, 26 Sep 2014 10:18:32 -0600, Jeff Law <law@redhat.com> wrote:
> On 09/26/14 07:23, Thomas Schwinge wrote:
> > On Fri, 26 Sep 2014 12:04:45 +0400, Maxim Ostapenko <m.ostapenko@partner.samsung.com> wrote:
> >> Done in r215633.

> > This is causing compiler warnings, respectively bootstrap errors: [...]

> > OK to fix as follows?  Only compile-tested, did not test the new
> > -freport-bug functionality.
> [ ... ]
> Please construct a ChangeLog and commit.  Thanks.

After Maxim had sent his email about having successfully tested it, I had
already taken the opportunity to commit it: r215644.


Grüße,
 Thomas

[-- Attachment #2: Type: application/pgp-signature, Size: 472 bytes --]

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/2] Add patch for debugging compiler ICEs.
  2014-09-26 16:31                         ` Thomas Schwinge
@ 2014-09-26 16:32                           ` Jeff Law
  0 siblings, 0 replies; 24+ messages in thread
From: Jeff Law @ 2014-09-26 16:32 UTC (permalink / raw)
  To: Thomas Schwinge, Maxim Ostapenko, Joseph S. Myers
  Cc: Jakub Jelinek, GCC Patches, Yury Gribov, Slava Garbuzov,
	Maxim Ostapenko, ian, dj, Yuri Gribov

On 09/26/14 10:31, Thomas Schwinge wrote:
> Hi!
>
> On Fri, 26 Sep 2014 10:18:32 -0600, Jeff Law <law@redhat.com> wrote:
>> On 09/26/14 07:23, Thomas Schwinge wrote:
>>> On Fri, 26 Sep 2014 12:04:45 +0400, Maxim Ostapenko <m.ostapenko@partner.samsung.com> wrote:
>>>> Done in r215633.
>
>>> This is causing compiler warnings, respectively bootstrap errors: [...]
>
>>> OK to fix as follows?  Only compile-tested, did not test the new
>>> -freport-bug functionality.
>> [ ... ]
>> Please construct a ChangeLog and commit.  Thanks.
>
> After Maxim had sent his email about having successfully tested it, I had
> already taken the opportunity to commit it: r215644.
Thanks.
jeff

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 2/2] Add patch for debugging compiler ICEs.
  2014-09-26  8:04                   ` Maxim Ostapenko
  2014-09-26 13:11                     ` Rainer Orth
  2014-09-26 13:24                     ` Thomas Schwinge
@ 2015-01-23  1:42                     ` H.J. Lu
  2 siblings, 0 replies; 24+ messages in thread
From: H.J. Lu @ 2015-01-23  1:42 UTC (permalink / raw)
  To: Maxim Ostapenko
  Cc: Jeff Law, Joseph S. Myers, Jakub Jelinek, GCC Patches,
	Yury Gribov, Slava Garbuzov, Maxim Ostapenko, Ian Lance Taylor,
	DJ Delorie, Yuri Gribov

On Fri, Sep 26, 2014 at 1:04 AM, Maxim Ostapenko
<m.ostapenko@partner.samsung.com> wrote:
> Thank you all for your help!
>
> Done in r215633.
>
> -Maxim
>
> On 09/25/2014 11:05 PM, Jeff Law wrote:
>>
>> On 09/23/14 01:14, Maxim Ostapenko wrote:
>>>
>>>
>>>
>>> 2014-09-04  Jakub Jelinek<jakub@redhat.com>
>>>         Max Ostapenko<m.ostapenko@partner.samsung.com>
>>>
>>>     * common.opt: New option.
>>>     * doc/invoke.texi: Describe new option.
>>>     * gcc.c (execute): Don't free first string early, but at the end
>>>     of the function.  Call retry_ice if compiler exited with
>>>     ICE_EXIT_CODE.
>>>     (main): Factor out common code.
>>>     (print_configuration): New function.
>>>     (files_equal_p): Likewise.
>>>     (check_repro): Likewise.
>>>     (run_attempt): Likewise.
>>>     (do_report_bug): Likewise.
>>>     (append_text): Likewise.
>>>     (try_generate_repro): Likewise
>>
>> Approved.  Please install.

Any particular reason for extra blank line:

  if (! strncmp (version_string, compiler_version, n)
      && compiler_version[n] == 0)
    fnotice (file, "gcc version %s %s\n\n", version_string,
             pkgversion_string);
  else
    fnotice (file, "gcc driver version %s %sexecuting gcc version %s\n\n",
             version_string, pkgversion_string, compiler_version);


I opened:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64737


-- 
H.J.

^ permalink raw reply	[flat|nested] 24+ messages in thread

end of thread, other threads:[~2015-01-22 23:12 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-08-04 17:03 [PATCH] Add patch for debugging compiler ICEs Maxim Ostapenko
2014-08-12 16:14 ` [PING][PATCH] " Maxim Ostapenko
2014-08-19 13:58 ` Fwd: [PATCH] " Maxim Ostapenko
2014-08-28  7:31   ` [Ping v2][PATCH] " Maxim Ostapenko
2014-09-05 14:16     ` [Ping v3][PATCH] " Maxim Ostapenko
2014-09-09 22:51     ` [Ping v2][PATCH] " Joseph S. Myers
2014-09-10  4:57       ` Jakub Jelinek
2014-09-10 16:37         ` Joseph S. Myers
2014-09-11 16:18           ` [PATCH 1/2] Extend libiberty to allow append stdout and stderr to existing files Maxim Ostapenko
2014-09-11 16:33             ` Ian Lance Taylor
2014-09-11 16:20           ` [PATCH 2/2] Add patch for debugging compiler ICEs Maxim Ostapenko
2014-09-18 15:37             ` [PING] " Maxim Ostapenko
2014-09-18 22:17             ` Joseph S. Myers
2014-09-19  3:33               ` Yury Gribov
2014-09-23  7:15               ` Maxim Ostapenko
2014-09-25 19:05                 ` Jeff Law
2014-09-26  8:04                   ` Maxim Ostapenko
2014-09-26 13:11                     ` Rainer Orth
2014-09-26 13:24                     ` Thomas Schwinge
2014-09-26 13:32                       ` Maxim Ostapenko
2014-09-26 16:18                       ` Jeff Law
2014-09-26 16:31                         ` Thomas Schwinge
2014-09-26 16:32                           ` Jeff Law
2015-01-23  1:42                     ` H.J. Lu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).