On 06/03/2014 10:55 PM, Joseph S. Myers wrote:
OK.
Thanks. Here's a new version of the original patch set. There are now three patches, the middle one containing just a few small cleanup steps towards unifying the code. There was confusion about the meaning of the "debug" variable, so I've created a new one "save_temps" which controls one aspect of the behaviour, while "debug" now just controls extra printout.
Bootstrapped/tested on x86_64-linux. A slightly earlier version was also tested on powerpc-ibm-aix7.1.0.0 (the gcc111 machine). Ok?
Bernd
commit af9bca9c6439e3f8f31b40d5813a3d016b1f21e5 Author: Bernd Schmidt <ber...@codesourcery.com> Date: Wed May 21 12:18:17 2014 +0200 Make a collect-utils library for use by tools like collect2 and lto-wrapper. * Makefile.in (ALL_HOST_BACKEND_OBJS): Add collect-utils.o. (lto-wrapper$(exeext)): Link with collect-utils.o. * collect-utils.c: New file. * collect-utils.h: New file. * lto-wrapper.c: Include "collect-utils.h". (args_name): Delete variable. (tool_name): New variable. (tool_cleanup): New function. (maybe_unlink): Renamed from maybe_unlink_file. All callers changed. (lto_wrapper_cleanup, fatal_signal, collect_execute, collect_wait, fork_execute): Remove functions. diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 3350186..24abad9 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1491,7 +1491,7 @@ ALL_HOST_FRONTEND_OBJS = $(foreach v,$(CONFIG_LANGUAGES),$($(v)_OBJS)) ALL_HOST_BACKEND_OBJS = $(GCC_OBJS) $(OBJS) $(OBJS-libcommon) \ $(OBJS-libcommon-target) @TREEBROWSER@ main.o c-family/cppspec.o \ $(COLLECT2_OBJS) $(EXTRA_GCC_OBJS) $(GCOV_OBJS) $(GCOV_DUMP_OBJS) \ - lto-wrapper.o + lto-wrapper.o collect-utils.o # This lists all host object files, whether they are included in this # compilation or not. @@ -1910,9 +1910,10 @@ collect2$(exeext): $(COLLECT2_OBJS) $(LIBDEPS) CFLAGS-collect2.o += -DTARGET_MACHINE=\"$(target_noncanonical)\" \ @TARGET_SYSTEM_ROOT_DEFINE@ -lto-wrapper$(exeext): lto-wrapper.o ggc-none.o libcommon-target.a $(LIBDEPS) +LTO_WRAPPER_OBJS = lto-wrapper.o collect-utils.o ggc-none.o +lto-wrapper$(exeext): $(LTO_WRAPPER_OBJS) libcommon-target.a $(LIBDEPS) +$(LINKER) $(ALL_COMPILERFLAGS) $(LDFLAGS) -o T$@ \ - lto-wrapper.o ggc-none.o libcommon-target.a $(LIBS) + $(LTO_WRAPPER_OBJS) libcommon-target.a $(LIBS) mv -f T$@ $@ # Files used by all variants of C or by the stand-alone pre-processor. diff --git a/gcc/collect-utils.c b/gcc/collect-utils.c new file mode 100644 index 0000000..004569c --- /dev/null +++ b/gcc/collect-utils.c @@ -0,0 +1,222 @@ +/* Utility functions used by tools like collect2 and lto-wrapper. + Copyright (C) 2009-2014 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "intl.h" +#include "diagnostic.h" +#include "obstack.h" +#include "opts.h" +#include "options.h" +#include "simple-object.h" +#include "lto-section-names.h" +#include "collect-utils.h" + +static char *response_file; + +bool debug; +bool verbose; + +/* Delete tempfiles. */ + +void +utils_cleanup (void) +{ + static bool cleanup_done = false; + + if (cleanup_done) + return; + + /* Setting cleanup_done prevents an infinite loop if one of the + calls to maybe_unlink fails. */ + cleanup_done = true; + + if (response_file) + maybe_unlink (response_file); + tool_cleanup (); +} + +/* Notify user of a non-error. */ +void +notice (const char *cmsgid, ...) +{ + va_list ap; + + va_start (ap, cmsgid); + vfprintf (stderr, _(cmsgid), ap); + va_end (ap); +} + +void +fatal_signal (int signum) +{ + signal (signum, SIG_DFL); + utils_cleanup (); + /* Get the same signal again, this time not handled, + so its normal effect occurs. */ + kill (getpid (), signum); +} + +/* Execute a program, and wait for the reply. ARGV are the arguments. The + last one must be NULL. */ + +struct pex_obj * +collect_execute (char **argv) +{ + struct pex_obj *pex; + const char *errmsg; + int err; + + if (verbose) + { + char **p_argv; + const char *str; + + for (p_argv = argv; (str = *p_argv) != (char *) 0; p_argv++) + fprintf (stderr, " %s", str); + + fprintf (stderr, "\n"); + } + + fflush (stdout); + fflush (stderr); + + pex = pex_init (0, tool_name, NULL); + if (pex == NULL) + fatal_error ("pex_init failed: %m"); + + /* Do not use PEX_LAST here, we use our stdout for communicating with + collect2 or the linker-plugin. Any output from the sub-process + will confuse that. */ + errmsg = pex_run (pex, PEX_SEARCH, argv[0], argv, NULL, + NULL, &err); + if (errmsg != NULL) + { + if (err != 0) + { + errno = err; + fatal_error ("%s: %m", _(errmsg)); + } + else + fatal_error (errmsg); + } + + return pex; +} + + +/* Wait for a process to finish, and exit if a nonzero status is found. + PROG is the program name. PEX is the process we should wait for. */ + +int +collect_wait (const char *prog, struct pex_obj *pex) +{ + int status; + + if (!pex_get_status (pex, 1, &status)) + fatal_error ("can't get program status: %m"); + pex_free (pex); + + if (status) + { + if (WIFSIGNALED (status)) + { + int sig = WTERMSIG (status); + if (WCOREDUMP (status)) + fatal_error ("%s terminated with signal %d [%s], core dumped", + prog, sig, strsignal (sig)); + else + fatal_error ("%s terminated with signal %d [%s]", + prog, sig, strsignal (sig)); + } + + if (WIFEXITED (status)) + fatal_error ("%s returned %d exit status", prog, WEXITSTATUS (status)); + } + + return 0; +} + +void +do_wait (const char *prog, struct pex_obj *pex) +{ + int ret = collect_wait (prog, pex); + if (ret != 0) + { + error ("%s returned %d exit status", prog, ret); + exit (ret); + } + + if (response_file && !debug) + { + unlink (response_file); + response_file = NULL; + } +} + +/* Unlink a temporary LTRANS file unless requested otherwise. */ + +void +maybe_unlink_file (const char *file) +{ + if (!debug) + { + if (unlink_if_ordinary (file) + && errno != ENOENT) + fatal_error ("deleting file %s: %m", file); + } + else + fprintf (stderr, "[Leaving %s]\n", file); +} + + +/* Execute program ARGV[0] with arguments ARGV. Wait for it to finish. */ + +void +fork_execute (char **argv) +{ + struct pex_obj *pex; + char *new_argv[3]; + char *at_args; + FILE *args; + int status; + + response_file = make_temp_file (".args"); + at_args = concat ("@", response_file, NULL); + args = fopen (response_file, "w"); + if (args == NULL) + fatal_error ("failed to open %s", response_file); + + status = writeargv (&argv[1], args); + + if (status) + fatal_error ("could not write to temporary file %s", response_file); + + fclose (args); + + new_argv[0] = argv[0]; + new_argv[1] = at_args; + new_argv[2] = NULL; + + pex = collect_execute (new_argv); + do_wait (new_argv[0], pex); + + free (at_args); +} diff --git a/gcc/collect-utils.h b/gcc/collect-utils.h new file mode 100644 index 0000000..e47ab29 --- /dev/null +++ b/gcc/collect-utils.h @@ -0,0 +1,40 @@ +/* Utility functions used by tools like collect2 and lto-wrapper. + Copyright (C) 2009-2014 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +/* Provided in collect-utils.c. */ +extern void notice (const char *, ...) + __attribute__ ((format (printf, 1, 2))); +extern void fatal_signal (int); + +extern struct pex_obj *collect_execute (char **); +extern int collect_wait (const char *, struct pex_obj *); +extern void do_wait (const char *, struct pex_obj *); +extern void fork_execute (char **); +extern void utils_cleanup (void); + +extern bool debug; +extern bool verbose; + +/* Provided by the tool itself. */ + +/* The name of the tool, printed in error messages. */ +extern const char tool_name[]; +/* Called by utils_cleanup. */ +extern void tool_cleanup (void); +extern void maybe_unlink (const char *); diff --git a/gcc/lto-wrapper.c b/gcc/lto-wrapper.c index f42b14e..45ce321 100644 --- a/gcc/lto-wrapper.c +++ b/gcc/lto-wrapper.c @@ -47,9 +47,7 @@ along with GCC; see the file COPYING3. If not see #include "options.h" #include "simple-object.h" #include "lto-section-names.h" - -int debug; /* true if -save-temps. */ -int verbose; /* true if -v. */ +#include "collect-utils.h" enum lto_mode_d { LTO_MODE_NONE, /* Not doing LTO. */ @@ -62,140 +60,44 @@ static enum lto_mode_d lto_mode = LTO_MODE_NONE; static char *ltrans_output_file; static char *flto_out; -static char *args_name; static unsigned int nr; static char **input_names; static char **output_names; static char *makefile; -static void maybe_unlink_file (const char *); +const char tool_name[] = "lto-wrapper"; - /* Delete tempfiles. */ +/* Delete tempfiles. Called from utils_cleanup. */ -static void -lto_wrapper_cleanup (void) +void +tool_cleanup (void) { - static bool cleanup_done = false; unsigned int i; - if (cleanup_done) - return; - - /* Setting cleanup_done prevents an infinite loop if one of the - calls to maybe_unlink_file fails. */ - cleanup_done = true; - if (ltrans_output_file) - maybe_unlink_file (ltrans_output_file); + maybe_unlink (ltrans_output_file); if (flto_out) - maybe_unlink_file (flto_out); - if (args_name) - maybe_unlink_file (args_name); + maybe_unlink (flto_out); if (makefile) - maybe_unlink_file (makefile); + maybe_unlink (makefile); for (i = 0; i < nr; ++i) { - maybe_unlink_file (input_names[i]); + maybe_unlink (input_names[i]); if (output_names[i]) - maybe_unlink_file (output_names[i]); + maybe_unlink (output_names[i]); } } static void -fatal_signal (int signum) -{ - signal (signum, SIG_DFL); - lto_wrapper_cleanup (); - /* Get the same signal again, this time not handled, - so its normal effect occurs. */ - kill (getpid (), signum); -} - -/* Execute a program, and wait for the reply. ARGV are the arguments. The - last one must be NULL. */ - -static struct pex_obj * -collect_execute (char **argv) -{ - struct pex_obj *pex; - const char *errmsg; - int err; - - if (verbose) - { - char **p_argv; - const char *str; - - for (p_argv = argv; (str = *p_argv) != (char *) 0; p_argv++) - fprintf (stderr, " %s", str); - - fprintf (stderr, "\n"); - } - - fflush (stdout); - fflush (stderr); - - pex = pex_init (0, "lto-wrapper", NULL); - if (pex == NULL) - fatal_error ("pex_init failed: %m"); - - /* Do not use PEX_LAST here, we use our stdout for communicating with - collect2 or the linker-plugin. Any output from the sub-process - will confuse that. */ - errmsg = pex_run (pex, PEX_SEARCH, argv[0], argv, NULL, - NULL, &err); - if (errmsg != NULL) - { - if (err != 0) - { - errno = err; - fatal_error ("%s: %m", _(errmsg)); - } - else - fatal_error (errmsg); - } - - return pex; -} - - -/* Wait for a process to finish, and exit if a nonzero status is found. - PROG is the program name. PEX is the process we should wait for. */ - -static int -collect_wait (const char *prog, struct pex_obj *pex) +lto_wrapper_cleanup (void) { - int status; - - if (!pex_get_status (pex, 1, &status)) - fatal_error ("can't get program status: %m"); - pex_free (pex); - - if (status) - { - if (WIFSIGNALED (status)) - { - int sig = WTERMSIG (status); - if (WCOREDUMP (status)) - fatal_error ("%s terminated with signal %d [%s], core dumped", - prog, sig, strsignal (sig)); - else - fatal_error ("%s terminated with signal %d [%s]", - prog, sig, strsignal (sig)); - } - - if (WIFEXITED (status)) - fatal_error ("%s returned %d exit status", prog, WEXITSTATUS (status)); - } - - return 0; + utils_cleanup (); } - /* Unlink a temporary LTRANS file unless requested otherwise. */ -static void -maybe_unlink_file (const char *file) +void +maybe_unlink (const char *file) { if (! debug) { @@ -207,43 +109,6 @@ maybe_unlink_file (const char *file) fprintf (stderr, "[Leaving LTRANS %s]\n", file); } - -/* Execute program ARGV[0] with arguments ARGV. Wait for it to finish. */ - -static void -fork_execute (char **argv) -{ - struct pex_obj *pex; - char *new_argv[3]; - char *at_args; - FILE *args; - int status; - - args_name = make_temp_file (".args"); - at_args = concat ("@", args_name, NULL); - args = fopen (args_name, "w"); - if (args == NULL) - fatal_error ("failed to open %s", args_name); - - status = writeargv (&argv[1], args); - - if (status) - fatal_error ("could not write to temporary file %s", args_name); - - fclose (args); - - new_argv[0] = argv[0]; - new_argv[1] = at_args; - new_argv[2] = NULL; - - pex = collect_execute (new_argv); - collect_wait (new_argv[0], pex); - - maybe_unlink_file (args_name); - args_name = NULL; - free (at_args); -} - /* Template of LTRANS dumpbase suffix. */ #define DUMPBASE_SUFFIX ".ltrans18446744073709551615" @@ -869,7 +734,7 @@ cont: output_names[nr-1] = output_name; } fclose (stream); - maybe_unlink_file (ltrans_output_file); + maybe_unlink (ltrans_output_file); ltrans_output_file = NULL; if (parallel) @@ -928,7 +793,7 @@ cont: else { fork_execute (CONST_CAST (char **, new_argv)); - maybe_unlink_file (input_name); + maybe_unlink (input_name); } output_names[i] = output_name; @@ -965,10 +830,10 @@ cont: new_argv[i++] = NULL; pex = collect_execute (CONST_CAST (char **, new_argv)); collect_wait (new_argv[0], pex); - maybe_unlink_file (makefile); + maybe_unlink (makefile); makefile = NULL; for (i = 0; i < nr; ++i) - maybe_unlink_file (input_names[i]); + maybe_unlink (input_names[i]); } for (i = 0; i < nr; ++i) {
commit f5757f8ddf9903319d429c468fcd43ed8b314e1b Author: Bernd Schmidt <ber...@codesourcery.com> Date: Fri Jun 6 13:36:04 2014 +0200 Small cleanups before making collect2 use collect-utils. * collect-utils.c (save_temps): New variable. (do_wait): Use it instead of debug. Use fatal_error. * collect-utils.h (save_temps): Declare. * collect2.c (verbose): Rename from vflag. All uses changed. (tool_cleanup): New function, copied from collect_atexit. (collect_atexit, handler): Just call it. * collect2.h (verbose): Declaration renamed from vflag. * lto-wrapper.c (maybe_unlink, run_gcc): Use save_temps instead of debug. diff --git a/gcc/collect-utils.c b/gcc/collect-utils.c index 004569c..e92513c 100644 --- a/gcc/collect-utils.c +++ b/gcc/collect-utils.c @@ -33,6 +33,7 @@ static char *response_file; bool debug; bool verbose; +bool save_temps; /* Delete tempfiles. */ @@ -159,12 +160,9 @@ do_wait (const char *prog, struct pex_obj *pex) { int ret = collect_wait (prog, pex); if (ret != 0) - { - error ("%s returned %d exit status", prog, ret); - exit (ret); - } + fatal_error ("%s returned %d exit status", prog, ret); - if (response_file && !debug) + if (response_file && !save_temps) { unlink (response_file); response_file = NULL; diff --git a/gcc/collect-utils.h b/gcc/collect-utils.h index e47ab29..46c1160 100644 --- a/gcc/collect-utils.h +++ b/gcc/collect-utils.h @@ -30,6 +30,7 @@ extern void utils_cleanup (void); extern bool debug; extern bool verbose; +extern bool save_temps; /* Provided by the tool itself. */ diff --git a/gcc/collect2.c b/gcc/collect2.c index ec8f733..5de1bb3 100644 --- a/gcc/collect2.c +++ b/gcc/collect2.c @@ -175,7 +175,7 @@ struct head int number; }; -bool vflag; /* true if -v or --version */ +bool verbose; /* true if -v or --version */ static int rflag; /* true if -r */ static int strip_flag; /* true if -s */ #ifdef COLLECT_EXPORT_LIST @@ -383,7 +383,7 @@ static void scan_prog_file (const char *, scanpass, scanfilter); /* Delete tempfiles and exit function. */ static void -collect_atexit (void) +tool_cleanup (bool from_signal) { if (c_file != 0 && c_file[0]) maybe_unlink (c_file); @@ -401,20 +401,33 @@ collect_atexit (void) if (ldout != 0 && ldout[0]) { - dump_ld_file (ldout, stdout); + if (!from_signal) + dump_ld_file (ldout, stdout); maybe_unlink (ldout); } if (lderrout != 0 && lderrout[0]) { - dump_ld_file (lderrout, stderr); + if (!from_signal) + dump_ld_file (lderrout, stderr); maybe_unlink (lderrout); } +} - if (response_file) - maybe_unlink (response_file); +static void +collect_atexit (void) +{ + tool_cleanup (false); } +static void +handler (int signo) +{ + tool_cleanup (true); + + signal (signo, SIG_DFL); + raise (signo); +} /* Notify user of a non-error. */ void @@ -438,37 +451,6 @@ notice_translated (const char *cmsgid, ...) va_end (ap); } -static void -handler (int signo) -{ - if (c_file != 0 && c_file[0]) - maybe_unlink (c_file); - - if (o_file != 0 && o_file[0]) - maybe_unlink (o_file); - - if (ldout != 0 && ldout[0]) - maybe_unlink (ldout); - - if (lderrout != 0 && lderrout[0]) - maybe_unlink (lderrout); - -#ifdef COLLECT_EXPORT_LIST - if (export_file != 0 && export_file[0]) - maybe_unlink (export_file); -#endif - - if (lto_o_files) - maybe_unlink_list (lto_o_files); - - if (response_file) - maybe_unlink (response_file); - - signal (signo, SIG_DFL); - raise (signo); -} - - int file_exists (const char *name) { @@ -1056,7 +1038,7 @@ main (int argc, char **argv) aixlazy_flag = 1; #endif } - vflag = debug; + verbose = debug; find_file_set_debug (debug); if (use_plugin) lto_mode = LTO_MODE_NONE; @@ -1451,7 +1433,7 @@ main (int argc, char **argv) case 'v': if (arg[2] == '\0') - vflag = true; + verbose = true; break; case '-': @@ -1483,7 +1465,7 @@ main (int argc, char **argv) else if (strncmp (arg, "--sysroot=", 10) == 0) target_system_root = arg + 10; else if (strcmp (arg, "--version") == 0) - vflag = true; + verbose = true; else if (strcmp (arg, "--help") == 0) helpflag = true; break; @@ -1578,7 +1560,7 @@ main (int argc, char **argv) *c_ptr++ = c_file; *c_ptr = *ld1 = *object = (char *) 0; - if (vflag) + if (verbose) notice ("collect2 version %s\n", version_string); if (helpflag) @@ -1947,7 +1929,7 @@ collect_execute (const char *prog, char **argv, const char *outname, argv = response_argv; } - if (vflag || debug) + if (verbose || debug) { char **p_argv; const char *str; @@ -2509,7 +2491,7 @@ scan_prog_file (const char *prog_name, scanpass which_pass, nm_argv[argc++] = (char *) 0; /* Trace if needed. */ - if (vflag) + if (verbose) { const char **p_argv; const char *str; @@ -2706,7 +2688,7 @@ scan_libraries (const char *prog_name) ldd_argv[argc++] = (char *) 0; /* Trace if needed. */ - if (vflag) + if (verbose) { const char **p_argv; const char *str; diff --git a/gcc/collect2.h b/gcc/collect2.h index bbfd676..344ad86 100644 --- a/gcc/collect2.h +++ b/gcc/collect2.h @@ -36,7 +36,7 @@ extern const char *lderrout; extern const char *c_file_name; extern struct obstack temporary_obstack; extern char *temporary_firstobj; -extern bool vflag, debug; +extern bool verbose, debug; extern bool may_unlink_output_file; extern void notice_translated (const char *, ...) ATTRIBUTE_PRINTF_1; diff --git a/gcc/lto-wrapper.c b/gcc/lto-wrapper.c index 45ce321..49f0895 100644 --- a/gcc/lto-wrapper.c +++ b/gcc/lto-wrapper.c @@ -99,7 +99,7 @@ lto_wrapper_cleanup (void) void maybe_unlink (const char *file) { - if (! debug) + if (!save_temps) { if (unlink_if_ordinary (file) && errno != ENOENT) @@ -540,7 +540,7 @@ run_gcc (unsigned argc, char *argv[]) continue; case OPT_save_temps: - debug = 1; + save_temps = 1; break; case OPT_v: @@ -647,7 +647,7 @@ run_gcc (unsigned argc, char *argv[]) obstack_ptr_grow (&argv_obstack, dumpbase); } - if (linker_output && debug) + if (linker_output && save_temps) { ltrans_output_file = (char *) xmalloc (strlen (linker_output) + sizeof (".ltrans.out") + 1); @@ -785,7 +785,7 @@ cont: /* If we are not preserving the ltrans input files then truncate them as soon as we have processed it. This reduces temporary disk-space usage. */ - if (! debug) + if (! save_temps) fprintf (mstream, "\t@-touch -r %s %s.tem > /dev/null 2>&1 " "&& mv %s.tem %s\n", input_name, input_name, input_name, input_name); diff --git a/gcc/tlink.c b/gcc/tlink.c index bc358b8..addea61 100644 --- a/gcc/tlink.c +++ b/gcc/tlink.c @@ -275,7 +275,7 @@ tlink_init (void) else { tlink_verbose = 1; - if (vflag) + if (verbose) tlink_verbose = 2; if (debug) tlink_verbose = 3;
commit 944ab9755774d5d6e3fcee2dcac8e1eeee07e9a8 Author: Bernd Schmidt <ber...@codesourcery.com> Date: Wed May 21 16:44:03 2014 +0200 Part 2 of the collect-utils library, now also used for collect2. * Makefile.in (COLLECT2_OBJS): Add collect-utils.o. (LTO_WRAPPER_OBJS): New variable. (lto-wrapper$(exeext)): Use it. * collect2.c: Include "collect-utils.h". (verbose, debug): Remove variables. (at_file_supplied): No longer static. (tool_name): New variable. (do_wait, fork_execute, maybe_unlink): Don't declare. (tool_cleanup): No longer static. (notice): Remove function. (maybe_run_lto_and_relink, main, do_dsymutil): Add new arg to fork_execute calls. (collect_wait, do_wait, collect_execute): Remove functions. (maybe_unlink): No longer static. * collect2.h (verbose, debug): Don't declare. (at_file_supplied): Declare. * collect-utils.c (utils_cleanup): New arg from_signal. All callers changed. (collect_execute): Replace with implementation from collect2, plus a new arg use_atfile. All callers changed. (collect_wait): Replace with implementation from collect2. (maybe_unlink_file): Remove function. (fork_execute): Replace with implementation from collect2, plus a new arg use_atfile. All callers changed. (do_wait): Add call to utils_cleanup to the error path. * collect-utils.h (collect_execute, fork_execute, utils_cleanup, tool_cleanup): Adjust declarations. * lto-wrapper.c (tool_cleanup): Add unused bool argument. * tlink.c: Include "collect-utils.h". (tlink_execute): New arg use_atfile. All callers changed. (tlink_init, tlink_execute): Remove declarations. diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 24abad9..c6448e9 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1899,7 +1899,8 @@ gcc-ranlib.c: gcc-ar.c gcc-nm.c: gcc-ar.c cp $^ $@ -COLLECT2_OBJS = collect2.o collect2-aix.o tlink.o vec.o ggc-none.o file-find.o +COLLECT2_OBJS = collect2.o collect2-aix.o tlink.o vec.o ggc-none.o \ + collect-utils.o file-find.o COLLECT2_LIBS = @COLLECT2_LIBS@ collect2$(exeext): $(COLLECT2_OBJS) $(LIBDEPS) # Don't try modifying collect2 (aka ld) in place--it might be linking this. diff --git a/gcc/collect-utils.c b/gcc/collect-utils.c index e92513c..febc519 100644 --- a/gcc/collect-utils.c +++ b/gcc/collect-utils.c @@ -35,24 +35,6 @@ bool debug; bool verbose; bool save_temps; -/* Delete tempfiles. */ - -void -utils_cleanup (void) -{ - static bool cleanup_done = false; - - if (cleanup_done) - return; - - /* Setting cleanup_done prevents an infinite loop if one of the - calls to maybe_unlink fails. */ - cleanup_done = true; - - if (response_file) - maybe_unlink (response_file); - tool_cleanup (); -} /* Notify user of a non-error. */ void @@ -69,62 +51,13 @@ void fatal_signal (int signum) { signal (signum, SIG_DFL); - utils_cleanup (); + utils_cleanup (true); /* Get the same signal again, this time not handled, so its normal effect occurs. */ kill (getpid (), signum); } - -/* Execute a program, and wait for the reply. ARGV are the arguments. The - last one must be NULL. */ - -struct pex_obj * -collect_execute (char **argv) -{ - struct pex_obj *pex; - const char *errmsg; - int err; - - if (verbose) - { - char **p_argv; - const char *str; - - for (p_argv = argv; (str = *p_argv) != (char *) 0; p_argv++) - fprintf (stderr, " %s", str); - - fprintf (stderr, "\n"); - } - - fflush (stdout); - fflush (stderr); - - pex = pex_init (0, tool_name, NULL); - if (pex == NULL) - fatal_error ("pex_init failed: %m"); - - /* Do not use PEX_LAST here, we use our stdout for communicating with - collect2 or the linker-plugin. Any output from the sub-process - will confuse that. */ - errmsg = pex_run (pex, PEX_SEARCH, argv[0], argv, NULL, - NULL, &err); - if (errmsg != NULL) - { - if (err != 0) - { - errno = err; - fatal_error ("%s: %m", _(errmsg)); - } - else - fatal_error (errmsg); - } - - return pex; -} - - -/* Wait for a process to finish, and exit if a nonzero status is found. - PROG is the program name. PEX is the process we should wait for. */ + +/* Wait for a process to finish, and exit if a nonzero status is found. */ int collect_wait (const char *prog, struct pex_obj *pex) @@ -140,18 +73,14 @@ collect_wait (const char *prog, struct pex_obj *pex) if (WIFSIGNALED (status)) { int sig = WTERMSIG (status); - if (WCOREDUMP (status)) - fatal_error ("%s terminated with signal %d [%s], core dumped", - prog, sig, strsignal (sig)); - else - fatal_error ("%s terminated with signal %d [%s]", - prog, sig, strsignal (sig)); + fatal_error ("%s terminated with signal %d [%s]%s", + prog, sig, strsignal (sig), + WCOREDUMP (status) ? ", core dumped" : ""); } if (WIFEXITED (status)) - fatal_error ("%s returned %d exit status", prog, WEXITSTATUS (status)); + return WEXITSTATUS (status); } - return 0; } @@ -169,52 +98,130 @@ do_wait (const char *prog, struct pex_obj *pex) } } -/* Unlink a temporary LTRANS file unless requested otherwise. */ + +/* Execute a program, and wait for the reply. */ -void -maybe_unlink_file (const char *file) +struct pex_obj * +collect_execute (const char *prog, char **argv, const char *outname, + const char *errname, int flags, bool use_atfile) { - if (!debug) + struct pex_obj *pex; + const char *errmsg; + int err; + char *response_arg = NULL; + char *response_argv[3]; + + if (use_atfile && argv[0] != NULL) { - if (unlink_if_ordinary (file) - && errno != ENOENT) - fatal_error ("deleting file %s: %m", file); + /* If using @file arguments, create a temporary file and put the + contents of argv into it. Then change argv to an array corresponding + to a single argument @FILE, where FILE is the temporary filename. */ + + char **current_argv = argv + 1; + char *argv0 = argv[0]; + int status; + FILE *f; + + /* Note: we assume argv contains at least one element; this is + checked above. */ + + response_file = make_temp_file (""); + + f = fopen (response_file, "w"); + + if (f == NULL) + fatal_error ("could not open response file %s", response_file); + + status = writeargv (current_argv, f); + + if (status) + fatal_error ("could not write to response file %s", response_file); + + status = fclose (f); + + if (EOF == status) + fatal_error ("could not close response file %s", response_file); + + response_arg = concat ("@", response_file, NULL); + response_argv[0] = argv0; + response_argv[1] = response_arg; + response_argv[2] = NULL; + + argv = response_argv; } - else - fprintf (stderr, "[Leaving %s]\n", file); -} + if (verbose || debug) + { + char **p_argv; + const char *str; + + if (argv[0]) + fprintf (stderr, "%s", argv[0]); + else + notice ("[cannot find %s]", prog); + + for (p_argv = &argv[1]; (str = *p_argv) != (char *) 0; p_argv++) + fprintf (stderr, " %s", str); + + fprintf (stderr, "\n"); + } + + fflush (stdout); + fflush (stderr); + + /* If we cannot find a program we need, complain error. Do this here + since we might not end up needing something that we could not find. */ + + if (argv[0] == 0) + fatal_error ("cannot find '%s'", prog); + + pex = pex_init (0, "collect2", NULL); + if (pex == NULL) + fatal_error ("pex_init failed: %m"); + + errmsg = pex_run (pex, flags, argv[0], argv, outname, + errname, &err); + if (errmsg != NULL) + { + if (err != 0) + { + errno = err; + fatal_error ("%s: %m", _(errmsg)); + } + else + fatal_error (errmsg); + } -/* Execute program ARGV[0] with arguments ARGV. Wait for it to finish. */ + free (response_arg); + + return pex; +} void -fork_execute (char **argv) +fork_execute (const char *prog, char **argv, bool use_atfile) { struct pex_obj *pex; - char *new_argv[3]; - char *at_args; - FILE *args; - int status; - - response_file = make_temp_file (".args"); - at_args = concat ("@", response_file, NULL); - args = fopen (response_file, "w"); - if (args == NULL) - fatal_error ("failed to open %s", response_file); - status = writeargv (&argv[1], args); + pex = collect_execute (prog, argv, NULL, NULL, + PEX_LAST | PEX_SEARCH, use_atfile); + do_wait (prog, pex); +} - if (status) - fatal_error ("could not write to temporary file %s", response_file); +/* Delete tempfiles. */ - fclose (args); +void +utils_cleanup (bool from_signal) +{ + static bool cleanup_done = false; - new_argv[0] = argv[0]; - new_argv[1] = at_args; - new_argv[2] = NULL; + if (cleanup_done) + return; - pex = collect_execute (new_argv); - do_wait (new_argv[0], pex); + /* Setting cleanup_done prevents an infinite loop if one of the + calls to maybe_unlink fails. */ + cleanup_done = true; - free (at_args); + if (response_file) + maybe_unlink (response_file); + tool_cleanup (from_signal); } diff --git a/gcc/collect-utils.h b/gcc/collect-utils.h index 46c1160..2989c6b 100644 --- a/gcc/collect-utils.h +++ b/gcc/collect-utils.h @@ -22,11 +22,14 @@ extern void notice (const char *, ...) __attribute__ ((format (printf, 1, 2))); extern void fatal_signal (int); -extern struct pex_obj *collect_execute (char **); +extern struct pex_obj *collect_execute (const char *, char **, + const char *, const char *, + int, bool); extern int collect_wait (const char *, struct pex_obj *); extern void do_wait (const char *, struct pex_obj *); -extern void fork_execute (char **); -extern void utils_cleanup (void); +extern void fork_execute (const char *, char **, bool); +extern void utils_cleanup (bool); + extern bool debug; extern bool verbose; @@ -37,5 +40,5 @@ extern bool save_temps; /* The name of the tool, printed in error messages. */ extern const char tool_name[]; /* Called by utils_cleanup. */ -extern void tool_cleanup (void); +extern void tool_cleanup (bool); extern void maybe_unlink (const char *); diff --git a/gcc/collect2.c b/gcc/collect2.c index 5de1bb3..c54e6fb 100644 --- a/gcc/collect2.c +++ b/gcc/collect2.c @@ -43,6 +43,7 @@ along with GCC; see the file COPYING3. If not see #include "collect2.h" #include "collect2-aix.h" +#include "collect-utils.h" #include "diagnostic.h" #include "demangle.h" #include "obstack.h" @@ -175,7 +176,6 @@ struct head int number; }; -bool verbose; /* true if -v or --version */ static int rflag; /* true if -r */ static int strip_flag; /* true if -s */ #ifdef COLLECT_EXPORT_LIST @@ -198,7 +198,6 @@ static enum lto_mode_d lto_mode = LTO_MODE_WHOPR; static enum lto_mode_d lto_mode = LTO_MODE_NONE; #endif -bool debug; /* true if -debug */ bool helpflag; /* true if --help */ static int shared_obj; /* true if -shared */ @@ -234,8 +233,7 @@ static struct head exports; /* list of exported symbols */ #endif static struct head frame_tables; /* list of frame unwind info tables */ -static bool at_file_supplied; /* Whether to use @file arguments */ -static char *response_file; /* Name of any current response file */ +bool at_file_supplied; /* Whether to use @file arguments */ struct obstack temporary_obstack; char * temporary_firstobj; @@ -296,12 +294,11 @@ typedef enum { SYM_AIXD = 7 } symkind; +const char tool_name[] = "collect2"; + static symkind is_ctor_dtor (const char *); static void handler (int); -static void do_wait (const char *, struct pex_obj *); -static void fork_execute (const char *, char **); -static void maybe_unlink (const char *); static void maybe_unlink_list (char **); static void add_to_list (struct head *, const char *); static int extract_init_priority (const char *); @@ -382,7 +379,7 @@ static void scan_prog_file (const char *, scanpass, scanfilter); /* Delete tempfiles and exit function. */ -static void +void tool_cleanup (bool from_signal) { if (c_file != 0 && c_file[0]) @@ -428,18 +425,6 @@ handler (int signo) signal (signo, SIG_DFL); raise (signo); } - -/* Notify user of a non-error. */ -void -notice (const char *cmsgid, ...) -{ - va_list ap; - - va_start (ap, cmsgid); - vfprintf (stderr, _(cmsgid), ap); - va_end (ap); -} - /* Notify user of a non-error, without translating the format string. */ void notice_translated (const char *cmsgid, ...) @@ -737,7 +722,8 @@ maybe_run_lto_and_relink (char **lto_ld_argv, char **object_lst, *lto_c_ptr = NULL; /* Run the LTO back end. */ - pex = collect_execute (prog, lto_c_argv, NULL, NULL, PEX_SEARCH); + pex = collect_execute (prog, lto_c_argv, NULL, NULL, PEX_SEARCH, + at_file_supplied); { int c; FILE *stream; @@ -817,7 +803,7 @@ maybe_run_lto_and_relink (char **lto_ld_argv, char **object_lst, /* Run the linker again, this time replacing the object files optimized by the LTO with the temporary file generated by the LTO. */ - fork_execute ("ld", out_lto_ld_argv); + fork_execute ("ld", out_lto_ld_argv, HAVE_GNU_LD && at_file_supplied); post_ld_pass (true); free (lto_ld_argv); @@ -827,7 +813,7 @@ maybe_run_lto_and_relink (char **lto_ld_argv, char **object_lst, { /* Our caller is relying on us to do the link even though there is no LTO back end work to be done. */ - fork_execute ("ld", lto_ld_argv); + fork_execute ("ld", lto_ld_argv, HAVE_GNU_LD && at_file_supplied); post_ld_pass (false); } else @@ -1713,7 +1699,7 @@ main (int argc, char **argv) strip_argv[0] = strip_file_name; strip_argv[1] = output_file; strip_argv[2] = (char *) 0; - fork_execute ("strip", real_strip_argv); + fork_execute ("strip", real_strip_argv, false); } #ifdef COLLECT_EXPORT_LIST @@ -1799,7 +1785,7 @@ main (int argc, char **argv) /* Assemble the constructor and destructor tables. Link the tables in with the rest of the program. */ - fork_execute ("gcc", c_argv); + fork_execute ("gcc", c_argv, at_file_supplied); #ifdef COLLECT_EXPORT_LIST /* On AIX we must call tlink because of possible templates resolution. */ do_tlink (ld2_argv, object_lst); @@ -1812,7 +1798,7 @@ main (int argc, char **argv) maybe_run_lto_and_relink (ld2_argv, object_lst, object, true); else { - fork_execute ("ld", ld2_argv); + fork_execute ("ld", ld2_argv, HAVE_GNU_LD && at_file_supplied); post_ld_pass (false); } @@ -1832,163 +1818,10 @@ main (int argc, char **argv) } -/* Wait for a process to finish, and exit if a nonzero status is found. */ - -int -collect_wait (const char *prog, struct pex_obj *pex) -{ - int status; - - if (!pex_get_status (pex, 1, &status)) - fatal_error ("can't get program status: %m"); - pex_free (pex); - - if (status) - { - if (WIFSIGNALED (status)) - { - int sig = WTERMSIG (status); - error ("%s terminated with signal %d [%s]%s", - prog, sig, strsignal (sig), - WCOREDUMP (status) ? ", core dumped" : ""); - exit (FATAL_EXIT_CODE); - } - - if (WIFEXITED (status)) - return WEXITSTATUS (status); - } - return 0; -} - -static void -do_wait (const char *prog, struct pex_obj *pex) -{ - int ret = collect_wait (prog, pex); - if (ret != 0) - { - error ("%s returned %d exit status", prog, ret); - exit (ret); - } - - if (response_file) - { - unlink (response_file); - response_file = NULL; - } -} - - -/* Execute a program, and wait for the reply. */ - -struct pex_obj * -collect_execute (const char *prog, char **argv, const char *outname, - const char *errname, int flags) -{ - struct pex_obj *pex; - const char *errmsg; - int err; - char *response_arg = NULL; - char *response_argv[3] ATTRIBUTE_UNUSED; - - if (HAVE_GNU_LD && at_file_supplied && argv[0] != NULL) - { - /* If using @file arguments, create a temporary file and put the - contents of argv into it. Then change argv to an array corresponding - to a single argument @FILE, where FILE is the temporary filename. */ - - char **current_argv = argv + 1; - char *argv0 = argv[0]; - int status; - FILE *f; - - /* Note: we assume argv contains at least one element; this is - checked above. */ - - response_file = make_temp_file (""); - - f = fopen (response_file, "w"); - - if (f == NULL) - fatal_error ("could not open response file %s", response_file); - - status = writeargv (current_argv, f); - - if (status) - fatal_error ("could not write to response file %s", response_file); - - status = fclose (f); - - if (EOF == status) - fatal_error ("could not close response file %s", response_file); - - response_arg = concat ("@", response_file, NULL); - response_argv[0] = argv0; - response_argv[1] = response_arg; - response_argv[2] = NULL; - - argv = response_argv; - } - - if (verbose || debug) - { - char **p_argv; - const char *str; - - if (argv[0]) - fprintf (stderr, "%s", argv[0]); - else - notice ("[cannot find %s]", prog); - - for (p_argv = &argv[1]; (str = *p_argv) != (char *) 0; p_argv++) - fprintf (stderr, " %s", str); - - fprintf (stderr, "\n"); - } - - fflush (stdout); - fflush (stderr); - - /* If we cannot find a program we need, complain error. Do this here - since we might not end up needing something that we could not find. */ - - if (argv[0] == 0) - fatal_error ("cannot find '%s'", prog); - - pex = pex_init (0, "collect2", NULL); - if (pex == NULL) - fatal_error ("pex_init failed: %m"); - - errmsg = pex_run (pex, flags, argv[0], argv, outname, - errname, &err); - if (errmsg != NULL) - { - if (err != 0) - { - errno = err; - fatal_error ("%s: %m", _(errmsg)); - } - else - fatal_error (errmsg); - } - - free (response_arg); - - return pex; -} - -static void -fork_execute (const char *prog, char **argv) -{ - struct pex_obj *pex; - - pex = collect_execute (prog, argv, NULL, NULL, PEX_LAST | PEX_SEARCH); - do_wait (prog, pex); -} - /* Unlink FILE unless we are debugging or this is the output_file and we may not unlink it. */ -static void +void maybe_unlink (const char *file) { if (debug) @@ -3177,7 +3010,8 @@ do_dsymutil (const char *output_file) { argv[1] = output_file; argv[2] = (char *) 0; - pex = collect_execute (dsymutil, real_argv, NULL, NULL, PEX_LAST | PEX_SEARCH); + pex = collect_execute (dsymutil, real_argv, NULL, NULL, + PEX_LAST | PEX_SEARCH, false); do_wait (dsymutil, pex); } diff --git a/gcc/collect2.h b/gcc/collect2.h index 344ad86..0fb7f51 100644 --- a/gcc/collect2.h +++ b/gcc/collect2.h @@ -36,10 +36,10 @@ extern const char *lderrout; extern const char *c_file_name; extern struct obstack temporary_obstack; extern char *temporary_firstobj; -extern bool verbose, debug; extern bool may_unlink_output_file; extern void notice_translated (const char *, ...) ATTRIBUTE_PRINTF_1; extern void notice (const char *, ...) ATTRIBUTE_PRINTF_1; +extern bool at_file_supplied; #endif /* ! GCC_COLLECT2_H */ diff --git a/gcc/lto-wrapper.c b/gcc/lto-wrapper.c index 49f0895..08fd090 100644 --- a/gcc/lto-wrapper.c +++ b/gcc/lto-wrapper.c @@ -70,7 +70,7 @@ const char tool_name[] = "lto-wrapper"; /* Delete tempfiles. Called from utils_cleanup. */ void -tool_cleanup (void) +tool_cleanup (bool) { unsigned int i; @@ -91,7 +91,7 @@ tool_cleanup (void) static void lto_wrapper_cleanup (void) { - utils_cleanup (); + utils_cleanup (false); } /* Unlink a temporary LTRANS file unless requested otherwise. */ @@ -684,7 +684,7 @@ run_gcc (unsigned argc, char *argv[]) new_argv = XOBFINISH (&argv_obstack, const char **); argv_ptr = &new_argv[new_head_argc]; - fork_execute (CONST_CAST (char **, new_argv)); + fork_execute (new_argv[0], CONST_CAST (char **, new_argv), true); if (lto_mode == LTO_MODE_LTO) { @@ -792,7 +792,8 @@ cont: } else { - fork_execute (CONST_CAST (char **, new_argv)); + fork_execute (new_argv[0], CONST_CAST (char **, new_argv), + true); maybe_unlink (input_name); } @@ -828,8 +829,9 @@ cont: } new_argv[i++] = "all"; new_argv[i++] = NULL; - pex = collect_execute (CONST_CAST (char **, new_argv)); - collect_wait (new_argv[0], pex); + pex = collect_execute (new_argv[0], CONST_CAST (char **, new_argv), + NULL, NULL, PEX_SEARCH, false); + do_wait (new_argv[0], pex); maybe_unlink (makefile); makefile = NULL; for (i = 0; i < nr; ++i) diff --git a/gcc/tlink.c b/gcc/tlink.c index addea61..89777ff 100644 --- a/gcc/tlink.c +++ b/gcc/tlink.c @@ -29,6 +29,7 @@ along with GCC; see the file COPYING3. If not see #include "hashtab.h" #include "demangle.h" #include "collect2.h" +#include "collect-utils.h" #include "filenames.h" #include "diagnostic-core.h" #include "vec.h" @@ -104,8 +105,6 @@ static void symbol_push (symbol *); static symbol * symbol_pop (void); static void file_push (file *); static file * file_pop (void); -static void tlink_init (void); -static int tlink_execute (const char *, char **, const char *, const char *); static char * frob_extension (const char *, const char *); static char * obstack_fgets (FILE *, struct obstack *); static char * tfgets (FILE *); @@ -286,11 +285,12 @@ tlink_init (void) static int tlink_execute (const char *prog, char **argv, const char *outname, - const char *errname) + const char *errname, bool use_atfile) { struct pex_obj *pex; - pex = collect_execute (prog, argv, outname, errname, PEX_LAST | PEX_SEARCH); + pex = collect_execute (prog, argv, outname, errname, + PEX_LAST | PEX_SEARCH, use_atfile); return collect_wait (prog, pex); } @@ -545,7 +545,7 @@ recompile_files (void) fprintf (stderr, _("collect: recompiling %s\n"), f->main); if (chdir (f->dir) != 0 - || tlink_execute (c_file_name, argv, NULL, NULL) != 0 + || tlink_execute (c_file_name, argv, NULL, NULL, false) != 0 || chdir (initial_cwd) != 0) return 0; @@ -817,7 +817,8 @@ scan_linker_output (const char *fname) void do_tlink (char **ld_argv, char **object_lst ATTRIBUTE_UNUSED) { - int ret = tlink_execute ("ld", ld_argv, ldout, lderrout); + int ret = tlink_execute ("ld", ld_argv, ldout, lderrout, + HAVE_GNU_LD && at_file_supplied); tlink_init (); @@ -843,7 +844,8 @@ do_tlink (char **ld_argv, char **object_lst ATTRIBUTE_UNUSED) break; if (tlink_verbose) fprintf (stderr, _("collect: relinking\n")); - ret = tlink_execute ("ld", ld_argv, ldout, lderrout); + ret = tlink_execute ("ld", ld_argv, ldout, lderrout, + HAVE_GNU_LD && at_file_supplied); } }