From 33521509a82eeed8e657642db2c2846cc9685bab Mon Sep 17 00:00:00 2001
From: Ian Lance Taylor <iant@google.com>
Date: Mon, 12 Nov 2012 21:24:19 +0000
Subject: [PATCH] configure.ac: Check for getexecname.

	* configure.ac: Check for getexecname.
	* fileline.c: #include <errno.h>.  Define getexecname if not
	available.
	(fileline_initialize): Try to find the executable in a few
	different ways.
	* print.c (error_callback): Only print the filename if it came
	from the backtrace state.
	* configure, config.h.in: Rebuild.

Co-Authored-By: Gerald Pfeifer <gerald@pfeifer.com>
Co-Authored-By: Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>

From-SVN: r193454
---
 libbacktrace/ChangeLog    | 13 ++++++++
 libbacktrace/config.h.in  |  3 ++
 libbacktrace/configure    | 21 +++++++++++++
 libbacktrace/configure.ac | 13 ++++++++
 libbacktrace/fileline.c   | 63 +++++++++++++++++++++++++++++++++++----
 libbacktrace/print.c      |  8 ++---
 6 files changed, 111 insertions(+), 10 deletions(-)

diff --git a/libbacktrace/ChangeLog b/libbacktrace/ChangeLog
index 91e1c9eccd42..dcd49d071d69 100644
--- a/libbacktrace/ChangeLog
+++ b/libbacktrace/ChangeLog
@@ -1,3 +1,16 @@
+2012-11-12  Ian Lance Taylor  <iant@google.com>
+	    Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>
+	    Gerald Pfeifer  <gerald@pfeifer.com>
+
+	* configure.ac: Check for getexecname.
+	* fileline.c: #include <errno.h>.  Define getexecname if not
+	available.
+	(fileline_initialize): Try to find the executable in a few
+	different ways.
+	* print.c (error_callback): Only print the filename if it came
+	from the backtrace state.
+	* configure, config.h.in: Rebuild.
+
 2012-10-29  Ian Lance Taylor  <iant@google.com>
 
 	* mmap.c (backtrace_vector_release): Correct last patch: add
diff --git a/libbacktrace/config.h.in b/libbacktrace/config.h.in
index ba564a82e85c..48ff63fdc05d 100644
--- a/libbacktrace/config.h.in
+++ b/libbacktrace/config.h.in
@@ -16,6 +16,9 @@
 /* Define to 1 if you have the fcntl function */
 #undef HAVE_FCNTL
 
+/* Define if getexecname is available. */
+#undef HAVE_GETEXECNAME
+
 /* Define if _Unwind_GetIPInfo is available. */
 #undef HAVE_GETIPINFO
 
diff --git a/libbacktrace/configure b/libbacktrace/configure
index 1f6a97b34aec..2a57c5102f35 100755
--- a/libbacktrace/configure
+++ b/libbacktrace/configure
@@ -12319,6 +12319,27 @@ cat >>confdefs.h <<_ACEOF
 _ACEOF
 
 
+# Check for getexecname function.
+if test -n "${with_target_subdir}"; then
+   case "${host}" in
+   *-*-solaris2*) have_getexecname=yes ;;
+   *) have_getexecname=no ;;
+   esac
+else
+  ac_fn_c_check_func "$LINENO" "getexecname" "ac_cv_func_getexecname"
+if test "x$ac_cv_func_getexecname" = x""yes; then :
+  have_getexecname=yes
+else
+  have_getexecname=no
+fi
+
+fi
+if test "$have_getexecname" = "yes"; then
+
+$as_echo "#define HAVE_GETEXECNAME 1" >>confdefs.h
+
+fi
+
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether tests can run" >&5
 $as_echo_n "checking whether tests can run... " >&6; }
 if test "${libbacktrace_cv_sys_native+set}" = set; then :
diff --git a/libbacktrace/configure.ac b/libbacktrace/configure.ac
index 534f9276cdbe..c9cba3e4e9c0 100644
--- a/libbacktrace/configure.ac
+++ b/libbacktrace/configure.ac
@@ -289,6 +289,19 @@ fi
 
 AC_CHECK_DECLS(strnlen)
 
+# Check for getexecname function.
+if test -n "${with_target_subdir}"; then
+   case "${host}" in
+   *-*-solaris2*) have_getexecname=yes ;;
+   *) have_getexecname=no ;;
+   esac
+else
+  AC_CHECK_FUNC(getexecname, [have_getexecname=yes], [have_getexecname=no])
+fi
+if test "$have_getexecname" = "yes"; then
+  AC_DEFINE(HAVE_GETEXECNAME, 1, [Define if getexecname is available.])
+fi
+
 AC_CACHE_CHECK([whether tests can run],
   [libbacktrace_cv_sys_native],
   [AC_RUN_IFELSE([AC_LANG_PROGRAM([], [return 0;])],
diff --git a/libbacktrace/fileline.c b/libbacktrace/fileline.c
index e577ecc90616..1ade81e9d493 100644
--- a/libbacktrace/fileline.c
+++ b/libbacktrace/fileline.c
@@ -34,12 +34,17 @@ POSSIBILITY OF SUCH DAMAGE.  */
 
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <errno.h>
 #include <fcntl.h>
 #include <stdlib.h>
 
 #include "backtrace.h"
 #include "internal.h"
 
+#ifndef HAVE_GETEXECNAME
+#define getexecname() NULL
+#endif
+
 /* Initialize the fileline information from the executable.  Returns 1
    on success, 0 on failure.  */
 
@@ -49,6 +54,8 @@ fileline_initialize (struct backtrace_state *state,
 {
   int failed;
   fileline fileline_fn;
+  int pass;
+  int called_error_callback;
   int descriptor;
 
   failed = state->fileline_initialization_failed;
@@ -79,12 +86,58 @@ fileline_initialize (struct backtrace_state *state,
 
   /* We have not initialized the information.  Do it now.  */
 
-  if (state->filename != NULL)
-    descriptor = backtrace_open (state->filename, error_callback, data, NULL);
-  else
-    descriptor = backtrace_open ("/proc/self/exe", error_callback, data, NULL);
+  descriptor = -1;
+  called_error_callback = 0;
+  for (pass = 0; pass < 4; ++pass)
+    {
+      const char *filename;
+      int does_not_exist;
+
+      switch (pass)
+	{
+	case 0:
+	  filename = state->filename;
+	  break;
+	case 1:
+	  filename = getexecname ();
+	  break;
+	case 2:
+	  filename = "/proc/self/exe";
+	  break;
+	case 3:
+	  filename = "/proc/curproc/file";
+	  break;
+	default:
+	  abort ();
+	}
+
+      if (filename == NULL)
+	continue;
+
+      descriptor = backtrace_open (filename, error_callback, data,
+				   &does_not_exist);
+      if (descriptor < 0 && !does_not_exist)
+	{
+	  called_error_callback = 1;
+	  break;
+	}
+      if (descriptor >= 0)
+	break;
+    }
+
   if (descriptor < 0)
-    failed = 1;
+    {
+      if (!called_error_callback)
+	{
+	  if (state->filename != NULL)
+	    error_callback (data, state->filename, ENOENT);
+	  else
+	    error_callback (data,
+			    "libbacktrace could not find executable to open",
+			    0);
+	}
+      failed = 1;
+    }
 
   if (!failed)
     {
diff --git a/libbacktrace/print.c b/libbacktrace/print.c
index 2d9d76aeba72..9b775584d476 100644
--- a/libbacktrace/print.c
+++ b/libbacktrace/print.c
@@ -69,12 +69,10 @@ static void
 error_callback (void *data, const char *msg, int errnum)
 {
   struct print_data *pdata = (struct print_data *) data;
-  const char *name;
 
-  name = pdata->state->filename;
-  if (name == NULL)
-    name = "/proc/self/exe";
-  fprintf (stderr, "%s: libbacktrace: %s", name, msg);
+  if (pdata->state->filename != NULL)
+    fprintf (stderr, "%s: ", pdata->state->filename);
+  fprintf (stderr, "libbacktrace: %s", msg);
   if (errnum > 0)
     fprintf (stderr, ": %s", strerror (errnum));
   fputc ('\n', stderr);
-- 
GitLab