public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [patch,libgfortran,toplevel] Use libbacktrace in libgfortran
@ 2015-08-14  9:23 FX
  2015-08-14 14:19 ` Ian Lance Taylor
  2015-08-24 12:27 ` Build break on SPU (and other non-mmap systems?) (Re: [patch,libgfortran,toplevel] Use libbacktrace in libgfortran) Ulrich Weigand
  0 siblings, 2 replies; 8+ messages in thread
From: FX @ 2015-08-14  9:23 UTC (permalink / raw)
  To: gcc-patches; +Cc: gfortran

[-- Attachment #1: Type: text/plain, Size: 2491 bytes --]

Use libbacktrace (instead of our own unwind-based code) to display backtraces from libgfortran upon error or user request.

  1. In toplevel Makefile.def, make libgfortran depend on libbacktrace (needs global reviewer approval)
  2. In gcc/fortran/config-lang.in, add libbacktrace to target_libs
  3. In libgfortran, we remove our own code and substitute calls to libbacktrace

Bootstrapped and regtested on x86_64-pc-linux-gnu (which has full libbacktrace support) and x86_64-apple-darwin14 (which has minimal libbacktrace support). OK to commit to trunk?

FX

------

The fine print:

This is a great simplification of the library code, because we get rid of the unwind code, and don’t need all the code to find out our executable’s absolute path, find addr2line, pipe-fork-exec addr2line, etc. Just libgfortran/runtime/backtrace.c’s size is reduced by half. And we will benefit from future possible improvements in libbacktrace.

One choice I have made is to not display in backtraces the libgfortran functions, i.e. anything starting with _gfortran_ or _gfortrani_ is simply not printed. I think this is more convenient for some users, because it will avoid them being confused by symbols they don’t recognize. It means, however, that runtime backtraces are a little less useful for us in debugging… but then, we know how to use gdb :)  I am open to being convinced otherwise and remove these few lines of code.

Other than that deliberate choice, no functionality is lost. On dwarf/elf targets (the majority), we get beautiful backtraces as before if code is compiled with “-g”:

#0  0x4006f5 __foo_MOD_gee
	/home/fx/gcc/irun/a.f90:4
#1  0x400706 bar
	/home/fx/gcc/irun/a.f90:16
#2  0x40072e foo
	/home/fx/gcc/irun/a.f90:12
#3  0x400715 test
	/home/fx/gcc/irun/a.f90:9
#4  0x400765 main
	/home/fx/gcc/irun/a.f90:9

and if not compiled with “-g”, we get the nonsymbolic backtrace, as before:

#0  0x4010bd ???
#1  0x4010ce ???
#2  0x4010f6 ???
#3  0x4010dd ???
#4  0x40112d ???
#5  0x42a6b3 ???
#6  0x400fbc ???


We will get backtraces on PE/COFF targets (i.e. Windows), where I don’t think we had them before (but cannot test).
And on non-elf targets such as Mac OS X, we stay with the same as before, i.e. non-symbolic backtraces.



PS: This is probably one of the last of my “summer” gfortran projects for this year. The end of holidays is near, and I’ll have to get back to work. It was fun, as always!



[-- Attachment #2: backtrace.ChangeLog --]
[-- Type: application/applefile, Size: 79 bytes --]

[-- Attachment #3: backtrace.diff --]
[-- Type: application/octet-stream, Size: 20876 bytes --]

Index: Makefile.def
===================================================================
--- Makefile.def	(revision 226823)
+++ Makefile.def	(working copy)
@@ -597,6 +597,7 @@ dependencies = { module=all-target-winsu
 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: gcc/fortran/config-lang.in
===================================================================
--- gcc/fortran/config-lang.in	(revision 226823)
+++ gcc/fortran/config-lang.in	(working copy)
@@ -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: libgfortran/Makefile.am
===================================================================
--- libgfortran/Makefile.am	(revision 226823)
+++ libgfortran/Makefile.am	(working copy)
@@ -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$(sr
 	      -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: libgfortran/configure.ac
===================================================================
--- libgfortran/configure.ac	(revision 226823)
+++ libgfortran/configure.ac	(working copy)
@@ -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: libgfortran/libgfortran.h
===================================================================
--- libgfortran/libgfortran.h	(revision 226823)
+++ libgfortran/libgfortran.h	(working copy)
@@ -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: libgfortran/runtime/backtrace.c
===================================================================
--- libgfortran/runtime/backtrace.c	(revision 226823)
+++ libgfortran/runtime/backtrace.c	(working copy)
@@ -31,249 +31,122 @@ see the files COPYING3 and COPYING.RUNTI
 #include <unistd.h>
 #endif
 
-#ifdef HAVE_SYS_WAIT_H
-#include <sys/wait.h>
-#endif
+#include "backtrace-supported.h"
+#include "backtrace.h"
 
-#include <limits.h>
 
-#include "unwind.h"
+/* Store our own state while backtracing.  */
+struct mystate
+{
+  int try_simple;
+  int frame;
+};
 
 
-/* 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))
+/* 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.  */
 
-#ifndef PATH_MAX
-#define PATH_MAX 4096
-#endif
+static int
+has_gfortran_prefix (const char *s)
+{
+  if (!s)
+    return 0;
 
+  while (*s == '_')
+    s++;
 
-/* GDB style #NUM index for each stack frame.  */
+  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 void 
-bt_header (int num)
+static void
+error_callback (void *data, const char *msg, int errnum)
 {
-  st_printf ("#%d  ", num);
-}
+  struct mystate *state = (struct mystate *) data;
+  if (errnum < 0)
+    {
+      state->try_simple = 1;
+      return;
+    }
 
+  estr_write ("\nSomething went wrong while printing the backtrace: ");
+  estr_write (msg);
+  estr_write ("\n");
+}
 
-/* 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.  */
+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;
+}
 
-static char *
-fd_gets (char *s, int size, int fd)
+static int
+full_callback (void *data, uintptr_t pc, const char *filename,
+	       int lineno, const char *function)
 {
-  for (int i = 0; i < size; i++)
-    {
-      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;
-	}
-    }
-  return s;
+  struct mystate *state = (struct mystate *) data;
+
+  if (has_gfortran_prefix (function))
+    return 0;
+
+  st_printf ("#%d  0x%lx %s\n", state->frame,
+	     (unsigned long) pc, function == NULL ? "???" : function);
+  if (filename || lineno != 0)
+    st_printf ("\t%s:%d\n", filename == NULL ? "???" : filename, lineno);
+  (state->frame)++;
+
+  if (function != NULL && strcmp (function, "main") == 0)
+    return 1;
+
+  return 0;
 }
 
 
-extern char *addr2line_path;
+/* Display the backtrace.  */
 
-/* Struct containing backtrace state.  */
-typedef struct
+void
+show_backtrace (int in_signal_handler)
 {
-  int frame_number;
-  int direct_output;
-  int outfd;
-  int infd;
-  int error;
-}
-bt_state;
-
-static _Unwind_Reason_Code
-trace_function (struct _Unwind_Context *context, void *state_ptr)
-{
-  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: libgfortran/runtime/compile_options.c
===================================================================
--- libgfortran/runtime/compile_options.c	(revision 226823)
+++ libgfortran/runtime/compile_options.c	(working copy)
@@ -30,7 +30,7 @@ see the files COPYING3 and COPYING.RUNTI
 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: libgfortran/runtime/error.c
===================================================================
--- libgfortran/runtime/error.c	(revision 226823)
+++ libgfortran/runtime/error.c	(working copy)
@@ -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: libgfortran/runtime/main.c
===================================================================
--- libgfortran/runtime/main.c	(revision 226823)
+++ libgfortran/runtime/main.c	(working copy)
@@ -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: libgfortran/runtime/minimal.c
===================================================================
--- libgfortran/runtime/minimal.c	(revision 226823)
+++ libgfortran/runtime/minimal.c	(working copy)
@@ -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
 }
 
 
-/* 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);
 
Index: gcc/testsuite/gfortran.dg/backtrace_1.f90
===================================================================
--- gcc/testsuite/gfortran.dg/backtrace_1.f90	(revision 0)
+++ gcc/testsuite/gfortran.dg/backtrace_1.f90	(working copy)
@@ -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

[-- Attachment #4: backtrace_withregeneratedfiles.diff --]
[-- Type: application/octet-stream, Size: 28916 bytes --]

Index: Makefile.def
===================================================================
--- Makefile.def	(revision 226823)
+++ Makefile.def	(working copy)
@@ -597,6 +597,7 @@ dependencies = { module=all-target-winsu
 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: Makefile.in
===================================================================
--- Makefile.in	(revision 226823)
+++ Makefile.in	(working copy)
@@ -50921,6 +50921,7 @@ all-target-winsup: maybe-all-target-libt
 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: gcc/fortran/config-lang.in
===================================================================
--- gcc/fortran/config-lang.in	(revision 226823)
+++ gcc/fortran/config-lang.in	(working copy)
@@ -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: libgfortran/Makefile.am
===================================================================
--- libgfortran/Makefile.am	(revision 226823)
+++ libgfortran/Makefile.am	(working copy)
@@ -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$(sr
 	      -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: libgfortran/Makefile.in
===================================================================
--- libgfortran/Makefile.in	(revision 226823)
+++ libgfortran/Makefile.in	(working copy)
@@ -132,7 +132,6 @@ am__aclocal_m4_deps = $(top_srcdir)/../c
 	$(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$(sr
 	      -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: libgfortran/aclocal.m4
===================================================================
--- libgfortran/aclocal.m4	(revision 226823)
+++ libgfortran/aclocal.m4	(working copy)
@@ -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: libgfortran/config.h.in
===================================================================
--- libgfortran/config.h.in	(revision 226823)
+++ libgfortran/config.h.in	(working copy)
@@ -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
 
Index: libgfortran/configure
===================================================================
--- libgfortran/configure	(revision 226823)
+++ libgfortran/configure	(working copy)
@@ -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_get
 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" >>conf
 $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.
@@ -16653,16 +16643,6 @@ done
 
 
 
-
-
-
-
-
-
-
-
-
-
 fi
 
 # Check strerror_r, cannot be above as versions with two and three arguments exist
@@ -26584,44 +26564,6 @@ $as_echo "#define HAVE_CRLF 1" >>confdef
 
 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: libgfortran/configure.ac
===================================================================
--- libgfortran/configure.ac	(revision 226823)
+++ libgfortran/configure.ac	(working copy)
@@ -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: libgfortran/libgfortran.h
===================================================================
--- libgfortran/libgfortran.h	(revision 226823)
+++ libgfortran/libgfortran.h	(working copy)
@@ -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: libgfortran/runtime/backtrace.c
===================================================================
--- libgfortran/runtime/backtrace.c	(revision 226823)
+++ libgfortran/runtime/backtrace.c	(working copy)
@@ -31,249 +31,122 @@ see the files COPYING3 and COPYING.RUNTI
 #include <unistd.h>
 #endif
 
-#ifdef HAVE_SYS_WAIT_H
-#include <sys/wait.h>
-#endif
+#include "backtrace-supported.h"
+#include "backtrace.h"
 
-#include <limits.h>
 
-#include "unwind.h"
+/* Store our own state while backtracing.  */
+struct mystate
+{
+  int try_simple;
+  int frame;
+};
 
 
-/* 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))
+/* 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.  */
 
-#ifndef PATH_MAX
-#define PATH_MAX 4096
-#endif
+static int
+has_gfortran_prefix (const char *s)
+{
+  if (!s)
+    return 0;
 
+  while (*s == '_')
+    s++;
 
-/* GDB style #NUM index for each stack frame.  */
+  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 void 
-bt_header (int num)
+static void
+error_callback (void *data, const char *msg, int errnum)
 {
-  st_printf ("#%d  ", num);
-}
+  struct mystate *state = (struct mystate *) data;
+  if (errnum < 0)
+    {
+      state->try_simple = 1;
+      return;
+    }
 
+  estr_write ("\nSomething went wrong while printing the backtrace: ");
+  estr_write (msg);
+  estr_write ("\n");
+}
 
-/* 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.  */
+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;
+}
 
-static char *
-fd_gets (char *s, int size, int fd)
+static int
+full_callback (void *data, uintptr_t pc, const char *filename,
+	       int lineno, const char *function)
 {
-  for (int i = 0; i < size; i++)
-    {
-      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;
-	}
-    }
-  return s;
+  struct mystate *state = (struct mystate *) data;
+
+  if (has_gfortran_prefix (function))
+    return 0;
+
+  st_printf ("#%d  0x%lx %s\n", state->frame,
+	     (unsigned long) pc, function == NULL ? "???" : function);
+  if (filename || lineno != 0)
+    st_printf ("\t%s:%d\n", filename == NULL ? "???" : filename, lineno);
+  (state->frame)++;
+
+  if (function != NULL && strcmp (function, "main") == 0)
+    return 1;
+
+  return 0;
 }
 
 
-extern char *addr2line_path;
+/* Display the backtrace.  */
 
-/* Struct containing backtrace state.  */
-typedef struct
+void
+show_backtrace (int in_signal_handler)
 {
-  int frame_number;
-  int direct_output;
-  int outfd;
-  int infd;
-  int error;
-}
-bt_state;
-
-static _Unwind_Reason_Code
-trace_function (struct _Unwind_Context *context, void *state_ptr)
-{
-  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: libgfortran/runtime/compile_options.c
===================================================================
--- libgfortran/runtime/compile_options.c	(revision 226823)
+++ libgfortran/runtime/compile_options.c	(working copy)
@@ -30,7 +30,7 @@ see the files COPYING3 and COPYING.RUNTI
 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: libgfortran/runtime/error.c
===================================================================
--- libgfortran/runtime/error.c	(revision 226823)
+++ libgfortran/runtime/error.c	(working copy)
@@ -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: libgfortran/runtime/main.c
===================================================================
--- libgfortran/runtime/main.c	(revision 226823)
+++ libgfortran/runtime/main.c	(working copy)
@@ -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: libgfortran/runtime/minimal.c
===================================================================
--- libgfortran/runtime/minimal.c	(revision 226823)
+++ libgfortran/runtime/minimal.c	(working copy)
@@ -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
 }
 
 
-/* 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);
 
Index: gcc/testsuite/gfortran.dg/backtrace_1.f90
===================================================================
--- gcc/testsuite/gfortran.dg/backtrace_1.f90	(revision 0)
+++ gcc/testsuite/gfortran.dg/backtrace_1.f90	(working copy)
@@ -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

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [patch,libgfortran,toplevel] Use libbacktrace in libgfortran
  2015-08-14  9:23 [patch,libgfortran,toplevel] Use libbacktrace in libgfortran FX
@ 2015-08-14 14:19 ` Ian Lance Taylor
  2015-08-24 12:27 ` Build break on SPU (and other non-mmap systems?) (Re: [patch,libgfortran,toplevel] Use libbacktrace in libgfortran) Ulrich Weigand
  1 sibling, 0 replies; 8+ messages in thread
From: Ian Lance Taylor @ 2015-08-14 14:19 UTC (permalink / raw)
  To: FX; +Cc: gcc-patches, gfortran

On Fri, Aug 14, 2015 at 1:32 AM, FX <fxcoudert@gmail.com> wrote:
> Use libbacktrace (instead of our own unwind-based code) to display backtraces from libgfortran upon error or user request.
>
>   1. In toplevel Makefile.def, make libgfortran depend on libbacktrace (needs global reviewer approval)

This change (and the corresponding change to Makefile.in) is OK.

Thanks.

Ian

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Build break on SPU (and other non-mmap systems?) (Re: [patch,libgfortran,toplevel] Use libbacktrace in libgfortran)
  2015-08-14  9:23 [patch,libgfortran,toplevel] Use libbacktrace in libgfortran FX
  2015-08-14 14:19 ` Ian Lance Taylor
@ 2015-08-24 12:27 ` Ulrich Weigand
  2015-08-24 12:41   ` FX
  1 sibling, 1 reply; 8+ messages in thread
From: Ulrich Weigand @ 2015-08-24 12:27 UTC (permalink / raw)
  To: FX, iant; +Cc: gfortran, gcc-patches

FX Coudert wrote:

>        PR libfortran/54572
>        * Makefile.def: Make libgfortran depend on libbacktrace.
>        * Makefile.in: Regenerate.

This causes GCC build to fail on SPU with the error:

/home/uweigand/dailybuild/spu-tc-2015-08-23/gcc-head/src/libbacktrace/mmapio.c: In function 'backtrace_get_view':
/home/uweigand/dailybuild/spu-tc-2015-08-23/gcc-head/src/libbacktrace/mmapio.c:70:9: error: implicit declaration of function 'mmap' [-Werror=implicit-function-declaration]
   map = mmap (NULL, size, PROT_READ, MAP_PRIVATE, descriptor, pageoff);
         ^
/home/uweigand/dailybuild/spu-tc-2015-08-23/gcc-head/src/libbacktrace/mmapio.c:70:7: error: assignment makes pointer from integer without a cast [-Werror=int-conversion]
   map = mmap (NULL, size, PROT_READ, MAP_PRIVATE, descriptor, pageoff);
       ^
/home/uweigand/dailybuild/spu-tc-2015-08-23/gcc-head/src/libbacktrace/mmapio.c: In function 'backtrace_release_view':
/home/uweigand/dailybuild/spu-tc-2015-08-23/gcc-head/src/libbacktrace/mmapio.c:98:7: error: implicit declaration of function 'munmap' [-Werror=implicit-function-declaration]
   if (munmap (const_cast.v, view->len) < 0)
       ^
make[3]: *** [mmapio.lo] Error 1

On the SPU, mmap is indeed not available.  Before that change, it was still
possible to build libgfortran for SPU ...

Is the intent to now require mmap on every system that supports libgfortran,
or should use of mmap in libbacktrace be optional in some form?

Bye,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU/Linux compilers and toolchain
  Ulrich.Weigand@de.ibm.com

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Build break on SPU (and other non-mmap systems?) (Re: [patch,libgfortran,toplevel] Use libbacktrace in libgfortran)
  2015-08-24 12:27 ` Build break on SPU (and other non-mmap systems?) (Re: [patch,libgfortran,toplevel] Use libbacktrace in libgfortran) Ulrich Weigand
@ 2015-08-24 12:41   ` FX
  2015-08-24 13:15     ` Ulrich Weigand
  0 siblings, 1 reply; 8+ messages in thread
From: FX @ 2015-08-24 12:41 UTC (permalink / raw)
  To: Ulrich Weigand; +Cc: iant, gfortran, gcc-patches

> On the SPU, mmap is indeed not available.  Before that change, it was still
> possible to build libgfortran for SPU ...
> 
> Is the intent to now require mmap on every system that supports libgfortran,
> or should use of mmap in libbacktrace be optional in some form?

The idea is that libbacktrace should be able to build on all targets, at least in a minimally-functional form: https://gcc.gnu.org/ml/gcc/2015-08/msg00038.html
libgfortran should continue to build on all targets, even those that don’t have an mmap().

I see that there is a test in libbacktrace/configure.ac for mmap(), but apparently it fails on your system:

--------------------------------
AC_CHECK_HEADERS(sys/mman.h)
if test "$ac_cv_header_sys_mman_h" = "no"; then
  have_mmap=no
else
  if test -n "${with_target_subdir}"; then
    # When built as a GCC target library, we can't do a link test.  We
    # simply assume that if we have mman.h, we have mmap.
    have_mmap=yes
  else
    AC_CHECK_FUNC(mmap, [have_mmap=yes], [have_mmap=no])
  fi
fi
--------------------------------

So this should be the place to patch things up. Relying on the presence of <sys/mman.h> is apparently not restrictive enough. Maybe we could use a AC_EGREP_HEADER test, as is currently done for dl_interate_phdr()?

FX

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Build break on SPU (and other non-mmap systems?) (Re: [patch,libgfortran,toplevel] Use libbacktrace in libgfortran)
  2015-08-24 12:41   ` FX
@ 2015-08-24 13:15     ` Ulrich Weigand
  2015-08-24 13:44       ` FX
  2015-08-24 17:31       ` Jeff Law
  0 siblings, 2 replies; 8+ messages in thread
From: Ulrich Weigand @ 2015-08-24 13:15 UTC (permalink / raw)
  To: FX; +Cc: iant, gfortran, gcc-patches

FX Coudert wrote:

> The idea is that libbacktrace should be able to build on all targets, at
> least in a minimally-functional form:
> https://gcc.gnu.org/ml/gcc/2015-08/msg00038.html
> libgfortran should continue to build on all targets, even those that
> don't have an mmap().
> 
> I see that there is a test in libbacktrace/configure.ac for mmap(), but
> apparently it fails on your system:

Ah, I see.  On the SPU, we do have an sys/mman.h header file, which provides
a "mmap_eaddr" routine used to map files into the DMA address space, and
associated mmap flags.  That's why the test gets confused.

> So this should be the place to patch things up. Relying on the presence of
> <sys/mman.h> is apparently not restrictive enough. Maybe we could use a
> AC_EGREP_HEADER test, as is currently done for dl_interate_phdr()?

Hmm, that seems tricky, since the SPU sys/mman.h file contains the prototype
for mmap_eaddr, and the string "mmap" in various comments ...

I guess we can always just hard-code that SPU does not have mmap, similar
to how Solaris is hard-coded to not have dl_iterate_phdr.

Would something like the below be OK (if it passes testing)?

Thanks,
Ulrich


Index: libbacktrace/configure.ac
===================================================================
--- libbacktrace/configure.ac	(revision 227056)
+++ libbacktrace/configure.ac	(working copy)
@@ -273,6 +273,12 @@ else
     # When built as a GCC target library, we can't do a link test.  We
     # simply assume that if we have mman.h, we have mmap.
     have_mmap=yes
+    case "${host}" in
+    spu-*-*)
+        # The SPU does not have mmap, but it has a sys/mman.h header file
+        # containing "mmap_eaddr" and the mmap flags, confusing the test.
+	have_mmap=no ;;
+    esac
   else
     AC_CHECK_FUNC(mmap, [have_mmap=yes], [have_mmap=no])
   fi


-- 
  Dr. Ulrich Weigand
  GNU/Linux compilers and toolchain
  Ulrich.Weigand@de.ibm.com

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Build break on SPU (and other non-mmap systems?) (Re: [patch,libgfortran,toplevel] Use libbacktrace in libgfortran)
  2015-08-24 13:15     ` Ulrich Weigand
@ 2015-08-24 13:44       ` FX
  2015-08-24 17:31       ` Jeff Law
  1 sibling, 0 replies; 8+ messages in thread
From: FX @ 2015-08-24 13:44 UTC (permalink / raw)
  To: Ulrich Weigand; +Cc: iant, gfortran, gcc-patches

> I guess we can always just hard-code that SPU does not have mmap, similar
> to how Solaris is hard-coded to not have dl_iterate_phdr.
> 
> Would something like the below be OK (if it passes testing)?

Looks good to me, though I cannot approve it.

FX

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Build break on SPU (and other non-mmap systems?) (Re: [patch,libgfortran,toplevel] Use libbacktrace in libgfortran)
  2015-08-24 13:15     ` Ulrich Weigand
  2015-08-24 13:44       ` FX
@ 2015-08-24 17:31       ` Jeff Law
  2015-08-24 18:56         ` Ulrich Weigand
  1 sibling, 1 reply; 8+ messages in thread
From: Jeff Law @ 2015-08-24 17:31 UTC (permalink / raw)
  To: Ulrich Weigand, FX; +Cc: iant, gfortran, gcc-patches

On 08/24/2015 06:55 AM, Ulrich Weigand wrote:
> FX Coudert wrote:
>
>> The idea is that libbacktrace should be able to build on all targets, at
>> least in a minimally-functional form:
>> https://gcc.gnu.org/ml/gcc/2015-08/msg00038.html
>> libgfortran should continue to build on all targets, even those that
>> don't have an mmap().
>>
>> I see that there is a test in libbacktrace/configure.ac for mmap(), but
>> apparently it fails on your system:
>
> Ah, I see.  On the SPU, we do have an sys/mman.h header file, which provides
> a "mmap_eaddr" routine used to map files into the DMA address space, and
> associated mmap flags.  That's why the test gets confused.
>
>> So this should be the place to patch things up. Relying on the presence of
>> <sys/mman.h> is apparently not restrictive enough. Maybe we could use a
>> AC_EGREP_HEADER test, as is currently done for dl_interate_phdr()?
>
> Hmm, that seems tricky, since the SPU sys/mman.h file contains the prototype
> for mmap_eaddr, and the string "mmap" in various comments ...
>
> I guess we can always just hard-code that SPU does not have mmap, similar
> to how Solaris is hard-coded to not have dl_iterate_phdr.
>
> Would something like the below be OK (if it passes testing)?
Yes.

Jeff

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Build break on SPU (and other non-mmap systems?) (Re: [patch,libgfortran,toplevel] Use libbacktrace in libgfortran)
  2015-08-24 17:31       ` Jeff Law
@ 2015-08-24 18:56         ` Ulrich Weigand
  0 siblings, 0 replies; 8+ messages in thread
From: Ulrich Weigand @ 2015-08-24 18:56 UTC (permalink / raw)
  To: Jeff Law; +Cc: FX, iant, gfortran, gcc-patches

Jeff Law wrote:
> On 08/24/2015 06:55 AM, Ulrich Weigand wrote:
> > I guess we can always just hard-code that SPU does not have mmap, similar
> > to how Solaris is hard-coded to not have dl_iterate_phdr.
> >
> > Would something like the below be OK (if it passes testing)?
> Yes.

I've checked this in now.

Thanks,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU/Linux compilers and toolchain
  Ulrich.Weigand@de.ibm.com

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2015-08-24 18:49 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-08-14  9:23 [patch,libgfortran,toplevel] Use libbacktrace in libgfortran FX
2015-08-14 14:19 ` Ian Lance Taylor
2015-08-24 12:27 ` Build break on SPU (and other non-mmap systems?) (Re: [patch,libgfortran,toplevel] Use libbacktrace in libgfortran) Ulrich Weigand
2015-08-24 12:41   ` FX
2015-08-24 13:15     ` Ulrich Weigand
2015-08-24 13:44       ` FX
2015-08-24 17:31       ` Jeff Law
2015-08-24 18:56         ` Ulrich Weigand

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).