* [PATCH] Add patch for debugging compiler ICEs. @ 2014-08-04 17:03 Maxim Ostapenko 2014-08-12 16:14 ` [PING][PATCH] " Maxim Ostapenko 2014-08-19 13:58 ` Fwd: [PATCH] " Maxim Ostapenko 0 siblings, 2 replies; 24+ messages in thread From: Maxim Ostapenko @ 2014-08-04 17:03 UTC (permalink / raw) To: GCC Patches Cc: Jeff Law, Jakub Jelinek, tsaunders, Yury Gribov, Slava Garbuzov [-- Attachment #1: Type: text/plain, Size: 1072 bytes --] Hi, A years ago there was a discussion (https://gcc.gnu.org/ml/gcc-patches/2004-01/msg02437.html) about debugging compiler ICEs that resulted in a patch from Jakub, which dumps useful information into temporary file, but for some reasons this patch wasn't applied to trunk. This is the resurrected patch with added GCC version information into generated repro file. I've updated the patch that I've posted earlier (https://gcc.gnu.org/ml/gcc-patches/2014-07/msg01649.html ) according to recent upstream discussion (https://gcc.gnu.org/ml/gcc-patches/2014-08/msg00020.html). The debugging functionality is disabled by default and can be enabled with adding -freport-bug into compile options. It can be also enabled by default with --with-spec during GCC build. There are several directions in which this can be improved e.g: 1) more user-friendly ways to report bugs (autosubmitting to Bugzilla, etc.) 2) generate repro in case of segfault. but having basic functionality (autogenerating reprocase in temprorary file) already seems quite useful. -Maxim [-- Attachment #2: ICE.diff --] [-- Type: text/x-patch, Size: 14866 bytes --] 2014-08-04 Jakub Jelinek <jakub@redhat.com> Max Ostapenko <m.ostapenko@partner.samsung.com> * common.opt: New option. * doc/invoke.texi: Describe new option. * diagnostic.c (diagnostic_action_after_output): Exit with ICE_EXIT_CODE instead of FATAL_EXIT_CODE. * gcc.c (execute): Don't free first string early, but at the end of the function. Call retry_ice if compiler exited with ICE_EXIT_CODE. (main): Factor out common code. (print_configuration): New function. (try_fork): Likewise. (redirect_stdout_stderr): Likewise. (files_equal_p): Likewise. (check_repro): Likewise. (run_attempt): Likewise. (do_report_bug): Likewise. (append_text): Likewise. (try_generate_repro): Likewise diff --git a/gcc/common.opt b/gcc/common.opt index 0c4f86b..aa79250 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -1120,6 +1120,11 @@ fdump-noaddr Common Report Var(flag_dump_noaddr) Suppress output of addresses in debugging dumps +freport-bug +Common Driver Var(flag_report_bug) +Collect and dump debug information into temporary file if ICE in C/C++ +compiler occured. + fdump-passes Common Var(flag_dump_passes) Init(0) Dump optimization passes diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c index 0cc7593..67b8c5b 100644 --- a/gcc/diagnostic.c +++ b/gcc/diagnostic.c @@ -492,7 +492,7 @@ diagnostic_action_after_output (diagnostic_context *context, real_abort (); diagnostic_finish (context); fnotice (stderr, "compilation terminated.\n"); - exit (FATAL_EXIT_CODE); + exit (ICE_EXIT_CODE); default: gcc_unreachable (); diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 4f327df..dafb573 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -6271,6 +6271,11 @@ feasible to use diff on debugging dumps for compiler invocations with different compiler binaries and/or different text / bss / data / heap / stack / dso start locations. +@item -freport-bug +@opindex freport-bug +Collect and dump debug information into temporary file if ICE in C/C++ +compiler occured. + @item -fdump-unnumbered @opindex fdump-unnumbered When doing debugging dumps, suppress instruction numbers and address output. diff --git a/gcc/gcc.c b/gcc/gcc.c index 44d0416..f7a56d1 100644 --- a/gcc/gcc.c +++ b/gcc/gcc.c @@ -43,6 +43,13 @@ compilation is specified by a string called a "spec". */ #include "params.h" #include "vec.h" #include "filenames.h" +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#if !(defined (__MSDOS__) || defined (OS2) || defined (VMS)) +#define RETRY_ICE_SUPPORTED +#endif /* By default there is no special suffix for target executables. */ /* FIXME: when autoconf is fixed, remove the host check - dj */ @@ -253,6 +260,9 @@ static void init_gcc_specs (struct obstack *, const char *, const char *, static const char *convert_filename (const char *, int, int); #endif +#ifdef RETRY_ICE_SUPPORTED +static void try_generate_repro (const char *prog, const char **argv); +#endif static const char *getenv_spec_function (int, const char **); static const char *if_exists_spec_function (int, const char **); static const char *if_exists_else_spec_function (int, const char **); @@ -2849,7 +2859,7 @@ execute (void) } } - if (string != commands[i].prog) + if (i && string != commands[i].prog) free (CONST_CAST (char *, string)); } @@ -2902,6 +2912,17 @@ execute (void) else if (WIFEXITED (status) && WEXITSTATUS (status) >= MIN_FATAL_STATUS) { +#ifdef RETRY_ICE_SUPPORTED + /* For ICEs in cc1, cc1obj, cc1plus see if it is + reproducible or not. */ + const char *p; + if (flag_report_bug + && WEXITSTATUS (status) == ICE_EXIT_CODE + && i == 0 + && (p = strrchr (commands[0].argv[0], DIR_SEPARATOR)) + && ! strncmp (p + 1, "cc1", 3)) + try_generate_repro (commands[0].prog, commands[0].argv); +#endif if (WEXITSTATUS (status) > greatest_status) greatest_status = WEXITSTATUS (status); ret_code = -1; @@ -2959,6 +2980,9 @@ execute (void) } } + if (commands[0].argv[0] != commands[0].prog) + free (CONST_CAST (char *, commands[0].argv[0])); + return ret_code; } } @@ -6150,6 +6174,342 @@ give_switch (int switchnum, int omit_first_word) switches[switchnum].validated = true; } \f +static void +print_configuration (void) +{ + int n; + const char *thrmod; + + fnotice (stderr, "Target: %s\n", spec_machine); + fnotice (stderr, "Configured with: %s\n", configuration_arguments); + +#ifdef THREAD_MODEL_SPEC + /* We could have defined THREAD_MODEL_SPEC to "%*" by default, + but there's no point in doing all this processing just to get + thread_model back. */ + obstack_init (&obstack); + do_spec_1 (THREAD_MODEL_SPEC, 0, thread_model); + obstack_1grow (&obstack, '\0'); + thrmod = XOBFINISH (&obstack, const char *); +#else + thrmod = thread_model; +#endif + + fnotice (stderr, "Thread model: %s\n", thrmod); + + /* compiler_version is truncated at the first space when initialized + from version string, so truncate version_string at the first space + before comparing. */ + for (n = 0; version_string[n]; n++) + if (version_string[n] == ' ') + break; + + if (! strncmp (version_string, compiler_version, n) + && compiler_version[n] == 0) + fnotice (stderr, "gcc version %s %s\n\n", version_string, + pkgversion_string); + else + fnotice (stderr, "gcc driver version %s %sexecuting gcc version %s\n\n", + version_string, pkgversion_string, compiler_version); +} + +#ifdef RETRY_ICE_SUPPORTED +#define RETRY_ICE_ATTEMPTS 3 + +static int +try_fork () +{ + int pid, retries, sleep_interval; + sleep_interval = 1; + pid = -1; + for (retries = 0; retries < 4; retries++) + { + pid = fork (); + if (pid >= 0) + break; + sleep (sleep_interval); + sleep_interval *= 2; + } + return pid; +} + + +static void +redirect_stdout_stderr (const char *out_temp, const char *err_temp, + int append) +{ + int fd; + fd = open (out_temp, append ? O_RDWR | O_APPEND : O_RDWR); + + if (fd < 0) + exit (-1); + + close (STDOUT_FILENO); + dup (fd); + close (fd); + + fd = open (err_temp, append ? O_RDWR | O_APPEND : O_RDWR); + + if (fd < 0) + exit (-1); + + close (STDERR_FILENO); + dup (fd); + close (fd); +} + +static int +files_equal_p (char *file1, char *file2, char *buf, const int bufsize) +{ + struct stat st1, st2; + size_t n, len; + int fd1, fd2; + + fd1 = open (file1, O_RDONLY); + fd2 = open (file2, O_RDONLY); + + if (fd1 < 0 || fd2 < 0) + goto error; + + if (fstat (fd1, &st1) < 0 || fstat (fd2, &st2) < 0) + goto error; + + if (st1.st_size != st2.st_size) + goto error; + + for (n = st1.st_size; n; n -= len) + { + len = n; + if ((int) len > bufsize / 2) + len = bufsize / 2; + + if (read (fd1, buf, len) != (int) len + || read (fd2, buf + bufsize / 2, len) != (int) len) + { + goto error; + } + + if (memcmp (buf, buf + bufsize / 2, len) != 0) + goto error; + } + + close (fd1); + close (fd2); + + return 1; + +error: + close (fd1); + close (fd2); + return 0; +} + +static int +check_repro (char **temp_stdout_files, char **temp_stderr_files) +{ + int i; + const int ice_bufsize = 8192; + char *ice_buf = XNEWVEC (char, ice_bufsize); + for (i = 0; i < RETRY_ICE_ATTEMPTS - 2; ++i) + { + if (!files_equal_p (temp_stdout_files[i], temp_stdout_files[i + 1], + ice_buf, ice_bufsize) + || !files_equal_p (temp_stderr_files[i], temp_stderr_files[i + 1], + ice_buf, ice_bufsize)) + { + fnotice (stderr, "The bug is not reproducible, so it is" + " likely a hardware or OS problem.\n"); + break; + } + } + free (ice_buf); + return i == RETRY_ICE_ATTEMPTS - 2; +} + +enum attempt_status { + ATTEMPT_STATUS_FAIL_TO_RUN, + ATTEMPT_STATUS_SUCCESS, + ATTEMPT_STATUS_ICE +}; + +static enum attempt_status +run_attempt (const char *prog, const char **new_argv, const char *out_temp, + const char *err_temp, int emit_system_info, int append) +{ + int status; + int pid = try_fork (); + if (pid < 0) + return ATTEMPT_STATUS_FAIL_TO_RUN; + else if (pid == 0) + { + redirect_stdout_stderr (out_temp, err_temp, append); + + if (emit_system_info) + print_configuration (); + + if (prog == new_argv[0]) + execvp (prog, CONST_CAST2 (char *const *, const char **, new_argv)); + else + execv (new_argv[0], CONST_CAST2 (char *const *, const char **, + new_argv)); + exit (-1); + } + + if (waitpid (pid, &status, 0) < 0) + return ATTEMPT_STATUS_FAIL_TO_RUN; + + switch (WEXITSTATUS (status)) + { + case ICE_EXIT_CODE: + return ATTEMPT_STATUS_ICE; + + case SUCCESS_EXIT_CODE: + return ATTEMPT_STATUS_SUCCESS; + + default: + return ATTEMPT_STATUS_FAIL_TO_RUN; + } +} + +static void +do_report_bug (const char *prog, const char **new_argv, + const int nargs, char **out_file, char **err_file) +{ + int i, status; + int fd = open (*out_file, O_RDWR | O_APPEND); + if (fd < 0) + return; + write (fd, "\n//", 3); + for (i = 0; i < nargs; i++) + { + write (fd, " ", 1); + write (fd, new_argv[i], strlen (new_argv[i])); + } + write (fd, "\n\n", 2); + close (fd); + new_argv[nargs] = "-E"; + new_argv[nargs + 1] = NULL; + + status = run_attempt (prog, new_argv, *out_file, *err_file, 0, 1); + + if (status == ATTEMPT_STATUS_SUCCESS) + { + fnotice (stderr, "Preprocessed source stored into %s file," + " please attach this to your bugreport.\n", + *out_file); + /* Make sure it is not deleted. */ + free (*out_file); + *out_file = NULL; + } +} + +static void +append_text (char *file, const char *str) +{ + int fd = open (file, O_RDWR | O_APPEND); + if (fd < 0) + return; + + write (fd, str, strlen (str)); + close (fd); +} + +static void +try_generate_repro (const char *prog, const char **argv) +{ + int i, nargs, out_arg = -1, quiet = 0, attempt; + const char **new_argv; + char *temp_files[RETRY_ICE_ATTEMPTS * 2]; + char **temp_stdout_files = &temp_files[0]; + char **temp_stderr_files = &temp_files[RETRY_ICE_ATTEMPTS]; + + if (gcc_input_filename == NULL || ! strcmp (gcc_input_filename, "-")) + return; + + for (nargs = 0; argv[nargs] != NULL; ++nargs) + /* Only retry compiler ICEs, not preprocessor ones. */ + if (! strcmp (argv[nargs], "-E")) + return; + else if (argv[nargs][0] == '-' && argv[nargs][1] == 'o') + { + if (out_arg == -1) + out_arg = nargs; + else + return; + } + /* If the compiler is going to output any time information, + it might varry between invocations. */ + else if (! strcmp (argv[nargs], "-quiet")) + quiet = 1; + else if (! strcmp (argv[nargs], "-ftime-report")) + return; + + if (out_arg == -1 || !quiet) + return; + + memset (temp_files, '\0', sizeof (temp_files)); + new_argv = XALLOCAVEC (const char *, nargs + 4); + memcpy (new_argv, argv, (nargs + 1) * sizeof (const char *)); + new_argv[nargs++] = "-frandom-seed=0"; + new_argv[nargs++] = "-fdump-noaddr"; + new_argv[nargs] = NULL; + if (new_argv[out_arg][2] == '\0') + new_argv[out_arg + 1] = "-"; + else + new_argv[out_arg] = "-o-"; + + int status; + for (attempt = 0; attempt < RETRY_ICE_ATTEMPTS; ++attempt) + { + int emit_system_info = 0; + int append = 0; + temp_stdout_files[attempt] = make_temp_file (".out"); + temp_stderr_files[attempt] = make_temp_file (".err"); + + if (attempt == RETRY_ICE_ATTEMPTS - 1) + { + append = 1; + emit_system_info = 1; + } + + if (emit_system_info) + append_text (temp_stderr_files[attempt], "/*\n"); + + /* Fork a subprocess; wait and retry if it fails. */ + status = run_attempt (prog, new_argv, temp_stdout_files[attempt], + temp_stderr_files[attempt], emit_system_info, + append); + + if (emit_system_info) + append_text (temp_stderr_files[attempt], "*/\n"); + + if (status != ATTEMPT_STATUS_ICE) + { + fnotice (stderr, "The bug is not reproducible, so it is" + " likely a hardware or OS problem.\n"); + goto out; + } + } + + if (!check_repro (temp_stdout_files, temp_stderr_files)) + goto out; + + /* In final attempt we append cc1 options and preprocesssed code to last + generated .err file with configuration and backtrace. */ + do_report_bug (prog, new_argv, nargs, + &temp_stderr_files[RETRY_ICE_ATTEMPTS - 1], + &temp_stdout_files[RETRY_ICE_ATTEMPTS - 1]); + +out: + for (i = 0; i < RETRY_ICE_ATTEMPTS * 2; i++) + if (temp_files[i]) + { + unlink (temp_stdout_files[i]); + free (temp_stdout_files[i]); + } +} +#endif + /* Search for a file named NAME trying various prefixes including the user's -B prefix and some standard ones. Return the absolute file name found. If nothing is found, return NAME. */ @@ -6919,43 +7279,9 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n" if (verbose_flag) { - int n; - const char *thrmod; - - fnotice (stderr, "Target: %s\n", spec_machine); - fnotice (stderr, "Configured with: %s\n", configuration_arguments); - -#ifdef THREAD_MODEL_SPEC - /* We could have defined THREAD_MODEL_SPEC to "%*" by default, - but there's no point in doing all this processing just to get - thread_model back. */ - obstack_init (&obstack); - do_spec_1 (THREAD_MODEL_SPEC, 0, thread_model); - obstack_1grow (&obstack, '\0'); - thrmod = XOBFINISH (&obstack, const char *); -#else - thrmod = thread_model; -#endif - - fnotice (stderr, "Thread model: %s\n", thrmod); - - /* compiler_version is truncated at the first space when initialized - from version string, so truncate version_string at the first space - before comparing. */ - for (n = 0; version_string[n]; n++) - if (version_string[n] == ' ') - break; - - if (! strncmp (version_string, compiler_version, n) - && compiler_version[n] == 0) - fnotice (stderr, "gcc version %s %s\n", version_string, - pkgversion_string); - else - fnotice (stderr, "gcc driver version %s %sexecuting gcc version %s\n", - version_string, pkgversion_string, compiler_version); - + print_configuration (); if (n_infiles == 0) - return (0); + return (0); } if (n_infiles == added_libraries) ^ permalink raw reply [flat|nested] 24+ messages in thread
* [PING][PATCH] Add patch for debugging compiler ICEs. 2014-08-04 17:03 [PATCH] Add patch for debugging compiler ICEs Maxim Ostapenko @ 2014-08-12 16:14 ` Maxim Ostapenko 2014-08-19 13:58 ` Fwd: [PATCH] " Maxim Ostapenko 1 sibling, 0 replies; 24+ messages in thread From: Maxim Ostapenko @ 2014-08-12 16:14 UTC (permalink / raw) To: Jeff Law, GCC Patches Cc: tsaunders, Yury Gribov, Slava Garbuzov, Maxim Ostapenko [-- Attachment #1: Type: text/plain, Size: 1593 bytes --] Ping. -Maxim -------- Original Message -------- Subject: [PATCH] Add patch for debugging compiler ICEs. Date: Mon, 04 Aug 2014 21:03:22 +0400 From: Maxim Ostapenko <m.ostapenko@partner.samsung.com> To: GCC Patches <gcc-patches@gcc.gnu.org> CC: Jeff Law <law@redhat.com>, Jakub Jelinek <jakub@redhat.com>, tsaunders@mozilla.com, Yury Gribov <y.gribov@samsung.com>, Slava Garbuzov <v.garbuzov@samsung.com> On 08/04/2014 09:03 PM, Maxim Ostapenko wrote: > Hi, > > A years ago there was a discussion > (https://gcc.gnu.org/ml/gcc-patches/2004-01/msg02437.html) about > debugging compiler ICEs that resulted in a patch from Jakub, which > dumps useful information into temporary file, but for some reasons > this patch wasn't applied to trunk. > > This is the resurrected patch with added GCC version information into > generated repro file. > > I've updated the patch that I've posted earlier > (https://gcc.gnu.org/ml/gcc-patches/2014-07/msg01649.html ) according > to recent upstream discussion > (https://gcc.gnu.org/ml/gcc-patches/2014-08/msg00020.html). > > The debugging functionality is disabled by default and can be enabled > with adding -freport-bug into compile options. It can be also enabled > by default with > --with-spec during GCC build. > > There are several directions in which this can be improved e.g: > > 1) more user-friendly ways to report bugs (autosubmitting to Bugzilla, > etc.) > > 2) generate repro in case of segfault. > > but having basic functionality (autogenerating reprocase in temprorary > file) already seems quite useful. > > -Maxim [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: ICE.diff --] [-- Type: text/x-patch; name="ICE.diff", Size: 0 bytes --] ^ permalink raw reply [flat|nested] 24+ messages in thread
* Fwd: [PATCH] Add patch for debugging compiler ICEs. 2014-08-04 17:03 [PATCH] Add patch for debugging compiler ICEs Maxim Ostapenko 2014-08-12 16:14 ` [PING][PATCH] " Maxim Ostapenko @ 2014-08-19 13:58 ` Maxim Ostapenko 2014-08-28 7:31 ` [Ping v2][PATCH] " Maxim Ostapenko 1 sibling, 1 reply; 24+ messages in thread From: Maxim Ostapenko @ 2014-08-19 13:58 UTC (permalink / raw) To: Jeff Law, GCC Patches Cc: tsaunders, Yury Gribov, Slava Garbuzov, Maxim Ostapenko [-- Attachment #1: Type: text/plain, Size: 1479 bytes --] Ping. -Maxim -------- Original Message -------- Subject: [PATCH] Add patch for debugging compiler ICEs. Date: Mon, 04 Aug 2014 21:03:22 +0400 From: Maxim Ostapenko <m.ostapenko@partner.samsung.com> To: GCC Patches <gcc-patches@gcc.gnu.org> CC: Jeff Law <law@redhat.com>, Jakub Jelinek <jakub@redhat.com>, tsaunders@mozilla.com, Yury Gribov <y.gribov@samsung.com>, Slava Garbuzov <v.garbuzov@samsung.com> Hi, A years ago there was a discussion (https://gcc.gnu.org/ml/gcc-patches/2004-01/msg02437.html) about debugging compiler ICEs that resulted in a patch from Jakub, which dumps useful information into temporary file, but for some reasons this patch wasn't applied to trunk. This is the resurrected patch with added GCC version information into generated repro file. I've updated the patch that I've posted earlier (https://gcc.gnu.org/ml/gcc-patches/2014-07/msg01649.html ) according to recent upstream discussion (https://gcc.gnu.org/ml/gcc-patches/2014-08/msg00020.html). The debugging functionality is disabled by default and can be enabled with adding -freport-bug into compile options. It can be also enabled by default with --with-spec during GCC build. There are several directions in which this can be improved e.g: 1) more user-friendly ways to report bugs (autosubmitting to Bugzilla, etc.) 2) generate repro in case of segfault. but having basic functionality (autogenerating reprocase in temprorary file) already seems quite useful. -Maxim [-- Attachment #2: ICE.diff --] [-- Type: text/x-patch, Size: 14867 bytes --] 2014-08-04 Jakub Jelinek <jakub@redhat.com> Max Ostapenko <m.ostapenko@partner.samsung.com> * common.opt: New option. * doc/invoke.texi: Describe new option. * diagnostic.c (diagnostic_action_after_output): Exit with ICE_EXIT_CODE instead of FATAL_EXIT_CODE. * gcc.c (execute): Don't free first string early, but at the end of the function. Call retry_ice if compiler exited with ICE_EXIT_CODE. (main): Factor out common code. (print_configuration): New function. (try_fork): Likewise. (redirect_stdout_stderr): Likewise. (files_equal_p): Likewise. (check_repro): Likewise. (run_attempt): Likewise. (do_report_bug): Likewise. (append_text): Likewise. (try_generate_repro): Likewise diff --git a/gcc/common.opt b/gcc/common.opt index 0c4f86b..aa79250 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -1120,6 +1120,11 @@ fdump-noaddr Common Report Var(flag_dump_noaddr) Suppress output of addresses in debugging dumps +freport-bug +Common Driver Var(flag_report_bug) +Collect and dump debug information into temporary file if ICE in C/C++ +compiler occured. + fdump-passes Common Var(flag_dump_passes) Init(0) Dump optimization passes diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c index 0cc7593..67b8c5b 100644 --- a/gcc/diagnostic.c +++ b/gcc/diagnostic.c @@ -492,7 +492,7 @@ diagnostic_action_after_output (diagnostic_context *context, real_abort (); diagnostic_finish (context); fnotice (stderr, "compilation terminated.\n"); - exit (FATAL_EXIT_CODE); + exit (ICE_EXIT_CODE); default: gcc_unreachable (); diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 4f327df..dafb573 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -6271,6 +6271,11 @@ feasible to use diff on debugging dumps for compiler invocations with different compiler binaries and/or different text / bss / data / heap / stack / dso start locations. +@item -freport-bug +@opindex freport-bug +Collect and dump debug information into temporary file if ICE in C/C++ +compiler occured. + @item -fdump-unnumbered @opindex fdump-unnumbered When doing debugging dumps, suppress instruction numbers and address output. diff --git a/gcc/gcc.c b/gcc/gcc.c index 44d0416..f7a56d1 100644 --- a/gcc/gcc.c +++ b/gcc/gcc.c @@ -43,6 +43,13 @@ compilation is specified by a string called a "spec". */ #include "params.h" #include "vec.h" #include "filenames.h" +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#if !(defined (__MSDOS__) || defined (OS2) || defined (VMS)) +#define RETRY_ICE_SUPPORTED +#endif /* By default there is no special suffix for target executables. */ /* FIXME: when autoconf is fixed, remove the host check - dj */ @@ -253,6 +260,9 @@ static void init_gcc_specs (struct obstack *, const char *, const char *, static const char *convert_filename (const char *, int, int); #endif +#ifdef RETRY_ICE_SUPPORTED +static void try_generate_repro (const char *prog, const char **argv); +#endif static const char *getenv_spec_function (int, const char **); static const char *if_exists_spec_function (int, const char **); static const char *if_exists_else_spec_function (int, const char **); @@ -2849,7 +2859,7 @@ execute (void) } } - if (string != commands[i].prog) + if (i && string != commands[i].prog) free (CONST_CAST (char *, string)); } @@ -2902,6 +2912,17 @@ execute (void) else if (WIFEXITED (status) && WEXITSTATUS (status) >= MIN_FATAL_STATUS) { +#ifdef RETRY_ICE_SUPPORTED + /* For ICEs in cc1, cc1obj, cc1plus see if it is + reproducible or not. */ + const char *p; + if (flag_report_bug + && WEXITSTATUS (status) == ICE_EXIT_CODE + && i == 0 + && (p = strrchr (commands[0].argv[0], DIR_SEPARATOR)) + && ! strncmp (p + 1, "cc1", 3)) + try_generate_repro (commands[0].prog, commands[0].argv); +#endif if (WEXITSTATUS (status) > greatest_status) greatest_status = WEXITSTATUS (status); ret_code = -1; @@ -2959,6 +2980,9 @@ execute (void) } } + if (commands[0].argv[0] != commands[0].prog) + free (CONST_CAST (char *, commands[0].argv[0])); + return ret_code; } } @@ -6150,6 +6174,342 @@ give_switch (int switchnum, int omit_first_word) switches[switchnum].validated = true; } \f +static void +print_configuration (void) +{ + int n; + const char *thrmod; + + fnotice (stderr, "Target: %s\n", spec_machine); + fnotice (stderr, "Configured with: %s\n", configuration_arguments); + +#ifdef THREAD_MODEL_SPEC + /* We could have defined THREAD_MODEL_SPEC to "%*" by default, + but there's no point in doing all this processing just to get + thread_model back. */ + obstack_init (&obstack); + do_spec_1 (THREAD_MODEL_SPEC, 0, thread_model); + obstack_1grow (&obstack, '\0'); + thrmod = XOBFINISH (&obstack, const char *); +#else + thrmod = thread_model; +#endif + + fnotice (stderr, "Thread model: %s\n", thrmod); + + /* compiler_version is truncated at the first space when initialized + from version string, so truncate version_string at the first space + before comparing. */ + for (n = 0; version_string[n]; n++) + if (version_string[n] == ' ') + break; + + if (! strncmp (version_string, compiler_version, n) + && compiler_version[n] == 0) + fnotice (stderr, "gcc version %s %s\n\n", version_string, + pkgversion_string); + else + fnotice (stderr, "gcc driver version %s %sexecuting gcc version %s\n\n", + version_string, pkgversion_string, compiler_version); +} + +#ifdef RETRY_ICE_SUPPORTED +#define RETRY_ICE_ATTEMPTS 3 + +static int +try_fork () +{ + int pid, retries, sleep_interval; + sleep_interval = 1; + pid = -1; + for (retries = 0; retries < 4; retries++) + { + pid = fork (); + if (pid >= 0) + break; + sleep (sleep_interval); + sleep_interval *= 2; + } + return pid; +} + + +static void +redirect_stdout_stderr (const char *out_temp, const char *err_temp, + int append) +{ + int fd; + fd = open (out_temp, append ? O_RDWR | O_APPEND : O_RDWR); + + if (fd < 0) + exit (-1); + + close (STDOUT_FILENO); + dup (fd); + close (fd); + + fd = open (err_temp, append ? O_RDWR | O_APPEND : O_RDWR); + + if (fd < 0) + exit (-1); + + close (STDERR_FILENO); + dup (fd); + close (fd); +} + +static int +files_equal_p (char *file1, char *file2, char *buf, const int bufsize) +{ + struct stat st1, st2; + size_t n, len; + int fd1, fd2; + + fd1 = open (file1, O_RDONLY); + fd2 = open (file2, O_RDONLY); + + if (fd1 < 0 || fd2 < 0) + goto error; + + if (fstat (fd1, &st1) < 0 || fstat (fd2, &st2) < 0) + goto error; + + if (st1.st_size != st2.st_size) + goto error; + + for (n = st1.st_size; n; n -= len) + { + len = n; + if ((int) len > bufsize / 2) + len = bufsize / 2; + + if (read (fd1, buf, len) != (int) len + || read (fd2, buf + bufsize / 2, len) != (int) len) + { + goto error; + } + + if (memcmp (buf, buf + bufsize / 2, len) != 0) + goto error; + } + + close (fd1); + close (fd2); + + return 1; + +error: + close (fd1); + close (fd2); + return 0; +} + +static int +check_repro (char **temp_stdout_files, char **temp_stderr_files) +{ + int i; + const int ice_bufsize = 8192; + char *ice_buf = XNEWVEC (char, ice_bufsize); + for (i = 0; i < RETRY_ICE_ATTEMPTS - 2; ++i) + { + if (!files_equal_p (temp_stdout_files[i], temp_stdout_files[i + 1], + ice_buf, ice_bufsize) + || !files_equal_p (temp_stderr_files[i], temp_stderr_files[i + 1], + ice_buf, ice_bufsize)) + { + fnotice (stderr, "The bug is not reproducible, so it is" + " likely a hardware or OS problem.\n"); + break; + } + } + free (ice_buf); + return i == RETRY_ICE_ATTEMPTS - 2; +} + +enum attempt_status { + ATTEMPT_STATUS_FAIL_TO_RUN, + ATTEMPT_STATUS_SUCCESS, + ATTEMPT_STATUS_ICE +}; + +static enum attempt_status +run_attempt (const char *prog, const char **new_argv, const char *out_temp, + const char *err_temp, int emit_system_info, int append) +{ + int status; + int pid = try_fork (); + if (pid < 0) + return ATTEMPT_STATUS_FAIL_TO_RUN; + else if (pid == 0) + { + redirect_stdout_stderr (out_temp, err_temp, append); + + if (emit_system_info) + print_configuration (); + + if (prog == new_argv[0]) + execvp (prog, CONST_CAST2 (char *const *, const char **, new_argv)); + else + execv (new_argv[0], CONST_CAST2 (char *const *, const char **, + new_argv)); + exit (-1); + } + + if (waitpid (pid, &status, 0) < 0) + return ATTEMPT_STATUS_FAIL_TO_RUN; + + switch (WEXITSTATUS (status)) + { + case ICE_EXIT_CODE: + return ATTEMPT_STATUS_ICE; + + case SUCCESS_EXIT_CODE: + return ATTEMPT_STATUS_SUCCESS; + + default: + return ATTEMPT_STATUS_FAIL_TO_RUN; + } +} + +static void +do_report_bug (const char *prog, const char **new_argv, + const int nargs, char **out_file, char **err_file) +{ + int i, status; + int fd = open (*out_file, O_RDWR | O_APPEND); + if (fd < 0) + return; + write (fd, "\n//", 3); + for (i = 0; i < nargs; i++) + { + write (fd, " ", 1); + write (fd, new_argv[i], strlen (new_argv[i])); + } + write (fd, "\n\n", 2); + close (fd); + new_argv[nargs] = "-E"; + new_argv[nargs + 1] = NULL; + + status = run_attempt (prog, new_argv, *out_file, *err_file, 0, 1); + + if (status == ATTEMPT_STATUS_SUCCESS) + { + fnotice (stderr, "Preprocessed source stored into %s file," + " please attach this to your bugreport.\n", + *out_file); + /* Make sure it is not deleted. */ + free (*out_file); + *out_file = NULL; + } +} + +static void +append_text (char *file, const char *str) +{ + int fd = open (file, O_RDWR | O_APPEND); + if (fd < 0) + return; + + write (fd, str, strlen (str)); + close (fd); +} + +static void +try_generate_repro (const char *prog, const char **argv) +{ + int i, nargs, out_arg = -1, quiet = 0, attempt; + const char **new_argv; + char *temp_files[RETRY_ICE_ATTEMPTS * 2]; + char **temp_stdout_files = &temp_files[0]; + char **temp_stderr_files = &temp_files[RETRY_ICE_ATTEMPTS]; + + if (gcc_input_filename == NULL || ! strcmp (gcc_input_filename, "-")) + return; + + for (nargs = 0; argv[nargs] != NULL; ++nargs) + /* Only retry compiler ICEs, not preprocessor ones. */ + if (! strcmp (argv[nargs], "-E")) + return; + else if (argv[nargs][0] == '-' && argv[nargs][1] == 'o') + { + if (out_arg == -1) + out_arg = nargs; + else + return; + } + /* If the compiler is going to output any time information, + it might varry between invocations. */ + else if (! strcmp (argv[nargs], "-quiet")) + quiet = 1; + else if (! strcmp (argv[nargs], "-ftime-report")) + return; + + if (out_arg == -1 || !quiet) + return; + + memset (temp_files, '\0', sizeof (temp_files)); + new_argv = XALLOCAVEC (const char *, nargs + 4); + memcpy (new_argv, argv, (nargs + 1) * sizeof (const char *)); + new_argv[nargs++] = "-frandom-seed=0"; + new_argv[nargs++] = "-fdump-noaddr"; + new_argv[nargs] = NULL; + if (new_argv[out_arg][2] == '\0') + new_argv[out_arg + 1] = "-"; + else + new_argv[out_arg] = "-o-"; + + int status; + for (attempt = 0; attempt < RETRY_ICE_ATTEMPTS; ++attempt) + { + int emit_system_info = 0; + int append = 0; + temp_stdout_files[attempt] = make_temp_file (".out"); + temp_stderr_files[attempt] = make_temp_file (".err"); + + if (attempt == RETRY_ICE_ATTEMPTS - 1) + { + append = 1; + emit_system_info = 1; + } + + if (emit_system_info) + append_text (temp_stderr_files[attempt], "/*\n"); + + /* Fork a subprocess; wait and retry if it fails. */ + status = run_attempt (prog, new_argv, temp_stdout_files[attempt], + temp_stderr_files[attempt], emit_system_info, + append); + + if (emit_system_info) + append_text (temp_stderr_files[attempt], "*/\n"); + + if (status != ATTEMPT_STATUS_ICE) + { + fnotice (stderr, "The bug is not reproducible, so it is" + " likely a hardware or OS problem.\n"); + goto out; + } + } + + if (!check_repro (temp_stdout_files, temp_stderr_files)) + goto out; + + /* In final attempt we append cc1 options and preprocesssed code to last + generated .err file with configuration and backtrace. */ + do_report_bug (prog, new_argv, nargs, + &temp_stderr_files[RETRY_ICE_ATTEMPTS - 1], + &temp_stdout_files[RETRY_ICE_ATTEMPTS - 1]); + +out: + for (i = 0; i < RETRY_ICE_ATTEMPTS * 2; i++) + if (temp_files[i]) + { + unlink (temp_stdout_files[i]); + free (temp_stdout_files[i]); + } +} +#endif + /* Search for a file named NAME trying various prefixes including the user's -B prefix and some standard ones. Return the absolute file name found. If nothing is found, return NAME. */ @@ -6919,43 +7279,9 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n" if (verbose_flag) { - int n; - const char *thrmod; - - fnotice (stderr, "Target: %s\n", spec_machine); - fnotice (stderr, "Configured with: %s\n", configuration_arguments); - -#ifdef THREAD_MODEL_SPEC - /* We could have defined THREAD_MODEL_SPEC to "%*" by default, - but there's no point in doing all this processing just to get - thread_model back. */ - obstack_init (&obstack); - do_spec_1 (THREAD_MODEL_SPEC, 0, thread_model); - obstack_1grow (&obstack, '\0'); - thrmod = XOBFINISH (&obstack, const char *); -#else - thrmod = thread_model; -#endif - - fnotice (stderr, "Thread model: %s\n", thrmod); - - /* compiler_version is truncated at the first space when initialized - from version string, so truncate version_string at the first space - before comparing. */ - for (n = 0; version_string[n]; n++) - if (version_string[n] == ' ') - break; - - if (! strncmp (version_string, compiler_version, n) - && compiler_version[n] == 0) - fnotice (stderr, "gcc version %s %s\n", version_string, - pkgversion_string); - else - fnotice (stderr, "gcc driver version %s %sexecuting gcc version %s\n", - version_string, pkgversion_string, compiler_version); - + print_configuration (); if (n_infiles == 0) - return (0); + return (0); } if (n_infiles == added_libraries) ^ permalink raw reply [flat|nested] 24+ messages in thread
* [Ping v2][PATCH] Add patch for debugging compiler ICEs. 2014-08-19 13:58 ` Fwd: [PATCH] " Maxim Ostapenko @ 2014-08-28 7:31 ` Maxim Ostapenko 2014-09-05 14:16 ` [Ping v3][PATCH] " Maxim Ostapenko 2014-09-09 22:51 ` [Ping v2][PATCH] " Joseph S. Myers 0 siblings, 2 replies; 24+ messages in thread From: Maxim Ostapenko @ 2014-08-28 7:31 UTC (permalink / raw) To: GCC Patches, Jeff Law, joseph Cc: Yury Gribov, Slava Garbuzov, Maxim Ostapenko [-- Attachment #1: Type: text/plain, Size: 1945 bytes --] Ping. Add Joseph S. Myers as driver maintainer. -Maxim -------- Original Message -------- Subject: Fwd: [PATCH] Add patch for debugging compiler ICEs. Date: Tue, 19 Aug 2014 17:57:51 +0400 From: Maxim Ostapenko <m.ostapenko@partner.samsung.com> To: Jeff Law <law@redhat.com>, GCC Patches <gcc-patches@gcc.gnu.org> CC: tsaunders@mozilla.com, Yury Gribov <y.gribov@samsung.com>, Slava Garbuzov <v.garbuzov@samsung.com>, Maxim Ostapenko <chefmax7@gmail.com> Ping. -Maxim -------- Original Message -------- Subject: [PATCH] Add patch for debugging compiler ICEs. Date: Mon, 04 Aug 2014 21:03:22 +0400 From: Maxim Ostapenko <m.ostapenko@partner.samsung.com> To: GCC Patches <gcc-patches@gcc.gnu.org> CC: Jeff Law <law@redhat.com>, Jakub Jelinek <jakub@redhat.com>, tsaunders@mozilla.com, Yury Gribov <y.gribov@samsung.com>, Slava Garbuzov <v.garbuzov@samsung.com> Hi, A years ago there was a discussion (https://gcc.gnu.org/ml/gcc-patches/2004-01/msg02437.html) about debugging compiler ICEs that resulted in a patch from Jakub, which dumps useful information into temporary file, but for some reasons this patch wasn't applied to trunk. This is the resurrected patch with added GCC version information into generated repro file. I've updated the patch that I've posted earlier (https://gcc.gnu.org/ml/gcc-patches/2014-07/msg01649.html ) according to recent upstream discussion (https://gcc.gnu.org/ml/gcc-patches/2014-08/msg00020.html). The debugging functionality is disabled by default and can be enabled with adding -freport-bug into compile options. It can be also enabled by default with --with-spec during GCC build. There are several directions in which this can be improved e.g: 1) more user-friendly ways to report bugs (autosubmitting to Bugzilla, etc.) 2) generate repro in case of segfault. but having basic functionality (autogenerating reprocase in temprorary file) already seems quite useful. -Maxim [-- Attachment #2: ICE.diff --] [-- Type: text/x-patch, Size: 14868 bytes --] 2014-08-04 Jakub Jelinek <jakub@redhat.com> Max Ostapenko <m.ostapenko@partner.samsung.com> * common.opt: New option. * doc/invoke.texi: Describe new option. * diagnostic.c (diagnostic_action_after_output): Exit with ICE_EXIT_CODE instead of FATAL_EXIT_CODE. * gcc.c (execute): Don't free first string early, but at the end of the function. Call retry_ice if compiler exited with ICE_EXIT_CODE. (main): Factor out common code. (print_configuration): New function. (try_fork): Likewise. (redirect_stdout_stderr): Likewise. (files_equal_p): Likewise. (check_repro): Likewise. (run_attempt): Likewise. (do_report_bug): Likewise. (append_text): Likewise. (try_generate_repro): Likewise diff --git a/gcc/common.opt b/gcc/common.opt index 0c4f86b..aa79250 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -1120,6 +1120,11 @@ fdump-noaddr Common Report Var(flag_dump_noaddr) Suppress output of addresses in debugging dumps +freport-bug +Common Driver Var(flag_report_bug) +Collect and dump debug information into temporary file if ICE in C/C++ +compiler occured. + fdump-passes Common Var(flag_dump_passes) Init(0) Dump optimization passes diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c index 0cc7593..67b8c5b 100644 --- a/gcc/diagnostic.c +++ b/gcc/diagnostic.c @@ -492,7 +492,7 @@ diagnostic_action_after_output (diagnostic_context *context, real_abort (); diagnostic_finish (context); fnotice (stderr, "compilation terminated.\n"); - exit (FATAL_EXIT_CODE); + exit (ICE_EXIT_CODE); default: gcc_unreachable (); diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 4f327df..dafb573 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -6271,6 +6271,11 @@ feasible to use diff on debugging dumps for compiler invocations with different compiler binaries and/or different text / bss / data / heap / stack / dso start locations. +@item -freport-bug +@opindex freport-bug +Collect and dump debug information into temporary file if ICE in C/C++ +compiler occured. + @item -fdump-unnumbered @opindex fdump-unnumbered When doing debugging dumps, suppress instruction numbers and address output. diff --git a/gcc/gcc.c b/gcc/gcc.c index 44d0416..f7a56d1 100644 --- a/gcc/gcc.c +++ b/gcc/gcc.c @@ -43,6 +43,13 @@ compilation is specified by a string called a "spec". */ #include "params.h" #include "vec.h" #include "filenames.h" +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#if !(defined (__MSDOS__) || defined (OS2) || defined (VMS)) +#define RETRY_ICE_SUPPORTED +#endif /* By default there is no special suffix for target executables. */ /* FIXME: when autoconf is fixed, remove the host check - dj */ @@ -253,6 +260,9 @@ static void init_gcc_specs (struct obstack *, const char *, const char *, static const char *convert_filename (const char *, int, int); #endif +#ifdef RETRY_ICE_SUPPORTED +static void try_generate_repro (const char *prog, const char **argv); +#endif static const char *getenv_spec_function (int, const char **); static const char *if_exists_spec_function (int, const char **); static const char *if_exists_else_spec_function (int, const char **); @@ -2849,7 +2859,7 @@ execute (void) } } - if (string != commands[i].prog) + if (i && string != commands[i].prog) free (CONST_CAST (char *, string)); } @@ -2902,6 +2912,17 @@ execute (void) else if (WIFEXITED (status) && WEXITSTATUS (status) >= MIN_FATAL_STATUS) { +#ifdef RETRY_ICE_SUPPORTED + /* For ICEs in cc1, cc1obj, cc1plus see if it is + reproducible or not. */ + const char *p; + if (flag_report_bug + && WEXITSTATUS (status) == ICE_EXIT_CODE + && i == 0 + && (p = strrchr (commands[0].argv[0], DIR_SEPARATOR)) + && ! strncmp (p + 1, "cc1", 3)) + try_generate_repro (commands[0].prog, commands[0].argv); +#endif if (WEXITSTATUS (status) > greatest_status) greatest_status = WEXITSTATUS (status); ret_code = -1; @@ -2959,6 +2980,9 @@ execute (void) } } + if (commands[0].argv[0] != commands[0].prog) + free (CONST_CAST (char *, commands[0].argv[0])); + return ret_code; } } @@ -6150,6 +6174,342 @@ give_switch (int switchnum, int omit_first_word) switches[switchnum].validated = true; } \f +static void +print_configuration (void) +{ + int n; + const char *thrmod; + + fnotice (stderr, "Target: %s\n", spec_machine); + fnotice (stderr, "Configured with: %s\n", configuration_arguments); + +#ifdef THREAD_MODEL_SPEC + /* We could have defined THREAD_MODEL_SPEC to "%*" by default, + but there's no point in doing all this processing just to get + thread_model back. */ + obstack_init (&obstack); + do_spec_1 (THREAD_MODEL_SPEC, 0, thread_model); + obstack_1grow (&obstack, '\0'); + thrmod = XOBFINISH (&obstack, const char *); +#else + thrmod = thread_model; +#endif + + fnotice (stderr, "Thread model: %s\n", thrmod); + + /* compiler_version is truncated at the first space when initialized + from version string, so truncate version_string at the first space + before comparing. */ + for (n = 0; version_string[n]; n++) + if (version_string[n] == ' ') + break; + + if (! strncmp (version_string, compiler_version, n) + && compiler_version[n] == 0) + fnotice (stderr, "gcc version %s %s\n\n", version_string, + pkgversion_string); + else + fnotice (stderr, "gcc driver version %s %sexecuting gcc version %s\n\n", + version_string, pkgversion_string, compiler_version); +} + +#ifdef RETRY_ICE_SUPPORTED +#define RETRY_ICE_ATTEMPTS 3 + +static int +try_fork () +{ + int pid, retries, sleep_interval; + sleep_interval = 1; + pid = -1; + for (retries = 0; retries < 4; retries++) + { + pid = fork (); + if (pid >= 0) + break; + sleep (sleep_interval); + sleep_interval *= 2; + } + return pid; +} + + +static void +redirect_stdout_stderr (const char *out_temp, const char *err_temp, + int append) +{ + int fd; + fd = open (out_temp, append ? O_RDWR | O_APPEND : O_RDWR); + + if (fd < 0) + exit (-1); + + close (STDOUT_FILENO); + dup (fd); + close (fd); + + fd = open (err_temp, append ? O_RDWR | O_APPEND : O_RDWR); + + if (fd < 0) + exit (-1); + + close (STDERR_FILENO); + dup (fd); + close (fd); +} + +static int +files_equal_p (char *file1, char *file2, char *buf, const int bufsize) +{ + struct stat st1, st2; + size_t n, len; + int fd1, fd2; + + fd1 = open (file1, O_RDONLY); + fd2 = open (file2, O_RDONLY); + + if (fd1 < 0 || fd2 < 0) + goto error; + + if (fstat (fd1, &st1) < 0 || fstat (fd2, &st2) < 0) + goto error; + + if (st1.st_size != st2.st_size) + goto error; + + for (n = st1.st_size; n; n -= len) + { + len = n; + if ((int) len > bufsize / 2) + len = bufsize / 2; + + if (read (fd1, buf, len) != (int) len + || read (fd2, buf + bufsize / 2, len) != (int) len) + { + goto error; + } + + if (memcmp (buf, buf + bufsize / 2, len) != 0) + goto error; + } + + close (fd1); + close (fd2); + + return 1; + +error: + close (fd1); + close (fd2); + return 0; +} + +static int +check_repro (char **temp_stdout_files, char **temp_stderr_files) +{ + int i; + const int ice_bufsize = 8192; + char *ice_buf = XNEWVEC (char, ice_bufsize); + for (i = 0; i < RETRY_ICE_ATTEMPTS - 2; ++i) + { + if (!files_equal_p (temp_stdout_files[i], temp_stdout_files[i + 1], + ice_buf, ice_bufsize) + || !files_equal_p (temp_stderr_files[i], temp_stderr_files[i + 1], + ice_buf, ice_bufsize)) + { + fnotice (stderr, "The bug is not reproducible, so it is" + " likely a hardware or OS problem.\n"); + break; + } + } + free (ice_buf); + return i == RETRY_ICE_ATTEMPTS - 2; +} + +enum attempt_status { + ATTEMPT_STATUS_FAIL_TO_RUN, + ATTEMPT_STATUS_SUCCESS, + ATTEMPT_STATUS_ICE +}; + +static enum attempt_status +run_attempt (const char *prog, const char **new_argv, const char *out_temp, + const char *err_temp, int emit_system_info, int append) +{ + int status; + int pid = try_fork (); + if (pid < 0) + return ATTEMPT_STATUS_FAIL_TO_RUN; + else if (pid == 0) + { + redirect_stdout_stderr (out_temp, err_temp, append); + + if (emit_system_info) + print_configuration (); + + if (prog == new_argv[0]) + execvp (prog, CONST_CAST2 (char *const *, const char **, new_argv)); + else + execv (new_argv[0], CONST_CAST2 (char *const *, const char **, + new_argv)); + exit (-1); + } + + if (waitpid (pid, &status, 0) < 0) + return ATTEMPT_STATUS_FAIL_TO_RUN; + + switch (WEXITSTATUS (status)) + { + case ICE_EXIT_CODE: + return ATTEMPT_STATUS_ICE; + + case SUCCESS_EXIT_CODE: + return ATTEMPT_STATUS_SUCCESS; + + default: + return ATTEMPT_STATUS_FAIL_TO_RUN; + } +} + +static void +do_report_bug (const char *prog, const char **new_argv, + const int nargs, char **out_file, char **err_file) +{ + int i, status; + int fd = open (*out_file, O_RDWR | O_APPEND); + if (fd < 0) + return; + write (fd, "\n//", 3); + for (i = 0; i < nargs; i++) + { + write (fd, " ", 1); + write (fd, new_argv[i], strlen (new_argv[i])); + } + write (fd, "\n\n", 2); + close (fd); + new_argv[nargs] = "-E"; + new_argv[nargs + 1] = NULL; + + status = run_attempt (prog, new_argv, *out_file, *err_file, 0, 1); + + if (status == ATTEMPT_STATUS_SUCCESS) + { + fnotice (stderr, "Preprocessed source stored into %s file," + " please attach this to your bugreport.\n", + *out_file); + /* Make sure it is not deleted. */ + free (*out_file); + *out_file = NULL; + } +} + +static void +append_text (char *file, const char *str) +{ + int fd = open (file, O_RDWR | O_APPEND); + if (fd < 0) + return; + + write (fd, str, strlen (str)); + close (fd); +} + +static void +try_generate_repro (const char *prog, const char **argv) +{ + int i, nargs, out_arg = -1, quiet = 0, attempt; + const char **new_argv; + char *temp_files[RETRY_ICE_ATTEMPTS * 2]; + char **temp_stdout_files = &temp_files[0]; + char **temp_stderr_files = &temp_files[RETRY_ICE_ATTEMPTS]; + + if (gcc_input_filename == NULL || ! strcmp (gcc_input_filename, "-")) + return; + + for (nargs = 0; argv[nargs] != NULL; ++nargs) + /* Only retry compiler ICEs, not preprocessor ones. */ + if (! strcmp (argv[nargs], "-E")) + return; + else if (argv[nargs][0] == '-' && argv[nargs][1] == 'o') + { + if (out_arg == -1) + out_arg = nargs; + else + return; + } + /* If the compiler is going to output any time information, + it might varry between invocations. */ + else if (! strcmp (argv[nargs], "-quiet")) + quiet = 1; + else if (! strcmp (argv[nargs], "-ftime-report")) + return; + + if (out_arg == -1 || !quiet) + return; + + memset (temp_files, '\0', sizeof (temp_files)); + new_argv = XALLOCAVEC (const char *, nargs + 4); + memcpy (new_argv, argv, (nargs + 1) * sizeof (const char *)); + new_argv[nargs++] = "-frandom-seed=0"; + new_argv[nargs++] = "-fdump-noaddr"; + new_argv[nargs] = NULL; + if (new_argv[out_arg][2] == '\0') + new_argv[out_arg + 1] = "-"; + else + new_argv[out_arg] = "-o-"; + + int status; + for (attempt = 0; attempt < RETRY_ICE_ATTEMPTS; ++attempt) + { + int emit_system_info = 0; + int append = 0; + temp_stdout_files[attempt] = make_temp_file (".out"); + temp_stderr_files[attempt] = make_temp_file (".err"); + + if (attempt == RETRY_ICE_ATTEMPTS - 1) + { + append = 1; + emit_system_info = 1; + } + + if (emit_system_info) + append_text (temp_stderr_files[attempt], "/*\n"); + + /* Fork a subprocess; wait and retry if it fails. */ + status = run_attempt (prog, new_argv, temp_stdout_files[attempt], + temp_stderr_files[attempt], emit_system_info, + append); + + if (emit_system_info) + append_text (temp_stderr_files[attempt], "*/\n"); + + if (status != ATTEMPT_STATUS_ICE) + { + fnotice (stderr, "The bug is not reproducible, so it is" + " likely a hardware or OS problem.\n"); + goto out; + } + } + + if (!check_repro (temp_stdout_files, temp_stderr_files)) + goto out; + + /* In final attempt we append cc1 options and preprocesssed code to last + generated .err file with configuration and backtrace. */ + do_report_bug (prog, new_argv, nargs, + &temp_stderr_files[RETRY_ICE_ATTEMPTS - 1], + &temp_stdout_files[RETRY_ICE_ATTEMPTS - 1]); + +out: + for (i = 0; i < RETRY_ICE_ATTEMPTS * 2; i++) + if (temp_files[i]) + { + unlink (temp_stdout_files[i]); + free (temp_stdout_files[i]); + } +} +#endif + /* Search for a file named NAME trying various prefixes including the user's -B prefix and some standard ones. Return the absolute file name found. If nothing is found, return NAME. */ @@ -6919,43 +7279,9 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n" if (verbose_flag) { - int n; - const char *thrmod; - - fnotice (stderr, "Target: %s\n", spec_machine); - fnotice (stderr, "Configured with: %s\n", configuration_arguments); - -#ifdef THREAD_MODEL_SPEC - /* We could have defined THREAD_MODEL_SPEC to "%*" by default, - but there's no point in doing all this processing just to get - thread_model back. */ - obstack_init (&obstack); - do_spec_1 (THREAD_MODEL_SPEC, 0, thread_model); - obstack_1grow (&obstack, '\0'); - thrmod = XOBFINISH (&obstack, const char *); -#else - thrmod = thread_model; -#endif - - fnotice (stderr, "Thread model: %s\n", thrmod); - - /* compiler_version is truncated at the first space when initialized - from version string, so truncate version_string at the first space - before comparing. */ - for (n = 0; version_string[n]; n++) - if (version_string[n] == ' ') - break; - - if (! strncmp (version_string, compiler_version, n) - && compiler_version[n] == 0) - fnotice (stderr, "gcc version %s %s\n", version_string, - pkgversion_string); - else - fnotice (stderr, "gcc driver version %s %sexecuting gcc version %s\n", - version_string, pkgversion_string, compiler_version); - + print_configuration (); if (n_infiles == 0) - return (0); + return (0); } if (n_infiles == added_libraries) ^ permalink raw reply [flat|nested] 24+ messages in thread
* [Ping v3][PATCH] Add patch for debugging compiler ICEs. 2014-08-28 7:31 ` [Ping v2][PATCH] " Maxim Ostapenko @ 2014-09-05 14:16 ` Maxim Ostapenko 2014-09-09 22:51 ` [Ping v2][PATCH] " Joseph S. Myers 1 sibling, 0 replies; 24+ messages in thread From: Maxim Ostapenko @ 2014-09-05 14:16 UTC (permalink / raw) To: GCC Patches, Jeff Law, joseph Cc: Yury Gribov, Slava Garbuzov, Maxim Ostapenko [-- Attachment #1: Type: text/plain, Size: 2148 bytes --] Ping. -Maxim On 08/28/2014 11:31 AM, Maxim Ostapenko wrote: > Ping. Add Joseph S. Myers as driver maintainer. > > -Maxim > -------- Original Message -------- > Subject: Fwd: [PATCH] Add patch for debugging compiler ICEs. > Date: Tue, 19 Aug 2014 17:57:51 +0400 > From: Maxim Ostapenko <m.ostapenko@partner.samsung.com> > To: Jeff Law <law@redhat.com>, GCC Patches <gcc-patches@gcc.gnu.org> > CC: tsaunders@mozilla.com, Yury Gribov <y.gribov@samsung.com>, > Slava Garbuzov <v.garbuzov@samsung.com>, Maxim Ostapenko > <chefmax7@gmail.com> > > > > Ping. > > -Maxim > -------- Original Message -------- > Subject: [PATCH] Add patch for debugging compiler ICEs. > Date: Mon, 04 Aug 2014 21:03:22 +0400 > From: Maxim Ostapenko <m.ostapenko@partner.samsung.com> > To: GCC Patches <gcc-patches@gcc.gnu.org> > CC: Jeff Law <law@redhat.com>, Jakub Jelinek <jakub@redhat.com>, > tsaunders@mozilla.com, Yury Gribov <y.gribov@samsung.com>, Slava > Garbuzov <v.garbuzov@samsung.com> > > > > Hi, > > A years ago there was a discussion > (https://gcc.gnu.org/ml/gcc-patches/2004-01/msg02437.html) about > debugging compiler ICEs that resulted in a patch from Jakub, which dumps > useful information into temporary file, but for some reasons this patch > wasn't applied to trunk. > > This is the resurrected patch with added GCC version information into > generated repro file. > > I've updated the patch that I've posted earlier > (https://gcc.gnu.org/ml/gcc-patches/2014-07/msg01649.html ) according to > recent upstream discussion > (https://gcc.gnu.org/ml/gcc-patches/2014-08/msg00020.html). > > The debugging functionality is disabled by default and can be enabled > with adding -freport-bug into compile options. It can be also enabled by > default with > --with-spec during GCC build. > > There are several directions in which this can be improved e.g: > > 1) more user-friendly ways to report bugs (autosubmitting to Bugzilla, > etc.) > > 2) generate repro in case of segfault. > > but having basic functionality (autogenerating reprocase in temprorary > file) already seems quite useful. > > -Maxim > > > > > > [-- Attachment #2: ICE.diff --] [-- Type: text/x-patch, Size: 14372 bytes --] 2014-08-04 Jakub Jelinek <jakub@redhat.com> Max Ostapenko <m.ostapenko@partner.samsung.com> * common.opt: New option. * doc/invoke.texi: Describe new option. * diagnostic.c (diagnostic_action_after_output): Exit with ICE_EXIT_CODE instead of FATAL_EXIT_CODE. * gcc.c (execute): Don't free first string early, but at the end of the function. Call retry_ice if compiler exited with ICE_EXIT_CODE. (main): Factor out common code. (print_configuration): New function. (try_fork): Likewise. (redirect_stdout_stderr): Likewise. (files_equal_p): Likewise. (check_repro): Likewise. (run_attempt): Likewise. (do_report_bug): Likewise. (append_text): Likewise. (try_generate_repro): Likewise diff --git a/gcc/common.opt b/gcc/common.opt index f7021102..1133e61 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -1120,6 +1120,11 @@ fdump-noaddr Common Report Var(flag_dump_noaddr) Suppress output of addresses in debugging dumps +freport-bug +Common Driver Var(flag_report_bug) +Collect and dump debug information into temporary file if ICE in C/C++ +compiler occured. + fdump-passes Common Var(flag_dump_passes) Init(0) Dump optimization passes diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c index 73666d6..60ed607 100644 --- a/gcc/diagnostic.c +++ b/gcc/diagnostic.c @@ -494,7 +494,7 @@ diagnostic_action_after_output (diagnostic_context *context, real_abort (); diagnostic_finish (context); fnotice (stderr, "compilation terminated.\n"); - exit (FATAL_EXIT_CODE); + exit (ICE_EXIT_CODE); default: gcc_unreachable (); diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index d15d4a9..f41a1d8 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -6316,6 +6316,11 @@ feasible to use diff on debugging dumps for compiler invocations with different compiler binaries and/or different text / bss / data / heap / stack / dso start locations. +@item -freport-bug +@opindex freport-bug +Collect and dump debug information into temporary file if ICE in C/C++ +compiler occured. + @item -fdump-unnumbered @opindex fdump-unnumbered When doing debugging dumps, suppress instruction numbers and address output. diff --git a/gcc/gcc.c b/gcc/gcc.c index 44d0416..e0c403d 100644 --- a/gcc/gcc.c +++ b/gcc/gcc.c @@ -43,6 +43,13 @@ compilation is specified by a string called a "spec". */ #include "params.h" #include "vec.h" #include "filenames.h" +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#if !(defined (__MSDOS__) || defined (OS2) || defined (VMS)) +#define RETRY_ICE_SUPPORTED +#endif /* By default there is no special suffix for target executables. */ /* FIXME: when autoconf is fixed, remove the host check - dj */ @@ -253,6 +260,9 @@ static void init_gcc_specs (struct obstack *, const char *, const char *, static const char *convert_filename (const char *, int, int); #endif +#ifdef RETRY_ICE_SUPPORTED +static void try_generate_repro (const char *prog, const char **argv); +#endif static const char *getenv_spec_function (int, const char **); static const char *if_exists_spec_function (int, const char **); static const char *if_exists_else_spec_function (int, const char **); @@ -2849,7 +2859,7 @@ execute (void) } } - if (string != commands[i].prog) + if (i && string != commands[i].prog) free (CONST_CAST (char *, string)); } @@ -2902,6 +2912,17 @@ execute (void) else if (WIFEXITED (status) && WEXITSTATUS (status) >= MIN_FATAL_STATUS) { +#ifdef RETRY_ICE_SUPPORTED + /* For ICEs in cc1, cc1obj, cc1plus see if it is + reproducible or not. */ + const char *p; + if (flag_report_bug + && WEXITSTATUS (status) == ICE_EXIT_CODE + && i == 0 + && (p = strrchr (commands[0].argv[0], DIR_SEPARATOR)) + && ! strncmp (p + 1, "cc1", 3)) + try_generate_repro (commands[0].prog, commands[0].argv); +#endif if (WEXITSTATUS (status) > greatest_status) greatest_status = WEXITSTATUS (status); ret_code = -1; @@ -2959,6 +2980,9 @@ execute (void) } } + if (commands[0].argv[0] != commands[0].prog) + free (CONST_CAST (char *, commands[0].argv[0])); + return ret_code; } } @@ -6150,6 +6174,342 @@ give_switch (int switchnum, int omit_first_word) switches[switchnum].validated = true; } \f +static void +print_configuration (void) +{ + int n; + const char *thrmod; + + fnotice (stderr, "Target: %s\n", spec_machine); + fnotice (stderr, "Configured with: %s\n", configuration_arguments); + +#ifdef THREAD_MODEL_SPEC + /* We could have defined THREAD_MODEL_SPEC to "%*" by default, + but there's no point in doing all this processing just to get + thread_model back. */ + obstack_init (&obstack); + do_spec_1 (THREAD_MODEL_SPEC, 0, thread_model); + obstack_1grow (&obstack, '\0'); + thrmod = XOBFINISH (&obstack, const char *); +#else + thrmod = thread_model; +#endif + + fnotice (stderr, "Thread model: %s\n", thrmod); + + /* compiler_version is truncated at the first space when initialized + from version string, so truncate version_string at the first space + before comparing. */ + for (n = 0; version_string[n]; n++) + if (version_string[n] == ' ') + break; + + if (! strncmp (version_string, compiler_version, n) + && compiler_version[n] == 0) + fnotice (stderr, "gcc version %s %s\n\n", version_string, + pkgversion_string); + else + fnotice (stderr, "gcc driver version %s %sexecuting gcc version %s\n\n", + version_string, pkgversion_string, compiler_version); +} + +#ifdef RETRY_ICE_SUPPORTED +#define RETRY_ICE_ATTEMPTS 3 + +static int +try_fork () +{ + int pid, retries, sleep_interval; + sleep_interval = 1; + pid = -1; + for (retries = 0; retries < 4; retries++) + { + pid = fork (); + if (pid >= 0) + break; + sleep (sleep_interval); + sleep_interval *= 2; + } + return pid; +} + + +static void +redirect_stdout_stderr (const char *out_temp, const char *err_temp, + int append) +{ + int fd; + fd = open (out_temp, append ? O_RDWR | O_APPEND : O_RDWR); + + if (fd < 0) + exit (-1); + + close (STDOUT_FILENO); + dup (fd); + close (fd); + + fd = open (err_temp, append ? O_RDWR | O_APPEND : O_RDWR); + + if (fd < 0) + exit (-1); + + close (STDERR_FILENO); + dup (fd); + close (fd); +} + +static int +files_equal_p (char *file1, char *file2, char *buf, const int bufsize) +{ + struct stat st1, st2; + size_t n, len; + int fd1, fd2; + + fd1 = open (file1, O_RDONLY); + fd2 = open (file2, O_RDONLY); + + if (fd1 < 0 || fd2 < 0) + goto error; + + if (fstat (fd1, &st1) < 0 || fstat (fd2, &st2) < 0) + goto error; + + if (st1.st_size != st2.st_size) + goto error; + + for (n = st1.st_size; n; n -= len) + { + len = n; + if ((int) len > bufsize / 2) + len = bufsize / 2; + + if (read (fd1, buf, len) != (int) len + || read (fd2, buf + bufsize / 2, len) != (int) len) + { + goto error; + } + + if (memcmp (buf, buf + bufsize / 2, len) != 0) + goto error; + } + + close (fd1); + close (fd2); + + return 1; + +error: + close (fd1); + close (fd2); + return 0; +} + +static int +check_repro (char **temp_stdout_files, char **temp_stderr_files) +{ + int i; + const int ice_bufsize = 8192; + char *ice_buf = XNEWVEC (char, ice_bufsize); + for (i = 0; i < RETRY_ICE_ATTEMPTS - 2; ++i) + { + if (!files_equal_p (temp_stdout_files[i], temp_stdout_files[i + 1], + ice_buf, ice_bufsize) + || !files_equal_p (temp_stderr_files[i], temp_stderr_files[i + 1], + ice_buf, ice_bufsize)) + { + fnotice (stderr, "The bug is not reproducible, so it is" + " likely a hardware or OS problem.\n"); + break; + } + } + free (ice_buf); + return i == RETRY_ICE_ATTEMPTS - 2; +} + +enum attempt_status { + ATTEMPT_STATUS_FAIL_TO_RUN, + ATTEMPT_STATUS_SUCCESS, + ATTEMPT_STATUS_ICE +}; + +static enum attempt_status +run_attempt (const char *prog, const char **new_argv, const char *out_temp, + const char *err_temp, int emit_system_info, int append) +{ + int status; + int pid = try_fork (); + if (pid < 0) + return ATTEMPT_STATUS_FAIL_TO_RUN; + else if (pid == 0) + { + redirect_stdout_stderr (out_temp, err_temp, append); + + if (emit_system_info) + print_configuration (); + + if (prog == new_argv[0]) + execvp (prog, CONST_CAST2 (char *const *, const char **, new_argv)); + else + execv (new_argv[0], CONST_CAST2 (char *const *, const char **, + new_argv)); + exit (-1); + } + + if (waitpid (pid, &status, 0) < 0) + return ATTEMPT_STATUS_FAIL_TO_RUN; + + switch (WEXITSTATUS (status)) + { + case ICE_EXIT_CODE: + return ATTEMPT_STATUS_ICE; + + case SUCCESS_EXIT_CODE: + return ATTEMPT_STATUS_SUCCESS; + + default: + return ATTEMPT_STATUS_FAIL_TO_RUN; + } +} + +static void +do_report_bug (const char *prog, const char **new_argv, + const int nargs, char **out_file, char **err_file) +{ + int i, status; + int fd = open (*out_file, O_RDWR | O_APPEND); + if (fd < 0) + return; + write (fd, "\n//", 3); + for (i = 0; i < nargs; i++) + { + write (fd, " ", 1); + write (fd, new_argv[i], strlen (new_argv[i])); + } + write (fd, "\n\n", 2); + close (fd); + new_argv[nargs] = "-E"; + new_argv[nargs + 1] = NULL; + + status = run_attempt (prog, new_argv, *out_file, *err_file, 0, 1); + + if (status == ATTEMPT_STATUS_SUCCESS) + { + fnotice (stderr, "Preprocessed source stored into %s file," + " please attach this to your bugreport.\n", + *out_file); + /* Make sure it is not deleted. */ + free (*out_file); + *out_file = NULL; + } +} + +static void +append_text (char *file, const char *str) +{ + int fd = open (file, O_RDWR | O_APPEND); + if (fd < 0) + return; + + write (fd, str, strlen (str)); + close (fd); +} + +static void +try_generate_repro (const char *prog, const char **argv) +{ + int i, nargs, out_arg = -1, quiet = 0, attempt; + const char **new_argv; + char *temp_files[RETRY_ICE_ATTEMPTS * 2]; + char **temp_stdout_files = &temp_files[0]; + char **temp_stderr_files = &temp_files[RETRY_ICE_ATTEMPTS]; + + if (gcc_input_filename == NULL || ! strcmp (gcc_input_filename, "-")) + return; + + for (nargs = 0; argv[nargs] != NULL; ++nargs) + /* Only retry compiler ICEs, not preprocessor ones. */ + if (! strcmp (argv[nargs], "-E")) + return; + else if (argv[nargs][0] == '-' && argv[nargs][1] == 'o') + { + if (out_arg == -1) + out_arg = nargs; + else + return; + } + /* If the compiler is going to output any time information, + it might varry between invocations. */ + else if (! strcmp (argv[nargs], "-quiet")) + quiet = 1; + else if (! strcmp (argv[nargs], "-ftime-report")) + return; + + if (out_arg == -1 || !quiet) + return; + + memset (temp_files, '\0', sizeof (temp_files)); + new_argv = XALLOCAVEC (const char *, nargs + 4); + memcpy (new_argv, argv, (nargs + 1) * sizeof (const char *)); + new_argv[nargs++] = "-frandom-seed=0"; + new_argv[nargs++] = "-fdump-noaddr"; + new_argv[nargs] = NULL; + if (new_argv[out_arg][2] == '\0') + new_argv[out_arg + 1] = "-"; + else + new_argv[out_arg] = "-o-"; + + int status; + for (attempt = 0; attempt < RETRY_ICE_ATTEMPTS; ++attempt) + { + int emit_system_info = 0; + int append = 0; + temp_stdout_files[attempt] = make_temp_file (".out"); + temp_stderr_files[attempt] = make_temp_file (".err"); + + if (attempt == RETRY_ICE_ATTEMPTS - 1) + { + append = 1; + emit_system_info = 1; + } + + if (emit_system_info) + append_text (temp_stderr_files[attempt], "/*\n"); + + /* Fork a subprocess; wait and retry if it fails. */ + status = run_attempt (prog, new_argv, temp_stdout_files[attempt], + temp_stderr_files[attempt], emit_system_info, + append); + + if (emit_system_info) + append_text (temp_stderr_files[attempt], "*/\n"); + + if (status != ATTEMPT_STATUS_ICE) + { + fnotice (stderr, "The bug is not reproducible, so it is" + " likely a hardware or OS problem.\n"); + goto out; + } + } + + if (!check_repro (temp_stdout_files, temp_stderr_files)) + goto out; + + /* In final attempt we append cc1 options and preprocesssed code to last + generated .err file with configuration and backtrace. */ + do_report_bug (prog, new_argv, nargs, + &temp_stderr_files[RETRY_ICE_ATTEMPTS - 1], + &temp_stdout_files[RETRY_ICE_ATTEMPTS - 1]); + +out: + for (i = 0; i < RETRY_ICE_ATTEMPTS * 2; i++) + if (temp_files[i]) + { + unlink (temp_stdout_files[i]); + free (temp_stdout_files[i]); + } +} +#endif + /* Search for a file named NAME trying various prefixes including the user's -B prefix and some standard ones. Return the absolute file name found. If nothing is found, return NAME. */ @@ -6919,41 +7279,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n" if (verbose_flag) { - int n; - const char *thrmod; - - fnotice (stderr, "Target: %s\n", spec_machine); - fnotice (stderr, "Configured with: %s\n", configuration_arguments); - -#ifdef THREAD_MODEL_SPEC - /* We could have defined THREAD_MODEL_SPEC to "%*" by default, - but there's no point in doing all this processing just to get - thread_model back. */ - obstack_init (&obstack); - do_spec_1 (THREAD_MODEL_SPEC, 0, thread_model); - obstack_1grow (&obstack, '\0'); - thrmod = XOBFINISH (&obstack, const char *); -#else - thrmod = thread_model; -#endif - - fnotice (stderr, "Thread model: %s\n", thrmod); - - /* compiler_version is truncated at the first space when initialized - from version string, so truncate version_string at the first space - before comparing. */ - for (n = 0; version_string[n]; n++) - if (version_string[n] == ' ') - break; - - if (! strncmp (version_string, compiler_version, n) - && compiler_version[n] == 0) - fnotice (stderr, "gcc version %s %s\n", version_string, - pkgversion_string); - else - fnotice (stderr, "gcc driver version %s %sexecuting gcc version %s\n", - version_string, pkgversion_string, compiler_version); - + print_configuration (); if (n_infiles == 0) return (0); } ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [Ping v2][PATCH] Add patch for debugging compiler ICEs. 2014-08-28 7:31 ` [Ping v2][PATCH] " Maxim Ostapenko 2014-09-05 14:16 ` [Ping v3][PATCH] " Maxim Ostapenko @ 2014-09-09 22:51 ` Joseph S. Myers 2014-09-10 4:57 ` Jakub Jelinek 1 sibling, 1 reply; 24+ messages in thread From: Joseph S. Myers @ 2014-09-09 22:51 UTC (permalink / raw) To: Maxim Ostapenko Cc: GCC Patches, Jeff Law, Yury Gribov, Slava Garbuzov, Maxim Ostapenko On Thu, 28 Aug 2014, Maxim Ostapenko wrote: > diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c > index 0cc7593..67b8c5b 100644 > --- a/gcc/diagnostic.c > +++ b/gcc/diagnostic.c > @@ -492,7 +492,7 @@ diagnostic_action_after_output (diagnostic_context *context, > real_abort (); > diagnostic_finish (context); > fnotice (stderr, "compilation terminated.\n"); > - exit (FATAL_EXIT_CODE); > + exit (ICE_EXIT_CODE); Why? This is the case for fatal_error. FATAL_EXIT_CODE seems right for this, and ICE_EXIT_CODE wrong. > diff --git a/gcc/gcc.c b/gcc/gcc.c > index 44d0416..f7a56d1 100644 > --- a/gcc/gcc.c > +++ b/gcc/gcc.c > @@ -43,6 +43,13 @@ compilation is specified by a string called a "spec". */ > #include "params.h" > #include "vec.h" > #include "filenames.h" > +#ifdef HAVE_UNISTD_H > +#include <unistd.h> > +#endif No, unistd.h is already included in system.h, so no other (host-side) source files need to include it directly. > +#if !(defined (__MSDOS__) || defined (OS2) || defined (VMS)) > +#define RETRY_ICE_SUPPORTED > +#endif I don't think it's a good idea to have this sort of host conditional in random source files if it can be avoided. And feature tests (e.g. HAVE_FORK) are better than tests for particular systems. In any case, it would be better to use libiberty's pexecute interface for running subprocesses, as used elsewhere in GCC, rather than using POSIX interfaces directly, unless there's a clear reason (which needs explaining in the patch submission) why it's unsuitable. Hopefully that would eliminate the need for this conditional. > +static void > +print_configuration (void) All the new functions need comments above them giving the semantics of the function and any arguments and return values. > +static int > +files_equal_p (char *file1, char *file2, char *buf, const int bufsize) > +{ > + struct stat st1, st2; > + size_t n, len; > + for (n = st1.st_size; n; n -= len) This assignment would silently truncate a large file size on 32-bit platforms. A variable that can store file sizes should be off_t not size_t (then you need to be careful about any mixing of signed and unsigned types). -- Joseph S. Myers joseph@codesourcery.com ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [Ping v2][PATCH] Add patch for debugging compiler ICEs. 2014-09-09 22:51 ` [Ping v2][PATCH] " Joseph S. Myers @ 2014-09-10 4:57 ` Jakub Jelinek 2014-09-10 16:37 ` Joseph S. Myers 0 siblings, 1 reply; 24+ messages in thread From: Jakub Jelinek @ 2014-09-10 4:57 UTC (permalink / raw) To: Joseph S. Myers Cc: Maxim Ostapenko, GCC Patches, Jeff Law, Yury Gribov, Slava Garbuzov, Maxim Ostapenko On Tue, Sep 09, 2014 at 10:51:23PM +0000, Joseph S. Myers wrote: > On Thu, 28 Aug 2014, Maxim Ostapenko wrote: > > > diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c > > index 0cc7593..67b8c5b 100644 > > --- a/gcc/diagnostic.c > > +++ b/gcc/diagnostic.c > > @@ -492,7 +492,7 @@ diagnostic_action_after_output (diagnostic_context *context, > > real_abort (); > > diagnostic_finish (context); > > fnotice (stderr, "compilation terminated.\n"); > > - exit (FATAL_EXIT_CODE); > > + exit (ICE_EXIT_CODE); > > Why? This is the case for fatal_error. FATAL_EXIT_CODE seems right for > this, and ICE_EXIT_CODE wrong. So that the driver can understand the difference between an ICE and other fatal errors (e.g. sorry etc.). Users are typically using the driver and for them it matters what exit code is returned from the driver, not from cc1/cc1plus etc. Jakub ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [Ping v2][PATCH] Add patch for debugging compiler ICEs. 2014-09-10 4:57 ` Jakub Jelinek @ 2014-09-10 16:37 ` Joseph S. Myers 2014-09-11 16:18 ` [PATCH 1/2] Extend libiberty to allow append stdout and stderr to existing files Maxim Ostapenko 2014-09-11 16:20 ` [PATCH 2/2] Add patch for debugging compiler ICEs Maxim Ostapenko 0 siblings, 2 replies; 24+ messages in thread From: Joseph S. Myers @ 2014-09-10 16:37 UTC (permalink / raw) To: Jakub Jelinek Cc: Maxim Ostapenko, GCC Patches, Jeff Law, Yury Gribov, Slava Garbuzov, Maxim Ostapenko On Wed, 10 Sep 2014, Jakub Jelinek wrote: > On Tue, Sep 09, 2014 at 10:51:23PM +0000, Joseph S. Myers wrote: > > On Thu, 28 Aug 2014, Maxim Ostapenko wrote: > > > > > diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c > > > index 0cc7593..67b8c5b 100644 > > > --- a/gcc/diagnostic.c > > > +++ b/gcc/diagnostic.c > > > @@ -492,7 +492,7 @@ diagnostic_action_after_output (diagnostic_context *context, > > > real_abort (); > > > diagnostic_finish (context); > > > fnotice (stderr, "compilation terminated.\n"); > > > - exit (FATAL_EXIT_CODE); > > > + exit (ICE_EXIT_CODE); > > > > Why? This is the case for fatal_error. FATAL_EXIT_CODE seems right for > > this, and ICE_EXIT_CODE wrong. > > So that the driver can understand the difference between an ICE and other > fatal errors (e.g. sorry etc.). > Users are typically using the driver and for them it matters what exit code > is returned from the driver, not from cc1/cc1plus etc. Well, I think the next revision of the patch submission needs more explanation in this area. What exit codes do cc1 and the driver now return for (normal error, fatal error, ICE), and what do they return after the patch, and how does the change to the fatal_error case avoid incorrect changes if either cc1 or the driver called fatal_error (as opposed to either cc1 or the driver having an ICE)? Maybe that explanation should be in the form of a comment on this exit call, explaining why the counterintuitive use of ICE_EXIT_CODE in the DK_FATAL case is correct. -- Joseph S. Myers joseph@codesourcery.com ^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH 1/2] Extend libiberty to allow append stdout and stderr to existing files. 2014-09-10 16:37 ` Joseph S. Myers @ 2014-09-11 16:18 ` Maxim Ostapenko 2014-09-11 16:33 ` Ian Lance Taylor 2014-09-11 16:20 ` [PATCH 2/2] Add patch for debugging compiler ICEs Maxim Ostapenko 1 sibling, 1 reply; 24+ messages in thread From: Maxim Ostapenko @ 2014-09-11 16:18 UTC (permalink / raw) To: Joseph S. Myers, Jakub Jelinek Cc: GCC Patches, Jeff Law, Yury Gribov, Slava Garbuzov, Maxim Ostapenko, ian, dj [-- Attachment #1: Type: text/plain, Size: 274 bytes --] Working on ICE debugging patch, I've noted that libiberty interface doesn't allow to append stdout and stderr to existing files. This small patch provides two new flags for pex_run and extends open_write interface to handle the issue. Does this patch look sane? -Maxim [-- Attachment #2: libiberty_allow_append-2.diff --] [-- Type: text/x-patch, Size: 6171 bytes --] libiberty/ChangeLog: 2014-09-11 Max Ostapenko <m.ostapenko@partner.samsung.com> * pex-common.h (struct pex_funcs): Add new parameter for open_write field. * pex-unix.c (pex_unix_open_write): Add support for new parameter. * pex-djgpp.c (pex_djgpp_open_write): Likewise. * pex-win32.c (pex_win32_open_write): Likewise. * pex-common.c (pex_run_in_environment): Likewise. include/ChangeLog: 2014-09-11 Max Ostapenko <m.ostapenko@partner.samsung.com> * libiberty.h (PEX_STDOUT_APPEND): New flag. (PEX_STDERR_APPEND): Likewise. diff --git a/include/libiberty.h b/include/libiberty.h index 56b8b43..bcc1f9a 100644 --- a/include/libiberty.h +++ b/include/libiberty.h @@ -445,6 +445,11 @@ extern struct pex_obj *pex_init (int flags, const char *pname, on Unix. */ #define PEX_BINARY_ERROR 0x80 +/* Append stdout to existing file instead of truncating it. */ +#define PEX_STDOUT_APPEND 0x100 + +/* Thes same as PEX_STDOUT_APPEND, but for STDERR. */ +#define PEX_STDERR_APPEND 0x200 /* Execute one program. Returns NULL on success. On error returns an error string (typically just the name of a system call); the error diff --git a/libiberty/pex-common.c b/libiberty/pex-common.c index 6fd3fde..146010a 100644 --- a/libiberty/pex-common.c +++ b/libiberty/pex-common.c @@ -267,7 +267,8 @@ pex_run_in_environment (struct pex_obj *obj, int flags, const char *executable, if (out < 0) { out = obj->funcs->open_write (obj, outname, - (flags & PEX_BINARY_OUTPUT) != 0); + (flags & PEX_BINARY_OUTPUT) != 0, + (flags & PEX_STDOUT_APPEND) != 0); if (out < 0) { *err = errno; @@ -319,8 +320,9 @@ pex_run_in_environment (struct pex_obj *obj, int flags, const char *executable, } else { - errdes = obj->funcs->open_write (obj, errname, - (flags & PEX_BINARY_ERROR) != 0); + errdes = obj->funcs->open_write (obj, errname, + (flags & PEX_BINARY_ERROR) != 0, + (flags & PEX_STDERR_APPEND) != 0); if (errdes < 0) { *err = errno; diff --git a/libiberty/pex-common.h b/libiberty/pex-common.h index af338e6..b6db248 100644 --- a/libiberty/pex-common.h +++ b/libiberty/pex-common.h @@ -104,7 +104,7 @@ struct pex_funcs /* Open file NAME for writing. If BINARY is non-zero, open in binary mode. Return >= 0 on success, -1 on error. */ int (*open_write) (struct pex_obj *, const char */* name */, - int /* binary */); + int /* binary */, int /* append */); /* Execute a child process. FLAGS, EXECUTABLE, ARGV, ERR are from pex_run. IN, OUT, ERRDES, TOCLOSE are all descriptors, from open_read, open_write, or pipe, or they are one of STDIN_FILE_NO, diff --git a/libiberty/pex-djgpp.c b/libiberty/pex-djgpp.c index 0721139..b014ffa 100644 --- a/libiberty/pex-djgpp.c +++ b/libiberty/pex-djgpp.c @@ -43,7 +43,7 @@ extern int errno; #endif static int pex_djgpp_open_read (struct pex_obj *, const char *, int); -static int pex_djgpp_open_write (struct pex_obj *, const char *, int); +static int pex_djgpp_open_write (struct pex_obj *, const char *, int, int); static pid_t pex_djgpp_exec_child (struct pex_obj *, int, const char *, char * const *, char * const *, int, int, int, int, @@ -90,10 +90,12 @@ pex_djgpp_open_read (struct pex_obj *obj ATTRIBUTE_UNUSED, static int pex_djgpp_open_write (struct pex_obj *obj ATTRIBUTE_UNUSED, - const char *name, int binary) + const char *name, int binary, int append) { /* Note that we can't use O_EXCL here because gcc may have already created the temporary file via make_temp_file. */ + if (append) + return -1; return open (name, (O_WRONLY | O_CREAT | O_TRUNC | (binary ? O_BINARY : O_TEXT)), diff --git a/libiberty/pex-unix.c b/libiberty/pex-unix.c index addf8ee..0715115 100644 --- a/libiberty/pex-unix.c +++ b/libiberty/pex-unix.c @@ -301,7 +301,7 @@ pex_wait (struct pex_obj *obj, pid_t pid, int *status, struct pex_time *time) static void pex_child_error (struct pex_obj *, const char *, const char *, int) ATTRIBUTE_NORETURN; static int pex_unix_open_read (struct pex_obj *, const char *, int); -static int pex_unix_open_write (struct pex_obj *, const char *, int); +static int pex_unix_open_write (struct pex_obj *, const char *, int, int); static pid_t pex_unix_exec_child (struct pex_obj *, int, const char *, char * const *, char * const *, int, int, int, int, @@ -350,11 +350,12 @@ pex_unix_open_read (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name, static int pex_unix_open_write (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name, - int binary ATTRIBUTE_UNUSED) + int binary ATTRIBUTE_UNUSED, int append) { /* Note that we can't use O_EXCL here because gcc may have already created the temporary file via make_temp_file. */ - return open (name, O_WRONLY | O_CREAT | O_TRUNC, PUBLIC_MODE); + return open (name, O_WRONLY | O_CREAT + | (append ? O_APPEND : O_TRUNC), PUBLIC_MODE); } /* Close a file. */ diff --git a/libiberty/pex-win32.c b/libiberty/pex-win32.c index 8b9d4f0..66d2f11 100644 --- a/libiberty/pex-win32.c +++ b/libiberty/pex-win32.c @@ -78,7 +78,7 @@ backslashify (char *s) } static int pex_win32_open_read (struct pex_obj *, const char *, int); -static int pex_win32_open_write (struct pex_obj *, const char *, int); +static int pex_win32_open_write (struct pex_obj *, const char *, int, int); static pid_t pex_win32_exec_child (struct pex_obj *, int, const char *, char * const *, char * const *, int, int, int, int, @@ -126,10 +126,12 @@ pex_win32_open_read (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name, static int pex_win32_open_write (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name, - int binary) + int binary, int append) { /* Note that we can't use O_EXCL here because gcc may have already created the temporary file via make_temp_file. */ + if (append) + return -1; return _open (name, (_O_WRONLY | _O_CREAT | _O_TRUNC | (binary ? _O_BINARY : _O_TEXT)), ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 1/2] Extend libiberty to allow append stdout and stderr to existing files. 2014-09-11 16:18 ` [PATCH 1/2] Extend libiberty to allow append stdout and stderr to existing files Maxim Ostapenko @ 2014-09-11 16:33 ` Ian Lance Taylor 0 siblings, 0 replies; 24+ messages in thread From: Ian Lance Taylor @ 2014-09-11 16:33 UTC (permalink / raw) To: Maxim Ostapenko Cc: Joseph S. Myers, Jakub Jelinek, GCC Patches, Jeff Law, Yury Gribov, Slava Garbuzov, Maxim Ostapenko, Ian Lance Taylor, DJ Delorie On Thu, Sep 11, 2014 at 9:18 AM, Maxim Ostapenko <m.ostapenko@partner.samsung.com> wrote: > > Working on ICE debugging patch, I've noted that libiberty interface doesn't > allow to append stdout and stderr to existing files. > > This small patch provides two new flags for pex_run and extends open_write > interface to handle the issue. > > Does this patch look sane? I'm not sure why you want to do this, but the patch looks sane. Ian ^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH 2/2] Add patch for debugging compiler ICEs. 2014-09-10 16:37 ` Joseph S. Myers 2014-09-11 16:18 ` [PATCH 1/2] Extend libiberty to allow append stdout and stderr to existing files Maxim Ostapenko @ 2014-09-11 16:20 ` Maxim Ostapenko 2014-09-18 15:37 ` [PING] " Maxim Ostapenko 2014-09-18 22:17 ` Joseph S. Myers 1 sibling, 2 replies; 24+ messages in thread From: Maxim Ostapenko @ 2014-09-11 16:20 UTC (permalink / raw) To: Joseph S. Myers, Jakub Jelinek Cc: GCC Patches, Jeff Law, Yury Gribov, Slava Garbuzov, Maxim Ostapenko, ian, dj [-- Attachment #1: Type: text/plain, Size: 2783 bytes --] Hi, Joseph, Thanks for your review! I've added comments for new functions and replaced POSIX subprocess interfaces with libiberty's ones. In general, when cc1 or cc1plus ICE-es, we try to reproduce the bug by running compiler 3 times and comparing stderr and stdout on each attempt with respective ones that were gotten as the result of previous compiler run (we use temporary dump files to do this). If these files are identical, we add GCC configuration (e.g. target, configure options and version), compiler command line and preprocessed source code into last dump file, containing backtrace. Following Jakub's approach, we trigger ICE_EXIT_CODE instead of FATAL_EXIT_CODE in case of DK_FATAL error to differ ICEs from other fatal errors, so try_generate_repro routine will be able to run even if fatal_error occurred in compiler. We've noticed that on rare occasion a particularly severe segfault can cause GCC to abort without ICE-ing. These (hopefully rare) errors will be missed by our patch, because SIGSEGV handler is not able to catch the signal due to corrupted stack. It could make sense to allocate separate stack for SIGSEGV handler to resolve this situation. -Maxim On 09/10/2014 08:37 PM, Joseph S. Myers wrote: > On Wed, 10 Sep 2014, Jakub Jelinek wrote: > >> On Tue, Sep 09, 2014 at 10:51:23PM +0000, Joseph S. Myers wrote: >>> On Thu, 28 Aug 2014, Maxim Ostapenko wrote: >>> >>>> diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c >>>> index 0cc7593..67b8c5b 100644 >>>> --- a/gcc/diagnostic.c >>>> +++ b/gcc/diagnostic.c >>>> @@ -492,7 +492,7 @@ diagnostic_action_after_output (diagnostic_context *context, >>>> real_abort (); >>>> diagnostic_finish (context); >>>> fnotice (stderr, "compilation terminated.\n"); >>>> - exit (FATAL_EXIT_CODE); >>>> + exit (ICE_EXIT_CODE); >>> Why? This is the case for fatal_error. FATAL_EXIT_CODE seems right for >>> this, and ICE_EXIT_CODE wrong. >> So that the driver can understand the difference between an ICE and other >> fatal errors (e.g. sorry etc.). >> Users are typically using the driver and for them it matters what exit code >> is returned from the driver, not from cc1/cc1plus etc. > Well, I think the next revision of the patch submission needs more > explanation in this area. What exit codes do cc1 and the driver now > return for (normal error, fatal error, ICE), and what do they return after > the patch, and how does the change to the fatal_error case avoid incorrect > changes if either cc1 or the driver called fatal_error (as opposed to > either cc1 or the driver having an ICE)? Maybe that explanation should be > in the form of a comment on this exit call, explaining why the > counterintuitive use of ICE_EXIT_CODE in the DK_FATAL case is correct. > [-- Attachment #2: ICE.diff --] [-- Type: text/x-patch, Size: 14720 bytes --] 2014-09-04 Jakub Jelinek <jakub@redhat.com> Max Ostapenko <m.ostapenko@partner.samsung.com> * common.opt: New option. * doc/invoke.texi: Describe new option. * diagnostic.c (diagnostic_action_after_output): Exit with ICE_EXIT_CODE instead of FATAL_EXIT_CODE. * gcc.c (execute): Don't free first string early, but at the end of the function. Call retry_ice if compiler exited with ICE_EXIT_CODE. (main): Factor out common code. (print_configuration): New function. (try_fork): Likewise. (redirect_stdout_stderr): Likewise. (files_equal_p): Likewise. (check_repro): Likewise. (run_attempt): Likewise. (do_report_bug): Likewise. (append_text): Likewise. (try_generate_repro): Likewise diff --git a/gcc/common.opt b/gcc/common.opt index 7d78803..ce71f09 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -1120,6 +1120,11 @@ fdump-noaddr Common Report Var(flag_dump_noaddr) Suppress output of addresses in debugging dumps +freport-bug +Common Driver Var(flag_report_bug) +Collect and dump debug information into temporary file if ICE in C/C++ +compiler occured. + fdump-passes Common Var(flag_dump_passes) Init(0) Dump optimization passes diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c index 73666d6..dbc928b 100644 --- a/gcc/diagnostic.c +++ b/gcc/diagnostic.c @@ -494,7 +494,10 @@ diagnostic_action_after_output (diagnostic_context *context, real_abort (); diagnostic_finish (context); fnotice (stderr, "compilation terminated.\n"); - exit (FATAL_EXIT_CODE); + /* Exit with ICE_EXIT_CODE rather then FATAL_EXIT_CODE so the driver + understands the difference between an ICE and other fatal errors + (DK_SORRY and DK_ERROR). */ + exit (ICE_EXIT_CODE); default: gcc_unreachable (); diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 863b382..565421c 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -6336,6 +6336,11 @@ feasible to use diff on debugging dumps for compiler invocations with different compiler binaries and/or different text / bss / data / heap / stack / dso start locations. +@item -freport-bug +@opindex freport-bug +Collect and dump debug information into temporary file if ICE in C/C++ +compiler occured. + @item -fdump-unnumbered @opindex fdump-unnumbered When doing debugging dumps, suppress instruction numbers and address output. diff --git a/gcc/gcc.c b/gcc/gcc.c index c550d9d..e32ff47 100644 --- a/gcc/gcc.c +++ b/gcc/gcc.c @@ -253,6 +253,7 @@ static void init_gcc_specs (struct obstack *, const char *, const char *, static const char *convert_filename (const char *, int, int); #endif +static void try_generate_repro (const char *prog, const char **argv); static const char *getenv_spec_function (int, const char **); static const char *if_exists_spec_function (int, const char **); static const char *if_exists_else_spec_function (int, const char **); @@ -2856,7 +2857,7 @@ execute (void) } } - if (string != commands[i].prog) + if (i && string != commands[i].prog) free (CONST_CAST (char *, string)); } @@ -2909,6 +2910,15 @@ execute (void) else if (WIFEXITED (status) && WEXITSTATUS (status) >= MIN_FATAL_STATUS) { + /* For ICEs in cc1, cc1obj, cc1plus see if it is + reproducible or not. */ + const char *p; + if (flag_report_bug + && WEXITSTATUS (status) == ICE_EXIT_CODE + && i == 0 + && (p = strrchr (commands[0].argv[0], DIR_SEPARATOR)) + && ! strncmp (p + 1, "cc1", 3)) + try_generate_repro (commands[0].prog, commands[0].argv); if (WEXITSTATUS (status) > greatest_status) greatest_status = WEXITSTATUS (status); ret_code = -1; @@ -2966,6 +2976,9 @@ execute (void) } } + if (commands[0].argv[0] != commands[0].prog) + free (CONST_CAST (char *, commands[0].argv[0])); + return ret_code; } } @@ -6157,6 +6170,338 @@ give_switch (int switchnum, int omit_first_word) switches[switchnum].validated = true; } \f +/* Print GCC configuration (e.g. version, thread model, target, + configuration_arguments) to a given FILE. */ + +static void +print_configuration (FILE *file) +{ + int n; + const char *thrmod; + + fnotice (file, "Target: %s\n", spec_machine); + fnotice (file, "Configured with: %s\n", configuration_arguments); + +#ifdef THREAD_MODEL_SPEC + /* We could have defined THREAD_MODEL_SPEC to "%*" by default, + but there's no point in doing all this processing just to get + thread_model back. */ + obstack_init (&obstack); + do_spec_1 (THREAD_MODEL_SPEC, 0, thread_model); + obstack_1grow (&obstack, '\0'); + thrmod = XOBFINISH (&obstack, const char *); +#else + thrmod = thread_model; +#endif + + fnotice (file, "Thread model: %s\n", thrmod); + + /* compiler_version is truncated at the first space when initialized + from version string, so truncate version_string at the first space + before comparing. */ + for (n = 0; version_string[n]; n++) + if (version_string[n] == ' ') + break; + + if (! strncmp (version_string, compiler_version, n) + && compiler_version[n] == 0) + fnotice (file, "gcc version %s %s\n\n", version_string, + pkgversion_string); + else + fnotice (file, "gcc driver version %s %sexecuting gcc version %s\n\n", + version_string, pkgversion_string, compiler_version); + +} + +#define RETRY_ICE_ATTEMPTS 3 + +/* Returns true if FILE1 and FILE2 contain equivalent data, 0 otherwise. */ + +static bool +files_equal_p (char *file1, char *file2) +{ + struct stat st1, st2; + off_t n, len; + int fd1, fd2; + const int bufsize = 8192; + char *buf = XNEWVEC (char, bufsize); + + fd1 = open (file1, O_RDONLY); + fd2 = open (file2, O_RDONLY); + + if (fd1 < 0 || fd2 < 0) + goto error; + + if (fstat (fd1, &st1) < 0 || fstat (fd2, &st2) < 0) + goto error; + + if (st1.st_size != st2.st_size) + goto error; + + for (n = st1.st_size; n; n -= len) + { + len = n; + if ((int) len > bufsize / 2) + len = bufsize / 2; + + if (read (fd1, buf, len) != (int) len + || read (fd2, buf + bufsize / 2, len) != (int) len) + { + goto error; + } + + if (memcmp (buf, buf + bufsize / 2, len) != 0) + goto error; + } + + free (buf); + close (fd1); + close (fd2); + + return 1; + +error: + free (buf); + close (fd1); + close (fd2); + return 0; +} + +/* Check that compiler's output doesn't differ across runs. + TEMP_STDOUT_FILES and TEMP_STDERR_FILES are arrays of files, containing + stdout and stderr for each compiler run. Return true if all of + TEMP_STDOUT_FILES and TEMP_STDERR_FILES are equivalent. */ + +static bool +check_repro (char **temp_stdout_files, char **temp_stderr_files) +{ + int i; + for (i = 0; i < RETRY_ICE_ATTEMPTS - 2; ++i) + { + if (!files_equal_p (temp_stdout_files[i], temp_stdout_files[i + 1]) + || !files_equal_p (temp_stderr_files[i], temp_stderr_files[i + 1])) + { + fnotice (stderr, "The bug is not reproducible, so it is" + " likely a hardware or OS problem.\n"); + break; + } + } + return i == RETRY_ICE_ATTEMPTS - 2; +} + +enum attempt_status { + ATTEMPT_STATUS_FAIL_TO_RUN, + ATTEMPT_STATUS_SUCCESS, + ATTEMPT_STATUS_ICE +}; + + +/* Run compiler with arguments NEW_ARGV to reproduce the ICE, storing stdout + to OUT_TEMP and stderr to ERR_TEMP. If APPEND is TRUE, append to OUT_TEMP + and ERR_TEMP instead of truncating. If EMIT_SYSTEM_INFO is TRUE, also write + GCC configuration into to ERR_TEMP. Return ATTEMPT_STATUS_FAIL_TO_RUN if + compiler failed to run, ATTEMPT_STATUS_ICE if compiled ICE-ed and + ATTEMPT_STATUS_SUCCESS otherwise. */ + +static enum attempt_status +run_attempt (const char **new_argv, const char *out_temp, + const char *err_temp, int emit_system_info, int append) +{ + + if (emit_system_info) + { + FILE *file_out = fopen (err_temp, "a"); + print_configuration (file_out); + fclose (file_out); + } + + int exit_status; + const char *errmsg; + struct pex_obj *pex; + int err; + int pex_flags = PEX_USE_PIPES | PEX_LAST; + enum attempt_status status = ATTEMPT_STATUS_FAIL_TO_RUN; + + if (append) + pex_flags |= PEX_STDOUT_APPEND | PEX_STDERR_APPEND; + + pex = pex_init (PEX_USE_PIPES, new_argv[0], NULL); + if (!pex) + fatal_error ("pex_init failed: %m"); + + errmsg = pex_run (pex, pex_flags, new_argv[0], + CONST_CAST2 (char *const *, const char **, &new_argv[1]), out_temp, + err_temp, &err); + + if (!pex_get_status (pex, 1, &exit_status)) + goto out; + + switch (WEXITSTATUS (exit_status)) + { + case ICE_EXIT_CODE: + status = ATTEMPT_STATUS_ICE; + break; + + case SUCCESS_EXIT_CODE: + status = ATTEMPT_STATUS_SUCCESS; + break; + + default: + ; + } + +out: + pex_free (pex); + return status; +} + +/* This routine adds preprocessed source code into the given ERR_FILE. + To do this, it adds "-E" to NEW_ARGV and execute RUN_ATTEMPT routine to + add information in report file. RUN_ATTEMPT should return + ATTEMPT_STATUS_SUCCESS, in other case we cannot generate the report. */ + +static void +do_report_bug (const char **new_argv, const int nargs, + char **out_file, char **err_file) +{ + int i, status; + int fd = open (*out_file, O_RDWR | O_APPEND); + if (fd < 0) + return; + write (fd, "\n//", 3); + for (i = 0; i < nargs; i++) + { + write (fd, " ", 1); + write (fd, new_argv[i], strlen (new_argv[i])); + } + write (fd, "\n\n", 2); + close (fd); + new_argv[nargs] = "-E"; + new_argv[nargs + 1] = NULL; + + status = run_attempt (new_argv, *out_file, *err_file, 0, 1); + + if (status == ATTEMPT_STATUS_SUCCESS) + { + fnotice (stderr, "Preprocessed source stored into %s file," + " please attach this to your bugreport.\n", *out_file); + /* Make sure it is not deleted. */ + free (*out_file); + *out_file = NULL; + } +} + +/* Append string STR to file FILE. */ + +static void +append_text (char *file, const char *str) +{ + int fd = open (file, O_RDWR | O_APPEND); + if (fd < 0) + return; + + write (fd, str, strlen (str)); + close (fd); +} + +/* Try to reproduce ICE. If bug is reproducible, generate report .err file + containing GCC configuration, backtrace, compiler's command line options + and preprocessed source code. */ + +static void +try_generate_repro (const char *prog, const char **argv) +{ + int i, nargs, out_arg = -1, quiet = 0, attempt; + const char **new_argv; + char *temp_files[RETRY_ICE_ATTEMPTS * 2]; + char **temp_stdout_files = &temp_files[0]; + char **temp_stderr_files = &temp_files[RETRY_ICE_ATTEMPTS]; + + if (gcc_input_filename == NULL || ! strcmp (gcc_input_filename, "-")) + return; + + for (nargs = 0; argv[nargs] != NULL; ++nargs) + /* Only retry compiler ICEs, not preprocessor ones. */ + if (! strcmp (argv[nargs], "-E")) + return; + else if (argv[nargs][0] == '-' && argv[nargs][1] == 'o') + { + if (out_arg == -1) + out_arg = nargs; + else + return; + } + /* If the compiler is going to output any time information, + it might varry between invocations. */ + else if (! strcmp (argv[nargs], "-quiet")) + quiet = 1; + else if (! strcmp (argv[nargs], "-ftime-report")) + return; + + if (out_arg == -1 || !quiet) + return; + + memset (temp_files, '\0', sizeof (temp_files)); + new_argv = XALLOCAVEC (const char *, nargs + 4); + memcpy (new_argv, argv, (nargs + 1) * sizeof (const char *)); + new_argv[nargs++] = "-frandom-seed=0"; + new_argv[nargs++] = "-fdump-noaddr"; + new_argv[nargs] = NULL; + if (new_argv[out_arg][2] == '\0') + new_argv[out_arg + 1] = "-"; + else + new_argv[out_arg] = "-o-"; + + int status; + for (attempt = 0; attempt < RETRY_ICE_ATTEMPTS; ++attempt) + { + int emit_system_info = 0; + int append = 0; + temp_stdout_files[attempt] = make_temp_file (".out"); + temp_stderr_files[attempt] = make_temp_file (".err"); + + if (attempt == RETRY_ICE_ATTEMPTS - 1) + { + append = 1; + emit_system_info = 1; + } + + if (emit_system_info) + append_text (temp_stderr_files[attempt], "/*\n"); + + status = run_attempt (new_argv, temp_stdout_files[attempt], + temp_stderr_files[attempt], emit_system_info, + append); + + if (emit_system_info) + append_text (temp_stderr_files[attempt], "*/\n"); + + if (status != ATTEMPT_STATUS_ICE) + { + fnotice (stderr, "The bug is not reproducible, so it is" + " likely a hardware or OS problem.\n"); + goto out; + } + } + + if (!check_repro (temp_stdout_files, temp_stderr_files)) + goto out; + + /* In final attempt we append compiler options and preprocesssed code to last + generated .err file with configuration and backtrace. */ + do_report_bug (new_argv, nargs, + &temp_stderr_files[RETRY_ICE_ATTEMPTS - 1], + &temp_stdout_files[RETRY_ICE_ATTEMPTS - 1]); + +out: + for (i = 0; i < RETRY_ICE_ATTEMPTS * 2; i++) + if (temp_files[i]) + { + unlink (temp_stdout_files[i]); + free (temp_stdout_files[i]); + } +} + /* Search for a file named NAME trying various prefixes including the user's -B prefix and some standard ones. Return the absolute file name found. If nothing is found, return NAME. */ @@ -6926,41 +7271,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n" if (verbose_flag) { - int n; - const char *thrmod; - - fnotice (stderr, "Target: %s\n", spec_machine); - fnotice (stderr, "Configured with: %s\n", configuration_arguments); - -#ifdef THREAD_MODEL_SPEC - /* We could have defined THREAD_MODEL_SPEC to "%*" by default, - but there's no point in doing all this processing just to get - thread_model back. */ - obstack_init (&obstack); - do_spec_1 (THREAD_MODEL_SPEC, 0, thread_model); - obstack_1grow (&obstack, '\0'); - thrmod = XOBFINISH (&obstack, const char *); -#else - thrmod = thread_model; -#endif - - fnotice (stderr, "Thread model: %s\n", thrmod); - - /* compiler_version is truncated at the first space when initialized - from version string, so truncate version_string at the first space - before comparing. */ - for (n = 0; version_string[n]; n++) - if (version_string[n] == ' ') - break; - - if (! strncmp (version_string, compiler_version, n) - && compiler_version[n] == 0) - fnotice (stderr, "gcc version %s %s\n", version_string, - pkgversion_string); - else - fnotice (stderr, "gcc driver version %s %sexecuting gcc version %s\n", - version_string, pkgversion_string, compiler_version); - + print_configuration (stderr); if (n_infiles == 0) return (0); } ^ permalink raw reply [flat|nested] 24+ messages in thread
* [PING] [PATCH 2/2] Add patch for debugging compiler ICEs. 2014-09-11 16:20 ` [PATCH 2/2] Add patch for debugging compiler ICEs Maxim Ostapenko @ 2014-09-18 15:37 ` Maxim Ostapenko 2014-09-18 22:17 ` Joseph S. Myers 1 sibling, 0 replies; 24+ messages in thread From: Maxim Ostapenko @ 2014-09-18 15:37 UTC (permalink / raw) To: Joseph S. Myers, Jakub Jelinek Cc: GCC Patches, Jeff Law, Yury Gribov, Slava Garbuzov, Maxim Ostapenko [-- Attachment #1: Type: text/plain, Size: 2953 bytes --] Ping. On 09/11/2014 08:20 PM, Maxim Ostapenko wrote: > Hi, Joseph, > > Thanks for your review! I've added comments for new functions and > replaced POSIX subprocess interfaces with libiberty's ones. > > In general, when cc1 or cc1plus ICE-es, we try to reproduce the bug by > running compiler 3 times and comparing stderr and stdout on each > attempt with respective ones that were gotten as the result of > previous compiler run (we use temporary dump files to do this). If > these files are identical, we add GCC configuration (e.g. target, > configure options and version), compiler command line and preprocessed > source code into last dump file, containing backtrace. Following > Jakub's approach, we trigger ICE_EXIT_CODE instead of FATAL_EXIT_CODE > in case of DK_FATAL error to differ ICEs from other fatal errors, so > try_generate_repro routine will be able to run even if fatal_error > occurred in compiler. > > We've noticed that on rare occasion a particularly severe segfault can > cause GCC to abort without ICE-ing. These (hopefully rare) errors will > be missed by our patch, because SIGSEGV handler is not able to catch > the signal due to corrupted stack. It could make sense to allocate > separate stack for SIGSEGV handler to resolve this situation. > > -Maxim > On 09/10/2014 08:37 PM, Joseph S. Myers wrote: >> On Wed, 10 Sep 2014, Jakub Jelinek wrote: >> >>> On Tue, Sep 09, 2014 at 10:51:23PM +0000, Joseph S. Myers wrote: >>>> On Thu, 28 Aug 2014, Maxim Ostapenko wrote: >>>> >>>>> diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c >>>>> index 0cc7593..67b8c5b 100644 >>>>> --- a/gcc/diagnostic.c >>>>> +++ b/gcc/diagnostic.c >>>>> @@ -492,7 +492,7 @@ diagnostic_action_after_output >>>>> (diagnostic_context *context, >>>>> real_abort (); >>>>> diagnostic_finish (context); >>>>> fnotice (stderr, "compilation terminated.\n"); >>>>> - exit (FATAL_EXIT_CODE); >>>>> + exit (ICE_EXIT_CODE); >>>> Why? This is the case for fatal_error. FATAL_EXIT_CODE seems >>>> right for >>>> this, and ICE_EXIT_CODE wrong. >>> So that the driver can understand the difference between an ICE and >>> other >>> fatal errors (e.g. sorry etc.). >>> Users are typically using the driver and for them it matters what >>> exit code >>> is returned from the driver, not from cc1/cc1plus etc. >> Well, I think the next revision of the patch submission needs more >> explanation in this area. What exit codes do cc1 and the driver now >> return for (normal error, fatal error, ICE), and what do they return >> after >> the patch, and how does the change to the fatal_error case avoid >> incorrect >> changes if either cc1 or the driver called fatal_error (as opposed to >> either cc1 or the driver having an ICE)? Maybe that explanation >> should be >> in the form of a comment on this exit call, explaining why the >> counterintuitive use of ICE_EXIT_CODE in the DK_FATAL case is correct. >> > [-- Attachment #2: ICE.diff --] [-- Type: text/x-patch, Size: 14720 bytes --] 2014-09-04 Jakub Jelinek <jakub@redhat.com> Max Ostapenko <m.ostapenko@partner.samsung.com> * common.opt: New option. * doc/invoke.texi: Describe new option. * diagnostic.c (diagnostic_action_after_output): Exit with ICE_EXIT_CODE instead of FATAL_EXIT_CODE. * gcc.c (execute): Don't free first string early, but at the end of the function. Call retry_ice if compiler exited with ICE_EXIT_CODE. (main): Factor out common code. (print_configuration): New function. (try_fork): Likewise. (redirect_stdout_stderr): Likewise. (files_equal_p): Likewise. (check_repro): Likewise. (run_attempt): Likewise. (do_report_bug): Likewise. (append_text): Likewise. (try_generate_repro): Likewise diff --git a/gcc/common.opt b/gcc/common.opt index 7d78803..ce71f09 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -1120,6 +1120,11 @@ fdump-noaddr Common Report Var(flag_dump_noaddr) Suppress output of addresses in debugging dumps +freport-bug +Common Driver Var(flag_report_bug) +Collect and dump debug information into temporary file if ICE in C/C++ +compiler occured. + fdump-passes Common Var(flag_dump_passes) Init(0) Dump optimization passes diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c index 73666d6..dbc928b 100644 --- a/gcc/diagnostic.c +++ b/gcc/diagnostic.c @@ -494,7 +494,10 @@ diagnostic_action_after_output (diagnostic_context *context, real_abort (); diagnostic_finish (context); fnotice (stderr, "compilation terminated.\n"); - exit (FATAL_EXIT_CODE); + /* Exit with ICE_EXIT_CODE rather then FATAL_EXIT_CODE so the driver + understands the difference between an ICE and other fatal errors + (DK_SORRY and DK_ERROR). */ + exit (ICE_EXIT_CODE); default: gcc_unreachable (); diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 863b382..565421c 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -6336,6 +6336,11 @@ feasible to use diff on debugging dumps for compiler invocations with different compiler binaries and/or different text / bss / data / heap / stack / dso start locations. +@item -freport-bug +@opindex freport-bug +Collect and dump debug information into temporary file if ICE in C/C++ +compiler occured. + @item -fdump-unnumbered @opindex fdump-unnumbered When doing debugging dumps, suppress instruction numbers and address output. diff --git a/gcc/gcc.c b/gcc/gcc.c index c550d9d..e32ff47 100644 --- a/gcc/gcc.c +++ b/gcc/gcc.c @@ -253,6 +253,7 @@ static void init_gcc_specs (struct obstack *, const char *, const char *, static const char *convert_filename (const char *, int, int); #endif +static void try_generate_repro (const char *prog, const char **argv); static const char *getenv_spec_function (int, const char **); static const char *if_exists_spec_function (int, const char **); static const char *if_exists_else_spec_function (int, const char **); @@ -2856,7 +2857,7 @@ execute (void) } } - if (string != commands[i].prog) + if (i && string != commands[i].prog) free (CONST_CAST (char *, string)); } @@ -2909,6 +2910,15 @@ execute (void) else if (WIFEXITED (status) && WEXITSTATUS (status) >= MIN_FATAL_STATUS) { + /* For ICEs in cc1, cc1obj, cc1plus see if it is + reproducible or not. */ + const char *p; + if (flag_report_bug + && WEXITSTATUS (status) == ICE_EXIT_CODE + && i == 0 + && (p = strrchr (commands[0].argv[0], DIR_SEPARATOR)) + && ! strncmp (p + 1, "cc1", 3)) + try_generate_repro (commands[0].prog, commands[0].argv); if (WEXITSTATUS (status) > greatest_status) greatest_status = WEXITSTATUS (status); ret_code = -1; @@ -2966,6 +2976,9 @@ execute (void) } } + if (commands[0].argv[0] != commands[0].prog) + free (CONST_CAST (char *, commands[0].argv[0])); + return ret_code; } } @@ -6157,6 +6170,338 @@ give_switch (int switchnum, int omit_first_word) switches[switchnum].validated = true; } \f +/* Print GCC configuration (e.g. version, thread model, target, + configuration_arguments) to a given FILE. */ + +static void +print_configuration (FILE *file) +{ + int n; + const char *thrmod; + + fnotice (file, "Target: %s\n", spec_machine); + fnotice (file, "Configured with: %s\n", configuration_arguments); + +#ifdef THREAD_MODEL_SPEC + /* We could have defined THREAD_MODEL_SPEC to "%*" by default, + but there's no point in doing all this processing just to get + thread_model back. */ + obstack_init (&obstack); + do_spec_1 (THREAD_MODEL_SPEC, 0, thread_model); + obstack_1grow (&obstack, '\0'); + thrmod = XOBFINISH (&obstack, const char *); +#else + thrmod = thread_model; +#endif + + fnotice (file, "Thread model: %s\n", thrmod); + + /* compiler_version is truncated at the first space when initialized + from version string, so truncate version_string at the first space + before comparing. */ + for (n = 0; version_string[n]; n++) + if (version_string[n] == ' ') + break; + + if (! strncmp (version_string, compiler_version, n) + && compiler_version[n] == 0) + fnotice (file, "gcc version %s %s\n\n", version_string, + pkgversion_string); + else + fnotice (file, "gcc driver version %s %sexecuting gcc version %s\n\n", + version_string, pkgversion_string, compiler_version); + +} + +#define RETRY_ICE_ATTEMPTS 3 + +/* Returns true if FILE1 and FILE2 contain equivalent data, 0 otherwise. */ + +static bool +files_equal_p (char *file1, char *file2) +{ + struct stat st1, st2; + off_t n, len; + int fd1, fd2; + const int bufsize = 8192; + char *buf = XNEWVEC (char, bufsize); + + fd1 = open (file1, O_RDONLY); + fd2 = open (file2, O_RDONLY); + + if (fd1 < 0 || fd2 < 0) + goto error; + + if (fstat (fd1, &st1) < 0 || fstat (fd2, &st2) < 0) + goto error; + + if (st1.st_size != st2.st_size) + goto error; + + for (n = st1.st_size; n; n -= len) + { + len = n; + if ((int) len > bufsize / 2) + len = bufsize / 2; + + if (read (fd1, buf, len) != (int) len + || read (fd2, buf + bufsize / 2, len) != (int) len) + { + goto error; + } + + if (memcmp (buf, buf + bufsize / 2, len) != 0) + goto error; + } + + free (buf); + close (fd1); + close (fd2); + + return 1; + +error: + free (buf); + close (fd1); + close (fd2); + return 0; +} + +/* Check that compiler's output doesn't differ across runs. + TEMP_STDOUT_FILES and TEMP_STDERR_FILES are arrays of files, containing + stdout and stderr for each compiler run. Return true if all of + TEMP_STDOUT_FILES and TEMP_STDERR_FILES are equivalent. */ + +static bool +check_repro (char **temp_stdout_files, char **temp_stderr_files) +{ + int i; + for (i = 0; i < RETRY_ICE_ATTEMPTS - 2; ++i) + { + if (!files_equal_p (temp_stdout_files[i], temp_stdout_files[i + 1]) + || !files_equal_p (temp_stderr_files[i], temp_stderr_files[i + 1])) + { + fnotice (stderr, "The bug is not reproducible, so it is" + " likely a hardware or OS problem.\n"); + break; + } + } + return i == RETRY_ICE_ATTEMPTS - 2; +} + +enum attempt_status { + ATTEMPT_STATUS_FAIL_TO_RUN, + ATTEMPT_STATUS_SUCCESS, + ATTEMPT_STATUS_ICE +}; + + +/* Run compiler with arguments NEW_ARGV to reproduce the ICE, storing stdout + to OUT_TEMP and stderr to ERR_TEMP. If APPEND is TRUE, append to OUT_TEMP + and ERR_TEMP instead of truncating. If EMIT_SYSTEM_INFO is TRUE, also write + GCC configuration into to ERR_TEMP. Return ATTEMPT_STATUS_FAIL_TO_RUN if + compiler failed to run, ATTEMPT_STATUS_ICE if compiled ICE-ed and + ATTEMPT_STATUS_SUCCESS otherwise. */ + +static enum attempt_status +run_attempt (const char **new_argv, const char *out_temp, + const char *err_temp, int emit_system_info, int append) +{ + + if (emit_system_info) + { + FILE *file_out = fopen (err_temp, "a"); + print_configuration (file_out); + fclose (file_out); + } + + int exit_status; + const char *errmsg; + struct pex_obj *pex; + int err; + int pex_flags = PEX_USE_PIPES | PEX_LAST; + enum attempt_status status = ATTEMPT_STATUS_FAIL_TO_RUN; + + if (append) + pex_flags |= PEX_STDOUT_APPEND | PEX_STDERR_APPEND; + + pex = pex_init (PEX_USE_PIPES, new_argv[0], NULL); + if (!pex) + fatal_error ("pex_init failed: %m"); + + errmsg = pex_run (pex, pex_flags, new_argv[0], + CONST_CAST2 (char *const *, const char **, &new_argv[1]), out_temp, + err_temp, &err); + + if (!pex_get_status (pex, 1, &exit_status)) + goto out; + + switch (WEXITSTATUS (exit_status)) + { + case ICE_EXIT_CODE: + status = ATTEMPT_STATUS_ICE; + break; + + case SUCCESS_EXIT_CODE: + status = ATTEMPT_STATUS_SUCCESS; + break; + + default: + ; + } + +out: + pex_free (pex); + return status; +} + +/* This routine adds preprocessed source code into the given ERR_FILE. + To do this, it adds "-E" to NEW_ARGV and execute RUN_ATTEMPT routine to + add information in report file. RUN_ATTEMPT should return + ATTEMPT_STATUS_SUCCESS, in other case we cannot generate the report. */ + +static void +do_report_bug (const char **new_argv, const int nargs, + char **out_file, char **err_file) +{ + int i, status; + int fd = open (*out_file, O_RDWR | O_APPEND); + if (fd < 0) + return; + write (fd, "\n//", 3); + for (i = 0; i < nargs; i++) + { + write (fd, " ", 1); + write (fd, new_argv[i], strlen (new_argv[i])); + } + write (fd, "\n\n", 2); + close (fd); + new_argv[nargs] = "-E"; + new_argv[nargs + 1] = NULL; + + status = run_attempt (new_argv, *out_file, *err_file, 0, 1); + + if (status == ATTEMPT_STATUS_SUCCESS) + { + fnotice (stderr, "Preprocessed source stored into %s file," + " please attach this to your bugreport.\n", *out_file); + /* Make sure it is not deleted. */ + free (*out_file); + *out_file = NULL; + } +} + +/* Append string STR to file FILE. */ + +static void +append_text (char *file, const char *str) +{ + int fd = open (file, O_RDWR | O_APPEND); + if (fd < 0) + return; + + write (fd, str, strlen (str)); + close (fd); +} + +/* Try to reproduce ICE. If bug is reproducible, generate report .err file + containing GCC configuration, backtrace, compiler's command line options + and preprocessed source code. */ + +static void +try_generate_repro (const char *prog, const char **argv) +{ + int i, nargs, out_arg = -1, quiet = 0, attempt; + const char **new_argv; + char *temp_files[RETRY_ICE_ATTEMPTS * 2]; + char **temp_stdout_files = &temp_files[0]; + char **temp_stderr_files = &temp_files[RETRY_ICE_ATTEMPTS]; + + if (gcc_input_filename == NULL || ! strcmp (gcc_input_filename, "-")) + return; + + for (nargs = 0; argv[nargs] != NULL; ++nargs) + /* Only retry compiler ICEs, not preprocessor ones. */ + if (! strcmp (argv[nargs], "-E")) + return; + else if (argv[nargs][0] == '-' && argv[nargs][1] == 'o') + { + if (out_arg == -1) + out_arg = nargs; + else + return; + } + /* If the compiler is going to output any time information, + it might varry between invocations. */ + else if (! strcmp (argv[nargs], "-quiet")) + quiet = 1; + else if (! strcmp (argv[nargs], "-ftime-report")) + return; + + if (out_arg == -1 || !quiet) + return; + + memset (temp_files, '\0', sizeof (temp_files)); + new_argv = XALLOCAVEC (const char *, nargs + 4); + memcpy (new_argv, argv, (nargs + 1) * sizeof (const char *)); + new_argv[nargs++] = "-frandom-seed=0"; + new_argv[nargs++] = "-fdump-noaddr"; + new_argv[nargs] = NULL; + if (new_argv[out_arg][2] == '\0') + new_argv[out_arg + 1] = "-"; + else + new_argv[out_arg] = "-o-"; + + int status; + for (attempt = 0; attempt < RETRY_ICE_ATTEMPTS; ++attempt) + { + int emit_system_info = 0; + int append = 0; + temp_stdout_files[attempt] = make_temp_file (".out"); + temp_stderr_files[attempt] = make_temp_file (".err"); + + if (attempt == RETRY_ICE_ATTEMPTS - 1) + { + append = 1; + emit_system_info = 1; + } + + if (emit_system_info) + append_text (temp_stderr_files[attempt], "/*\n"); + + status = run_attempt (new_argv, temp_stdout_files[attempt], + temp_stderr_files[attempt], emit_system_info, + append); + + if (emit_system_info) + append_text (temp_stderr_files[attempt], "*/\n"); + + if (status != ATTEMPT_STATUS_ICE) + { + fnotice (stderr, "The bug is not reproducible, so it is" + " likely a hardware or OS problem.\n"); + goto out; + } + } + + if (!check_repro (temp_stdout_files, temp_stderr_files)) + goto out; + + /* In final attempt we append compiler options and preprocesssed code to last + generated .err file with configuration and backtrace. */ + do_report_bug (new_argv, nargs, + &temp_stderr_files[RETRY_ICE_ATTEMPTS - 1], + &temp_stdout_files[RETRY_ICE_ATTEMPTS - 1]); + +out: + for (i = 0; i < RETRY_ICE_ATTEMPTS * 2; i++) + if (temp_files[i]) + { + unlink (temp_stdout_files[i]); + free (temp_stdout_files[i]); + } +} + /* Search for a file named NAME trying various prefixes including the user's -B prefix and some standard ones. Return the absolute file name found. If nothing is found, return NAME. */ @@ -6926,41 +7271,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n" if (verbose_flag) { - int n; - const char *thrmod; - - fnotice (stderr, "Target: %s\n", spec_machine); - fnotice (stderr, "Configured with: %s\n", configuration_arguments); - -#ifdef THREAD_MODEL_SPEC - /* We could have defined THREAD_MODEL_SPEC to "%*" by default, - but there's no point in doing all this processing just to get - thread_model back. */ - obstack_init (&obstack); - do_spec_1 (THREAD_MODEL_SPEC, 0, thread_model); - obstack_1grow (&obstack, '\0'); - thrmod = XOBFINISH (&obstack, const char *); -#else - thrmod = thread_model; -#endif - - fnotice (stderr, "Thread model: %s\n", thrmod); - - /* compiler_version is truncated at the first space when initialized - from version string, so truncate version_string at the first space - before comparing. */ - for (n = 0; version_string[n]; n++) - if (version_string[n] == ' ') - break; - - if (! strncmp (version_string, compiler_version, n) - && compiler_version[n] == 0) - fnotice (stderr, "gcc version %s %s\n", version_string, - pkgversion_string); - else - fnotice (stderr, "gcc driver version %s %sexecuting gcc version %s\n", - version_string, pkgversion_string, compiler_version); - + print_configuration (stderr); if (n_infiles == 0) return (0); } ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 2/2] Add patch for debugging compiler ICEs. 2014-09-11 16:20 ` [PATCH 2/2] Add patch for debugging compiler ICEs Maxim Ostapenko 2014-09-18 15:37 ` [PING] " Maxim Ostapenko @ 2014-09-18 22:17 ` Joseph S. Myers 2014-09-19 3:33 ` Yury Gribov 2014-09-23 7:15 ` Maxim Ostapenko 1 sibling, 2 replies; 24+ messages in thread From: Joseph S. Myers @ 2014-09-18 22:17 UTC (permalink / raw) To: Maxim Ostapenko Cc: Jakub Jelinek, GCC Patches, Jeff Law, Yury Gribov, Slava Garbuzov, Maxim Ostapenko, ian, dj On Thu, 11 Sep 2014, Maxim Ostapenko wrote: > In general, when cc1 or cc1plus ICE-es, we try to reproduce the bug by running > compiler 3 times and comparing stderr and stdout on each attempt with > respective ones that were gotten as the result of previous compiler run (we > use temporary dump files to do this). If these files are identical, we add GCC > configuration (e.g. target, configure options and version), compiler command > line and preprocessed source code into last dump file, containing backtrace. > Following Jakub's approach, we trigger ICE_EXIT_CODE instead of > FATAL_EXIT_CODE in case of DK_FATAL error to differ ICEs from other fatal > errors, so try_generate_repro routine will be able to run even if fatal_error > occurred in compiler. I still don't understand what's going on here with exit codes. Suppose cc1 calls fatal_error (not for an ICE, not -Wfatal-errors - a normal DK_FATAL arising from a call to fatal_error). What exit code does it exit with? What path leads to that exit code? How does the driver distinguish this from an ICE? Suppose cc1 calls internal_error. What exit code does it exit with? What path leads to that exit code? How does the driver distinguish this from a call to fatal_error? What about the above exit codes was different before the patch, that means the driver ICE detection can only work given the diagnostic.c changes? -- Joseph S. Myers joseph@codesourcery.com ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 2/2] Add patch for debugging compiler ICEs. 2014-09-18 22:17 ` Joseph S. Myers @ 2014-09-19 3:33 ` Yury Gribov 2014-09-23 7:15 ` Maxim Ostapenko 1 sibling, 0 replies; 24+ messages in thread From: Yury Gribov @ 2014-09-19 3:33 UTC (permalink / raw) To: Joseph S. Myers, Maxim Ostapenko Cc: Jakub Jelinek, GCC Patches, Jeff Law, Slava Garbuzov, Maxim Ostapenko, ian, dj On 09/19/2014 02:16 AM, Joseph S. Myers wrote: > On Thu, 11 Sep 2014, Maxim Ostapenko wrote: > >> In general, when cc1 or cc1plus ICE-es, we try to reproduce the bug by running >> compiler 3 times and comparing stderr and stdout on each attempt with >> respective ones that were gotten as the result of previous compiler run (we >> use temporary dump files to do this). If these files are identical, we add GCC >> configuration (e.g. target, configure options and version), compiler command >> line and preprocessed source code into last dump file, containing backtrace. >> Following Jakub's approach, we trigger ICE_EXIT_CODE instead of >> FATAL_EXIT_CODE in case of DK_FATAL error to differ ICEs from other fatal >> errors, so try_generate_repro routine will be able to run even if fatal_error >> occurred in compiler. > > I still don't understand what's going on here with exit codes. I'd second this, internal_error already exits with ICE_EXIT_CODE via DK_ICE. Forcing fatal errors to return ICE_EXIT_CODE as well seems unnecessary. -Y ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 2/2] Add patch for debugging compiler ICEs. 2014-09-18 22:17 ` Joseph S. Myers 2014-09-19 3:33 ` Yury Gribov @ 2014-09-23 7:15 ` Maxim Ostapenko 2014-09-25 19:05 ` Jeff Law 1 sibling, 1 reply; 24+ messages in thread From: Maxim Ostapenko @ 2014-09-23 7:15 UTC (permalink / raw) To: Joseph S. Myers Cc: Jakub Jelinek, GCC Patches, Jeff Law, Yury Gribov, Slava Garbuzov, Maxim Ostapenko, ian, dj, Yuri Gribov [-- Attachment #1: Type: text/plain, Size: 1639 bytes --] On 09/19/2014 02:16 AM, Joseph S. Myers wrote: > On Thu, 11 Sep 2014, Maxim Ostapenko wrote: > >> In general, when cc1 or cc1plus ICE-es, we try to reproduce the bug by running >> compiler 3 times and comparing stderr and stdout on each attempt with >> respective ones that were gotten as the result of previous compiler run (we >> use temporary dump files to do this). If these files are identical, we add GCC >> configuration (e.g. target, configure options and version), compiler command >> line and preprocessed source code into last dump file, containing backtrace. >> Following Jakub's approach, we trigger ICE_EXIT_CODE instead of >> FATAL_EXIT_CODE in case of DK_FATAL error to differ ICEs from other fatal >> errors, so try_generate_repro routine will be able to run even if fatal_error >> occurred in compiler. > I still don't understand what's going on here with exit codes. > > Suppose cc1 calls fatal_error (not for an ICE, not -Wfatal-errors - a > normal DK_FATAL arising from a call to fatal_error). What exit code does > it exit with? What path leads to that exit code? How does the driver > distinguish this from an ICE? > > Suppose cc1 calls internal_error. What exit code does it exit with? What > path leads to that exit code? How does the driver distinguish this from a > call to fatal_error? Hm, this line is indeed redundant, thanks. Removed the line. > What about the above exit codes was different before the patch, that means > the driver ICE detection can only work given the diagnostic.c changes? > The new patch version seems to work fine on some current ICEs in GCC 5.0 (pr55843 and pr58987). -Maxim [-- Attachment #2: ICE.diff --] [-- Type: text/x-patch, Size: 19580 bytes --] 2014-09-04 Jakub Jelinek <jakub@redhat.com> Max Ostapenko <m.ostapenko@partner.samsung.com> * common.opt: New option. * doc/invoke.texi: Describe new option. * gcc.c (execute): Don't free first string early, but at the end of the function. Call retry_ice if compiler exited with ICE_EXIT_CODE. (main): Factor out common code. (print_configuration): New function. (files_equal_p): Likewise. (check_repro): Likewise. (run_attempt): Likewise. (do_report_bug): Likewise. (append_text): Likewise. (try_generate_repro): Likewise diff --git a/gcc/common.opt b/gcc/common.opt index 634a72b..b4f0ed4 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -1120,6 +1120,11 @@ fdump-noaddr Common Report Var(flag_dump_noaddr) Suppress output of addresses in debugging dumps +freport-bug +Common Driver Var(flag_report_bug) +Collect and dump debug information into temporary file if ICE in C/C++ +compiler occured. + fdump-passes Common Var(flag_dump_passes) Init(0) Dump optimization passes diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index eae4ab1..2be8475 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -6344,6 +6344,11 @@ feasible to use diff on debugging dumps for compiler invocations with different compiler binaries and/or different text / bss / data / heap / stack / dso start locations. +@item -freport-bug +@opindex freport-bug +Collect and dump debug information into temporary file if ICE in C/C++ +compiler occured. + @item -fdump-unnumbered @opindex fdump-unnumbered When doing debugging dumps, suppress instruction numbers and address output. diff --git a/gcc/gcc.c b/gcc/gcc.c index c550d9d..e32ff47 100644 --- a/gcc/gcc.c +++ b/gcc/gcc.c @@ -253,6 +253,7 @@ static void init_gcc_specs (struct obstack *, const char *, const char *, static const char *convert_filename (const char *, int, int); #endif +static void try_generate_repro (const char *prog, const char **argv); static const char *getenv_spec_function (int, const char **); static const char *if_exists_spec_function (int, const char **); static const char *if_exists_else_spec_function (int, const char **); @@ -2856,7 +2857,7 @@ execute (void) } } - if (string != commands[i].prog) + if (i && string != commands[i].prog) free (CONST_CAST (char *, string)); } @@ -2909,6 +2910,15 @@ execute (void) else if (WIFEXITED (status) && WEXITSTATUS (status) >= MIN_FATAL_STATUS) { + /* For ICEs in cc1, cc1obj, cc1plus see if it is + reproducible or not. */ + const char *p; + if (flag_report_bug + && WEXITSTATUS (status) == ICE_EXIT_CODE + && i == 0 + && (p = strrchr (commands[0].argv[0], DIR_SEPARATOR)) + && ! strncmp (p + 1, "cc1", 3)) + try_generate_repro (commands[0].prog, commands[0].argv); if (WEXITSTATUS (status) > greatest_status) greatest_status = WEXITSTATUS (status); ret_code = -1; @@ -2966,6 +2976,9 @@ execute (void) } } + if (commands[0].argv[0] != commands[0].prog) + free (CONST_CAST (char *, commands[0].argv[0])); + return ret_code; } } @@ -6157,6 +6170,338 @@ give_switch (int switchnum, int omit_first_word) switches[switchnum].validated = true; } \f +/* Print GCC configuration (e.g. version, thread model, target, + configuration_arguments) to a given FILE. */ + +static void +print_configuration (FILE *file) +{ + int n; + const char *thrmod; + + fnotice (file, "Target: %s\n", spec_machine); + fnotice (file, "Configured with: %s\n", configuration_arguments); + +#ifdef THREAD_MODEL_SPEC + /* We could have defined THREAD_MODEL_SPEC to "%*" by default, + but there's no point in doing all this processing just to get + thread_model back. */ + obstack_init (&obstack); + do_spec_1 (THREAD_MODEL_SPEC, 0, thread_model); + obstack_1grow (&obstack, '\0'); + thrmod = XOBFINISH (&obstack, const char *); +#else + thrmod = thread_model; +#endif + + fnotice (file, "Thread model: %s\n", thrmod); + + /* compiler_version is truncated at the first space when initialized + from version string, so truncate version_string at the first space + before comparing. */ + for (n = 0; version_string[n]; n++) + if (version_string[n] == ' ') + break; + + if (! strncmp (version_string, compiler_version, n) + && compiler_version[n] == 0) + fnotice (file, "gcc version %s %s\n\n", version_string, + pkgversion_string); + else + fnotice (file, "gcc driver version %s %sexecuting gcc version %s\n\n", + version_string, pkgversion_string, compiler_version); + +} + +#define RETRY_ICE_ATTEMPTS 3 + +/* Returns true if FILE1 and FILE2 contain equivalent data, 0 otherwise. */ + +static bool +files_equal_p (char *file1, char *file2) +{ + struct stat st1, st2; + off_t n, len; + int fd1, fd2; + const int bufsize = 8192; + char *buf = XNEWVEC (char, bufsize); + + fd1 = open (file1, O_RDONLY); + fd2 = open (file2, O_RDONLY); + + if (fd1 < 0 || fd2 < 0) + goto error; + + if (fstat (fd1, &st1) < 0 || fstat (fd2, &st2) < 0) + goto error; + + if (st1.st_size != st2.st_size) + goto error; + + for (n = st1.st_size; n; n -= len) + { + len = n; + if ((int) len > bufsize / 2) + len = bufsize / 2; + + if (read (fd1, buf, len) != (int) len + || read (fd2, buf + bufsize / 2, len) != (int) len) + { + goto error; + } + + if (memcmp (buf, buf + bufsize / 2, len) != 0) + goto error; + } + + free (buf); + close (fd1); + close (fd2); + + return 1; + +error: + free (buf); + close (fd1); + close (fd2); + return 0; +} + +/* Check that compiler's output doesn't differ across runs. + TEMP_STDOUT_FILES and TEMP_STDERR_FILES are arrays of files, containing + stdout and stderr for each compiler run. Return true if all of + TEMP_STDOUT_FILES and TEMP_STDERR_FILES are equivalent. */ + +static bool +check_repro (char **temp_stdout_files, char **temp_stderr_files) +{ + int i; + for (i = 0; i < RETRY_ICE_ATTEMPTS - 2; ++i) + { + if (!files_equal_p (temp_stdout_files[i], temp_stdout_files[i + 1]) + || !files_equal_p (temp_stderr_files[i], temp_stderr_files[i + 1])) + { + fnotice (stderr, "The bug is not reproducible, so it is" + " likely a hardware or OS problem.\n"); + break; + } + } + return i == RETRY_ICE_ATTEMPTS - 2; +} + +enum attempt_status { + ATTEMPT_STATUS_FAIL_TO_RUN, + ATTEMPT_STATUS_SUCCESS, + ATTEMPT_STATUS_ICE +}; + + +/* Run compiler with arguments NEW_ARGV to reproduce the ICE, storing stdout + to OUT_TEMP and stderr to ERR_TEMP. If APPEND is TRUE, append to OUT_TEMP + and ERR_TEMP instead of truncating. If EMIT_SYSTEM_INFO is TRUE, also write + GCC configuration into to ERR_TEMP. Return ATTEMPT_STATUS_FAIL_TO_RUN if + compiler failed to run, ATTEMPT_STATUS_ICE if compiled ICE-ed and + ATTEMPT_STATUS_SUCCESS otherwise. */ + +static enum attempt_status +run_attempt (const char **new_argv, const char *out_temp, + const char *err_temp, int emit_system_info, int append) +{ + + if (emit_system_info) + { + FILE *file_out = fopen (err_temp, "a"); + print_configuration (file_out); + fclose (file_out); + } + + int exit_status; + const char *errmsg; + struct pex_obj *pex; + int err; + int pex_flags = PEX_USE_PIPES | PEX_LAST; + enum attempt_status status = ATTEMPT_STATUS_FAIL_TO_RUN; + + if (append) + pex_flags |= PEX_STDOUT_APPEND | PEX_STDERR_APPEND; + + pex = pex_init (PEX_USE_PIPES, new_argv[0], NULL); + if (!pex) + fatal_error ("pex_init failed: %m"); + + errmsg = pex_run (pex, pex_flags, new_argv[0], + CONST_CAST2 (char *const *, const char **, &new_argv[1]), out_temp, + err_temp, &err); + + if (!pex_get_status (pex, 1, &exit_status)) + goto out; + + switch (WEXITSTATUS (exit_status)) + { + case ICE_EXIT_CODE: + status = ATTEMPT_STATUS_ICE; + break; + + case SUCCESS_EXIT_CODE: + status = ATTEMPT_STATUS_SUCCESS; + break; + + default: + ; + } + +out: + pex_free (pex); + return status; +} + +/* This routine adds preprocessed source code into the given ERR_FILE. + To do this, it adds "-E" to NEW_ARGV and execute RUN_ATTEMPT routine to + add information in report file. RUN_ATTEMPT should return + ATTEMPT_STATUS_SUCCESS, in other case we cannot generate the report. */ + +static void +do_report_bug (const char **new_argv, const int nargs, + char **out_file, char **err_file) +{ + int i, status; + int fd = open (*out_file, O_RDWR | O_APPEND); + if (fd < 0) + return; + write (fd, "\n//", 3); + for (i = 0; i < nargs; i++) + { + write (fd, " ", 1); + write (fd, new_argv[i], strlen (new_argv[i])); + } + write (fd, "\n\n", 2); + close (fd); + new_argv[nargs] = "-E"; + new_argv[nargs + 1] = NULL; + + status = run_attempt (new_argv, *out_file, *err_file, 0, 1); + + if (status == ATTEMPT_STATUS_SUCCESS) + { + fnotice (stderr, "Preprocessed source stored into %s file," + " please attach this to your bugreport.\n", *out_file); + /* Make sure it is not deleted. */ + free (*out_file); + *out_file = NULL; + } +} + +/* Append string STR to file FILE. */ + +static void +append_text (char *file, const char *str) +{ + int fd = open (file, O_RDWR | O_APPEND); + if (fd < 0) + return; + + write (fd, str, strlen (str)); + close (fd); +} + +/* Try to reproduce ICE. If bug is reproducible, generate report .err file + containing GCC configuration, backtrace, compiler's command line options + and preprocessed source code. */ + +static void +try_generate_repro (const char *prog, const char **argv) +{ + int i, nargs, out_arg = -1, quiet = 0, attempt; + const char **new_argv; + char *temp_files[RETRY_ICE_ATTEMPTS * 2]; + char **temp_stdout_files = &temp_files[0]; + char **temp_stderr_files = &temp_files[RETRY_ICE_ATTEMPTS]; + + if (gcc_input_filename == NULL || ! strcmp (gcc_input_filename, "-")) + return; + + for (nargs = 0; argv[nargs] != NULL; ++nargs) + /* Only retry compiler ICEs, not preprocessor ones. */ + if (! strcmp (argv[nargs], "-E")) + return; + else if (argv[nargs][0] == '-' && argv[nargs][1] == 'o') + { + if (out_arg == -1) + out_arg = nargs; + else + return; + } + /* If the compiler is going to output any time information, + it might varry between invocations. */ + else if (! strcmp (argv[nargs], "-quiet")) + quiet = 1; + else if (! strcmp (argv[nargs], "-ftime-report")) + return; + + if (out_arg == -1 || !quiet) + return; + + memset (temp_files, '\0', sizeof (temp_files)); + new_argv = XALLOCAVEC (const char *, nargs + 4); + memcpy (new_argv, argv, (nargs + 1) * sizeof (const char *)); + new_argv[nargs++] = "-frandom-seed=0"; + new_argv[nargs++] = "-fdump-noaddr"; + new_argv[nargs] = NULL; + if (new_argv[out_arg][2] == '\0') + new_argv[out_arg + 1] = "-"; + else + new_argv[out_arg] = "-o-"; + + int status; + for (attempt = 0; attempt < RETRY_ICE_ATTEMPTS; ++attempt) + { + int emit_system_info = 0; + int append = 0; + temp_stdout_files[attempt] = make_temp_file (".out"); + temp_stderr_files[attempt] = make_temp_file (".err"); + + if (attempt == RETRY_ICE_ATTEMPTS - 1) + { + append = 1; + emit_system_info = 1; + } + + if (emit_system_info) + append_text (temp_stderr_files[attempt], "/*\n"); + + status = run_attempt (new_argv, temp_stdout_files[attempt], + temp_stderr_files[attempt], emit_system_info, + append); + + if (emit_system_info) + append_text (temp_stderr_files[attempt], "*/\n"); + + if (status != ATTEMPT_STATUS_ICE) + { + fnotice (stderr, "The bug is not reproducible, so it is" + " likely a hardware or OS problem.\n"); + goto out; + } + } + + if (!check_repro (temp_stdout_files, temp_stderr_files)) + goto out; + + /* In final attempt we append compiler options and preprocesssed code to last + generated .err file with configuration and backtrace. */ + do_report_bug (new_argv, nargs, + &temp_stderr_files[RETRY_ICE_ATTEMPTS - 1], + &temp_stdout_files[RETRY_ICE_ATTEMPTS - 1]); + +out: + for (i = 0; i < RETRY_ICE_ATTEMPTS * 2; i++) + if (temp_files[i]) + { + unlink (temp_stdout_files[i]); + free (temp_stdout_files[i]); + } +} + /* Search for a file named NAME trying various prefixes including the user's -B prefix and some standard ones. Return the absolute file name found. If nothing is found, return NAME. */ @@ -6926,41 +7271,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n" if (verbose_flag) { - int n; - const char *thrmod; - - fnotice (stderr, "Target: %s\n", spec_machine); - fnotice (stderr, "Configured with: %s\n", configuration_arguments); - -#ifdef THREAD_MODEL_SPEC - /* We could have defined THREAD_MODEL_SPEC to "%*" by default, - but there's no point in doing all this processing just to get - thread_model back. */ - obstack_init (&obstack); - do_spec_1 (THREAD_MODEL_SPEC, 0, thread_model); - obstack_1grow (&obstack, '\0'); - thrmod = XOBFINISH (&obstack, const char *); -#else - thrmod = thread_model; -#endif - - fnotice (stderr, "Thread model: %s\n", thrmod); - - /* compiler_version is truncated at the first space when initialized - from version string, so truncate version_string at the first space - before comparing. */ - for (n = 0; version_string[n]; n++) - if (version_string[n] == ' ') - break; - - if (! strncmp (version_string, compiler_version, n) - && compiler_version[n] == 0) - fnotice (stderr, "gcc version %s %s\n", version_string, - pkgversion_string); - else - fnotice (stderr, "gcc driver version %s %sexecuting gcc version %s\n", - version_string, pkgversion_string, compiler_version); - + print_configuration (stderr); if (n_infiles == 0) return (0); } diff --git a/include/libiberty.h b/include/libiberty.h index 56b8b43..bcc1f9a 100644 --- a/include/libiberty.h +++ b/include/libiberty.h @@ -445,6 +445,11 @@ extern struct pex_obj *pex_init (int flags, const char *pname, on Unix. */ #define PEX_BINARY_ERROR 0x80 +/* Append stdout to existing file instead of truncating it. */ +#define PEX_STDOUT_APPEND 0x100 + +/* Thes same as PEX_STDOUT_APPEND, but for STDERR. */ +#define PEX_STDERR_APPEND 0x200 /* Execute one program. Returns NULL on success. On error returns an error string (typically just the name of a system call); the error diff --git a/libiberty/pex-common.c b/libiberty/pex-common.c index 6fd3fde..146010a 100644 --- a/libiberty/pex-common.c +++ b/libiberty/pex-common.c @@ -267,7 +267,8 @@ pex_run_in_environment (struct pex_obj *obj, int flags, const char *executable, if (out < 0) { out = obj->funcs->open_write (obj, outname, - (flags & PEX_BINARY_OUTPUT) != 0); + (flags & PEX_BINARY_OUTPUT) != 0, + (flags & PEX_STDOUT_APPEND) != 0); if (out < 0) { *err = errno; @@ -319,8 +320,9 @@ pex_run_in_environment (struct pex_obj *obj, int flags, const char *executable, } else { - errdes = obj->funcs->open_write (obj, errname, - (flags & PEX_BINARY_ERROR) != 0); + errdes = obj->funcs->open_write (obj, errname, + (flags & PEX_BINARY_ERROR) != 0, + (flags & PEX_STDERR_APPEND) != 0); if (errdes < 0) { *err = errno; diff --git a/libiberty/pex-common.h b/libiberty/pex-common.h index af338e6..b6db248 100644 --- a/libiberty/pex-common.h +++ b/libiberty/pex-common.h @@ -104,7 +104,7 @@ struct pex_funcs /* Open file NAME for writing. If BINARY is non-zero, open in binary mode. Return >= 0 on success, -1 on error. */ int (*open_write) (struct pex_obj *, const char */* name */, - int /* binary */); + int /* binary */, int /* append */); /* Execute a child process. FLAGS, EXECUTABLE, ARGV, ERR are from pex_run. IN, OUT, ERRDES, TOCLOSE are all descriptors, from open_read, open_write, or pipe, or they are one of STDIN_FILE_NO, diff --git a/libiberty/pex-djgpp.c b/libiberty/pex-djgpp.c index 0721139..b014ffa 100644 --- a/libiberty/pex-djgpp.c +++ b/libiberty/pex-djgpp.c @@ -43,7 +43,7 @@ extern int errno; #endif static int pex_djgpp_open_read (struct pex_obj *, const char *, int); -static int pex_djgpp_open_write (struct pex_obj *, const char *, int); +static int pex_djgpp_open_write (struct pex_obj *, const char *, int, int); static pid_t pex_djgpp_exec_child (struct pex_obj *, int, const char *, char * const *, char * const *, int, int, int, int, @@ -90,10 +90,12 @@ pex_djgpp_open_read (struct pex_obj *obj ATTRIBUTE_UNUSED, static int pex_djgpp_open_write (struct pex_obj *obj ATTRIBUTE_UNUSED, - const char *name, int binary) + const char *name, int binary, int append) { /* Note that we can't use O_EXCL here because gcc may have already created the temporary file via make_temp_file. */ + if (append) + return -1; return open (name, (O_WRONLY | O_CREAT | O_TRUNC | (binary ? O_BINARY : O_TEXT)), diff --git a/libiberty/pex-unix.c b/libiberty/pex-unix.c index addf8ee..0715115 100644 --- a/libiberty/pex-unix.c +++ b/libiberty/pex-unix.c @@ -301,7 +301,7 @@ pex_wait (struct pex_obj *obj, pid_t pid, int *status, struct pex_time *time) static void pex_child_error (struct pex_obj *, const char *, const char *, int) ATTRIBUTE_NORETURN; static int pex_unix_open_read (struct pex_obj *, const char *, int); -static int pex_unix_open_write (struct pex_obj *, const char *, int); +static int pex_unix_open_write (struct pex_obj *, const char *, int, int); static pid_t pex_unix_exec_child (struct pex_obj *, int, const char *, char * const *, char * const *, int, int, int, int, @@ -350,11 +350,12 @@ pex_unix_open_read (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name, static int pex_unix_open_write (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name, - int binary ATTRIBUTE_UNUSED) + int binary ATTRIBUTE_UNUSED, int append) { /* Note that we can't use O_EXCL here because gcc may have already created the temporary file via make_temp_file. */ - return open (name, O_WRONLY | O_CREAT | O_TRUNC, PUBLIC_MODE); + return open (name, O_WRONLY | O_CREAT + | (append ? O_APPEND : O_TRUNC), PUBLIC_MODE); } /* Close a file. */ diff --git a/libiberty/pex-win32.c b/libiberty/pex-win32.c index 8b9d4f0..66d2f11 100644 --- a/libiberty/pex-win32.c +++ b/libiberty/pex-win32.c @@ -78,7 +78,7 @@ backslashify (char *s) } static int pex_win32_open_read (struct pex_obj *, const char *, int); -static int pex_win32_open_write (struct pex_obj *, const char *, int); +static int pex_win32_open_write (struct pex_obj *, const char *, int, int); static pid_t pex_win32_exec_child (struct pex_obj *, int, const char *, char * const *, char * const *, int, int, int, int, @@ -126,10 +126,12 @@ pex_win32_open_read (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name, static int pex_win32_open_write (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name, - int binary) + int binary, int append) { /* Note that we can't use O_EXCL here because gcc may have already created the temporary file via make_temp_file. */ + if (append) + return -1; return _open (name, (_O_WRONLY | _O_CREAT | _O_TRUNC | (binary ? _O_BINARY : _O_TEXT)), ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 2/2] Add patch for debugging compiler ICEs. 2014-09-23 7:15 ` Maxim Ostapenko @ 2014-09-25 19:05 ` Jeff Law 2014-09-26 8:04 ` Maxim Ostapenko 0 siblings, 1 reply; 24+ messages in thread From: Jeff Law @ 2014-09-25 19:05 UTC (permalink / raw) To: Maxim Ostapenko, Joseph S. Myers Cc: Jakub Jelinek, GCC Patches, Yury Gribov, Slava Garbuzov, Maxim Ostapenko, ian, dj, Yuri Gribov On 09/23/14 01:14, Maxim Ostapenko wrote: > > > 2014-09-04 Jakub Jelinek<jakub@redhat.com> > Max Ostapenko<m.ostapenko@partner.samsung.com> > > * common.opt: New option. > * doc/invoke.texi: Describe new option. > * gcc.c (execute): Don't free first string early, but at the end > of the function. Call retry_ice if compiler exited with > ICE_EXIT_CODE. > (main): Factor out common code. > (print_configuration): New function. > (files_equal_p): Likewise. > (check_repro): Likewise. > (run_attempt): Likewise. > (do_report_bug): Likewise. > (append_text): Likewise. > (try_generate_repro): Likewise Approved. Please install. Thanks for your patience, Jeff ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 2/2] Add patch for debugging compiler ICEs. 2014-09-25 19:05 ` Jeff Law @ 2014-09-26 8:04 ` Maxim Ostapenko 2014-09-26 13:11 ` Rainer Orth ` (2 more replies) 0 siblings, 3 replies; 24+ messages in thread From: Maxim Ostapenko @ 2014-09-26 8:04 UTC (permalink / raw) To: Jeff Law, Joseph S. Myers Cc: Jakub Jelinek, GCC Patches, Yury Gribov, Slava Garbuzov, Maxim Ostapenko, ian, dj, Yuri Gribov Thank you all for your help! Done in r215633. -Maxim On 09/25/2014 11:05 PM, Jeff Law wrote: > On 09/23/14 01:14, Maxim Ostapenko wrote: >> >> >> 2014-09-04 Jakub Jelinek<jakub@redhat.com> >> Max Ostapenko<m.ostapenko@partner.samsung.com> >> >> * common.opt: New option. >> * doc/invoke.texi: Describe new option. >> * gcc.c (execute): Don't free first string early, but at the end >> of the function. Call retry_ice if compiler exited with >> ICE_EXIT_CODE. >> (main): Factor out common code. >> (print_configuration): New function. >> (files_equal_p): Likewise. >> (check_repro): Likewise. >> (run_attempt): Likewise. >> (do_report_bug): Likewise. >> (append_text): Likewise. >> (try_generate_repro): Likewise > Approved. Please install. > > Thanks for your patience, > Jeff > > ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 2/2] Add patch for debugging compiler ICEs. 2014-09-26 8:04 ` Maxim Ostapenko @ 2014-09-26 13:11 ` Rainer Orth 2014-09-26 13:24 ` Thomas Schwinge 2015-01-23 1:42 ` H.J. Lu 2 siblings, 0 replies; 24+ messages in thread From: Rainer Orth @ 2014-09-26 13:11 UTC (permalink / raw) To: Maxim Ostapenko Cc: Jeff Law, Joseph S. Myers, Jakub Jelinek, GCC Patches, Yury Gribov, Slava Garbuzov, Maxim Ostapenko, ian, dj, Yuri Gribov Hi Maxim, > Thank you all for your help! > > Done in r215633. unfortuntely, the applied patch cannot have been tested properly and breaks native i386-pc-solaris2.11 (and every other) bootstrap: /vol/gcc/src/hg/trunk/local/gcc/gcc.c: In function 'attempt_status run_attempt(const char**, const char*, const char*, int, int)': /vol/gcc/src/hg/trunk/local/gcc/gcc.c:6319:15: error: variable 'errmsg' set but not used [-Werror=unused-but-set-variable] const char *errmsg; ^ /vol/gcc/src/hg/trunk/local/gcc/gcc.c: At global scope: /vol/gcc/src/hg/trunk/local/gcc/gcc.c:6412:33: error: unused parameter 'prog' [-Werror=unused-parameter] try_generate_repro (const char *prog, const char **argv) ^ Removing the errmsg variable and the prog parameter name fixes this. I'm not sure if the errmsg is intentionally unused, though. Rainer -- ----------------------------------------------------------------------------- Rainer Orth, Center for Biotechnology, Bielefeld University ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 2/2] Add patch for debugging compiler ICEs. 2014-09-26 8:04 ` Maxim Ostapenko 2014-09-26 13:11 ` Rainer Orth @ 2014-09-26 13:24 ` Thomas Schwinge 2014-09-26 13:32 ` Maxim Ostapenko 2014-09-26 16:18 ` Jeff Law 2015-01-23 1:42 ` H.J. Lu 2 siblings, 2 replies; 24+ messages in thread From: Thomas Schwinge @ 2014-09-26 13:24 UTC (permalink / raw) To: Maxim Ostapenko, Jeff Law, Joseph S. Myers Cc: Jakub Jelinek, GCC Patches, Yury Gribov, Slava Garbuzov, Maxim Ostapenko, ian, dj, Yuri Gribov [-- Attachment #1: Type: text/plain, Size: 4189 bytes --] Hi! On Fri, 26 Sep 2014 12:04:45 +0400, Maxim Ostapenko <m.ostapenko@partner.samsung.com> wrote: > Thank you all for your help! > > Done in r215633. > > -Maxim > On 09/25/2014 11:05 PM, Jeff Law wrote: > > On 09/23/14 01:14, Maxim Ostapenko wrote: > >> > >> > >> 2014-09-04 Jakub Jelinek<jakub@redhat.com> > >> Max Ostapenko<m.ostapenko@partner.samsung.com> > >> > >> * common.opt: New option. > >> * doc/invoke.texi: Describe new option. > >> * gcc.c (execute): Don't free first string early, but at the end > >> of the function. Call retry_ice if compiler exited with > >> ICE_EXIT_CODE. > >> (main): Factor out common code. > >> (print_configuration): New function. > >> (files_equal_p): Likewise. > >> (check_repro): Likewise. > >> (run_attempt): Likewise. > >> (do_report_bug): Likewise. > >> (append_text): Likewise. > >> (try_generate_repro): Likewise > > Approved. Please install. > > > > Thanks for your patience, > > Jeff This is causing compiler warnings, respectively bootstrap errors: [...] ../../master/gcc/gcc.c: In function 'attempt_status run_attempt(const char**, const char*, const char*, int, int)': ../../master/gcc/gcc.c:6319:15: error: variable 'errmsg' set but not used [-Werror=unused-but-set-variable] const char *errmsg; ^ ../../master/gcc/gcc.c: At global scope: ../../master/gcc/gcc.c:6412:33: error: unused parameter 'prog' [-Werror=unused-parameter] try_generate_repro (const char *prog, const char **argv) ^ cc1plus: all warnings being treated as errors Makefile:1040: recipe for target 'gcc.o' failed make[3]: *** [gcc.o] Error 1 make[3]: Leaving directory '/media/erich/home/thomas/tmp/gcc/hurd/master.build/gcc' Makefile:4285: recipe for target 'all-stage2-gcc' failed make[2]: *** [all-stage2-gcc] Error 2 make[2]: Leaving directory '/media/erich/home/thomas/tmp/gcc/hurd/master.build' Makefile:21561: recipe for target 'stage2-bubble' failed make[1]: *** [stage2-bubble] Error 2 make[1]: Leaving directory '/media/erich/home/thomas/tmp/gcc/hurd/master.build' Makefile:892: recipe for target 'all' failed make: *** [all] Error 2 OK to fix as follows? Only compile-tested, did not test the new -freport-bug functionality. diff --git gcc/gcc.c gcc/gcc.c index e32ff47..47c4e28 100644 --- gcc/gcc.c +++ gcc/gcc.c @@ -253,7 +253,7 @@ static void init_gcc_specs (struct obstack *, const char *, const char *, static const char *convert_filename (const char *, int, int); #endif -static void try_generate_repro (const char *prog, const char **argv); +static void try_generate_repro (const char **argv); static const char *getenv_spec_function (int, const char **); static const char *if_exists_spec_function (int, const char **); static const char *if_exists_else_spec_function (int, const char **); @@ -2918,7 +2918,7 @@ execute (void) && i == 0 && (p = strrchr (commands[0].argv[0], DIR_SEPARATOR)) && ! strncmp (p + 1, "cc1", 3)) - try_generate_repro (commands[0].prog, commands[0].argv); + try_generate_repro (commands[0].argv); if (WEXITSTATUS (status) > greatest_status) greatest_status = WEXITSTATUS (status); ret_code = -1; @@ -6332,6 +6332,16 @@ run_attempt (const char **new_argv, const char *out_temp, errmsg = pex_run (pex, pex_flags, new_argv[0], CONST_CAST2 (char *const *, const char **, &new_argv[1]), out_temp, err_temp, &err); + if (errmsg != NULL) + { + if (err == 0) + fatal_error (errmsg); + else + { + errno = err; + pfatal_with_name (errmsg); + } + } if (!pex_get_status (pex, 1, &exit_status)) goto out; @@ -6409,7 +6419,7 @@ append_text (char *file, const char *str) and preprocessed source code. */ static void -try_generate_repro (const char *prog, const char **argv) +try_generate_repro (const char **argv) { int i, nargs, out_arg = -1, quiet = 0, attempt; const char **new_argv; Grüße, Thomas [-- Attachment #2: Type: application/pgp-signature, Size: 472 bytes --] ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 2/2] Add patch for debugging compiler ICEs. 2014-09-26 13:24 ` Thomas Schwinge @ 2014-09-26 13:32 ` Maxim Ostapenko 2014-09-26 16:18 ` Jeff Law 1 sibling, 0 replies; 24+ messages in thread From: Maxim Ostapenko @ 2014-09-26 13:32 UTC (permalink / raw) To: Thomas Schwinge, Jeff Law, Joseph S. Myers Cc: Jakub Jelinek, GCC Patches, Yury Gribov, Slava Garbuzov, Maxim Ostapenko, ian, dj, Yuri Gribov Ugh, sorry. Thanks for fixing this. On 09/26/2014 05:23 PM, Thomas Schwinge wrote: > Hi! > > On Fri, 26 Sep 2014 12:04:45 +0400, Maxim Ostapenko <m.ostapenko@partner.samsung.com> wrote: >> Thank you all for your help! >> >> Done in r215633. >> >> -Maxim >> On 09/25/2014 11:05 PM, Jeff Law wrote: >>> On 09/23/14 01:14, Maxim Ostapenko wrote: >>>> >>>> 2014-09-04 Jakub Jelinek<jakub@redhat.com> >>>> Max Ostapenko<m.ostapenko@partner.samsung.com> >>>> >>>> * common.opt: New option. >>>> * doc/invoke.texi: Describe new option. >>>> * gcc.c (execute): Don't free first string early, but at the end >>>> of the function. Call retry_ice if compiler exited with >>>> ICE_EXIT_CODE. >>>> (main): Factor out common code. >>>> (print_configuration): New function. >>>> (files_equal_p): Likewise. >>>> (check_repro): Likewise. >>>> (run_attempt): Likewise. >>>> (do_report_bug): Likewise. >>>> (append_text): Likewise. >>>> (try_generate_repro): Likewise >>> Approved. Please install. >>> >>> Thanks for your patience, >>> Jeff > This is causing compiler warnings, respectively bootstrap errors: > > [...] > ../../master/gcc/gcc.c: In function 'attempt_status run_attempt(const char**, const char*, const char*, int, int)': > ../../master/gcc/gcc.c:6319:15: error: variable 'errmsg' set but not used [-Werror=unused-but-set-variable] > const char *errmsg; > ^ > ../../master/gcc/gcc.c: At global scope: > ../../master/gcc/gcc.c:6412:33: error: unused parameter 'prog' [-Werror=unused-parameter] > try_generate_repro (const char *prog, const char **argv) > ^ > cc1plus: all warnings being treated as errors > Makefile:1040: recipe for target 'gcc.o' failed > make[3]: *** [gcc.o] Error 1 > make[3]: Leaving directory '/media/erich/home/thomas/tmp/gcc/hurd/master.build/gcc' > Makefile:4285: recipe for target 'all-stage2-gcc' failed > make[2]: *** [all-stage2-gcc] Error 2 > make[2]: Leaving directory '/media/erich/home/thomas/tmp/gcc/hurd/master.build' > Makefile:21561: recipe for target 'stage2-bubble' failed > make[1]: *** [stage2-bubble] Error 2 > make[1]: Leaving directory '/media/erich/home/thomas/tmp/gcc/hurd/master.build' > Makefile:892: recipe for target 'all' failed > make: *** [all] Error 2 > > OK to fix as follows? Only compile-tested, did not test the new > -freport-bug functionality. This works fine on pr55843 and pr58987. > diff --git gcc/gcc.c gcc/gcc.c > index e32ff47..47c4e28 100644 > --- gcc/gcc.c > +++ gcc/gcc.c > @@ -253,7 +253,7 @@ static void init_gcc_specs (struct obstack *, const char *, const char *, > static const char *convert_filename (const char *, int, int); > #endif > > -static void try_generate_repro (const char *prog, const char **argv); > +static void try_generate_repro (const char **argv); > static const char *getenv_spec_function (int, const char **); > static const char *if_exists_spec_function (int, const char **); > static const char *if_exists_else_spec_function (int, const char **); > @@ -2918,7 +2918,7 @@ execute (void) > && i == 0 > && (p = strrchr (commands[0].argv[0], DIR_SEPARATOR)) > && ! strncmp (p + 1, "cc1", 3)) > - try_generate_repro (commands[0].prog, commands[0].argv); > + try_generate_repro (commands[0].argv); > if (WEXITSTATUS (status) > greatest_status) > greatest_status = WEXITSTATUS (status); > ret_code = -1; > @@ -6332,6 +6332,16 @@ run_attempt (const char **new_argv, const char *out_temp, > errmsg = pex_run (pex, pex_flags, new_argv[0], > CONST_CAST2 (char *const *, const char **, &new_argv[1]), out_temp, > err_temp, &err); > + if (errmsg != NULL) > + { > + if (err == 0) > + fatal_error (errmsg); > + else > + { > + errno = err; > + pfatal_with_name (errmsg); > + } > + } > > if (!pex_get_status (pex, 1, &exit_status)) > goto out; > @@ -6409,7 +6419,7 @@ append_text (char *file, const char *str) > and preprocessed source code. */ > > static void > -try_generate_repro (const char *prog, const char **argv) > +try_generate_repro (const char **argv) > { > int i, nargs, out_arg = -1, quiet = 0, attempt; > const char **new_argv; > > > > GrüÃe, > Thomas -Maxim ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 2/2] Add patch for debugging compiler ICEs. 2014-09-26 13:24 ` Thomas Schwinge 2014-09-26 13:32 ` Maxim Ostapenko @ 2014-09-26 16:18 ` Jeff Law 2014-09-26 16:31 ` Thomas Schwinge 1 sibling, 1 reply; 24+ messages in thread From: Jeff Law @ 2014-09-26 16:18 UTC (permalink / raw) To: Thomas Schwinge, Maxim Ostapenko, Joseph S. Myers Cc: Jakub Jelinek, GCC Patches, Yury Gribov, Slava Garbuzov, Maxim Ostapenko, ian, dj, Yuri Gribov On 09/26/14 07:23, Thomas Schwinge wrote: > Hi! > > On Fri, 26 Sep 2014 12:04:45 +0400, Maxim Ostapenko <m.ostapenko@partner.samsung.com> wrote: >> Thank you all for your help! >> >> Done in r215633. >> >> -Maxim >> On 09/25/2014 11:05 PM, Jeff Law wrote: >>> On 09/23/14 01:14, Maxim Ostapenko wrote: >>>> >>>> >>>> 2014-09-04 Jakub Jelinek<jakub@redhat.com> >>>> Max Ostapenko<m.ostapenko@partner.samsung.com> >>>> >>>> * common.opt: New option. >>>> * doc/invoke.texi: Describe new option. >>>> * gcc.c (execute): Don't free first string early, but at the end >>>> of the function. Call retry_ice if compiler exited with >>>> ICE_EXIT_CODE. >>>> (main): Factor out common code. >>>> (print_configuration): New function. >>>> (files_equal_p): Likewise. >>>> (check_repro): Likewise. >>>> (run_attempt): Likewise. >>>> (do_report_bug): Likewise. >>>> (append_text): Likewise. >>>> (try_generate_repro): Likewise >>> Approved. Please install. >>> >>> Thanks for your patience, >>> Jeff > > This is causing compiler warnings, respectively bootstrap errors: > > [...] > ../../master/gcc/gcc.c: In function 'attempt_status run_attempt(const char**, const char*, const char*, int, int)': > ../../master/gcc/gcc.c:6319:15: error: variable 'errmsg' set but not used [-Werror=unused-but-set-variable] > const char *errmsg; > ^ > ../../master/gcc/gcc.c: At global scope: > ../../master/gcc/gcc.c:6412:33: error: unused parameter 'prog' [-Werror=unused-parameter] > try_generate_repro (const char *prog, const char **argv) > ^ > cc1plus: all warnings being treated as errors > Makefile:1040: recipe for target 'gcc.o' failed > make[3]: *** [gcc.o] Error 1 > make[3]: Leaving directory '/media/erich/home/thomas/tmp/gcc/hurd/master.build/gcc' > Makefile:4285: recipe for target 'all-stage2-gcc' failed > make[2]: *** [all-stage2-gcc] Error 2 > make[2]: Leaving directory '/media/erich/home/thomas/tmp/gcc/hurd/master.build' > Makefile:21561: recipe for target 'stage2-bubble' failed > make[1]: *** [stage2-bubble] Error 2 > make[1]: Leaving directory '/media/erich/home/thomas/tmp/gcc/hurd/master.build' > Makefile:892: recipe for target 'all' failed > make: *** [all] Error 2 > > OK to fix as follows? Only compile-tested, did not test the new > -freport-bug functionality. [ ... ] Please construct a ChangeLog and commit. Thanks. jeff ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 2/2] Add patch for debugging compiler ICEs. 2014-09-26 16:18 ` Jeff Law @ 2014-09-26 16:31 ` Thomas Schwinge 2014-09-26 16:32 ` Jeff Law 0 siblings, 1 reply; 24+ messages in thread From: Thomas Schwinge @ 2014-09-26 16:31 UTC (permalink / raw) To: Jeff Law, Maxim Ostapenko, Joseph S. Myers Cc: Jakub Jelinek, GCC Patches, Yury Gribov, Slava Garbuzov, Maxim Ostapenko, ian, dj, Yuri Gribov [-- Attachment #1: Type: text/plain, Size: 645 bytes --] Hi! On Fri, 26 Sep 2014 10:18:32 -0600, Jeff Law <law@redhat.com> wrote: > On 09/26/14 07:23, Thomas Schwinge wrote: > > On Fri, 26 Sep 2014 12:04:45 +0400, Maxim Ostapenko <m.ostapenko@partner.samsung.com> wrote: > >> Done in r215633. > > This is causing compiler warnings, respectively bootstrap errors: [...] > > OK to fix as follows? Only compile-tested, did not test the new > > -freport-bug functionality. > [ ... ] > Please construct a ChangeLog and commit. Thanks. After Maxim had sent his email about having successfully tested it, I had already taken the opportunity to commit it: r215644. Grüße, Thomas [-- Attachment #2: Type: application/pgp-signature, Size: 472 bytes --] ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 2/2] Add patch for debugging compiler ICEs. 2014-09-26 16:31 ` Thomas Schwinge @ 2014-09-26 16:32 ` Jeff Law 0 siblings, 0 replies; 24+ messages in thread From: Jeff Law @ 2014-09-26 16:32 UTC (permalink / raw) To: Thomas Schwinge, Maxim Ostapenko, Joseph S. Myers Cc: Jakub Jelinek, GCC Patches, Yury Gribov, Slava Garbuzov, Maxim Ostapenko, ian, dj, Yuri Gribov On 09/26/14 10:31, Thomas Schwinge wrote: > Hi! > > On Fri, 26 Sep 2014 10:18:32 -0600, Jeff Law <law@redhat.com> wrote: >> On 09/26/14 07:23, Thomas Schwinge wrote: >>> On Fri, 26 Sep 2014 12:04:45 +0400, Maxim Ostapenko <m.ostapenko@partner.samsung.com> wrote: >>>> Done in r215633. > >>> This is causing compiler warnings, respectively bootstrap errors: [...] > >>> OK to fix as follows? Only compile-tested, did not test the new >>> -freport-bug functionality. >> [ ... ] >> Please construct a ChangeLog and commit. Thanks. > > After Maxim had sent his email about having successfully tested it, I had > already taken the opportunity to commit it: r215644. Thanks. jeff ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH 2/2] Add patch for debugging compiler ICEs. 2014-09-26 8:04 ` Maxim Ostapenko 2014-09-26 13:11 ` Rainer Orth 2014-09-26 13:24 ` Thomas Schwinge @ 2015-01-23 1:42 ` H.J. Lu 2 siblings, 0 replies; 24+ messages in thread From: H.J. Lu @ 2015-01-23 1:42 UTC (permalink / raw) To: Maxim Ostapenko Cc: Jeff Law, Joseph S. Myers, Jakub Jelinek, GCC Patches, Yury Gribov, Slava Garbuzov, Maxim Ostapenko, Ian Lance Taylor, DJ Delorie, Yuri Gribov On Fri, Sep 26, 2014 at 1:04 AM, Maxim Ostapenko <m.ostapenko@partner.samsung.com> wrote: > Thank you all for your help! > > Done in r215633. > > -Maxim > > On 09/25/2014 11:05 PM, Jeff Law wrote: >> >> On 09/23/14 01:14, Maxim Ostapenko wrote: >>> >>> >>> >>> 2014-09-04 Jakub Jelinek<jakub@redhat.com> >>> Max Ostapenko<m.ostapenko@partner.samsung.com> >>> >>> * common.opt: New option. >>> * doc/invoke.texi: Describe new option. >>> * gcc.c (execute): Don't free first string early, but at the end >>> of the function. Call retry_ice if compiler exited with >>> ICE_EXIT_CODE. >>> (main): Factor out common code. >>> (print_configuration): New function. >>> (files_equal_p): Likewise. >>> (check_repro): Likewise. >>> (run_attempt): Likewise. >>> (do_report_bug): Likewise. >>> (append_text): Likewise. >>> (try_generate_repro): Likewise >> >> Approved. Please install. Any particular reason for extra blank line: if (! strncmp (version_string, compiler_version, n) && compiler_version[n] == 0) fnotice (file, "gcc version %s %s\n\n", version_string, pkgversion_string); else fnotice (file, "gcc driver version %s %sexecuting gcc version %s\n\n", version_string, pkgversion_string, compiler_version); I opened: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64737 -- H.J. ^ permalink raw reply [flat|nested] 24+ messages in thread
end of thread, other threads:[~2015-01-22 23:12 UTC | newest] Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2014-08-04 17:03 [PATCH] Add patch for debugging compiler ICEs Maxim Ostapenko 2014-08-12 16:14 ` [PING][PATCH] " Maxim Ostapenko 2014-08-19 13:58 ` Fwd: [PATCH] " Maxim Ostapenko 2014-08-28 7:31 ` [Ping v2][PATCH] " Maxim Ostapenko 2014-09-05 14:16 ` [Ping v3][PATCH] " Maxim Ostapenko 2014-09-09 22:51 ` [Ping v2][PATCH] " Joseph S. Myers 2014-09-10 4:57 ` Jakub Jelinek 2014-09-10 16:37 ` Joseph S. Myers 2014-09-11 16:18 ` [PATCH 1/2] Extend libiberty to allow append stdout and stderr to existing files Maxim Ostapenko 2014-09-11 16:33 ` Ian Lance Taylor 2014-09-11 16:20 ` [PATCH 2/2] Add patch for debugging compiler ICEs Maxim Ostapenko 2014-09-18 15:37 ` [PING] " Maxim Ostapenko 2014-09-18 22:17 ` Joseph S. Myers 2014-09-19 3:33 ` Yury Gribov 2014-09-23 7:15 ` Maxim Ostapenko 2014-09-25 19:05 ` Jeff Law 2014-09-26 8:04 ` Maxim Ostapenko 2014-09-26 13:11 ` Rainer Orth 2014-09-26 13:24 ` Thomas Schwinge 2014-09-26 13:32 ` Maxim Ostapenko 2014-09-26 16:18 ` Jeff Law 2014-09-26 16:31 ` Thomas Schwinge 2014-09-26 16:32 ` Jeff Law 2015-01-23 1:42 ` H.J. Lu
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).