diff --git a/libbacktrace/ChangeLog b/libbacktrace/ChangeLog index 91e1c9eccd4..dcd49d071d6 100644 --- a/libbacktrace/ChangeLog +++ b/libbacktrace/ChangeLog @@ -1,3 +1,16 @@ +2012-11-12 Ian Lance Taylor + Rainer Orth + Gerald Pfeifer + + * configure.ac: Check for getexecname. + * fileline.c: #include . 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 * mmap.c (backtrace_vector_release): Correct last patch: add diff --git a/libbacktrace/config.h.in b/libbacktrace/config.h.in index ba564a82e85..48ff63fdc05 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 1f6a97b34ae..2a57c5102f3 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 534f9276cdb..c9cba3e4e9c 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 e577ecc9061..1ade81e9d49 100644 --- a/libbacktrace/fileline.c +++ b/libbacktrace/fileline.c @@ -34,12 +34,17 @@ POSSIBILITY OF SUCH DAMAGE. */ #include #include +#include #include #include #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 2d9d76aeba7..9b775584d47 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);