1 /* Copyright (C) 2006-2015 Free Software Foundation, Inc.
2 Contributed by François-Xavier Coudert
4 This file is part of the GNU Fortran runtime library (libgfortran).
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)
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.
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.
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/>. */
25 #include "libgfortran.h"
34 #include "backtrace-supported.h"
35 #include "backtrace.h"
38 /* Store our own state while backtracing. */
46 /* Does a function name have "_gfortran_" or "_gfortrani_" prefix, possibly
47 with additional underscore(s) at the beginning? Cannot use strncmp()
48 because we might be called from a signal handler. */
51 has_gfortran_prefix (const char *s
)
59 return (s
[0] == 'g' && s
[1] == 'f' && s
[2] == 'o' && s
[3] == 'r'
60 && s
[4] == 't' && s
[5] == 'r' && s
[6] == 'a' && s
[7] == 'n'
61 && (s
[8] == '_' || (s
[8] == 'i' && s
[9] == '_')));
65 error_callback (void *data
, const char *msg
, int errnum
)
67 struct mystate
*state
= (struct mystate
*) data
;
70 state
->try_simple
= 1;
74 estr_write ("\nSomething went wrong while printing the backtrace: ");
80 simple_callback (void *data
, uintptr_t pc
)
82 struct mystate
*state
= (struct mystate
*) data
;
83 st_printf ("#%d 0x%lx\n", state
->frame
, (unsigned long) pc
);
89 full_callback (void *data
, uintptr_t pc
, const char *filename
,
90 int lineno
, const char *function
)
92 struct mystate
*state
= (struct mystate
*) data
;
94 if (has_gfortran_prefix (function
))
97 st_printf ("#%d 0x%lx in %s\n", state
->frame
,
98 (unsigned long) pc
, function
== NULL
? "???" : function
);
99 if (filename
|| lineno
!= 0)
100 st_printf ("\tat %s:%d\n", filename
== NULL
? "???" : filename
, lineno
);
103 if (function
!= NULL
&& strcmp (function
, "main") == 0)
110 /* Display the backtrace. */
113 show_backtrace (int in_signal_handler
)
115 struct backtrace_state
*lbstate
;
116 struct mystate state
= { 0, 0 };
118 lbstate
= backtrace_create_state (NULL
, 1, error_callback
, NULL
);
120 if (!BACKTRACE_SUPPORTED
|| (in_signal_handler
&& BACKTRACE_USES_MALLOC
))
122 /* If symbolic backtrace is not supported on this target, or would
123 require malloc() and we are in a signal handler, go with a
126 backtrace_simple (lbstate
, 0, simple_callback
, error_callback
, &state
);
130 /* libbacktrace uses mmap, which is safe to call from a signal handler
131 (in practice, if not in theory). Thus we can generate a symbolic
132 backtrace, if debug symbols are available. */
134 backtrace_full (lbstate
, 0, full_callback
, error_callback
, &state
);
135 if (state
.try_simple
)
136 backtrace_simple (lbstate
, 0, simple_callback
, error_callback
, &state
);
142 /* Function called by the front-end translating the BACKTRACE intrinsic. */
144 extern void backtrace (void);
145 export_proto (backtrace
);