Skip to content

Commit 0f06cda

Browse files
libbacktrace: support fetching executable name using sysctl
This supports FreeBSD and NetBSD when /proc is not mounted.
1 parent 559ab7c commit 0f06cda

File tree

4 files changed

+191
-1
lines changed

4 files changed

+191
-1
lines changed

config.h.in

+8
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,14 @@
3434
/* Define to 1 if you have the <inttypes.h> header file. */
3535
#undef HAVE_INTTYPES_H
3636

37+
/* Define to 1 if you have KERN_PROC and KERN_PROC_PATHNAME in <sys/sysctl.h>.
38+
*/
39+
#undef HAVE_KERN_PROC
40+
41+
/* Define to 1 if you have KERN_PROCARGS and KERN_PROC_PATHNAME in
42+
<sys/sysctl.h>. */
43+
#undef HAVE_KERN_PROC_ARGS
44+
3745
/* Define to 1 if you have the <link.h> header file. */
3846
#undef HAVE_LINK_H
3947

configure

+70
Original file line numberDiff line numberDiff line change
@@ -12469,6 +12469,76 @@ $as_echo "#define HAVE_GETEXECNAME 1" >>confdefs.h
1246912469
1247012470
fi
1247112471
12472+
# Check for sysctl definitions.
12473+
12474+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for KERN_PROC" >&5
12475+
$as_echo_n "checking for KERN_PROC... " >&6; }
12476+
if ${libbacktrace_cv_proc+:} false; then :
12477+
$as_echo_n "(cached) " >&6
12478+
else
12479+
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
12480+
/* end confdefs.h. */
12481+
12482+
#include <sys/types.h>
12483+
#include <sys/sysctl.h>
12484+
12485+
int
12486+
main ()
12487+
{
12488+
int mib0 = CTL_KERN; int mib1 = KERN_PROC; int mib2 = KERN_PROC_PATHNAME;
12489+
;
12490+
return 0;
12491+
}
12492+
_ACEOF
12493+
if ac_fn_c_try_compile "$LINENO"; then :
12494+
libbacktrace_cv_proc=yes
12495+
else
12496+
libbacktrace_cv_proc=no
12497+
fi
12498+
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
12499+
fi
12500+
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libbacktrace_cv_proc" >&5
12501+
$as_echo "$libbacktrace_cv_proc" >&6; }
12502+
if test "$libbacktrace_cv_proc" = "yes"; then
12503+
12504+
$as_echo "#define HAVE_KERN_PROC 1" >>confdefs.h
12505+
12506+
fi
12507+
12508+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for KERN_PROG_ARGS" >&5
12509+
$as_echo_n "checking for KERN_PROG_ARGS... " >&6; }
12510+
if ${libbacktrace_cv_procargs+:} false; then :
12511+
$as_echo_n "(cached) " >&6
12512+
else
12513+
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
12514+
/* end confdefs.h. */
12515+
12516+
#include <sys/types.h>
12517+
#include <sys/sysctl.h>
12518+
12519+
int
12520+
main ()
12521+
{
12522+
int mib0 = CTL_KERN; int mib1 = KERN_PROC_ARGS; int mib2 = KERN_PROC_PATHNAME;
12523+
;
12524+
return 0;
12525+
}
12526+
_ACEOF
12527+
if ac_fn_c_try_compile "$LINENO"; then :
12528+
libbacktrace_cv_procargs=yes
12529+
else
12530+
libbacktrace_cv_procargs=no
12531+
fi
12532+
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
12533+
fi
12534+
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libbacktrace_cv_procargs" >&5
12535+
$as_echo "$libbacktrace_cv_procargs" >&6; }
12536+
if test "$libbacktrace_cv_procargs" = "yes"; then
12537+
12538+
$as_echo "#define HAVE_KERN_PROC_ARGS 1" >>confdefs.h
12539+
12540+
fi
12541+
1247212542
# Check for the clock_gettime function.
1247312543
for ac_func in clock_gettime
1247412544
do :

configure.ac

+30
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,36 @@ if test "$have_getexecname" = "yes"; then
395395
AC_DEFINE(HAVE_GETEXECNAME, 1, [Define if getexecname is available.])
396396
fi
397397

398+
# Check for sysctl definitions.
399+
400+
AC_CACHE_CHECK([for KERN_PROC],
401+
[libbacktrace_cv_proc],
402+
[AC_COMPILE_IFELSE(
403+
[AC_LANG_PROGRAM([
404+
#include <sys/types.h>
405+
#include <sys/sysctl.h>
406+
], [int mib0 = CTL_KERN; int mib1 = KERN_PROC; int mib2 = KERN_PROC_PATHNAME;])],
407+
[libbacktrace_cv_proc=yes],
408+
[libbacktrace_cv_proc=no])])
409+
if test "$libbacktrace_cv_proc" = "yes"; then
410+
AC_DEFINE([HAVE_KERN_PROC], 1,
411+
[Define to 1 if you have KERN_PROC and KERN_PROC_PATHNAME in <sys/sysctl.h>.])
412+
fi
413+
414+
AC_CACHE_CHECK([for KERN_PROG_ARGS],
415+
[libbacktrace_cv_procargs],
416+
[AC_COMPILE_IFELSE(
417+
[AC_LANG_PROGRAM([
418+
#include <sys/types.h>
419+
#include <sys/sysctl.h>
420+
], [int mib0 = CTL_KERN; int mib1 = KERN_PROC_ARGS; int mib2 = KERN_PROC_PATHNAME;])],
421+
[libbacktrace_cv_procargs=yes],
422+
[libbacktrace_cv_procargs=no])])
423+
if test "$libbacktrace_cv_procargs" = "yes"; then
424+
AC_DEFINE([HAVE_KERN_PROC_ARGS], 1,
425+
[Define to 1 if you have KERN_PROCARGS and KERN_PROC_PATHNAME in <sys/sysctl.h>.])
426+
fi
427+
398428
# Check for the clock_gettime function.
399429
AC_CHECK_FUNCS(clock_gettime)
400430
clock_gettime_link=

fileline.c

+83-1
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,89 @@ POSSIBILITY OF SUCH DAMAGE. */
3939
#include <stdlib.h>
4040
#include <unistd.h>
4141

42+
#if defined (HAVE_KERN_PROC_ARGS) || defined (HAVE_KERN_PROC)
43+
#include <sys/sysctl.h>
44+
#endif
45+
4246
#include "backtrace.h"
4347
#include "internal.h"
4448

4549
#ifndef HAVE_GETEXECNAME
4650
#define getexecname() NULL
4751
#endif
4852

53+
#if !defined (HAVE_KERN_PROC_ARGS) && !defined (HAVE_KERN_PROC)
54+
55+
#define sysctl_exec_name1(state, error_callback, data) NULL
56+
#define sysctl_exec_name2(state, error_callback, data) NULL
57+
58+
#else /* defined (HAVE_KERN_PROC_ARGS) || |defined (HAVE_KERN_PROC) */
59+
60+
static char *
61+
sysctl_exec_name (struct backtrace_state *state,
62+
int mib0, int mib1, int mib2, int mib3,
63+
backtrace_error_callback error_callback, void *data)
64+
{
65+
int mib[4];
66+
size_t len;
67+
char *name;
68+
size_t rlen;
69+
70+
mib[0] = mib0;
71+
mib[1] = mib1;
72+
mib[2] = mib2;
73+
mib[3] = mib3;
74+
75+
if (sysctl (mib, 4, NULL, &len, NULL, 0) < 0)
76+
return NULL;
77+
name = (char *) backtrace_alloc (state, len, error_callback, data);
78+
if (name == NULL)
79+
return NULL;
80+
rlen = len;
81+
if (sysctl (mib, 4, name, &rlen, NULL, 0) < 0)
82+
{
83+
backtrace_free (state, name, len, error_callback, data);
84+
return NULL;
85+
}
86+
return name;
87+
}
88+
89+
#ifdef HAVE_KERN_PROC_ARGS
90+
91+
static char *
92+
sysctl_exec_name1 (struct backtrace_state *state,
93+
backtrace_error_callback error_callback, void *data)
94+
{
95+
/* This variant is used on NetBSD. */
96+
return sysctl_exec_name (state, CTL_KERN, KERN_PROC_ARGS, -1,
97+
KERN_PROC_PATHNAME, error_callback, data);
98+
}
99+
100+
#else
101+
102+
#define sysctl_exec_name1(state, error_callback, data) NULL
103+
104+
#endif
105+
106+
#ifdef HAVE_KERN_PROC
107+
108+
static char *
109+
sysctl_exec_name2 (struct backtrace_state *state,
110+
backtrace_error_callback error_callback, void *data)
111+
{
112+
/* This variant is used on FreeBSD. */
113+
return sysctl_exec_name (state, CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1,
114+
error_callback, data);
115+
}
116+
117+
#else
118+
119+
#define sysctl_exec_name2(state, error_callback, data) NULL
120+
121+
#endif
122+
123+
#endif /* defined (HAVE_KERN_PROC_ARGS) || |defined (HAVE_KERN_PROC) */
124+
49125
/* Initialize the fileline information from the executable. Returns 1
50126
on success, 0 on failure. */
51127

@@ -83,7 +159,7 @@ fileline_initialize (struct backtrace_state *state,
83159

84160
descriptor = -1;
85161
called_error_callback = 0;
86-
for (pass = 0; pass < 5; ++pass)
162+
for (pass = 0; pass < 7; ++pass)
87163
{
88164
int does_not_exist;
89165

@@ -106,6 +182,12 @@ fileline_initialize (struct backtrace_state *state,
106182
(long) getpid ());
107183
filename = buf;
108184
break;
185+
case 5:
186+
filename = sysctl_exec_name1 (state, error_callback, data);
187+
break;
188+
case 6:
189+
filename = sysctl_exec_name2 (state, error_callback, data);
190+
break;
109191
default:
110192
abort ();
111193
}

0 commit comments

Comments
 (0)