Small cleanups before making collect2 use collect-utils.
[gcc.git] / gcc / collect-utils.c
1 /* Utility functions used by tools like collect2 and lto-wrapper.
2 Copyright (C) 2009-2014 Free Software Foundation, Inc.
3
4 This file is part of GCC.
5
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
9 version.
10
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
19
20 #include "config.h"
21 #include "system.h"
22 #include "coretypes.h"
23 #include "intl.h"
24 #include "diagnostic.h"
25 #include "obstack.h"
26 #include "opts.h"
27 #include "options.h"
28 #include "simple-object.h"
29 #include "lto-section-names.h"
30 #include "collect-utils.h"
31
32 static char *response_file;
33
34 bool debug;
35 bool verbose;
36 bool save_temps;
37
38 /* Delete tempfiles. */
39
40 void
41 utils_cleanup (void)
42 {
43 static bool cleanup_done = false;
44
45 if (cleanup_done)
46 return;
47
48 /* Setting cleanup_done prevents an infinite loop if one of the
49 calls to maybe_unlink fails. */
50 cleanup_done = true;
51
52 if (response_file)
53 maybe_unlink (response_file);
54 tool_cleanup ();
55 }
56
57 /* Notify user of a non-error. */
58 void
59 notice (const char *cmsgid, ...)
60 {
61 va_list ap;
62
63 va_start (ap, cmsgid);
64 vfprintf (stderr, _(cmsgid), ap);
65 va_end (ap);
66 }
67
68 void
69 fatal_signal (int signum)
70 {
71 signal (signum, SIG_DFL);
72 utils_cleanup ();
73 /* Get the same signal again, this time not handled,
74 so its normal effect occurs. */
75 kill (getpid (), signum);
76 }
77
78 /* Execute a program, and wait for the reply. ARGV are the arguments. The
79 last one must be NULL. */
80
81 struct pex_obj *
82 collect_execute (char **argv)
83 {
84 struct pex_obj *pex;
85 const char *errmsg;
86 int err;
87
88 if (verbose)
89 {
90 char **p_argv;
91 const char *str;
92
93 for (p_argv = argv; (str = *p_argv) != (char *) 0; p_argv++)
94 fprintf (stderr, " %s", str);
95
96 fprintf (stderr, "\n");
97 }
98
99 fflush (stdout);
100 fflush (stderr);
101
102 pex = pex_init (0, tool_name, NULL);
103 if (pex == NULL)
104 fatal_error ("pex_init failed: %m");
105
106 /* Do not use PEX_LAST here, we use our stdout for communicating with
107 collect2 or the linker-plugin. Any output from the sub-process
108 will confuse that. */
109 errmsg = pex_run (pex, PEX_SEARCH, argv[0], argv, NULL,
110 NULL, &err);
111 if (errmsg != NULL)
112 {
113 if (err != 0)
114 {
115 errno = err;
116 fatal_error ("%s: %m", _(errmsg));
117 }
118 else
119 fatal_error (errmsg);
120 }
121
122 return pex;
123 }
124
125
126 /* Wait for a process to finish, and exit if a nonzero status is found.
127 PROG is the program name. PEX is the process we should wait for. */
128
129 int
130 collect_wait (const char *prog, struct pex_obj *pex)
131 {
132 int status;
133
134 if (!pex_get_status (pex, 1, &status))
135 fatal_error ("can't get program status: %m");
136 pex_free (pex);
137
138 if (status)
139 {
140 if (WIFSIGNALED (status))
141 {
142 int sig = WTERMSIG (status);
143 if (WCOREDUMP (status))
144 fatal_error ("%s terminated with signal %d [%s], core dumped",
145 prog, sig, strsignal (sig));
146 else
147 fatal_error ("%s terminated with signal %d [%s]",
148 prog, sig, strsignal (sig));
149 }
150
151 if (WIFEXITED (status))
152 fatal_error ("%s returned %d exit status", prog, WEXITSTATUS (status));
153 }
154
155 return 0;
156 }
157
158 void
159 do_wait (const char *prog, struct pex_obj *pex)
160 {
161 int ret = collect_wait (prog, pex);
162 if (ret != 0)
163 fatal_error ("%s returned %d exit status", prog, ret);
164
165 if (response_file && !save_temps)
166 {
167 unlink (response_file);
168 response_file = NULL;
169 }
170 }
171
172 /* Unlink a temporary LTRANS file unless requested otherwise. */
173
174 void
175 maybe_unlink_file (const char *file)
176 {
177 if (!debug)
178 {
179 if (unlink_if_ordinary (file)
180 && errno != ENOENT)
181 fatal_error ("deleting file %s: %m", file);
182 }
183 else
184 fprintf (stderr, "[Leaving %s]\n", file);
185 }
186
187
188 /* Execute program ARGV[0] with arguments ARGV. Wait for it to finish. */
189
190 void
191 fork_execute (char **argv)
192 {
193 struct pex_obj *pex;
194 char *new_argv[3];
195 char *at_args;
196 FILE *args;
197 int status;
198
199 response_file = make_temp_file (".args");
200 at_args = concat ("@", response_file, NULL);
201 args = fopen (response_file, "w");
202 if (args == NULL)
203 fatal_error ("failed to open %s", response_file);
204
205 status = writeargv (&argv[1], args);
206
207 if (status)
208 fatal_error ("could not write to temporary file %s", response_file);
209
210 fclose (args);
211
212 new_argv[0] = argv[0];
213 new_argv[1] = at_args;
214 new_argv[2] = NULL;
215
216 pex = collect_execute (new_argv);
217 do_wait (new_argv[0], pex);
218
219 free (at_args);
220 }