From 261356844a6cb3404f2627a58302f296fb6bebb2 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Sat, 15 Feb 2020 15:29:02 -0800 Subject: [PATCH] libbacktrace: support fetching executable name using sysctl 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 | 10 +++++ libbacktrace/config.h.in | 8 ++++ libbacktrace/configure | 70 ++++++++++++++++++++++++++++++++ libbacktrace/configure.ac | 30 ++++++++++++++ libbacktrace/fileline.c | 84 ++++++++++++++++++++++++++++++++++++++- 5 files changed, 201 insertions(+), 1 deletion(-) diff --git a/libbacktrace/ChangeLog b/libbacktrace/ChangeLog index c031dffb6b9..1739be9eedd 100644 --- a/libbacktrace/ChangeLog +++ b/libbacktrace/ChangeLog @@ -1,3 +1,13 @@ +2020-05-08 Ian Lance Taylor + + * 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 * ztest.c (test_large): Update file to current libgo test file. diff --git a/libbacktrace/config.h.in b/libbacktrace/config.h.in index d2c0bdb260a..034ef81c3ec 100644 --- a/libbacktrace/config.h.in +++ b/libbacktrace/config.h.in @@ -34,6 +34,14 @@ /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H +/* Define to 1 if you have KERN_PROC and KERN_PROC_PATHNAME in . + */ +#undef HAVE_KERN_PROC + +/* Define to 1 if you have KERN_PROCARGS and KERN_PROC_PATHNAME in + . */ +#undef HAVE_KERN_PROC_ARGS + /* Define to 1 if you have the header file. */ #undef HAVE_LINK_H diff --git a/libbacktrace/configure b/libbacktrace/configure index 676adb89224..33ce5891e6e 100755 --- a/libbacktrace/configure +++ b/libbacktrace/configure @@ -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 +#include + +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 +#include + +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 : diff --git a/libbacktrace/configure.ac b/libbacktrace/configure.ac index 3730d7c4b06..5beed68ccf6 100644 --- a/libbacktrace/configure.ac +++ b/libbacktrace/configure.ac @@ -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 +#include +], [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 .]) +fi + +AC_CACHE_CHECK([for KERN_PROG_ARGS], +[libbacktrace_cv_procargs], +[AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([ +#include +#include +], [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 .]) +fi + # Check for the clock_gettime function. AC_CHECK_FUNCS(clock_gettime) clock_gettime_link= diff --git a/libbacktrace/fileline.c b/libbacktrace/fileline.c index fd5edbe5ddb..cc1011e8b5d 100644 --- a/libbacktrace/fileline.c +++ b/libbacktrace/fileline.c @@ -39,6 +39,10 @@ POSSIBILITY OF SUCH DAMAGE. */ #include #include +#if defined (HAVE_KERN_PROC_ARGS) || defined (HAVE_KERN_PROC) +#include +#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 (); } -- 2.30.2