From ad4f95e395b752371643327c1fdf71fac70de526 Mon Sep 17 00:00:00 2001
From: Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
Date: Sun, 23 Aug 2015 21:50:30 +0000
Subject: [PATCH] re PR libfortran/54572 (Use libbacktrace library)

	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
---
 ChangeLog                                 |   6 +
 Makefile.def                              |   1 +
 Makefile.in                               |   1 +
 gcc/fortran/ChangeLog                     |   5 +
 gcc/fortran/config-lang.in                |   2 +-
 gcc/testsuite/ChangeLog                   |   5 +
 gcc/testsuite/gfortran.dg/backtrace_1.f90 |  10 +
 libgfortran/ChangeLog                     |  26 ++
 libgfortran/Makefile.am                   |   8 +-
 libgfortran/Makefile.in                   |   9 +-
 libgfortran/aclocal.m4                    |   1 -
 libgfortran/config.h.in                   |  18 --
 libgfortran/configure                     |  62 +----
 libgfortran/configure.ac                  |   8 +-
 libgfortran/libgfortran.h                 |  11 +-
 libgfortran/runtime/backtrace.c           | 297 +++++++---------------
 libgfortran/runtime/compile_options.c     |  16 +-
 libgfortran/runtime/error.c               |   2 +-
 libgfortran/runtime/main.c                | 166 +-----------
 libgfortran/runtime/minimal.c             |  11 -
 20 files changed, 166 insertions(+), 499 deletions(-)
 create mode 100644 gcc/testsuite/gfortran.dg/backtrace_1.f90

diff --git a/ChangeLog b/ChangeLog
index 913b9caaaa50..0c7ce18d080e 100644
--- 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.
diff --git a/Makefile.def b/Makefile.def
index 01445e4ff6a5..8b4dad99160e 100644
--- a/Makefile.def
+++ b/Makefile.def
@@ -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++;
diff --git a/Makefile.in b/Makefile.in
index 13f3740e9f66..bc2bae6d7fa7 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -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
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 9cbaf6c6c0b8..d345368b70f6 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -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,
diff --git a/gcc/fortran/config-lang.in b/gcc/fortran/config-lang.in
index de8a499646a0..a6c6b92e2528 100644
--- a/gcc/fortran/config-lang.in
+++ b/gcc/fortran/config-lang.in
@@ -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"
 
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 35b7da236d56..6235844f5348 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 000000000000..fdde832d238f
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/backtrace_1.f90
@@ -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
diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog
index 9ffaa035b606..b74b71d3c2fd 100644
--- a/libgfortran/ChangeLog
+++ b/libgfortran/ChangeLog
@@ -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
diff --git a/libgfortran/Makefile.am b/libgfortran/Makefile.am
index 0e816acd2034..e4764337310f 100644
--- a/libgfortran/Makefile.am
+++ b/libgfortran/Makefile.am
@@ -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
diff --git a/libgfortran/Makefile.in b/libgfortran/Makefile.in
index ab71b3874d34..f0ddb38f5aba 100644
--- a/libgfortran/Makefile.in
+++ b/libgfortran/Makefile.in
@@ -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 = \
diff --git a/libgfortran/aclocal.m4 b/libgfortran/aclocal.m4
index 0ec2c8fe438a..403feabae9d5 100644
--- a/libgfortran/aclocal.m4
+++ b/libgfortran/aclocal.m4
@@ -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])
diff --git a/libgfortran/config.h.in b/libgfortran/config.h.in
index 833d8b42aad5..5dfa7c67a257 100644
--- a/libgfortran/config.h.in
+++ b/libgfortran/config.h.in
@@ -315,9 +315,6 @@
 /* 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
 
@@ -339,9 +336,6 @@
 /* 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
 
@@ -462,9 +456,6 @@
 /* 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
 
@@ -636,9 +627,6 @@
 /* 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
 
@@ -753,9 +741,6 @@
 /* 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
 
@@ -855,9 +840,6 @@
 /* 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
 
diff --git a/libgfortran/configure b/libgfortran/configure
index 07542e1387d9..d7dad11a1614 100755
--- a/libgfortran/configure
+++ b/libgfortran/configure
@@ -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
diff --git a/libgfortran/configure.ac b/libgfortran/configure.ac
index 35a8b395885f..c1113a0188db 100644
--- a/libgfortran/configure.ac
+++ b/libgfortran/configure.ac
@@ -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
diff --git a/libgfortran/libgfortran.h b/libgfortran/libgfortran.h
index 39e5e4ae6421..7c6e79995422 100644
--- a/libgfortran/libgfortran.h
+++ b/libgfortran/libgfortran.h
@@ -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 */
 
diff --git a/libgfortran/runtime/backtrace.c b/libgfortran/runtime/backtrace.c
index 317da1f49317..0d7c1fcea22b 100644
--- a/libgfortran/runtime/backtrace.c
+++ b/libgfortran/runtime/backtrace.c
@@ -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);
+
diff --git a/libgfortran/runtime/compile_options.c b/libgfortran/runtime/compile_options.c
index 1bae1a294d8f..f44256b43b42 100644
--- a/libgfortran/runtime/compile_options.c
+++ b/libgfortran/runtime/compile_options.c
@@ -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
 }
diff --git a/libgfortran/runtime/error.c b/libgfortran/runtime/error.c
index 098231916aa2..9eb07645411a 100644
--- a/libgfortran/runtime/error.c
+++ b/libgfortran/runtime/error.c
@@ -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);
     }
 
diff --git a/libgfortran/runtime/main.c b/libgfortran/runtime/main.c
index cb8e518b5829..ecb613dc91d3 100644
--- a/libgfortran/runtime/main.c
+++ b/libgfortran/runtime/main.c
@@ -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);
 }
diff --git a/libgfortran/runtime/minimal.c b/libgfortran/runtime/minimal.c
index 72a134a48dc4..693d748222bf 100644
--- a/libgfortran/runtime/minimal.c
+++ b/libgfortran/runtime/minimal.c
@@ -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);
 
-- 
GitLab