Hi,
the attached patch changes the backtracing functionality, which is
used to print a stack trace before aborting when something goes
belly-up, to use the stack unwinding functionality provided by libgcc
instead of using the glibc backtrace_symbols and backtrace_symbols_fd
functions, or the pstack utility which is available on some systems
(Solaris?). There are some nice benefits of this:
- It should work on all targets, not only those which use glibc or pstack.
- It gets the correct line numbers, whereas the backtrace_symbols_fd
output was usually (but not always) offset by one. This is probably
related to the use of _Unwind_GetIPInfo and in some cases decrementing
the IP.
- Based on some googling, it's a bit unclear whether backtrace()
and/or backtrace_symbols_fd() actually are async-signal-safe due to
usage of dlsym/dladdr and such.
It still uses addr2line if available to print out function and file
names and line numbers. If addr2line is not found on the path during
program startup, it resorts to printing out the addresses only.
Regtested on x86_64-unknown-linux-gnu, Ok for trunk?
2011-11-01 Janne Blomqvist j...@gcc.gnu.org
PR fortran/46686
* configure.ac: Don't check execinfo.h, backtrace,
backtrace_symbols_fd. Check execve instead of execvp. Call
GCC_CHECK_UNWIND_GETIPINFO.
* runtime/backtrace.c: Don't include unused headers, include
limits.h and unwind.h.
(CAN_FORK): Check execve instead of execvp.
(GLIBC_BACKTRACE): Remove.
(bt_header): Conform to gdb backtrace format.
(struct bt_state): New struct.
(trace_function): New function.
(show_backtrace): Use _Unwind_Backtrace from libgcc instead of
glibc backtrace functions.
--
Janne Blomqvist
diff --git a/libgfortran/configure.ac b/libgfortran/configure.ac
index 74cfe44..32431c0 100644
--- a/libgfortran/configure.ac
+++ b/libgfortran/configure.ac
@@ -249,7 +249,7 @@ AC_HEADER_TIME
AC_HAVE_HEADERS(stdio.h stdlib.h string.h unistd.h signal.h stdarg.h)
AC_CHECK_HEADERS(time.h sys/time.h sys/times.h sys/resource.h)
AC_CHECK_HEADERS(sys/types.h sys/stat.h sys/wait.h floatingpoint.h ieeefp.h)
-AC_CHECK_HEADERS(fenv.h fptrap.h float.h execinfo.h pwd.h)
+AC_CHECK_HEADERS(fenv.h fptrap.h float.h pwd.h)
AC_CHECK_HEADER([complex.h],[AC_DEFINE([HAVE_COMPLEX_H], [1], [complex.h exists])])
GCC_HEADER_STDINT(gstdint.h)
@@ -261,14 +261,11 @@ AC_CHECK_MEMBERS([struct stat.st_rdev])
AC_CHECK_FUNCS(getrusage times mkstemp strtof strtold snprintf ftruncate chsize)
AC_CHECK_FUNCS(chdir strerror getlogin gethostname kill link symlink perror)
AC_CHECK_FUNCS(sleep time ttyname signal alarm clock access fork execl)
-AC_CHECK_FUNCS(wait setmode execvp pipe dup2 close fdopen strcasestr getrlimit)
+AC_CHECK_FUNCS(wait setmode execve pipe dup2 close fdopen strcasestr getrlimit)
AC_CHECK_FUNCS(gettimeofday stat fstat lstat getpwuid vsnprintf dup getcwd)
AC_CHECK_FUNCS(localtime_r gmtime_r strerror_r getpwuid_r ttyname_r)
AC_CHECK_FUNCS(clock_gettime strftime readlink)
-# Check for glibc backtrace functions
-AC_CHECK_FUNCS(backtrace backtrace_symbols_fd)
-
# Check libc for getgid, getpid, getuid
AC_CHECK_LIB([c],[getgid],[AC_DEFINE([HAVE_GETGID],[1],[libc includes getgid])])
AC_CHECK_LIB([c],[getpid],[AC_DEFINE([HAVE_GETPID],[1],[libc includes getpid])])
@@ -562,6 +559,9 @@ LIBGFOR_CHECK_UNLINK_OPEN_FILE
# Check whether line terminator is LF or CRLF
LIBGFOR_CHECK_CRLF
+# Check whether we have _Unwind_GetIPInfo for backtrace
+GCC_CHECK_UNWIND_GETIPINFO
+
AC_CACHE_SAVE
if test ${multilib} = yes; then
diff --git a/libgfortran/runtime/backtrace.c b/libgfortran/runtime/backtrace.c
index 7d6479f..70aae91 100644
--- a/libgfortran/runtime/backtrace.c
+++ b/libgfortran/runtime/backtrace.c
@@ -26,46 +26,38 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include string.h
-#ifdef HAVE_STDLIB_H
-#include stdlib.h
-#endif
-
-#ifdef HAVE_INTTYPES_H
-#include inttypes.h
-#endif
-
#ifdef HAVE_UNISTD_H
#include unistd.h
#endif
-#ifdef HAVE_EXECINFO_H
-#include execinfo.h
-#endif
-
#ifdef HAVE_SYS_WAIT_H
#include sys/wait.h
#endif
-#include ctype.h
+#include limits.h
+
+#include unwind.h
/* Macros for common sets of capabilities: can we fork and exec, can
we use glibc-style backtrace functions, and can we use pipes. */
-#define CAN_FORK (defined(HAVE_FORK) defined(HAVE_EXECVP) \
+#define CAN_FORK (defined(HAVE_FORK) defined(HAVE_EXECVE) \
defined(HAVE_WAIT))
-#define GLIBC_BACKTRACE (defined(HAVE_BACKTRACE) \
- defined(HAVE_BACKTRACE_SYMBOLS_FD))
#define CAN_PIPE (CAN_FORK defined(HAVE_PIPE) \
defined(HAVE_DUP2) defined(HAVE_FDOPEN) \
defined(HAVE_CLOSE))
+#ifndef PATH_MAX
+#define PATH_MAX 4096
+#endif
+
/* GDB style #NUM index for each stack frame. */
static void
bt_header (int num)
{
- st_printf ( #%d , num);
+ st_printf (#%d , num);
}
@@ -106,24 +98,105 @@