re PR libfortran/54572 (Use libbacktrace library)
authorFrancois-Xavier Coudert <fxcoudert@gcc.gnu.org>
Sun, 23 Aug 2015 21:50:30 +0000 (21:50 +0000)
committerFrançois-Xavier Coudert <fxcoudert@gcc.gnu.org>
Sun, 23 Aug 2015 21:50:30 +0000 (21:50 +0000)
PR libfortran/54572

* Makefile.def: Make libgfortran depend on libbacktrace.
* Makefile.in: Regenerate.

* config-lang.in: Add libbacktrace to target_libs.

* Makefile.am (libgfortran_la_LDFLAGS): Link in libbacktrace.
(AM_CPPFLAGS): Add libbacktrace directories to include paths.
* Makefile.in: Regenerate.
* aclocal.m4: Regenerate.
* config.h.in: Regenerate.
* configure: Regenerate.
* configure.ac: Remove checks for strtok_r, wait, execve, pipe,
and dup2. Remove call to GCC_CHECK_UNWIND_GETIPINFO.
* libgfortran.h (full_exe_path, find_addr2line, backtrace): Remove
prototypes.
(show_backtrace): Add prototype.
* runtime/backtrace.c: Rework file entirely.
* runtime/compile_options.c (backtrace_handler): Rename backtrace
to show_backtrace.
(maybe_find_addr2line): Remove function.
(set_options): Remove call to maybe_find_addr2line.
* runtime/error.c (sys_abort): Rename backtrace to show_backtrace.
* runtime/main.c (store_exe_path): Empty function body.
(full_exe_path, gfstrtok_r, find_addr2line): Remove functions.
(cleanup): Don't free removed variables.
* runtime/minimal.c (full_exe_path): Remove function.
(set_args): Don't set exe_path.

* gfortran.dg/backtrace_1.f90: New test.

From-SVN: r227106

20 files changed:
ChangeLog
Makefile.def
Makefile.in
gcc/fortran/ChangeLog
gcc/fortran/config-lang.in
gcc/testsuite/ChangeLog
gcc/testsuite/gfortran.dg/backtrace_1.f90 [new file with mode: 0644]
libgfortran/ChangeLog
libgfortran/Makefile.am
libgfortran/Makefile.in
libgfortran/aclocal.m4
libgfortran/config.h.in
libgfortran/configure
libgfortran/configure.ac
libgfortran/libgfortran.h
libgfortran/runtime/backtrace.c
libgfortran/runtime/compile_options.c
libgfortran/runtime/error.c
libgfortran/runtime/main.c
libgfortran/runtime/minimal.c

index 913b9caaaa50b99637e9856a2f79ab430ac01a59..0c7ce18d080e559f09b1d1287c283ce19d1f7a01 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2015-08-23  Francois-Xavier Coudert  <fxcoudert@gcc.gnu.org>
+
+       PR libfortran/54572
+       * Makefile.def: Make libgfortran depend on libbacktrace.
+       * Makefile.in: Regenerate.
+
 2015-08-20  Simon Dardis  <simon.dardis@imgtec.com>
 
        * MAINTAINERS (Write After Approval): Add myself.
index 01445e4ff6a516da6f5b23c9a265fea7580cbe93..8b4dad99160e187dea10abef5ac07ea7342a680b 100644 (file)
@@ -597,6 +597,7 @@ dependencies = { module=all-target-winsup; on=all-target-libtermcap; };
 dependencies = { module=configure-target-newlib; on=all-binutils; };
 dependencies = { module=configure-target-newlib; on=all-ld; };
 dependencies = { module=configure-target-libgfortran; on=all-target-libquadmath; };
+dependencies = { module=configure-target-libgfortran; on=all-target-libbacktrace; };
 
 languages = { language=c;      gcc-check-target=check-gcc; };
 languages = { language=c++;    gcc-check-target=check-c++;
index 13f3740e9f66656ef7f68064500154d1fb612a21..bc2bae6d7fa7fe98951b93e78207a16abd718c6f 100644 (file)
@@ -50921,6 +50921,7 @@ all-target-winsup: maybe-all-target-libtermcap
 configure-target-newlib: maybe-all-binutils
 configure-target-newlib: maybe-all-ld
 configure-target-libgfortran: maybe-all-target-libquadmath
+configure-target-libgfortran: maybe-all-target-libbacktrace
 
 
 # Dependencies for target modules on other target modules are
index 9cbaf6c6c0b8dacb051144436e7ae7d1114b6124..d345368b70f6739129a0176e4a5e28bf17cf611f 100644 (file)
@@ -1,3 +1,8 @@
+2015-08-23  Francois-Xavier Coudert  <fxcoudert@gcc.gnu.org>
+
+       PR libfortran/54572
+       * config-lang.in: Add libbacktrace to target_libs.
+
 2015-08-18  Trevor Saunders  <tbsaunde@tbsaunde.org>
 
        * dependency.c, dependency.h, gfortran.h, io.c, module.c,
index de8a499646a0c3ab73746418cb517bdc89a492a4..a6c6b92e25286ff03854e29b831c282536e8c460 100644 (file)
@@ -27,7 +27,7 @@ language="fortran"
 
 compilers="f951\$(exeext)"
 
-target_libs=target-libgfortran
+target_libs="target-libgfortran target-libbacktrace"
 
 gtfiles="\$(srcdir)/fortran/f95-lang.c \$(srcdir)/fortran/trans-decl.c \$(srcdir)/fortran/trans-intrinsic.c \$(srcdir)/fortran/trans-io.c \$(srcdir)/fortran/trans-stmt.c \$(srcdir)/fortran/trans-types.c \$(srcdir)/fortran/trans-types.h \$(srcdir)/fortran/trans.h \$(srcdir)/fortran/trans-const.h"
 
index 35b7da236d5621293042ff00f31eaeb4a32b193d..6235844f53482e4ec06bed412de549a030784ecd 100644 (file)
@@ -1,3 +1,8 @@
+2015-08-23  Francois-Xavier Coudert  <fxcoudert@gcc.gnu.org>
+
+       PR libfortran/54572
+       * gfortran.dg/backtrace_1.f90: New test.
+
 2015-08-23  Francois-Xavier Coudert  <fxcoudert@gcc.gnu.org>
 
        PR libfortran/62296
diff --git a/gcc/testsuite/gfortran.dg/backtrace_1.f90 b/gcc/testsuite/gfortran.dg/backtrace_1.f90
new file mode 100644 (file)
index 0000000..fdde832
--- /dev/null
@@ -0,0 +1,10 @@
+! { dg-do run }
+! 
+! Check that BACKTRACE is available on all targets. We cannot actually
+! check its output, but we should at least be able to call it, then exit
+! normally.
+!
+program test
+  call backtrace
+  stop
+end program test
index 9ffaa035b6064cd251ec43e94a17e5a8b019bf51..b74b71d3c2fde1a8e3e962d64d993657b929d9fc 100644 (file)
@@ -1,3 +1,29 @@
+2015-08-23  Francois-Xavier Coudert  <fxcoudert@gcc.gnu.org>
+
+       PR libfortran/54572
+       * Makefile.am (libgfortran_la_LDFLAGS): Link in libbacktrace.
+       (AM_CPPFLAGS): Add libbacktrace directories to include paths.
+       * Makefile.in: Regenerate.
+       * aclocal.m4: Regenerate.
+       * config.h.in: Regenerate.
+       * configure: Regenerate.
+       * configure.ac: Remove checks for strtok_r, wait, execve, pipe,
+       and dup2. Remove call to GCC_CHECK_UNWIND_GETIPINFO.
+       * libgfortran.h (full_exe_path, find_addr2line, backtrace): Remove
+       prototypes.
+       (show_backtrace): Add prototype.
+       * runtime/backtrace.c: Rework file entirely.
+       * runtime/compile_options.c (backtrace_handler): Rename backtrace
+       to show_backtrace.
+       (maybe_find_addr2line): Remove function.
+       (set_options): Remove call to maybe_find_addr2line.
+       * runtime/error.c (sys_abort): Rename backtrace to show_backtrace.
+       * runtime/main.c (store_exe_path): Empty function body.
+       (full_exe_path, gfstrtok_r, find_addr2line): Remove functions.
+       (cleanup): Don't free removed variables.
+       * runtime/minimal.c (full_exe_path): Remove function.
+       (set_args): Don't set exe_path.
+
 2015-08-23  Francois-Xavier Coudert  <fxcoudert@gcc.gnu.org>
 
        PR libfortran/62296
index 0e816acd2034fb9b017cbc6add3da212bc3fce74..e4764337310fb583f3b15b1cedccd7d6756ff693 100644 (file)
@@ -37,7 +37,8 @@ toolexeclib_LTLIBRARIES = libgfortran.la
 toolexeclib_DATA = libgfortran.spec
 libgfortran_la_LINK = $(LINK) $(libgfortran_la_LDFLAGS)
 libgfortran_la_LDFLAGS = -version-info `grep -v '^\#' $(srcdir)/libtool-version` \
-       $(LTLDFLAGS) $(LIBQUADLIB) -lm $(extra_ldflags_libgfortran) \
+       $(LTLDFLAGS) $(LIBQUADLIB) ../libbacktrace/libbacktrace.la \
+       -lm $(extra_ldflags_libgfortran) \
        $(version_arg) -Wc,-shared-libgcc
 libgfortran_la_DEPENDENCIES = $(version_dep) libgfortran.spec $(LIBQUADLIB_DEP)
 
@@ -59,7 +60,10 @@ AM_CPPFLAGS = -iquote$(srcdir)/io -I$(srcdir)/$(MULTISRCTOP)../gcc \
              -I$(srcdir)/$(MULTISRCTOP)../gcc/config $(LIBQUADINCLUDE) \
              -I$(MULTIBUILDTOP)../../$(host_subdir)/gcc \
              -I$(srcdir)/$(MULTISRCTOP)../libgcc \
-             -I$(MULTIBUILDTOP)../libgcc
+             -I$(MULTIBUILDTOP)../libgcc \
+             -I$(srcdir)/$(MULTISRCTOP)../libbacktrace \
+             -I$(MULTIBUILDTOP)../libbacktrace \
+             -I../libbacktrace
 
 # Fortran rules for complex multiplication and division
 AM_CFLAGS += -fcx-fortran-rules
index ab71b3874d342875f420aeeb1e458d276c5bc59b..f0ddb38f5aba3431f89fe932d8d89116a09f07c3 100644 (file)
@@ -132,7 +132,6 @@ am__aclocal_m4_deps = $(top_srcdir)/../config/depstand.m4 \
        $(top_srcdir)/../config/multi.m4 \
        $(top_srcdir)/../config/override.m4 \
        $(top_srcdir)/../config/stdint.m4 \
-       $(top_srcdir)/../config/unwind_ipinfo.m4 \
        $(top_srcdir)/../ltoptions.m4 $(top_srcdir)/../ltsugar.m4 \
        $(top_srcdir)/../ltversion.m4 $(top_srcdir)/../lt~obsolete.m4 \
        $(top_srcdir)/acinclude.m4 $(top_srcdir)/../config/acx.m4 \
@@ -598,7 +597,8 @@ toolexeclib_LTLIBRARIES = libgfortran.la
 toolexeclib_DATA = libgfortran.spec
 libgfortran_la_LINK = $(LINK) $(libgfortran_la_LDFLAGS)
 libgfortran_la_LDFLAGS = -version-info `grep -v '^\#' $(srcdir)/libtool-version` \
-       $(LTLDFLAGS) $(LIBQUADLIB) -lm $(extra_ldflags_libgfortran) \
+       $(LTLDFLAGS) $(LIBQUADLIB) ../libbacktrace/libbacktrace.la \
+       -lm $(extra_ldflags_libgfortran) \
        $(version_arg) -Wc,-shared-libgcc
 
 libgfortran_la_DEPENDENCIES = $(version_dep) libgfortran.spec $(LIBQUADLIB_DEP)
@@ -614,7 +614,10 @@ AM_CPPFLAGS = -iquote$(srcdir)/io -I$(srcdir)/$(MULTISRCTOP)../gcc \
              -I$(srcdir)/$(MULTISRCTOP)../gcc/config $(LIBQUADINCLUDE) \
              -I$(MULTIBUILDTOP)../../$(host_subdir)/gcc \
              -I$(srcdir)/$(MULTISRCTOP)../libgcc \
-             -I$(MULTIBUILDTOP)../libgcc
+             -I$(MULTIBUILDTOP)../libgcc \
+             -I$(srcdir)/$(MULTISRCTOP)../libbacktrace \
+             -I$(MULTIBUILDTOP)../libbacktrace \
+             -I../libbacktrace
 
 gfor_io_src = io/size_from_kind.c $(am__append_2)
 gfor_io_headers = \
index 0ec2c8fe438a06a6994ed5b8e1d8b91d80f89de9..403feabae9d5887eaeb7e21b31c6226d33d9e92a 100644 (file)
@@ -1029,7 +1029,6 @@ m4_include([../config/lthostflags.m4])
 m4_include([../config/multi.m4])
 m4_include([../config/override.m4])
 m4_include([../config/stdint.m4])
-m4_include([../config/unwind_ipinfo.m4])
 m4_include([../ltoptions.m4])
 m4_include([../ltsugar.m4])
 m4_include([../ltversion.m4])
index 833d8b42aad5aa8855ff07461b1ad824d506db79..5dfa7c67a25756a2314c5d2c10f25c5a53763744 100644 (file)
 /* Define to 1 if you have the `dup' function. */
 #undef HAVE_DUP
 
-/* Define to 1 if you have the `dup2' function. */
-#undef HAVE_DUP2
-
 /* Define to 1 if you have the `erf' function. */
 #undef HAVE_ERF
 
 /* Define to 1 if you have the `execl' function. */
 #undef HAVE_EXECL
 
-/* Define to 1 if you have the `execve' function. */
-#undef HAVE_EXECVE
-
 /* Define to 1 if you have the `exp' function. */
 #undef HAVE_EXP
 
 /* Define to 1 if you have the `gethostname' function. */
 #undef HAVE_GETHOSTNAME
 
-/* Define if _Unwind_GetIPInfo is available. */
-#undef HAVE_GETIPINFO
-
 /* Define to 1 if you have the `getlogin' function. */
 #undef HAVE_GETLOGIN
 
 /* Define to 1 if you have the `nextafterl' function. */
 #undef HAVE_NEXTAFTERL
 
-/* Define to 1 if you have the `pipe' function. */
-#undef HAVE_PIPE
-
 /* Define to 1 if we have POSIX getpwuid_r which takes 5 arguments. */
 #undef HAVE_POSIX_GETPWUID_R
 
 /* Define to 1 if you have the `strtof' function. */
 #undef HAVE_STRTOF
 
-/* Define to 1 if you have the `strtok_r' function. */
-#undef HAVE_STRTOK_R
-
 /* Define to 1 if you have the `strtold' function. */
 #undef HAVE_STRTOLD
 
 /* Define to 1 if you have the `vsnprintf' function. */
 #undef HAVE_VSNPRINTF
 
-/* Define to 1 if you have the `wait' function. */
-#undef HAVE_WAIT
-
 /* Define if target has a reliable stat. */
 #undef HAVE_WORKING_STAT
 
index 07542e1387d99f9756aa24d03de1a7709670b745..d7dad11a161444c08182f20eab1395badeb46d8a 100755 (executable)
@@ -776,7 +776,6 @@ with_gnu_ld
 enable_libtool_lock
 enable_largefile
 enable_libquadmath_support
-with_system_libunwind
 '
       ac_precious_vars='build_alias
 host_alias
@@ -1435,7 +1434,6 @@ Optional Packages:
   --with-pic              try to use only PIC/non-PIC objects [default=use
                           both]
   --with-gnu-ld           assume the C compiler uses GNU ld [default=no]
-  --with-system-libunwind use installed libunwind
 
 Some influential environment variables:
   CC          C compiler command
@@ -2572,11 +2570,7 @@ as_fn_append ac_func_list " alarm"
 as_fn_append ac_func_list " access"
 as_fn_append ac_func_list " fork"
 as_fn_append ac_func_list " execl"
-as_fn_append ac_func_list " wait"
 as_fn_append ac_func_list " setmode"
-as_fn_append ac_func_list " execve"
-as_fn_append ac_func_list " pipe"
-as_fn_append ac_func_list " dup2"
 as_fn_append ac_func_list " close"
 as_fn_append ac_func_list " fcntl"
 as_fn_append ac_func_list " strcasestr"
@@ -2607,7 +2601,6 @@ as_fn_append ac_func_list " __secure_getenv"
 as_fn_append ac_func_list " mkostemp"
 as_fn_append ac_func_list " strnlen"
 as_fn_append ac_func_list " strndup"
-as_fn_append ac_func_list " strtok_r"
 as_fn_append ac_func_list " newlocale"
 as_fn_append ac_func_list " freelocale"
 as_fn_append ac_func_list " uselocale"
@@ -12376,7 +12369,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 12379 "configure"
+#line 12372 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -12482,7 +12475,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 12485 "configure"
+#line 12478 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -16514,9 +16507,6 @@ $as_echo "#define HAVE_STRNLEN 1" >>confdefs.h
 $as_echo "#define HAVE_STRNDUP 1" >>confdefs.h
 
 
-$as_echo "#define HAVE_STRTOK_R 1" >>confdefs.h
-
-
    # At some point, we should differentiate between architectures
    # like x86, which have long double versions, and alpha/powerpc/etc.,
    # which don't. For the time being, punt.
@@ -16642,16 +16632,6 @@ done
 
 
 
-
-
-
-
-
-
-
-
-
-
 
 
 
@@ -26584,44 +26564,6 @@ $as_echo "#define HAVE_CRLF 1" >>confdefs.h
 
 fi
 
-# Check whether we have _Unwind_GetIPInfo for backtrace
-
-
-# Check whether --with-system-libunwind was given.
-if test "${with_system_libunwind+set}" = set; then :
-  withval=$with_system_libunwind;
-fi
-
-  # If system-libunwind was not specifically set, pick a default setting.
-  if test x$with_system_libunwind = x; then
-    case ${target} in
-      ia64-*-hpux*) with_system_libunwind=yes ;;
-      *) with_system_libunwind=no ;;
-    esac
-  fi
-  # Based on system-libunwind and target, do we have ipinfo?
-  if  test x$with_system_libunwind = xyes; then
-    case ${target} in
-      ia64-*-*) have_unwind_getipinfo=no ;;
-      *) have_unwind_getipinfo=yes ;;
-    esac
-  else
-    # Darwin before version 9 does not have _Unwind_GetIPInfo.
-
-    case ${target} in
-      *-*-darwin[3-8]|*-*-darwin[3-8].*) have_unwind_getipinfo=no ;;
-      *) have_unwind_getipinfo=yes ;;
-    esac
-
-  fi
-
-  if test x$have_unwind_getipinfo = xyes; then
-
-$as_echo "#define HAVE_GETIPINFO 1" >>confdefs.h
-
-  fi
-
-
 cat >confcache <<\_ACEOF
 # This file is a shell script that caches the results of configure
 # tests run on this system so they can be shared between configure
index 35a8b395885f28d9b276dc5f6432317c1bc48d43..c1113a0188db4e613e8d647a4fc33a2aaa35d0be 100644 (file)
@@ -287,7 +287,6 @@ if test "x${with_newlib}" = "xyes"; then
    AC_DEFINE(HAVE_GMTIME_R, 1, [Define if you have gmtime_r.])
    AC_DEFINE(HAVE_STRNLEN, 1, [Define if you have strnlen.])
    AC_DEFINE(HAVE_STRNDUP, 1, [Define if you have strndup.])
-   AC_DEFINE(HAVE_STRTOK_R, 1, [Define if you have strtok_r.])
 
    # At some point, we should differentiate between architectures
    # like x86, which have long double versions, and alpha/powerpc/etc.,
@@ -298,11 +297,11 @@ if test "x${with_newlib}" = "xyes"; then
 else
    AC_CHECK_FUNCS_ONCE(getrusage times mkstemp strtof strtold snprintf \
    ftruncate chsize chdir getlogin gethostname kill link symlink sleep ttyname \
-   alarm access fork execl wait setmode execve pipe dup2 close fcntl \
+   alarm access fork execl setmode close fcntl \
    strcasestr getrlimit gettimeofday stat fstat lstat getpwuid vsnprintf dup \
    getcwd localtime_r gmtime_r getpwuid_r ttyname_r clock_gettime \
    readlink getgid getpid getppid getuid geteuid umask getegid \
-   secure_getenv __secure_getenv mkostemp strnlen strndup strtok_r newlocale \
+   secure_getenv __secure_getenv mkostemp strnlen strndup newlocale \
    freelocale uselocale strerror_l)
 fi
 
@@ -610,9 +609,6 @@ 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
index 39e5e4ae6421eb75ee606f97847e8e16250a06f6..7c6e79995422a6ec4f9e1f3e77459e22edc9366d 100644 (file)
@@ -649,16 +649,11 @@ internal_proto(get_args);
 extern void store_exe_path (const char *);
 export_proto(store_exe_path);
 
-extern char * full_exe_path (void);
-internal_proto(full_exe_path);
-
-extern void find_addr2line (void);
-internal_proto(find_addr2line);
-
 /* backtrace.c */
 
-extern void backtrace (void);
-iexport_proto(backtrace);
+extern void show_backtrace (int);
+internal_proto(show_backtrace);
+
 
 /* error.c */
 
index 317da1f493175290fd6c0370ed87f14aeb597dfe..0d7c1fcea22b4e93cdbdc4b906b32f776a1bf350 100644 (file)
@@ -31,249 +31,122 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #include <unistd.h>
 #endif
 
-#ifdef HAVE_SYS_WAIT_H
-#include <sys/wait.h>
-#endif
-
-#include <limits.h>
-
-#include "unwind.h"
-
+#include "backtrace-supported.h"
+#include "backtrace.h"
 
-/* Macros for common sets of capabilities: can we fork and exec, and
-   can we use pipes to communicate with the subprocess.  */
-#define CAN_FORK (defined(HAVE_FORK) && defined(HAVE_EXECVE) \
-                 && defined(HAVE_WAIT))
-#define CAN_PIPE (CAN_FORK && defined(HAVE_PIPE) \
-                 && defined(HAVE_DUP2) && defined(HAVE_CLOSE))
 
-#ifndef PATH_MAX
-#define PATH_MAX 4096
-#endif
+/* Store our own state while backtracing.  */
+struct mystate
+{
+  int try_simple;
+  int frame;
+};
 
 
-/* GDB style #NUM index for each stack frame.  */
+/* Does a function name have "_gfortran_" or "_gfortrani_" prefix, possibly
+   with additional underscore(s) at the beginning?  Cannot use strncmp()
+   because we might be called from a signal handler.  */
 
-static void 
-bt_header (int num)
+static int
+has_gfortran_prefix (const char *s)
 {
-  st_printf ("#%d  ", num);
-}
+  if (!s)
+    return 0;
 
+  while (*s == '_')
+    s++;
 
-/* fgets()-like function that reads a line from a fd, without
-   needing to malloc() a buffer, and does not use locks, hence should
-   be async-signal-safe.  */
+  return (s[0] == 'g' && s[1] == 'f' && s[2] == 'o' && s[3] == 'r'
+         && s[4] == 't' && s[5] == 'r' && s[6] == 'a' && s[7] == 'n'
+         && (s[8] == '_' || (s[8] == 'i' && s[9] == '_')));
+}
 
-static char *
-fd_gets (char *s, int size, int fd)
+static void
+error_callback (void *data, const char *msg, int errnum)
 {
-  for (int i = 0; i < size; i++)
+  struct mystate *state = (struct mystate *) data;
+  if (errnum < 0)
     {
-      char c;
-      ssize_t nread = read (fd, &c, 1);
-      if (nread == 1)
-       {
-         s[i] = c;
-         if (c == '\n')
-           {
-             if (i + 1 < size)
-               s[i+1] = '\0';
-             else
-               s[i] = '\0';
-             break;
-           }
-       }
-      else
-       {
-         s[i] = '\0';
-         if (i == 0)
-           return NULL;
-         break;
-       }
+      state->try_simple = 1;
+      return;
     }
-  return s;
-}
 
+  estr_write ("\nSomething went wrong while printing the backtrace: ");
+  estr_write (msg);
+  estr_write ("\n");
+}
 
-extern char *addr2line_path;
+static int
+simple_callback (void *data, uintptr_t pc)
+{
+  struct mystate *state = (struct mystate *) data;
+  st_printf ("#%d  0x%lx\n", state->frame, (unsigned long) pc);
+  (state->frame)++;
+  return 0;
+}
 
-/* Struct containing backtrace state.  */
-typedef struct
+static int
+full_callback (void *data, uintptr_t pc, const char *filename,
+              int lineno, const char *function)
 {
-  int frame_number;
-  int direct_output;
-  int outfd;
-  int infd;
-  int error;
+  struct mystate *state = (struct mystate *) data;
+
+  if (has_gfortran_prefix (function))
+    return 0;
+
+  st_printf ("#%d  0x%lx in %s\n", state->frame,
+            (unsigned long) pc, function == NULL ? "???" : function);
+  if (filename || lineno != 0)
+    st_printf ("\tat %s:%d\n", filename == NULL ? "???" : filename, lineno);
+  (state->frame)++;
+
+  if (function != NULL && strcmp (function, "main") == 0)
+    return 1;
+
+  return 0;
 }
-bt_state;
 
-static _Unwind_Reason_Code
-trace_function (struct _Unwind_Context *context, void *state_ptr)
+
+/* Display the backtrace.  */
+
+void
+show_backtrace (int in_signal_handler)
 {
-  bt_state* state = (bt_state*) state_ptr;
-  _Unwind_Ptr ip;
-#ifdef HAVE_GETIPINFO
-  int ip_before_insn = 0;
-  ip = _Unwind_GetIPInfo (context, &ip_before_insn);
-  
-  /* If the unwinder gave us a 'return' address, roll it back a little
-     to ensure we get the correct line number for the call itself.  */
-  if (! ip_before_insn)
-    --ip;
-#else  
-  ip = _Unwind_GetIP (context);
-#endif
+  struct backtrace_state *lbstate;
+  struct mystate state = { 0, 0 };
+  lbstate = backtrace_create_state (NULL, 1, error_callback, NULL);
 
-  if (state->direct_output)
+  if (!BACKTRACE_SUPPORTED || (in_signal_handler && BACKTRACE_USES_MALLOC))
     {
-      bt_header(state->frame_number);
-      st_printf ("%p\n", (void*) ip);
+      /* If symbolic backtrace is not supported on this target, or would
+        require malloc() and we are in a signal handler, go with a
+        simple backtrace.  */
+
+      backtrace_simple (lbstate, 0, simple_callback, error_callback, &state);
     }
   else
     {
-      char addr_buf[GFC_XTOA_BUF_SIZE], func[1024], file[PATH_MAX];
-      char *p;
-      const char* addr = gfc_xtoa (ip, addr_buf, sizeof (addr_buf));
-      write (state->outfd, addr, strlen (addr));
-      write (state->outfd, "\n", 1);
-
-      if (! fd_gets (func, sizeof(func), state->infd))
-       {
-         state->error = 1;
-         goto done;
-       }
-      if (! fd_gets (file, sizeof(file), state->infd))
-       {
-         state->error = 1;
-         goto done;
-       }
-           
-       for (p = func; *p != '\n' && *p != '\r'; p++)
-         ;
-       *p = '\0';
-       
-       /* _start is a setup routine that calls main(), and main() is
-          the frontend routine that calls some setup stuff and then
-          calls MAIN__, so at this point we should stop.  */
-       if (strcmp (func, "_start") == 0 || strcmp (func, "main") == 0)
-         return _URC_END_OF_STACK;
-       
-       bt_header (state->frame_number);
-       estr_write ("0x");
-       estr_write (addr);
-
-       if (func[0] != '?' && func[1] != '?')
-         {
-           estr_write (" in ");
-           estr_write (func);
-         }
-       
-       if (strncmp (file, "??", 2) == 0)
-         estr_write ("\n");
-       else
-         {
-           estr_write (" at ");
-           estr_write (file);
-         }
+      /* libbacktrace uses mmap, which is safe to call from a signal handler
+        (in practice, if not in theory).  Thus we can generate a symbolic
+        backtrace, if debug symbols are available.  */
+
+      backtrace_full (lbstate, 0, full_callback, error_callback, &state);
+      if (state.try_simple)
+       backtrace_simple (lbstate, 0, simple_callback, error_callback, &state);
     }
+}
 
- done:
 
-  state->frame_number++;
-  
-  return _URC_NO_REASON;
-}
 
+/* Function called by the front-end translating the BACKTRACE intrinsic.  */
 
-/* Display the backtrace.  */
+extern void backtrace (void);
+export_proto (backtrace);
 
 void
 backtrace (void)
 {
-  bt_state state;
-  state.frame_number = 0;
-  state.error = 0;
-
-#if CAN_PIPE
-
-  if (addr2line_path == NULL)
-    goto fallback_noerr;
-
-  /* We attempt to extract file and line information from addr2line.  */
-  do
-  {
-    /* Local variables.  */
-    int f[2], pid, inp[2];
-
-    /* Don't output an error message if something goes wrong, we'll simply
-       fall back to printing the addresses.  */
-    if (pipe (f) != 0)
-      break;
-    if (pipe (inp) != 0)
-      break;
-    if ((pid = fork ()) == -1)
-      break;
-
-    if (pid == 0)
-      {
-       /* Child process.  */
-#define NUM_FIXEDARGS 7
-       char *arg[NUM_FIXEDARGS];
-       char *newenv[] = { NULL };
-
-       close (f[0]);
-
-       close (inp[1]);
-       if (dup2 (inp[0], STDIN_FILENO) == -1)
-         _exit (1);
-       close (inp[0]);
-
-       close (STDERR_FILENO);
-
-       if (dup2 (f[1], STDOUT_FILENO) == -1)
-         _exit (1);
-       close (f[1]);
-
-       arg[0] = addr2line_path;
-       arg[1] = (char *) "-e";
-       arg[2] = full_exe_path ();
-       arg[3] = (char *) "-f";
-       arg[4] = (char *) "-s";
-       arg[5] = (char *) "-C";
-       arg[6] = NULL;
-       execve (addr2line_path, arg, newenv);
-       _exit (1);
-#undef NUM_FIXEDARGS
-      }
-
-    /* Father process.  */
-    close (f[1]);
-    close (inp[0]);
-
-    state.outfd = inp[1];
-    state.infd = f[0];
-    state.direct_output = 0;
-    _Unwind_Backtrace (trace_function, &state);
-    if (state.error)
-      goto fallback;
-    close (inp[1]);
-    close (f[0]);
-    wait (NULL);
-    return;
-
-fallback:
-    estr_write ("** Something went wrong while running addr2line. **\n"
-               "** Falling back to a simpler backtrace scheme. **\n");
-  }
-  while (0);
-
-fallback_noerr:
-#endif /* CAN_PIPE */
-
-  /* Fallback to the simple backtrace without addr2line.  */
-  state.direct_output = 1;
-  _Unwind_Backtrace (trace_function, &state);
+  show_backtrace (0);
 }
-iexport(backtrace);
+
index 1bae1a294d8f4f667b60e5936b7cd373a5138ff9..f44256b43b425e899b4f7cbc18e2cf754921d7ec 100644 (file)
@@ -30,7 +30,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 compile_options_t compile_options;
 
 #ifndef LIBGFOR_MINIMAL
-volatile sig_atomic_t fatal_error_in_progress = 0;
+static volatile sig_atomic_t fatal_error_in_progress = 0;
 
 
 /* Helper function for backtrace_handler to write information about the
@@ -126,7 +126,7 @@ backtrace_handler (int signum)
 
   show_signal (signum);
   estr_write ("\nBacktrace for this error:\n");
-  backtrace ();
+  show_backtrace (1);
 
   /* Now reraise the signal.  We reactivate the signal's
      default handling, which is to terminate the process.
@@ -136,16 +136,6 @@ backtrace_handler (int signum)
   signal (signum, SIG_DFL);
   raise (signum);
 }
-
-
-/* Helper function for set_options because we need to access the
-   global variable options which is not seen in set_options.  */
-static void
-maybe_find_addr2line (void)
-{
-  if (options.backtrace == -1)
-    find_addr2line ();
-}
 #endif
 
 /* Set the usual compile-time options.  */
@@ -211,8 +201,6 @@ set_options (int num, int options[])
 #if defined(SIGXFSZ)
       signal (SIGXFSZ, backtrace_handler);
 #endif
-
-      maybe_find_addr2line ();
     }
 #endif
 }
index 098231916aa26e05160a6c9d6a4c31cab6a692cb..9eb07645411ab7f6857bd113b42838b62d013249 100644 (file)
@@ -173,7 +173,7 @@ sys_abort (void)
       || (options.backtrace == -1 && compile_options.backtrace == 1))
     {
       estr_write ("\nProgram aborted. Backtrace:\n");
-      backtrace ();
+      show_backtrace (0);
       signal (SIGABRT, SIG_DFL);
     }
 
index cb8e518b582913ee59b0d8ff56ce37194ea41b2c..ecb613dc91d3d31ff3254056acd3564a9200c137 100644 (file)
@@ -70,162 +70,13 @@ determine_endianness (void)
 static int argc_save;
 static char **argv_save;
 
-static const char *exe_path;
-static bool please_free_exe_path_when_done;
 
-/* Save the path under which the program was called, for use in the
-   backtrace routines.  */
 void
-store_exe_path (const char * argv0)
+store_exe_path (const char * argv0 __attribute__ ((unused)))
 {
-#ifndef DIR_SEPARATOR   
-#define DIR_SEPARATOR '/'
-#endif
-
-  char *cwd, *path;
-
-  /* This can only happen if store_exe_path is called multiple times.  */
-  if (please_free_exe_path_when_done)
-    free ((char *) exe_path);
-
-  /* Reading the /proc/self/exe symlink is Linux-specific(?), but if
-     it works it gives the correct answer.  */
-#ifdef HAVE_READLINK
-  ssize_t len, psize = 256;
-  while (1)
-    {
-      path = xmalloc (psize);
-      len = readlink ("/proc/self/exe", path, psize);
-      if (len < 0)
-       {
-         free (path);
-         break;
-       }
-      else if (len < psize)
-       {
-         path[len] = '\0';
-         exe_path = strdup (path);
-         free (path);
-         please_free_exe_path_when_done = true;
-         return;
-       }
-      /* The remaining option is len == psize.  */
-      free (path);
-      psize *= 4;
-    }
-#endif
-
-  /* If the path is absolute or on a simulator where argv is not set.  */
-#ifdef __MINGW32__
-  if (argv0 == NULL
-      || ('A' <= argv0[0] && argv0[0] <= 'Z' && argv0[1] == ':')
-      || ('a' <= argv0[0] && argv0[0] <= 'z' && argv0[1] == ':')
-      || (argv0[0] == '/' && argv0[1] == '/')
-      || (argv0[0] == '\\' && argv0[1] == '\\'))
-#else
-  if (argv0 == NULL || argv0[0] == DIR_SEPARATOR)
-#endif
-    {
-      exe_path = argv0;
-      please_free_exe_path_when_done = false;
-      return;
-    }
-
-#ifdef HAVE_GETCWD
-  size_t cwdsize = 256;
-  while (1)
-    {
-      cwd = xmalloc (cwdsize);
-      if (getcwd (cwd, cwdsize))
-       break;
-      else if (errno == ERANGE)
-       {
-         free (cwd);
-         cwdsize *= 4;
-       }
-      else
-       {
-         free (cwd);
-         cwd = NULL;
-         break;
-       }
-    }
-#else
-  cwd = NULL;
-#endif
-
-  if (!cwd)
-    {
-      exe_path = argv0;
-      please_free_exe_path_when_done = false;
-      return;
-    }
-
-  /* exe_path will be cwd + "/" + argv[0] + "\0".  This will not work
-     if the executable is not in the cwd, but at this point we're out
-     of better ideas.  */
-  size_t pathlen = strlen (cwd) + 1 + strlen (argv0) + 1;
-  path = xmalloc (pathlen);
-  snprintf (path, pathlen, "%s%c%s", cwd, DIR_SEPARATOR, argv0);
-  free (cwd);
-  exe_path = path;
-  please_free_exe_path_when_done = true;
-}
-
-
-/* Return the full path of the executable.  */
-char *
-full_exe_path (void)
-{
-  return (char *) exe_path;
-}
-
-
-#ifndef HAVE_STRTOK_R
-static char*
-gfstrtok_r (char *str, const char *delim, 
-           char **saveptr __attribute__ ((unused)))
-{
-  return strtok (str, delim);
-}
-#define strtok_r gfstrtok_r
-#endif
-
-char *addr2line_path;
-
-/* Find addr2line and store the path.  */
-
-void
-find_addr2line (void)
-{
-#ifdef HAVE_ACCESS
-#define A2L_LEN 11
-  char *path = secure_getenv ("PATH");
-  if (!path)
-    return;
-  char *tp = strdup (path);
-  if (!tp)
-    return;
-  size_t n = strlen (path);
-  char *ap = xmalloc (n + A2L_LEN);
-  char *saveptr;
-  for (char *str = tp;; str = NULL)
-    {
-      char *token = strtok_r (str, ":", &saveptr);
-      if (!token)
-       break;
-      size_t toklen = strlen (token);
-      memcpy (ap, token, toklen);
-      memcpy (ap + toklen, "/addr2line", A2L_LEN);
-      if (access (ap, R_OK|X_OK) == 0)
-       {
-         addr2line_path = strdup (ap);
-         break;
-       }
-    }
-  free (tp);
-  free (ap);
-#endif
+  /* This function is now useless, but is retained due to ABI compatibility.
+    Remove when bumping the library ABI.  */
+  ;
 }
 
 
@@ -236,7 +87,6 @@ set_args (int argc, char **argv)
 {
   argc_save = argc;
   argv_save = argv;
-  store_exe_path (argv[0]);
 }
 iexport(set_args);
 
@@ -279,9 +129,6 @@ init (void)
   /* if (argc > 1 && strcmp(argv[1], "--resume") == 0) resume();  */
 #endif
 
-  if (options.backtrace == 1)
-    find_addr2line ();
-
   random_seed_i4 (NULL, NULL, NULL);
 }
 
@@ -292,9 +139,4 @@ static void __attribute__((destructor))
 cleanup (void)
 {
   close_units ();
-  
-  if (please_free_exe_path_when_done)
-    free ((char *) exe_path);
-
-  free (addr2line_path);
 }
index 72a134a48dc442289108133a5981849145f0bfc3..693d748222bf2cf669732bf717c168eae999f6d8 100644 (file)
@@ -53,8 +53,6 @@ int big_endian = 0;
 static int argc_save;
 static char **argv_save;
 
-static const char *exe_path;
-
 /* recursion_check()-- It's possible for additional errors to occur
  * during fatal error processing.  We detect this condition here and
  * exit with code 4 immediately. */
@@ -163,14 +161,6 @@ internal_error (st_parameter_common *cmp, const char *message)
 }
 
 
-/* Return the full path of the executable.  */
-char *
-full_exe_path (void)
-{
-  return (char *) exe_path;
-}
-
-
 /* Set the saved values of the command line arguments.  */
 
 void
@@ -178,7 +168,6 @@ set_args (int argc, char **argv)
 {
   argc_save = argc;
   argv_save = argv;
-  exe_path = argv[0];
 }
 iexport(set_args);