On Mon, May 26, 2014 at 11:54:04AM +0400, 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. > > Is this still considered a useful feature for 4.10? If yes, we can resurrect > and submit this patch.
definitely! bonus points if you handle building with FDO enabled. thanks! Trev > > -Maxim > # DP: Retry the build on an ice, save the calling options and preprocessed > # DP: source when the ice is reproducible. > > 2004-01-23 Jakub Jelinek <ja...@redhat.com> > > * 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. > (retry_ice): New function. > * diagnostic.c (diagnostic_count_diagnostic, > diagnostic_action_after_output, error_recursion): Exit with > ICE_EXIT_CODE instead of FATAL_EXIT_CODE. > > #--- a/src/gcc/Makefile.in > #+++ b/src/gcc/Makefile.in > #@@ -181,6 +181,8 @@ SYSCALLS.c.X-warn = -Wno-strict-prototypes -Wno-error > # dfp.o-warn = -Wno-error > # # mips-tfile.c contains -Wcast-qual warnings. > # mips-tfile.o-warn = -Wno-error > #+# gcc-ice-hack > #+gcc.o-warn = -Wno-error > # > # # All warnings have to be shut off in stage1 if the compiler used then > # # isn't gcc; configure determines that. WARN_CFLAGS will be either > --- a/src/gcc/gcc.c > +++ b/src/gcc/gcc.c > @@ -250,6 +250,9 @@ > #if defined(HAVE_TARGET_OBJECT_SUFFIX) || > defined(HAVE_TARGET_EXECUTABLE_SUFFIX) > static const char *convert_filename (const char *, int, int); > #endif > +#if !(defined (__MSDOS__) || defined (OS2) || defined (VMS)) > +static void retry_ice (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 **); > @@ -2638,7 +2643,7 @@ > } > } > > - if (string != commands[i].prog) > + if (i && string != commands[i].prog) > free (CONST_CAST (char *, string)); > } > > @@ -2691,6 +2696,16 @@ > else if (WIFEXITED (status) > && WEXITSTATUS (status) >= MIN_FATAL_STATUS) > { > +#if !(defined (__MSDOS__) || defined (OS2) || defined (VMS)) > + /* 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)) > + retry_ice (commands[0].prog, commands[0].argv); > +#endif > if (WEXITSTATUS (status) > greatest_status) > greatest_status = WEXITSTATUS (status); > ret_code = -1; > @@ -2748,6 +2763,9 @@ > } > } > > + if (commands[0].argv[0] != commands[0].prog) > + free (CONST_CAST (char *, commands[0].argv[0])); > + > return ret_code; > } > } > @@ -5874,6 +5892,227 @@ > switches[switchnum].validated = 1; > } > > +#if !(defined (__MSDOS__) || defined (OS2) || defined (VMS)) > +#define RETRY_ICE_ATTEMPTS 2 > + > +static void > +retry_ice (const char *prog, const char **argv) > +{ > + int nargs, out_arg = -1, quiet = 0, attempt; > + int pid, retries, sleep_interval; > + const char **new_argv; > + char *temp_filenames[RETRY_ICE_ATTEMPTS * 2 + 2]; > + > + 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_filenames, '\0', sizeof (temp_filenames)); > + 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-"; > + > + for (attempt = 0; attempt < RETRY_ICE_ATTEMPTS + 1; ++attempt) > + { > + int fd = -1; > + int status; > + > + temp_filenames[attempt * 2] = make_temp_file (".out"); > + temp_filenames[attempt * 2 + 1] = make_temp_file (".err"); > + > + if (attempt == RETRY_ICE_ATTEMPTS) > + { > + int i; > + int fd1, fd2; > + struct stat st1, st2; > + size_t n, len; > + char *buf; > + > + buf = XNEWVEC (char, 8192); > + > + for (i = 0; i < 2; ++i) > + { > + fd1 = open (temp_filenames[i], O_RDONLY); > + fd2 = open (temp_filenames[2 + i], O_RDONLY); > + > + if (fd1 < 0 || fd2 < 0) > + { > + i = -1; > + close (fd1); > + close (fd2); > + break; > + } > + > + if (fstat (fd1, &st1) < 0 || fstat (fd2, &st2) < 0) > + { > + i = -1; > + close (fd1); > + close (fd2); > + break; > + } > + > + if (st1.st_size != st2.st_size) > + { > + close (fd1); > + close (fd2); > + break; > + } > + > + len = 0; > + for (n = st1.st_size; n; n -= len) > + { > + len = n; > + if (len > 4096) > + len = 4096; > + > + if (read (fd1, buf, len) != (int) len > + || read (fd2, buf + 4096, len) != (int) len) > + { > + i = -1; > + break; > + } > + > + if (memcmp (buf, buf + 4096, len) != 0) > + break; > + } > + > + close (fd1); > + close (fd2); > + > + if (n) > + break; > + } > + > + free (buf); > + if (i == -1) > + break; > + > + if (i != 2) > + { > + fnotice (stderr, "The bug is not reproducible, so it is" > + " likely a hardware or OS problem.\n"); > + break; > + } > + > + fd = open (temp_filenames[attempt * 2], O_RDWR); > + if (fd < 0) > + break; > + write (fd, "//", 2); > + for (i = 0; i < nargs; i++) > + { > + write (fd, " ", 1); > + write (fd, new_argv[i], strlen (new_argv[i])); > + } > + write (fd, "\n", 1); > + new_argv[nargs] = "-E"; > + new_argv[nargs + 1] = NULL; > + } > + > + /* Fork a subprocess; wait and retry if it fails. */ > + sleep_interval = 1; > + pid = -1; > + for (retries = 0; retries < 4; retries++) > + { > + pid = fork (); > + if (pid >= 0) > + break; > + sleep (sleep_interval); > + sleep_interval *= 2; > + } > + > + if (pid < 0) > + break; > + else if (pid == 0) > + { > + if (attempt != RETRY_ICE_ATTEMPTS) > + fd = open (temp_filenames[attempt * 2], O_RDWR); > + if (fd < 0) > + exit (-1); > + if (fd != 1) > + { > + close (1); > + dup (fd); > + close (fd); > + } > + > + fd = open (temp_filenames[attempt * 2 + 1], O_RDWR); > + if (fd < 0) > + exit (-1); > + if (fd != 2) > + { > + close (2); > + dup (fd); > + close (fd); > + } > + > + 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) > + break; > + > + if (attempt < RETRY_ICE_ATTEMPTS > + && (! WIFEXITED (status) || WEXITSTATUS (status) != ICE_EXIT_CODE)) > + { > + fnotice (stderr, "The bug is not reproducible, so it is" > + " likely a hardware or OS problem.\n"); > + break; > + } > + else if (attempt == RETRY_ICE_ATTEMPTS) > + { > + close (fd); > + if (WIFEXITED (status) > + && WEXITSTATUS (status) == SUCCESS_EXIT_CODE) > + { > + fnotice (stderr, "Preprocessed source stored into %s file," > + " please attach this to your bugreport.\n", > + temp_filenames[attempt * 2]); > + /* Make sure it is not deleted. */ > + free (temp_filenames[attempt * 2]); > + temp_filenames[attempt * 2] = NULL; > + break; > + } > + } > + } > + > + for (attempt = 0; attempt < RETRY_ICE_ATTEMPTS * 2 + 2; attempt++) > + if (temp_filenames[attempt]) > + { > + unlink (temp_filenames[attempt]); > + free (temp_filenames[attempt]); > + } > +} > +#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. > */ > --- a/src/gcc/diagnostic.c > +++ b/src/gcc/diagnostic.c > @@ -247,7 +247,7 @@ > real_abort (); > diagnostic_finish (context); > fnotice (stderr, "compilation terminated.\n"); > - exit (FATAL_EXIT_CODE); > + exit (ICE_EXIT_CODE); > > default: > gcc_unreachable ();
signature.asc
Description: Digital signature