summaryrefslogtreecommitdiff
path: root/gcc/collect-utils.c
diff options
context:
space:
mode:
authorbernds <bernds@138bc75d-0d04-0410-961f-82ee72b054a4>2014-06-26 09:16:11 +0000
committerbernds <bernds@138bc75d-0d04-0410-961f-82ee72b054a4>2014-06-26 09:16:11 +0000
commiteb9ccb017b3efc536a6ccacbc61c9736cac7cecf (patch)
tree7149ab9414fb61c620960a84164a685ca78e72d8 /gcc/collect-utils.c
parent334e3c3ae5777fea241fca82816bd69b6cbcb298 (diff)
downloadgcc-eb9ccb017b3efc536a6ccacbc61c9736cac7cecf.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@212018 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/collect-utils.c')
-rw-r--r--gcc/collect-utils.c222
1 files changed, 222 insertions, 0 deletions
diff --git a/gcc/collect-utils.c b/gcc/collect-utils.c
new file mode 100644
index 00000000000..004569c9957
--- /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);
+}