Skip to content

Commit

Permalink
libbacktrace: support fetching executable name using sysctl
Browse files Browse the repository at this point in the history
This supports FreeBSD and NetBSD when /proc is not mounted.
  • Loading branch information
ianlancetaylor committed Feb 15, 2020
1 parent 559ab7c commit 0f06cda
Show file tree
Hide file tree
Showing 4 changed files with 191 additions and 1 deletion.
8 changes: 8 additions & 0 deletions config.h.in
Expand Up @@ -34,6 +34,14 @@
/* 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

Expand Down
70 changes: 70 additions & 0 deletions configure
Expand Up @@ -12469,6 +12469,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 :
Expand Down
30 changes: 30 additions & 0 deletions configure.ac
Expand Up @@ -395,6 +395,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=
Expand Down
84 changes: 83 additions & 1 deletion fileline.c
Expand Up @@ -39,13 +39,89 @@ 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"

#ifndef HAVE_GETEXECNAME
#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. */

Expand Down Expand Up @@ -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;

Expand All @@ -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 ();
}
Expand Down

0 comments on commit 0f06cda

Please sign in to comment.