public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Add patch for debugging compiler ICEs
@ 2014-06-02 15:21 Maxim Ostapenko
  2014-06-10  7:40 ` Yury Gribov
                   ` (2 more replies)
  0 siblings, 3 replies; 18+ messages in thread
From: Maxim Ostapenko @ 2014-06-02 15:21 UTC (permalink / raw)
  To: GCC Patches
  Cc: Yury Gribov, Slava Garbuzov, Jakub Jelinek, tsaunders, chefmax7

[-- Attachment #1: Type: text/plain, Size: 377 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.

-Maxim


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

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

	* 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.
	(generate_preprocessed_code): Likewise.
	(append_text): Likewise.
	(try_generate_repro): Likewise.

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/gcc.c b/gcc/gcc.c
index 9ac18e6..86dce03 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 **);
@@ -2797,7 +2807,7 @@ execute (void)
 	    }
 	}
 
-      if (string != commands[i].prog)
+      if (i && string != commands[i].prog)
 	free (CONST_CAST (char *, string));
     }
 
@@ -2850,6 +2860,16 @@ 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 (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;
@@ -2907,6 +2927,9 @@ execute (void)
 	  }
       }
 
+   if (commands[0].argv[0] != commands[0].prog)
+     free (CONST_CAST (char *, commands[0].argv[0]));
+
     return ret_code;
   }
 }
@@ -6098,6 +6121,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
+generate_preprocessed_code (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\n//", 4);
+  for (i = 0; i < nargs; i++)
+    {
+      write (fd, " ", 1);
+      write (fd, new_argv[i], strlen (new_argv[i]));
+    }
+  write (fd, "\n", 1);
+  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_stdout_files, '\0', sizeof (temp_stdout_files));
+  memset (temp_stderr_files, '\0', sizeof (temp_stderr_files));
+  new_argv = XALLOCAVEC (const char *, nargs + 3);
+  memcpy (new_argv, argv, (nargs + 1) * sizeof (const char *));
+  new_argv[nargs++] = "-frandom-seed=0";
+  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.  */
+  generate_preprocessed_code (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.  */
@@ -6867,43 +7226,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] 18+ messages in thread

* Re: [PATCH] Add patch for debugging compiler ICEs
  2014-06-02 15:21 [PATCH] Add patch for debugging compiler ICEs Maxim Ostapenko
@ 2014-06-10  7:40 ` Yury Gribov
  2014-06-11 14:15 ` [PATCH][Ping] " Maxim Ostapenko
  2014-07-04 15:13 ` [PATCH] " James Greenhalgh
  2 siblings, 0 replies; 18+ messages in thread
From: Yury Gribov @ 2014-06-10  7:40 UTC (permalink / raw)
  To: Maxim Ostapenko, GCC Patches
  Cc: Slava Garbuzov, Jakub Jelinek, tsaunders, chefmax7

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

I wonder whether we should also set ADDR_NO_RANDOMIZE and 
ADDR_COMPAT_LAYOUT in addition to -frandom-seed (according to 
https://gcc.gnu.org/wiki/Randomization).

-Y

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

* [PATCH][Ping] Add patch for debugging compiler ICEs
  2014-06-02 15:21 [PATCH] Add patch for debugging compiler ICEs Maxim Ostapenko
  2014-06-10  7:40 ` Yury Gribov
@ 2014-06-11 14:15 ` Maxim Ostapenko
  2014-06-26 15:46   ` [PATCH][Ping v2] " Maxim Ostapenko
  2014-07-04 15:13 ` [PATCH] " James Greenhalgh
  2 siblings, 1 reply; 18+ messages in thread
From: Maxim Ostapenko @ 2014-06-11 14:15 UTC (permalink / raw)
  To: GCC Patches
  Cc: Yury Gribov, Slava Garbuzov, Jakub Jelinek, tsaunders, chefmax7

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

Ping.


-------- Original Message --------
Subject: 	[PATCH] Add patch for debugging compiler ICEs
Date: 	Mon, 02 Jun 2014 19:21:14 +0400
From: 	Maxim Ostapenko <m.ostapenko@partner.samsung.com>
To: 	GCC Patches <gcc-patches@gcc.gnu.org>
CC: 	Yury Gribov <y.gribov@samsung.com>, Slava Garbuzov 
<v.garbuzov@samsung.com>, Jakub Jelinek <jakub@redhat.com>, 
tsaunders@mozilla.com, chefmax7@gmail.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.

-Maxim


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

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

	* 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.
	(generate_preprocessed_code): Likewise.
	(append_text): Likewise.
	(try_generate_repro): Likewise.

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/gcc.c b/gcc/gcc.c
index 9ac18e6..86dce03 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 **);
@@ -2797,7 +2807,7 @@ execute (void)
 	    }
 	}
 
-      if (string != commands[i].prog)
+      if (i && string != commands[i].prog)
 	free (CONST_CAST (char *, string));
     }
 
@@ -2850,6 +2860,16 @@ 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 (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;
@@ -2907,6 +2927,9 @@ execute (void)
 	  }
       }
 
+   if (commands[0].argv[0] != commands[0].prog)
+     free (CONST_CAST (char *, commands[0].argv[0]));
+
     return ret_code;
   }
 }
@@ -6098,6 +6121,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
+generate_preprocessed_code (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\n//", 4);
+  for (i = 0; i < nargs; i++)
+    {
+      write (fd, " ", 1);
+      write (fd, new_argv[i], strlen (new_argv[i]));
+    }
+  write (fd, "\n", 1);
+  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_stdout_files, '\0', sizeof (temp_stdout_files));
+  memset (temp_stderr_files, '\0', sizeof (temp_stderr_files));
+  new_argv = XALLOCAVEC (const char *, nargs + 3);
+  memcpy (new_argv, argv, (nargs + 1) * sizeof (const char *));
+  new_argv[nargs++] = "-frandom-seed=0";
+  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.  */
+  generate_preprocessed_code (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.  */
@@ -6867,43 +7226,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] 18+ messages in thread

* [PATCH][Ping v2] Add patch for debugging compiler ICEs
  2014-06-11 14:15 ` [PATCH][Ping] " Maxim Ostapenko
@ 2014-06-26 15:46   ` Maxim Ostapenko
  2014-07-04 14:33     ` [PATCH][Ping v3] " Maxim Ostapenko
  0 siblings, 1 reply; 18+ messages in thread
From: Maxim Ostapenko @ 2014-06-26 15:46 UTC (permalink / raw)
  To: GCC Patches
  Cc: Yury Gribov, Slava Garbuzov, Jakub Jelinek, tsaunders, Maxim Ostapenko

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

Ping.


-------- Original Message --------
Subject: 	[PATCH][Ping] Add patch for debugging compiler ICEs
Date: 	Wed, 11 Jun 2014 18:15:27 +0400
From: 	Maxim Ostapenko <m.ostapenko@partner.samsung.com>
To: 	GCC Patches <gcc-patches@gcc.gnu.org>
CC: 	Yury Gribov <y.gribov@samsung.com>, Slava Garbuzov 
<v.garbuzov@samsung.com>, Jakub Jelinek <jakub@redhat.com>, 
tsaunders@mozilla.com, chefmax7@gmail.com



Ping.


-------- Original Message --------
Subject: 	[PATCH] Add patch for debugging compiler ICEs
Date: 	Mon, 02 Jun 2014 19:21:14 +0400
From: 	Maxim Ostapenko <m.ostapenko@partner.samsung.com>
To: 	GCC Patches <gcc-patches@gcc.gnu.org>
CC: 	Yury Gribov <y.gribov@samsung.com>, Slava Garbuzov
<v.garbuzov@samsung.com>, Jakub Jelinek <jakub@redhat.com>,
tsaunders@mozilla.com, chefmax7@gmail.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.

-Maxim





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

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

	* 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.
	(generate_preprocessed_code): Likewise.
	(append_text): Likewise.
	(try_generate_repro): Likewise.

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/gcc.c b/gcc/gcc.c
index 9ac18e6..86dce03 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 **);
@@ -2797,7 +2807,7 @@ execute (void)
 	    }
 	}
 
-      if (string != commands[i].prog)
+      if (i && string != commands[i].prog)
 	free (CONST_CAST (char *, string));
     }
 
@@ -2850,6 +2860,16 @@ 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 (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;
@@ -2907,6 +2927,9 @@ execute (void)
 	  }
       }
 
+   if (commands[0].argv[0] != commands[0].prog)
+     free (CONST_CAST (char *, commands[0].argv[0]));
+
     return ret_code;
   }
 }
@@ -6098,6 +6121,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
+generate_preprocessed_code (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\n//", 4);
+  for (i = 0; i < nargs; i++)
+    {
+      write (fd, " ", 1);
+      write (fd, new_argv[i], strlen (new_argv[i]));
+    }
+  write (fd, "\n", 1);
+  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_stdout_files, '\0', sizeof (temp_stdout_files));
+  memset (temp_stderr_files, '\0', sizeof (temp_stderr_files));
+  new_argv = XALLOCAVEC (const char *, nargs + 3);
+  memcpy (new_argv, argv, (nargs + 1) * sizeof (const char *));
+  new_argv[nargs++] = "-frandom-seed=0";
+  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.  */
+  generate_preprocessed_code (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.  */
@@ -6867,43 +7226,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] 18+ messages in thread

* [PATCH][Ping v3] Add patch for debugging compiler ICEs
  2014-06-26 15:46   ` [PATCH][Ping v2] " Maxim Ostapenko
@ 2014-07-04 14:33     ` Maxim Ostapenko
  2014-07-11 13:44       ` [PATCH][Ping v4] " Maxim Ostapenko
  0 siblings, 1 reply; 18+ messages in thread
From: Maxim Ostapenko @ 2014-07-04 14:33 UTC (permalink / raw)
  To: GCC Patches
  Cc: Yury Gribov, Slava Garbuzov, Jakub Jelinek, tsaunders, Maxim Ostapenko

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

Ping.


-------- Original Message --------
Subject: 	[PATCH][Ping v2] Add patch for debugging compiler ICEs
Date: 	Thu, 26 Jun 2014 19:46:08 +0400
From: 	Maxim Ostapenko <m.ostapenko@partner.samsung.com>
To: 	GCC Patches <gcc-patches@gcc.gnu.org>
CC: 	Yury Gribov <y.gribov@samsung.com>, Slava Garbuzov 
<v.garbuzov@samsung.com>, Jakub Jelinek <jakub@redhat.com>, 
tsaunders@mozilla.com, Maxim Ostapenko <chefmax7@gmail.com>



Ping.


-------- Original Message --------
Subject: 	[PATCH][Ping] Add patch for debugging compiler ICEs
Date: 	Wed, 11 Jun 2014 18:15:27 +0400
From: 	Maxim Ostapenko <m.ostapenko@partner.samsung.com>
To: 	GCC Patches <gcc-patches@gcc.gnu.org>
CC: 	Yury Gribov <y.gribov@samsung.com>, Slava Garbuzov
<v.garbuzov@samsung.com>, Jakub Jelinek <jakub@redhat.com>,
tsaunders@mozilla.com, chefmax7@gmail.com



Ping.


-------- Original Message --------
Subject: 	[PATCH] Add patch for debugging compiler ICEs
Date: 	Mon, 02 Jun 2014 19:21:14 +0400
From: 	Maxim Ostapenko <m.ostapenko@partner.samsung.com>
To: 	GCC Patches <gcc-patches@gcc.gnu.org>
CC: 	Yury Gribov <y.gribov@samsung.com>, Slava Garbuzov
<v.garbuzov@samsung.com>, Jakub Jelinek <jakub@redhat.com>,
tsaunders@mozilla.com, chefmax7@gmail.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.

-Maxim








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

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

	* 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.
	(generate_preprocessed_code): Likewise.
	(append_text): Likewise.
	(try_generate_repro): Likewise.

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/gcc.c b/gcc/gcc.c
index 9ac18e6..86dce03 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 **);
@@ -2797,7 +2807,7 @@ execute (void)
 	    }
 	}
 
-      if (string != commands[i].prog)
+      if (i && string != commands[i].prog)
 	free (CONST_CAST (char *, string));
     }
 
@@ -2850,6 +2860,16 @@ 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 (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;
@@ -2907,6 +2927,9 @@ execute (void)
 	  }
       }
 
+   if (commands[0].argv[0] != commands[0].prog)
+     free (CONST_CAST (char *, commands[0].argv[0]));
+
     return ret_code;
   }
 }
@@ -6098,6 +6121,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
+generate_preprocessed_code (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\n//", 4);
+  for (i = 0; i < nargs; i++)
+    {
+      write (fd, " ", 1);
+      write (fd, new_argv[i], strlen (new_argv[i]));
+    }
+  write (fd, "\n", 1);
+  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_stdout_files, '\0', sizeof (temp_stdout_files));
+  memset (temp_stderr_files, '\0', sizeof (temp_stderr_files));
+  new_argv = XALLOCAVEC (const char *, nargs + 3);
+  memcpy (new_argv, argv, (nargs + 1) * sizeof (const char *));
+  new_argv[nargs++] = "-frandom-seed=0";
+  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.  */
+  generate_preprocessed_code (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.  */
@@ -6867,43 +7226,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] 18+ messages in thread

* Re: [PATCH] Add patch for debugging compiler ICEs
  2014-06-02 15:21 [PATCH] Add patch for debugging compiler ICEs Maxim Ostapenko
  2014-06-10  7:40 ` Yury Gribov
  2014-06-11 14:15 ` [PATCH][Ping] " Maxim Ostapenko
@ 2014-07-04 15:13 ` James Greenhalgh
  2014-07-04 15:21   ` Jakub Jelinek
  2 siblings, 1 reply; 18+ messages in thread
From: James Greenhalgh @ 2014-07-04 15:13 UTC (permalink / raw)
  To: Maxim Ostapenko
  Cc: GCC Patches, Yury Gribov, Slava Garbuzov, Jakub Jelinek,
	tsaunders, chefmax7

On Mon, Jun 02, 2014 at 04:21:14PM +0100, 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.
> 

How can I test this patch?

I tried applying it and injecting a segmentation fault in to the AArch64 CPU
option parsing code, but I didn't see anything new when the ICE was triggered.

What am I doing wrong?

Thanks,
James


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

* Re: [PATCH] Add patch for debugging compiler ICEs
  2014-07-04 15:13 ` [PATCH] " James Greenhalgh
@ 2014-07-04 15:21   ` Jakub Jelinek
  2014-07-09 17:20     ` Yury Gribov
  0 siblings, 1 reply; 18+ messages in thread
From: Jakub Jelinek @ 2014-07-04 15:21 UTC (permalink / raw)
  To: James Greenhalgh
  Cc: Maxim Ostapenko, GCC Patches, Yury Gribov, Slava Garbuzov,
	tsaunders, chefmax7

On Fri, Jul 04, 2014 at 04:13:31PM +0100, James Greenhalgh wrote:
> On Mon, Jun 02, 2014 at 04:21:14PM +0100, 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.
> > 
> 
> How can I test this patch?
> 
> I tried applying it and injecting a segmentation fault in to the AArch64 CPU
> option parsing code, but I didn't see anything new when the ICE was triggered.
> 
> What am I doing wrong?

It is a driver patch, so you get something only when you invoke the driver,
not when compiling with cc1 or cc1plus etc. directly.

Just pick up any known ICE from bugzilla and try it...

	Jakub

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

* Re: [PATCH] Add patch for debugging compiler ICEs
  2014-07-04 15:21   ` Jakub Jelinek
@ 2014-07-09 17:20     ` Yury Gribov
  0 siblings, 0 replies; 18+ messages in thread
From: Yury Gribov @ 2014-07-09 17:20 UTC (permalink / raw)
  To: Jakub Jelinek, James Greenhalgh
  Cc: Maxim Ostapenko, GCC Patches, Slava Garbuzov, tsaunders, chefmax7

 > It is a driver patch, so you get something only
 > when you invoke the driver,
 > not when compiling with cc1 or cc1plus etc. directly.
 >
 > Just pick up any known ICE from bugzilla and try it...

Tried that with some recent ICEs:
* PR 61445 - generated expected repro
* PR 60990 and 61623 - reports "The bug is not reproducible, so it is 
likely a hardware or OS problem." (I guess error messages include 
pointer values which change across runs and cause this patch to bail out)

-Y

-----------------------------------------------
From: Jakub Jelinek
Sent:  Friday, July 04, 2014 7:21PM
To: James Greenhalgh <james.greenhalgh@arm.com>
Cc: Max Ostapenko, GCC Patches, Yury Gribov, Viacheslav Garbuzov, Trevor 
Saunders, Maxim Ostapenko
Subject: Re: [PATCH] Add patch for debugging compiler ICEs

On 07/04/2014 07:21 PM, Jakub Jelinek wrote:
On Fri, Jul 04, 2014 at 04:13:31PM +0100, James Greenhalgh wrote:
> On Mon, Jun 02, 2014 at 04:21:14PM +0100, 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.
>>
>>
> How can I test this patch?
>
> I tried applying it and injecting a segmentation fault in to the AArch64 CPU
> option parsing code, but I didn't see anything new when the ICE was triggered.
>
> What am I doing wrong?

It is a driver patch, so you get something only when you invoke the driver,
not when compiling with cc1 or cc1plus etc. directly.

Just pick up any known ICE from bugzilla and try it...

	Jakub




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

* [PATCH][Ping v4] Add patch for debugging compiler ICEs
  2014-07-04 14:33     ` [PATCH][Ping v3] " Maxim Ostapenko
@ 2014-07-11 13:44       ` Maxim Ostapenko
  2014-07-24 12:43         ` [PATCH][Ping v5] " Maxim Ostapenko
  0 siblings, 1 reply; 18+ messages in thread
From: Maxim Ostapenko @ 2014-07-11 13:44 UTC (permalink / raw)
  To: GCC Patches
  Cc: Yury Gribov, Slava Garbuzov, Jakub Jelinek, tsaunders, Maxim Ostapenko

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

Ping. Added small changes due to previous discussion in community.


-------- Original Message --------
Subject: 	[PATCH][Ping v3] Add patch for debugging compiler ICEs
Date: 	Fri, 04 Jul 2014 18:32:44 +0400
From: 	Maxim Ostapenko <m.ostapenko@partner.samsung.com>
To: 	GCC Patches <gcc-patches@gcc.gnu.org>
CC: 	Yury Gribov <y.gribov@samsung.com>, Slava Garbuzov 
<v.garbuzov@samsung.com>, Jakub Jelinek <jakub@redhat.com>, 
tsaunders@mozilla.com, Maxim Ostapenko <chefmax7@gmail.com>



Ping.


-------- Original Message --------
Subject: 	[PATCH][Ping v2] Add patch for debugging compiler ICEs
Date: 	Thu, 26 Jun 2014 19:46:08 +0400
From: 	Maxim Ostapenko <m.ostapenko@partner.samsung.com>
To: 	GCC Patches <gcc-patches@gcc.gnu.org>
CC: 	Yury Gribov <y.gribov@samsung.com>, Slava Garbuzov
<v.garbuzov@samsung.com>, Jakub Jelinek <jakub@redhat.com>,
tsaunders@mozilla.com, Maxim Ostapenko <chefmax7@gmail.com>



Ping.


-------- Original Message --------
Subject: 	[PATCH][Ping] Add patch for debugging compiler ICEs
Date: 	Wed, 11 Jun 2014 18:15:27 +0400
From: 	Maxim Ostapenko <m.ostapenko@partner.samsung.com>
To: 	GCC Patches <gcc-patches@gcc.gnu.org>
CC: 	Yury Gribov <y.gribov@samsung.com>, Slava Garbuzov
<v.garbuzov@samsung.com>, Jakub Jelinek <jakub@redhat.com>,
tsaunders@mozilla.com, chefmax7@gmail.com



Ping.


-------- Original Message --------
Subject: 	[PATCH] Add patch for debugging compiler ICEs
Date: 	Mon, 02 Jun 2014 19:21:14 +0400
From: 	Maxim Ostapenko <m.ostapenko@partner.samsung.com>
To: 	GCC Patches <gcc-patches@gcc.gnu.org>
CC: 	Yury Gribov <y.gribov@samsung.com>, Slava Garbuzov
<v.garbuzov@samsung.com>, Jakub Jelinek <jakub@redhat.com>,
tsaunders@mozilla.com, chefmax7@gmail.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.

-Maxim











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

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

	* 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.
	(generate_preprocessed_code): Likewise.
	(append_text): Likewise.
	(try_generate_repro): Likewise.

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/gcc.c b/gcc/gcc.c
index 6cd08ea..045363c 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 **);
@@ -2850,7 +2860,7 @@ execute (void)
 	    }
 	}
 
-      if (string != commands[i].prog)
+      if (i && string != commands[i].prog)
 	free (CONST_CAST (char *, string));
     }
 
@@ -2903,6 +2913,16 @@ 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 (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;
@@ -2960,6 +2980,9 @@ execute (void)
 	  }
       }
 
+   if (commands[0].argv[0] != commands[0].prog)
+     free (CONST_CAST (char *, commands[0].argv[0]));
+
     return ret_code;
   }
 }
@@ -6151,6 +6174,341 @@ 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 void
+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);
+}
+
+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
+generate_preprocessed_code (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 + 3);
+  memcpy (new_argv, argv, (nargs + 1) * sizeof (const char *));
+  new_argv[nargs++] = "-frandom-seed=0";
+  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;
+        }
+    }
+
+  /* Don't abort because stderr messages can be different in various
+     attempts.  */
+  check_repro (temp_stdout_files, temp_stderr_files);
+
+  /* In final attempt we append cc1 options and preprocesssed code to last
+     generated .err file with configuration and backtrace.  */
+  generate_preprocessed_code (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.  */
@@ -6920,43 +7278,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] 18+ messages in thread

* [PATCH][Ping v5] Add patch for debugging compiler ICEs
  2014-07-11 13:44       ` [PATCH][Ping v4] " Maxim Ostapenko
@ 2014-07-24 12:43         ` Maxim Ostapenko
  2014-08-01  8:00           ` Jakub Jelinek
  0 siblings, 1 reply; 18+ messages in thread
From: Maxim Ostapenko @ 2014-07-24 12:43 UTC (permalink / raw)
  To: GCC Patches
  Cc: Yury Gribov, Slava Garbuzov, Jakub Jelinek, tsaunders, Maxim Ostapenko

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

Ping.

-------- Original Message --------
Subject: 	[PATCH][Ping v4] Add patch for debugging compiler ICEs
Date: 	Fri, 11 Jul 2014 17:44:28 +0400
From: 	Maxim Ostapenko <m.ostapenko@partner.samsung.com>
To: 	GCC Patches <gcc-patches@gcc.gnu.org>
CC: 	Yury Gribov <y.gribov@samsung.com>, Slava Garbuzov 
<v.garbuzov@samsung.com>, Jakub Jelinek <jakub@redhat.com>, 
tsaunders@mozilla.com, Maxim Ostapenko <chefmax7@gmail.com>



Ping. Added small changes due to previous discussion in community.


-------- Original Message --------
Subject: 	[PATCH][Ping v3] Add patch for debugging compiler ICEs
Date: 	Fri, 04 Jul 2014 18:32:44 +0400
From: 	Maxim Ostapenko <m.ostapenko@partner.samsung.com>
To: 	GCC Patches <gcc-patches@gcc.gnu.org>
CC: 	Yury Gribov <y.gribov@samsung.com>, Slava Garbuzov
<v.garbuzov@samsung.com>, Jakub Jelinek <jakub@redhat.com>,
tsaunders@mozilla.com, Maxim Ostapenko <chefmax7@gmail.com>



Ping.


-------- Original Message --------
Subject: 	[PATCH][Ping v2] Add patch for debugging compiler ICEs
Date: 	Thu, 26 Jun 2014 19:46:08 +0400
From: 	Maxim Ostapenko <m.ostapenko@partner.samsung.com>
To: 	GCC Patches <gcc-patches@gcc.gnu.org>
CC: 	Yury Gribov <y.gribov@samsung.com>, Slava Garbuzov
<v.garbuzov@samsung.com>, Jakub Jelinek <jakub@redhat.com>,
tsaunders@mozilla.com, Maxim Ostapenko <chefmax7@gmail.com>



Ping.


-------- Original Message --------
Subject: 	[PATCH][Ping] Add patch for debugging compiler ICEs
Date: 	Wed, 11 Jun 2014 18:15:27 +0400
From: 	Maxim Ostapenko <m.ostapenko@partner.samsung.com>
To: 	GCC Patches <gcc-patches@gcc.gnu.org>
CC: 	Yury Gribov <y.gribov@samsung.com>, Slava Garbuzov
<v.garbuzov@samsung.com>, Jakub Jelinek <jakub@redhat.com>,
tsaunders@mozilla.com, chefmax7@gmail.com



Ping.


-------- Original Message --------
Subject: 	[PATCH] Add patch for debugging compiler ICEs
Date: 	Mon, 02 Jun 2014 19:21:14 +0400
From: 	Maxim Ostapenko <m.ostapenko@partner.samsung.com>
To: 	GCC Patches <gcc-patches@gcc.gnu.org>
CC: 	Yury Gribov <y.gribov@samsung.com>, Slava Garbuzov
<v.garbuzov@samsung.com>, Jakub Jelinek <jakub@redhat.com>,
tsaunders@mozilla.com, chefmax7@gmail.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.

-Maxim














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

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

	* 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.
	(generate_preprocessed_code): Likewise.
	(append_text): Likewise.
	(try_generate_repro): Likewise.

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/gcc.c b/gcc/gcc.c
index 6cd08ea..045363c 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 **);
@@ -2850,7 +2860,7 @@ execute (void)
 	    }
 	}
 
-      if (string != commands[i].prog)
+      if (i && string != commands[i].prog)
 	free (CONST_CAST (char *, string));
     }
 
@@ -2903,6 +2913,16 @@ 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 (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;
@@ -2960,6 +2980,9 @@ execute (void)
 	  }
       }
 
+   if (commands[0].argv[0] != commands[0].prog)
+     free (CONST_CAST (char *, commands[0].argv[0]));
+
     return ret_code;
   }
 }
@@ -6151,6 +6174,341 @@ 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 void
+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);
+}
+
+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
+generate_preprocessed_code (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 + 3);
+  memcpy (new_argv, argv, (nargs + 1) * sizeof (const char *));
+  new_argv[nargs++] = "-frandom-seed=0";
+  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;
+        }
+    }
+
+  /* Don't abort because stderr messages can be different in various
+     attempts.  */
+  check_repro (temp_stdout_files, temp_stderr_files);
+
+  /* In final attempt we append cc1 options and preprocesssed code to last
+     generated .err file with configuration and backtrace.  */
+  generate_preprocessed_code (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.  */
@@ -6920,43 +7278,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] 18+ messages in thread

* Re: [PATCH][Ping v5] Add patch for debugging compiler ICEs
  2014-07-24 12:43         ` [PATCH][Ping v5] " Maxim Ostapenko
@ 2014-08-01  8:00           ` Jakub Jelinek
  2014-08-01  8:13             ` Yury Gribov
                               ` (2 more replies)
  0 siblings, 3 replies; 18+ messages in thread
From: Jakub Jelinek @ 2014-08-01  8:00 UTC (permalink / raw)
  To: Maxim Ostapenko
  Cc: GCC Patches, Yury Gribov, Slava Garbuzov, tsaunders, Maxim Ostapenko

On Thu, Jul 24, 2014 at 04:39:28PM +0400, Maxim Ostapenko wrote:
> Ping.

Don't want to review a patch I wrote partially, so just a few comments:
1) IMHO it should be configure time selectable (not sure about the default,
but for non-release branches IMHO it should default to off, for release
branches I don't know).  The point is that while it is useful for
people to report gcc bugs in production compilers, it is not useful for
gcc developers on their boxes, having ICEs take 3 times as long is not
desirable for people who deal with those all the time
2) recently a bug has been reported that some ICEs which print RTL
to stderr are considered non-reproduceable, because the addresses e.g.
in call_insn fndecl change through address space randomization.  For the
retries the driver should supposedly append -fdump-noaddr.

	Jakub

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

* Re: [PATCH][Ping v5] Add patch for debugging compiler ICEs
  2014-08-01  8:00           ` Jakub Jelinek
@ 2014-08-01  8:13             ` Yury Gribov
  2014-08-01 15:54               ` Jakub Jelinek
  2014-08-01 15:43             ` Andi Kleen
  2014-08-01 19:29             ` Jeff Law
  2 siblings, 1 reply; 18+ messages in thread
From: Yury Gribov @ 2014-08-01  8:13 UTC (permalink / raw)
  To: Jakub Jelinek, Maxim Ostapenko
  Cc: GCC Patches, Slava Garbuzov, tsaunders, Maxim Ostapenko

On 08/01/2014 12:00 PM, Jakub Jelinek wrote:
> Don't want to review a patch I wrote partially, so just a few comments:
> 1) IMHO it should be configure time selectable (not sure about the default,
> but for non-release branches IMHO it should default to off, for release
> branches I don't know).  The point is that while it is useful for
> people to report gcc bugs in production compilers, it is not useful for
> gcc developers on their boxes, having ICEs take 3 times as long is not
> desirable for people who deal with those all the time

I think we should use David Malcolm's approach i.e. add some 
--report-bug flag
to driver. This could be enabled by default at configure time via 
--with-spec.

> 2) recently a bug has been reported that some ICEs which print RTL
> to stderr are considered non-reproduceable, because the addresses e.g.
> in call_insn fndecl change through address space randomization.  For the
> etries the driver should supposedly append -fdump-noaddr.

+1

-Y

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

* Re: [PATCH][Ping v5] Add patch for debugging compiler ICEs
  2014-08-01  8:00           ` Jakub Jelinek
  2014-08-01  8:13             ` Yury Gribov
@ 2014-08-01 15:43             ` Andi Kleen
  2014-08-01 15:49               ` Jakub Jelinek
  2014-08-01 19:29             ` Jeff Law
  2 siblings, 1 reply; 18+ messages in thread
From: Andi Kleen @ 2014-08-01 15:43 UTC (permalink / raw)
  To: Jakub Jelinek
  Cc: Maxim Ostapenko, GCC Patches, Yury Gribov, Slava Garbuzov,
	tsaunders, Maxim Ostapenko

Jakub Jelinek <jakub@redhat.com> writes:
> Don't want to review a patch I wrote partially, so just a few comments:
> 1) IMHO it should be configure time selectable (not sure about the default,
> but for non-release branches IMHO it should default to off, for release
> branches I don't know).  The point is that while it is useful for
> people to report gcc bugs in production compilers, it is not useful for
> gcc developers on their boxes, having ICEs take 3 times as long is not
> desirable for people who deal with those all the time

It may also not be desirable for LTO builds, which can take very long
by themselves.

-Andi
-- 
ak@linux.intel.com -- Speaking for myself only

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

* Re: [PATCH][Ping v5] Add patch for debugging compiler ICEs
  2014-08-01 15:43             ` Andi Kleen
@ 2014-08-01 15:49               ` Jakub Jelinek
  0 siblings, 0 replies; 18+ messages in thread
From: Jakub Jelinek @ 2014-08-01 15:49 UTC (permalink / raw)
  To: Andi Kleen
  Cc: Maxim Ostapenko, GCC Patches, Yury Gribov, Slava Garbuzov,
	tsaunders, Maxim Ostapenko

On Fri, Aug 01, 2014 at 08:43:27AM -0700, Andi Kleen wrote:
> Jakub Jelinek <jakub@redhat.com> writes:
> > Don't want to review a patch I wrote partially, so just a few comments:
> > 1) IMHO it should be configure time selectable (not sure about the default,
> > but for non-release branches IMHO it should default to off, for release
> > branches I don't know).  The point is that while it is useful for
> > people to report gcc bugs in production compilers, it is not useful for
> > gcc developers on their boxes, having ICEs take 3 times as long is not
> > desirable for people who deal with those all the time
> 
> It may also not be desirable for LTO builds, which can take very long
> by themselves.

Indeed, and preparing preprocessed sources for all the files is hard in that
case anyway.  But as it is keyed on cc1 substring being present in the
compiler's name and lto uses lto1, it shouldn't trigger for that.
Only if you get ICEs with -flto already when compiling from C/C++ source,
but then it doesn't take very long usually and there is preprocessed source
available.

	Jakub

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

* Re: [PATCH][Ping v5] Add patch for debugging compiler ICEs
  2014-08-01  8:13             ` Yury Gribov
@ 2014-08-01 15:54               ` Jakub Jelinek
  2014-08-04  6:41                 ` Yury Gribov
  0 siblings, 1 reply; 18+ messages in thread
From: Jakub Jelinek @ 2014-08-01 15:54 UTC (permalink / raw)
  To: Yury Gribov
  Cc: Maxim Ostapenko, GCC Patches, Slava Garbuzov, tsaunders, Maxim Ostapenko

On Fri, Aug 01, 2014 at 12:13:18PM +0400, Yury Gribov wrote:
> On 08/01/2014 12:00 PM, Jakub Jelinek wrote:
> >Don't want to review a patch I wrote partially, so just a few comments:
> >1) IMHO it should be configure time selectable (not sure about the default,
> >but for non-release branches IMHO it should default to off, for release
> >branches I don't know).  The point is that while it is useful for
> >people to report gcc bugs in production compilers, it is not useful for
> >gcc developers on their boxes, having ICEs take 3 times as long is not
> >desirable for people who deal with those all the time
> 
> I think we should use David Malcolm's approach i.e. add some --report-bug
> flag
> to driver. This could be enabled by default at configure time via
> --with-spec.

-freport-bug or whatever we call it should not be, at least if it attempts
to communicate over the network, should not be required though, lots of
people do e.g. package builds in various chroots etc. and you really don't
want to perform any network activity from there.  Still, having
info whether an ICE was reproduceable or not is useful in that case, and
having preprocessed source left in /tmp with the path printed to stderr
is also useful, you can e.g. grab those /tmp/cc*.out files from the chroot
and allow people to report later on.  The ICE message can of course suggest
an option or script or command line to run to report the bug or navigate the
user through bug reporting process.

	Jakub

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

* Re: [PATCH][Ping v5] Add patch for debugging compiler ICEs
  2014-08-01  8:00           ` Jakub Jelinek
  2014-08-01  8:13             ` Yury Gribov
  2014-08-01 15:43             ` Andi Kleen
@ 2014-08-01 19:29             ` Jeff Law
  2014-08-04 17:13               ` Maxim Ostapenko
  2 siblings, 1 reply; 18+ messages in thread
From: Jeff Law @ 2014-08-01 19:29 UTC (permalink / raw)
  To: Jakub Jelinek, Maxim Ostapenko
  Cc: GCC Patches, Yury Gribov, Slava Garbuzov, tsaunders, Maxim Ostapenko

On 08/01/14 02:00, Jakub Jelinek wrote:
> On Thu, Jul 24, 2014 at 04:39:28PM +0400, Maxim Ostapenko wrote:
>> Ping.
>
> Don't want to review a patch I wrote partially, so just a few comments:
> 1) IMHO it should be configure time selectable (not sure about the default,
> but for non-release branches IMHO it should default to off, for release
> branches I don't know).  The point is that while it is useful for
> people to report gcc bugs in production compilers, it is not useful for
> gcc developers on their boxes, having ICEs take 3 times as long is not
> desirable for people who deal with those all the time
We definitely want the ability to select.  Waiting on an ICE to trigger 
3 times would be painful for the developers.  So I'd think that enabled 
for the release branches and disabled for the trunk would be the right 
default.


> 2) recently a bug has been reported that some ICEs which print RTL
> to stderr are considered non-reproduceable, because the addresses e.g.
> in call_insn fndecl change through address space randomization.  For the
> retries the driver should supposedly append -fdump-noaddr.
Right.  I think we discussed this at Cauldron.

I think it's conceptually ok with those two changes, then it's just 
reviewing the details.

If you or Maxim could make those changes and repost, I'll cover the review.

jeff

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

* Re: [PATCH][Ping v5] Add patch for debugging compiler ICEs
  2014-08-01 15:54               ` Jakub Jelinek
@ 2014-08-04  6:41                 ` Yury Gribov
  0 siblings, 0 replies; 18+ messages in thread
From: Yury Gribov @ 2014-08-04  6:41 UTC (permalink / raw)
  To: Jakub Jelinek
  Cc: Maxim Ostapenko, GCC Patches, Slava Garbuzov, tsaunders, Maxim Ostapenko

On 08/01/2014 07:53 PM, Jakub Jelinek wrote:
>> I think we should use David Malcolm's approach i.e. add some --report-bug
>> flag
>> to driver. This could be enabled by default at configure time via
>> --with-spec.
> -freport-bug or whatever we call it should not be, at least if it attempts
> to communicate over the network, should not be required though, lots of
> people do e.g. package builds in various chroots etc. and you really don't
> want to perform any network activity from there.

Oh sure, the actual "backend" of --report-bug could vary from just
generating the repro and storing it in /tmp (what your patch did in the 
first place)
to David's full blown automatic Bugzilla submission.

-Y

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

* Re: [PATCH][Ping v5] Add patch for debugging compiler ICEs
  2014-08-01 19:29             ` Jeff Law
@ 2014-08-04 17:13               ` Maxim Ostapenko
  0 siblings, 0 replies; 18+ messages in thread
From: Maxim Ostapenko @ 2014-08-04 17:13 UTC (permalink / raw)
  To: Jeff Law, Jakub Jelinek
  Cc: GCC Patches, Yury Gribov, Slava Garbuzov, tsaunders, Maxim Ostapenko

Thanks Jeff and Jakub, I've reposted ICE debugging patch into 
gcc-patches mailing list 
(https://gcc.gnu.org/ml/gcc-patches/2014-08/msg00285.html).

-Maxim
On 08/01/2014 11:29 PM, Jeff Law wrote:
> On 08/01/14 02:00, Jakub Jelinek wrote:
>> On Thu, Jul 24, 2014 at 04:39:28PM +0400, Maxim Ostapenko wrote:
>>> Ping.
>>
>> Don't want to review a patch I wrote partially, so just a few comments:
>> 1) IMHO it should be configure time selectable (not sure about the 
>> default,
>> but for non-release branches IMHO it should default to off, for release
>> branches I don't know).  The point is that while it is useful for
>> people to report gcc bugs in production compilers, it is not useful for
>> gcc developers on their boxes, having ICEs take 3 times as long is not
>> desirable for people who deal with those all the time
> We definitely want the ability to select.  Waiting on an ICE to 
> trigger 3 times would be painful for the developers.  So I'd think 
> that enabled for the release branches and disabled for the trunk would 
> be the right default.
>
>
>> 2) recently a bug has been reported that some ICEs which print RTL
>> to stderr are considered non-reproduceable, because the addresses e.g.
>> in call_insn fndecl change through address space randomization. For the
>> retries the driver should supposedly append -fdump-noaddr.
> Right.  I think we discussed this at Cauldron.
>
> I think it's conceptually ok with those two changes, then it's just 
> reviewing the details.
>
> If you or Maxim could make those changes and repost, I'll cover the 
> review.
>
> jeff
>

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

end of thread, other threads:[~2014-08-04 17:13 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-06-02 15:21 [PATCH] Add patch for debugging compiler ICEs Maxim Ostapenko
2014-06-10  7:40 ` Yury Gribov
2014-06-11 14:15 ` [PATCH][Ping] " Maxim Ostapenko
2014-06-26 15:46   ` [PATCH][Ping v2] " Maxim Ostapenko
2014-07-04 14:33     ` [PATCH][Ping v3] " Maxim Ostapenko
2014-07-11 13:44       ` [PATCH][Ping v4] " Maxim Ostapenko
2014-07-24 12:43         ` [PATCH][Ping v5] " Maxim Ostapenko
2014-08-01  8:00           ` Jakub Jelinek
2014-08-01  8:13             ` Yury Gribov
2014-08-01 15:54               ` Jakub Jelinek
2014-08-04  6:41                 ` Yury Gribov
2014-08-01 15:43             ` Andi Kleen
2014-08-01 15:49               ` Jakub Jelinek
2014-08-01 19:29             ` Jeff Law
2014-08-04 17:13               ` Maxim Ostapenko
2014-07-04 15:13 ` [PATCH] " James Greenhalgh
2014-07-04 15:21   ` Jakub Jelinek
2014-07-09 17:20     ` Yury Gribov

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).