PR 48931 Make backtrace async-signal-safe, reformat output
[gcc.git] / libgfortran / runtime / backtrace.c
1 /* Copyright (C) 2006, 2007, 2009, 2011 Free Software Foundation, Inc.
2 Contributed by François-Xavier Coudert
3
4 This file is part of the GNU Fortran runtime library (libgfortran).
5
6 Libgfortran is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
9 any later version.
10
11 Libgfortran is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 Under Section 7 of GPL version 3, you are granted additional
17 permissions described in the GCC Runtime Library Exception, version
18 3.1, as published by the Free Software Foundation.
19
20 You should have received a copy of the GNU General Public License and
21 a copy of the GCC Runtime Library Exception along with this program;
22 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 <http://www.gnu.org/licenses/>. */
24
25 #include "libgfortran.h"
26
27 #include <string.h>
28
29 #ifdef HAVE_STDLIB_H
30 #include <stdlib.h>
31 #endif
32
33 #ifdef HAVE_INTTYPES_H
34 #include <inttypes.h>
35 #endif
36
37 #ifdef HAVE_UNISTD_H
38 #include <unistd.h>
39 #endif
40
41 #ifdef HAVE_EXECINFO_H
42 #include <execinfo.h>
43 #endif
44
45 #ifdef HAVE_SYS_WAIT_H
46 #include <sys/wait.h>
47 #endif
48
49 #include <ctype.h>
50
51
52 /* Macros for common sets of capabilities: can we fork and exec, can
53 we use glibc-style backtrace functions, and can we use pipes. */
54 #define CAN_FORK (defined(HAVE_FORK) && defined(HAVE_EXECVP) \
55 && defined(HAVE_WAIT))
56 #define GLIBC_BACKTRACE (defined(HAVE_BACKTRACE) \
57 && defined(HAVE_BACKTRACE_SYMBOLS_FD))
58 #define CAN_PIPE (CAN_FORK && defined(HAVE_PIPE) \
59 && defined(HAVE_DUP2) && defined(HAVE_FDOPEN) \
60 && defined(HAVE_CLOSE))
61
62
63 /* GDB style #NUM index for each stack frame. */
64
65 static void
66 bt_header (int num)
67 {
68 st_printf (" #%d ", num);
69 }
70
71
72 /* fgets()-like function that reads a line from a fd, without
73 needing to malloc() a buffer, and does not use locks, hence should
74 be async-signal-safe. */
75
76 static char *
77 fd_gets (char *s, int size, int fd)
78 {
79 for (int i = 0; i < size; i++)
80 {
81 char c;
82 ssize_t nread = read (fd, &c, 1);
83 if (nread == 1)
84 {
85 s[i] = c;
86 if (c == '\n')
87 {
88 if (i + 1 < size)
89 s[i+1] = '\0';
90 else
91 s[i] = '\0';
92 break;
93 }
94 }
95 else
96 {
97 s[i] = '\0';
98 break;
99 }
100 }
101 return s;
102 }
103
104
105 /* show_backtrace displays the backtrace, currently obtained by means of
106 the glibc backtrace* functions. */
107
108 void
109 show_backtrace (void)
110 {
111 #if GLIBC_BACKTRACE
112
113 #define DEPTH 50
114 #define BUFSIZE 1024
115
116 void *trace[DEPTH];
117 int depth;
118
119 depth = backtrace (trace, DEPTH);
120 if (depth <= 0)
121 return;
122
123 #if CAN_PIPE
124
125 /* We attempt to extract file and line information from addr2line. */
126 do
127 {
128 /* Local variables. */
129 int f[2], pid, bt[2], inp[2];
130 char addr_buf[GFC_XTOA_BUF_SIZE], func[BUFSIZE], file[BUFSIZE];
131 char *p;
132
133 /* Don't output an error message if something goes wrong, we'll simply
134 fall back to the pstack and glibc backtraces. */
135 if (pipe (f) != 0)
136 break;
137 if (pipe (inp) != 0)
138 break;
139 if ((pid = fork ()) == -1)
140 break;
141
142 if (pid == 0)
143 {
144 /* Child process. */
145 #define NUM_FIXEDARGS 7
146 char *arg[NUM_FIXEDARGS];
147
148 close (f[0]);
149
150 close (inp[1]);
151 if (dup2 (inp[0], STDIN_FILENO) == -1)
152 _exit (1);
153 close (inp[0]);
154
155 close (STDERR_FILENO);
156
157 if (dup2 (f[1], STDOUT_FILENO) == -1)
158 _exit (1);
159 close (f[1]);
160
161 arg[0] = (char *) "addr2line";
162 arg[1] = (char *) "-e";
163 arg[2] = full_exe_path ();
164 arg[3] = (char *) "-f";
165 arg[4] = (char *) "-s";
166 arg[5] = (char *) "-C";
167 arg[6] = NULL;
168 execvp (arg[0], arg);
169 _exit (1);
170 #undef NUM_FIXEDARGS
171 }
172
173 /* Father process. */
174 close (f[1]);
175 close (inp[0]);
176 if (pipe (bt) != 0)
177 break;
178 backtrace_symbols_fd (trace, depth, bt[1]);
179 close (bt[1]);
180
181 estr_write ("\nBacktrace for this error:\n");
182 for (int j = 0; j < depth; j++)
183 {
184 const char *addr = gfc_xtoa
185 ((GFC_UINTEGER_LARGEST) (intptr_t) trace[j],
186 addr_buf, sizeof (addr_buf));
187
188 write (inp[1], addr, strlen (addr));
189 write (inp[1], "\n", 1);
190
191 if (! fd_gets (func, sizeof(func), f[0]))
192 goto fallback;
193 if (! fd_gets (file, sizeof(file), f[0]))
194 goto fallback;
195
196 for (p = func; *p != '\n' && *p != '\r'; p++)
197 ;
198 *p = '\0';
199
200 /* If we only have the address, use the glibc backtrace. */
201 if (func[0] == '?' && func[1] == '?' && file[0] == '?'
202 && file[1] == '?')
203 {
204 bt_header (j);
205 while (1)
206 {
207 char bc;
208 ssize_t nread = read (bt[0], &bc, 1);
209 if (nread != 1 || bc == '\n')
210 break;
211 write (STDERR_FILENO, &bc, 1);
212 }
213 estr_write ("\n");
214 continue;
215 }
216 else
217 {
218 /* Forward to the next entry in the backtrace. */
219 while (1)
220 {
221 char bc;
222 ssize_t nread = read (bt[0], &bc, 1);
223 if (nread != 1 || bc == '\n')
224 break;
225 }
226 }
227
228 /* _start is a setup routine that calls main(), and main() is
229 the frontend routine that calls some setup stuff and then
230 calls MAIN__, so at this point we should stop. */
231 if (strcmp (func, "_start") == 0 || strcmp (func, "main") == 0)
232 break;
233
234 bt_header (j);
235 estr_write (full_exe_path ());
236 estr_write ("[0x");
237 estr_write (addr);
238 estr_write ("] in ");
239 estr_write (func);
240
241 if (strncmp (file, "??", 2) == 0)
242 estr_write ("\n");
243 else
244 {
245 estr_write (" at ");
246 estr_write (file);
247 }
248 } /* Loop over each hex address. */
249 close (inp[1]);
250 close (bt[0]);
251 wait (NULL);
252 return;
253
254 fallback:
255 estr_write ("** Something went wrong while running addr2line. **\n"
256 "** Falling back to a simpler backtrace scheme. **\n");
257 }
258 while (0);
259
260 #undef DEPTH
261 #undef BUFSIZE
262
263 #endif /* CAN_PIPE */
264
265 /* Fallback to the glibc backtrace. */
266 estr_write ("\nBacktrace for this error:\n");
267 backtrace_symbols_fd (trace, depth, STDERR_FILENO);
268 return;
269
270 #elif defined(CAN_FORK) && defined(HAVE_GETPPID)
271 /* Try to call pstack. */
272 do
273 {
274 /* Local variables. */
275 int pid;
276
277 /* Don't output an error message if something goes wrong, we'll simply
278 fall back to the pstack and glibc backtraces. */
279 if ((pid = fork ()) == -1)
280 break;
281
282 if (pid == 0)
283 {
284 /* Child process. */
285 #define NUM_ARGS 2
286 char *arg[NUM_ARGS+1];
287 char buf[20];
288
289 estr_write ("\nBacktrace for this error:\n");
290 arg[0] = (char *) "pstack";
291 snprintf (buf, sizeof(buf), "%d", (int) getppid ());
292 arg[1] = buf;
293 arg[2] = NULL;
294 execvp (arg[0], arg);
295 #undef NUM_ARGS
296
297 /* pstack didn't work. */
298 estr_write (" unable to produce a backtrace, sorry!\n");
299 _exit (1);
300 }
301
302 /* Father process. */
303 wait (NULL);
304 return;
305 }
306 while(0);
307 #else
308 estr_write ("\nBacktrace not yet available on this platform, sorry!\n");
309 #endif
310 }