libbacktrace: support fetching executable name using sysctl
authorIan Lance Taylor <iant@golang.org>
Sat, 15 Feb 2020 23:29:02 +0000 (15:29 -0800)
committerIan Lance Taylor <iant@golang.org>
Sat, 9 May 2020 22:20:13 +0000 (15:20 -0700)
This supports FreeBSD and NetBSD when /proc is not mounted.

libbacktrace/
* fileline.c (sysctl_exec_name): New static function.
(sysctl_exec_name1): New macro or static function.
(sysctl_exec_name2): Likewise.
(fileline_initialize): Try sysctl_exec_name[12].
* configure.ac: Check for sysctl args to fetch executable name.
* configure: Regenerate.
* config.h.in: Regenerate.

libbacktrace/ChangeLog
libbacktrace/config.h.in
libbacktrace/configure
libbacktrace/configure.ac
libbacktrace/fileline.c

index c031dffb6b9ffbc3a818b6c82d197a454567e3dd..1739be9eedd2b22176de0b6e36c05542bf37ec39 100644 (file)
@@ -1,3 +1,13 @@
+2020-05-08  Ian Lance Taylor  <iant@golang.org>
+
+       * fileline.c (sysctl_exec_name): New static function.
+       (sysctl_exec_name1): New macro or static function.
+       (sysctl_exec_name2): Likewise.
+       (fileline_initialize): Try sysctl_exec_name[12].
+       * configure.ac: Check for sysctl args to fetch executable name.
+       * configure: Regenerate.
+       * config.h.in: Regenerate.
+
 2020-02-15  Ian Lance Taylor  <iant@golang.org>
 
        * ztest.c (test_large): Update file to current libgo test file.
index d2c0bdb260a31451552209436f884ef64a7e5085..034ef81c3ec4870bd3ec266924d3862fe67959eb 100644 (file)
 /* Define to 1 if you have the <inttypes.h> header file. */
 #undef HAVE_INTTYPES_H
 
+/* Define to 1 if you have KERN_PROC and KERN_PROC_PATHNAME in <sys/sysctl.h>.
+   */
+#undef HAVE_KERN_PROC
+
+/* Define to 1 if you have KERN_PROCARGS and KERN_PROC_PATHNAME in
+   <sys/sysctl.h>. */
+#undef HAVE_KERN_PROC_ARGS
+
 /* Define to 1 if you have the <link.h> header file. */
 #undef HAVE_LINK_H
 
index 676adb89224e23a78bf406e02f32edbce8fc1ebc..33ce5891e6edea38c6c335dd0bc58967bae08e22 100755 (executable)
@@ -13182,6 +13182,76 @@ $as_echo "#define HAVE_GETEXECNAME 1" >>confdefs.h
 
 fi
 
+# Check for sysctl definitions.
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for KERN_PROC" >&5
+$as_echo_n "checking for KERN_PROC... " >&6; }
+if ${libbacktrace_cv_proc+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <sys/types.h>
+#include <sys/sysctl.h>
+
+int
+main ()
+{
+int mib0 = CTL_KERN; int mib1 = KERN_PROC; int mib2 = KERN_PROC_PATHNAME;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  libbacktrace_cv_proc=yes
+else
+  libbacktrace_cv_proc=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libbacktrace_cv_proc" >&5
+$as_echo "$libbacktrace_cv_proc" >&6; }
+if test "$libbacktrace_cv_proc" = "yes"; then
+
+$as_echo "#define HAVE_KERN_PROC 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for KERN_PROG_ARGS" >&5
+$as_echo_n "checking for KERN_PROG_ARGS... " >&6; }
+if ${libbacktrace_cv_procargs+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <sys/types.h>
+#include <sys/sysctl.h>
+
+int
+main ()
+{
+int mib0 = CTL_KERN; int mib1 = KERN_PROC_ARGS; int mib2 = KERN_PROC_PATHNAME;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  libbacktrace_cv_procargs=yes
+else
+  libbacktrace_cv_procargs=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libbacktrace_cv_procargs" >&5
+$as_echo "$libbacktrace_cv_procargs" >&6; }
+if test "$libbacktrace_cv_procargs" = "yes"; then
+
+$as_echo "#define HAVE_KERN_PROC_ARGS 1" >>confdefs.h
+
+fi
+
 # Check for the clock_gettime function.
 for ac_func in clock_gettime
 do :
index 3730d7c4b06f80d4a1c353fa68112ba6c3a7b1b2..5beed68ccf6a85243466463d66913c957b4c99b4 100644 (file)
@@ -388,6 +388,36 @@ if test "$have_getexecname" = "yes"; then
   AC_DEFINE(HAVE_GETEXECNAME, 1, [Define if getexecname is available.])
 fi
 
+# Check for sysctl definitions.
+
+AC_CACHE_CHECK([for KERN_PROC],
+[libbacktrace_cv_proc],
+[AC_COMPILE_IFELSE(
+  [AC_LANG_PROGRAM([
+#include <sys/types.h>
+#include <sys/sysctl.h>
+], [int mib0 = CTL_KERN; int mib1 = KERN_PROC; int mib2 = KERN_PROC_PATHNAME;])],
+  [libbacktrace_cv_proc=yes],
+  [libbacktrace_cv_proc=no])])
+if test "$libbacktrace_cv_proc" = "yes"; then
+  AC_DEFINE([HAVE_KERN_PROC], 1,
+            [Define to 1 if you have KERN_PROC and KERN_PROC_PATHNAME in <sys/sysctl.h>.])
+fi
+
+AC_CACHE_CHECK([for KERN_PROG_ARGS],
+[libbacktrace_cv_procargs],
+[AC_COMPILE_IFELSE(
+  [AC_LANG_PROGRAM([
+#include <sys/types.h>
+#include <sys/sysctl.h>
+], [int mib0 = CTL_KERN; int mib1 = KERN_PROC_ARGS; int mib2 = KERN_PROC_PATHNAME;])],
+  [libbacktrace_cv_procargs=yes],
+  [libbacktrace_cv_procargs=no])])
+if test "$libbacktrace_cv_procargs" = "yes"; then
+  AC_DEFINE([HAVE_KERN_PROC_ARGS], 1,
+            [Define to 1 if you have KERN_PROCARGS and KERN_PROC_PATHNAME in <sys/sysctl.h>.])
+fi
+
 # Check for the clock_gettime function.
 AC_CHECK_FUNCS(clock_gettime)
 clock_gettime_link=
index fd5edbe5ddbea46d8128ae115e08284a8f9df9fc..cc1011e8b5ddab19e18db94f6a8fce824bb27822 100644 (file)
@@ -39,6 +39,10 @@ POSSIBILITY OF SUCH DAMAGE.  */
 #include <stdlib.h>
 #include <unistd.h>
 
+#if defined (HAVE_KERN_PROC_ARGS) || defined (HAVE_KERN_PROC)
+#include <sys/sysctl.h>
+#endif
+
 #include "backtrace.h"
 #include "internal.h"
 
@@ -46,6 +50,78 @@ POSSIBILITY OF SUCH DAMAGE.  */
 #define getexecname() NULL
 #endif
 
+#if !defined (HAVE_KERN_PROC_ARGS) && !defined (HAVE_KERN_PROC)
+
+#define sysctl_exec_name1(state, error_callback, data) NULL
+#define sysctl_exec_name2(state, error_callback, data) NULL
+
+#else /* defined (HAVE_KERN_PROC_ARGS) || |defined (HAVE_KERN_PROC) */
+
+static char *
+sysctl_exec_name (struct backtrace_state *state,
+                 int mib0, int mib1, int mib2, int mib3,
+                 backtrace_error_callback error_callback, void *data)
+{
+  int mib[4];
+  size_t len;
+  char *name;
+  size_t rlen;
+
+  mib[0] = mib0;
+  mib[1] = mib1;
+  mib[2] = mib2;
+  mib[3] = mib3;
+
+  if (sysctl (mib, 4, NULL, &len, NULL, 0) < 0)
+    return NULL;
+  name = (char *) backtrace_alloc (state, len, error_callback, data);
+  if (name == NULL)
+    return NULL;
+  rlen = len;
+  if (sysctl (mib, 4, name, &rlen, NULL, 0) < 0)
+    {
+      backtrace_free (state, name, len, error_callback, data);
+      return NULL;
+    }
+  return name;
+}
+
+#ifdef HAVE_KERN_PROC_ARGS
+
+static char *
+sysctl_exec_name1 (struct backtrace_state *state,
+                  backtrace_error_callback error_callback, void *data)
+{
+  /* This variant is used on NetBSD.  */
+  return sysctl_exec_name (state, CTL_KERN, KERN_PROC_ARGS, -1,
+                          KERN_PROC_PATHNAME, error_callback, data);
+}
+
+#else
+
+#define sysctl_exec_name1(state, error_callback, data) NULL
+
+#endif
+
+#ifdef HAVE_KERN_PROC
+
+static char *
+sysctl_exec_name2 (struct backtrace_state *state,
+                  backtrace_error_callback error_callback, void *data)
+{
+  /* This variant is used on FreeBSD.  */
+  return sysctl_exec_name (state, CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1,
+                          error_callback, data);
+}
+
+#else
+
+#define sysctl_exec_name2(state, error_callback, data) NULL
+
+#endif
+
+#endif /* defined (HAVE_KERN_PROC_ARGS) || |defined (HAVE_KERN_PROC) */
+
 /* Initialize the fileline information from the executable.  Returns 1
    on success, 0 on failure.  */
 
@@ -83,7 +159,7 @@ fileline_initialize (struct backtrace_state *state,
 
   descriptor = -1;
   called_error_callback = 0;
-  for (pass = 0; pass < 5; ++pass)
+  for (pass = 0; pass < 7; ++pass)
     {
       int does_not_exist;
 
@@ -106,6 +182,12 @@ fileline_initialize (struct backtrace_state *state,
                    (long) getpid ());
          filename = buf;
          break;
+       case 5:
+         filename = sysctl_exec_name1 (state, error_callback, data);
+         break;
+       case 6:
+         filename = sysctl_exec_name2 (state, error_callback, data);
+         break;
        default:
          abort ();
        }