]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Let Asterisk find better backtrace information with libbfd.
authorTilghman Lesher <tilghman@meg.abyt.es>
Fri, 17 Dec 2010 21:40:56 +0000 (21:40 +0000)
committerTilghman Lesher <tilghman@meg.abyt.es>
Fri, 17 Dec 2010 21:40:56 +0000 (21:40 +0000)
The menuselect option BETTER_BACKTRACES, if enabled, will use libbfd to search
for better symbol information within both the Asterisk binary, as well as
loaded modules, to assist when using inline backtraces to track down problems.

git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.4@298905 65c4cc65-6c06-0410-ace0-fbb531ad65f3

build_tools/cflags-devmode.xml
build_tools/menuselect-deps.in
configure
configure.ac
doc/asterisk.8
include/asterisk/autoconfig.h.in
include/asterisk/utils.h
main/Makefile
main/logger.c
main/utils.c
makeopts.in

index 6e7e645c9b7a9cde1a7bd38b9428012405f15913..a501ce171564bfed920b11da2109093d62885c59 100644 (file)
@@ -14,4 +14,9 @@
                </member>
                <member name="TEST_FRAMEWORK" displayname="Enable Test Framework API">
                </member>
+               <member name="BETTER_BACKTRACES" displayname="Use libbfd to generate better inline backtraces">
+                       <depend>BFD</depend>
+                       <depend>DLADDR</depend>
+                       <defaultenabled>no</defaultenabled>
+               </member>
        </category>
index cb0bd9f7210c483a757591da3ce69e24a6e1902b..7cb90e8f13a5fab2aa677ad3491c9bc9364412ae 100644 (file)
@@ -1,8 +1,10 @@
 ASOUND=@PBX_ALSA@
+BFD=@PBX_BFD@
 BISON=@PBX_BISON@
 CURL=@PBX_CURL@
 DAHDI=@PBX_DAHDI@
 DAHDI_TRANSCODE=@PBX_DAHDI_TRANSCODE@
+DLADDR=@PBX_DLADDR@
 FLEX=@PBX_FLEX@
 FREETDS=@PBX_FREETDS@
 GSM=@PBX_GSM@
index 0b3bfeee7ee7056787bc91b125b0de34405393a0..b50a69da9cd95ce4e20d7135a714825a4ba274dc 100755 (executable)
--- a/configure
+++ b/configure
@@ -630,6 +630,7 @@ KDEDIR
 KDEINIT
 GSM_INTERNAL
 PBX_DAHDI_TRANSCODE
+PBX_DLADDR
 AST_NO_STRICT_OVERFLOW
 AST_FORTIFY_SOURCE
 AST_DECLARATION_AFTER_STATEMENT
@@ -819,6 +820,10 @@ PBX_CAP
 CAP_DIR
 CAP_INCLUDE
 CAP_LIB
+PBX_BFD
+BFD_DIR
+BFD_INCLUDE
+BFD_LIB
 PBX_ALSA
 ALSA_DIR
 ALSA_INCLUDE
@@ -934,6 +939,7 @@ enable_option_checking
 with_gnu_ld
 enable_dev_mode
 with_asound
+with_bfd
 with_cap
 with_curses
 with_dahdi
@@ -1613,6 +1619,7 @@ Optional Packages:
   --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
   --with-gnu-ld           assume the C compiler uses GNU ld [default=no]
   --with-asound=PATH      use Advanced Linux Sound Architecture files in PATH
+  --with-bfd=PATH         use Debug symbol decoding files in PATH
   --with-cap=PATH         use POSIX 1.e capabilities files in PATH
   --with-curses=PATH      use curses files in PATH
   --with-dahdi=PATH       use DAHDI files in PATH
@@ -7863,6 +7870,35 @@ PBX_ALSA=0
 
 
 
+BFD_DESCRIP="Debug symbol decoding"
+BFD_OPTION="bfd"
+
+# Check whether --with-bfd was given.
+if test "${with_bfd+set}" = set; then :
+  withval=$with_bfd;
+case ${withval} in
+     n|no)
+     USE_BFD=no
+     ;;
+     y|ye|yes)
+     BFD_MANDATORY="yes"
+     ;;
+     *)
+     BFD_DIR="${withval}"
+     BFD_MANDATORY="yes"
+     ;;
+esac
+
+fi
+
+PBX_BFD=0
+
+
+
+
+
+
+
 CAP_DESCRIP="POSIX 1.e capabilities"
 CAP_OPTION="cap"
 
@@ -13179,6 +13215,41 @@ $as_echo "#define TYPEOF_FD_SET_FDS_BITS long long" >>confdefs.h
 
 fi ; fi ; fi
 
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for dladdr in dlfcn.h" >&5
+$as_echo_n "checking for dladdr in dlfcn.h... " >&6; }
+PBX_DLADDR=0
+old_LIBS=${LIBS}
+LIBS="${LIBS} -ldl"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#define _GNU_SOURCE 1
+#include <dlfcn.h>
+int
+main ()
+{
+dladdr((void *)0, (void *)0)
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+       PBX_DLADDR=1
+
+
+$as_echo "#define HAVE_DLADDR 1" >>confdefs.h
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=${old_LIBS}
+
 
 # do the package library checks now
 
 
 
 
+if test "${USE_BFD}" != "no"; then
+   pbxlibdir=""
+   if test "x${BFD_DIR}" != "x"; then
+      if test -d ${BFD_DIR}/lib; then
+        pbxlibdir="-L${BFD_DIR}/lib"
+      else
+        pbxlibdir="-L${BFD_DIR}"
+      fi
+   fi
+   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for bfd_openr in -lbfd" >&5
+$as_echo_n "checking for bfd_openr in -lbfd... " >&6; }
+if test "${ac_cv_lib_bfd_bfd_openr+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lbfd ${pbxlibdir}  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char bfd_openr ();
+int
+main ()
+{
+return bfd_openr ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_bfd_bfd_openr=yes
+else
+  ac_cv_lib_bfd_bfd_openr=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bfd_bfd_openr" >&5
+$as_echo "$ac_cv_lib_bfd_bfd_openr" >&6; }
+if test "x$ac_cv_lib_bfd_bfd_openr" = x""yes; then :
+  AST_BFD_FOUND=yes
+else
+  AST_BFD_FOUND=no
+fi
+
+
+   if test "${AST_BFD_FOUND}" = "yes"; then
+      BFD_LIB="-lbfd "
+      BFD_HEADER_FOUND="1"
+      if test "x${BFD_DIR}" != "x"; then
+         BFD_LIB="${pbxlibdir} ${BFD_LIB}"
+        BFD_INCLUDE="-I${BFD_DIR}/include"
+      fi
+      BFD_INCLUDE="${BFD_INCLUDE} "
+      saved_cppflags="${CPPFLAGS}"
+      CPPFLAGS="${CPPFLAGS} ${BFD_INCLUDE}"
+      if test "xbfd.h" != "x" ; then
+         ac_fn_c_check_header_mongrel "$LINENO" "bfd.h" "ac_cv_header_bfd_h" "$ac_includes_default"
+if test "x$ac_cv_header_bfd_h" = x""yes; then :
+  BFD_HEADER_FOUND=1
+else
+  BFD_HEADER_FOUND=0
+fi
+
+
+      fi
+      CPPFLAGS="${saved_cppflags}"
+      if test "x${BFD_HEADER_FOUND}" = "x0" ; then
+         if test -n "${BFD_MANDATORY}" ;
+         then
+            { $as_echo "$as_me:${as_lineno-$LINENO}: ***" >&5
+$as_echo "$as_me: ***" >&6;}
+            { $as_echo "$as_me:${as_lineno-$LINENO}: *** It appears that you do not have the bfd development package installed." >&5
+$as_echo "$as_me: *** It appears that you do not have the bfd development package installed." >&6;}
+            if test "x${BFD_OPTION}" = "x" ; then
+               { $as_echo "$as_me:${as_lineno-$LINENO}: *** Please install it to include ${BFD_DESCRIP} support" >&5
+$as_echo "$as_me: *** Please install it to include ${BFD_DESCRIP} support" >&6;}
+            else
+               { $as_echo "$as_me:${as_lineno-$LINENO}: *** Please install it to include ${BFD_DESCRIP} support, or re-run configure" >&5
+$as_echo "$as_me: *** Please install it to include ${BFD_DESCRIP} support, or re-run configure" >&6;}
+               { $as_echo "$as_me:${as_lineno-$LINENO}: *** without explicitly specifying --with-${BFD_OPTION}" >&5
+$as_echo "$as_me: *** without explicitly specifying --with-${BFD_OPTION}" >&6;}
+            fi
+            exit 1
+         fi
+         BFD_LIB=""
+         BFD_INCLUDE=""
+         PBX_BFD=0
+      else
+         PBX_BFD=1
+         cat >>confdefs.h <<_ACEOF
+#define HAVE_BFD 1
+_ACEOF
+      fi
+   elif test -n "${BFD_MANDATORY}";
+   then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: ***" >&5
+$as_echo "$as_me: ***" >&6;}
+      { $as_echo "$as_me:${as_lineno-$LINENO}: *** The ${BFD_DESCRIP} installation on this system appears to be broken." >&5
+$as_echo "$as_me: *** The ${BFD_DESCRIP} installation on this system appears to be broken." >&6;}
+      if test "x${BFD_OPTION}" = "x" ; then
+         { $as_echo "$as_me:${as_lineno-$LINENO}: *** Please correct the installation" >&5
+$as_echo "$as_me: *** Please correct the installation" >&6;}
+      else
+         { $as_echo "$as_me:${as_lineno-$LINENO}: *** Either correct the installation, or run configure" >&5
+$as_echo "$as_me: *** Either correct the installation, or run configure" >&6;}
+         { $as_echo "$as_me:${as_lineno-$LINENO}: *** without explicitly specifying --with-${BFD_OPTION}" >&5
+$as_echo "$as_me: *** without explicitly specifying --with-${BFD_OPTION}" >&6;}
+      fi
+      exit 1
+   fi
+fi
+
+
+
 if test "${USE_CURSES}" != "no"; then
    pbxlibdir=""
    if test "x${CURSES_DIR}" != "x"; then
index 755631e7f760d140081f0a2392f58165c26c6aa9..4dd33748bd10b52691a0bdbecde15204ea36c158 100644 (file)
@@ -232,6 +232,7 @@ AC_SUBST(AST_DEVMODE)
 # by the --with option name, to make things easier for the users :-)
 
 AST_EXT_LIB_SETUP([ALSA], [Advanced Linux Sound Architecture], [asound])
+AST_EXT_LIB_SETUP([BFD], [Debug symbol decoding], [bfd])
 AST_EXT_LIB_SETUP([CAP], [POSIX 1.e capabilities], [cap])
 AST_EXT_LIB_SETUP([CURSES], [curses], [curses])
 AST_EXT_LIB_SETUP([DAHDI], [DAHDI], [dahdi])
@@ -673,11 +674,30 @@ else if test $ac_cv_sizeof_long_long = $ac_cv_sizeof_fd_set_fds_bits; then
   AC_DEFINE([TYPEOF_FD_SET_FDS_BITS], [long long], [Define to a type of the same size as fd_set.fds_bits[[0]]])
 fi ; fi ; fi
 
+AC_MSG_CHECKING(for dladdr in dlfcn.h)
+PBX_DLADDR=0
+old_LIBS=${LIBS}
+LIBS="${LIBS} -ldl"
+AC_LINK_IFELSE(
+       AC_LANG_PROGRAM([#define _GNU_SOURCE 1
+#include <dlfcn.h>],
+               [dladdr((void *)0, (void *)0)]
+       ),
+       AC_MSG_RESULT(yes)
+       PBX_DLADDR=1
+       AC_SUBST([PBX_DLADDR])
+       AC_DEFINE([HAVE_DLADDR], 1, [Define to 1 if your system has the dladdr() GNU extension]),
+       AC_MSG_RESULT(no)
+)
+LIBS=${old_LIBS}
+
 
 # do the package library checks now
 
 AST_EXT_LIB_CHECK([ALSA], [asound], [snd_spcm_init], [alsa/asoundlib.h], [-lm -ldl])
 
+AST_EXT_LIB_CHECK([BFD], [bfd], [bfd_openr], [bfd.h])
+
 AST_EXT_LIB_CHECK([CURSES], [curses], [initscr], [curses.h])
 
 if test "x${OSARCH}" = "xlinux-gnu" ; then
index 35f95411a05bcdf55036c2b6121506536876328c..a2fb33ea2f77d1c26aa1873563cee163e3274cf6 100644 (file)
@@ -58,10 +58,7 @@ even if it is running in the background. This will affect the size
 of your log files.
 .TP
 \fB-f\fR
-Do not fork or detach from controlling terminal.  Overrides \fB-F\fR.
-.TP
-\fB-F\fR
-Always fork and detach from controlling terminal.  Overrides \fB-f\fR.
+Do not fork or detach from controlling terminal.
 .TP
 \fB-g\fR
 Remove resource limit on core size, thus forcing Asterisk to dump
index 852caaecc8e24911b2cc645631304b047c5aed94..0a81d2787848e51f7290c0990de6b1ec9ceb57c3 100644 (file)
@@ -74,6 +74,9 @@
    attribute. */
 #undef HAVE_ATTRIBUTE_warn_unused_result
 
+/* Define to 1 if you have the Debug symbol decoding library. */
+#undef HAVE_BFD
+
 /* Define to 1 if you have the `bzero' function. */
 #undef HAVE_BZERO
 
    */
 #undef HAVE_DIRENT_H
 
+/* Define to 1 if your system has the dladdr() GNU extension */
+#undef HAVE_DLADDR
+
 /* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
 #undef HAVE_DOPRNT
 
index 85638d7b41062b20969aa0999625ade04043b688..bacb551612ac0b616090a4430538132aa27dbb9e 100644 (file)
@@ -563,4 +563,13 @@ static void force_inline _ast_assert(int condition, const char *condition_str,
 #define ast_assert(a)
 #endif
 
+/*!\brief Resolve a binary to a full pathname
+ * \param binary Name of the executable to resolve
+ * \param fullpath Buffer to hold the complete pathname
+ * \param fullpath_size Size of \a fullpath
+ * \retval NULL \a binary was not found or the environment variable PATH is not set
+ * \return \a fullpath
+ */
+char *ast_utils_which(const char *binary, char *fullpath, size_t fullpath_size);
+
 #endif /* _ASTERISK_UTILS_H */
index e91795898794b9399d9b8b06697728b1f5d81c9a..d688a58a9ee961143c2ed8fa2540778015f4ba20 100644 (file)
@@ -50,6 +50,10 @@ else
   AST_LIBS+=$(EDITLINE_LIB) -lm
 endif
 
+ifneq ($(findstring BETTER_BACKTRACES,$(MENUSELECT_CFLAGS)),)
+  AST_LIBS+=$(BFD_LIB)
+endif
+
 ifneq ($(findstring darwin,$(OSARCH)),)
   AST_LIBS+=-lresolv
   ifneq ($(findstring LOADABLE_MODULES,$(MENUSELECT_CFLAGS)),)
index 741ffb96a1525fa85183f874644d29f47019f590..18ae8f9bb18d5650ad511f2ed56ed0716127d876 100644 (file)
@@ -39,8 +39,12 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include <errno.h>
 #include <sys/stat.h>
 #if ((defined(AST_DEVMODE)) && (defined(linux)))
-#include <execinfo.h>
-#define MAX_BACKTRACE_FRAMES 20
+#  include <execinfo.h>
+#  define MAX_BACKTRACE_FRAMES 20
+#  if defined(HAVE_DLADDR) && defined(HAVE_BFD) && defined(BETTER_BACKTRACES)
+#    include <dlfcn.h>
+#    include <bfd.h>
+#  endif
 #endif
 
 #define SYSLOG_NAMES /* so we can map syslog facilities names to their numeric values,
@@ -829,31 +833,160 @@ void ast_log(int level, const char *file, int line, const char *function, const
 void ast_backtrace(void)
 {
 #ifdef linux
-#ifdef AST_DEVMODE
-       int count=0, i=0;
+#  ifdef AST_DEVMODE
+       int stackcount = 0, stackfr;
        void **addresses;
+#    if defined(HAVE_DLADDR) && defined(HAVE_BFD) && defined(BETTER_BACKTRACES)
+       bfd *bfdobj;           /* bfd.h */
+       Dl_info dli;           /* dlfcn.h */
+       long allocsize;
+       asymbol **syms = NULL; /* bfd.h */
+       bfd_vma offset;        /* bfd.h */
+       const char *lastslash;
+       asection *section;
+       const char *file, *func;
+       unsigned int line;
+       char address_str[128];
+#    else
        char **strings;
+#    endif
 
        if ((addresses = ast_calloc(MAX_BACKTRACE_FRAMES, sizeof(*addresses)))) {
-               count = backtrace(addresses, MAX_BACKTRACE_FRAMES);
-               if ((strings = backtrace_symbols(addresses, count))) {
-                       ast_log(LOG_DEBUG, "Got %d backtrace record%c\n", count, count != 1 ? 's' : ' ');
-                       for (i=0; i < count ; i++) {
-#if __WORDSIZE == 32
-                               ast_log(LOG_DEBUG, "#%d: [%08X] %s\n", i, (unsigned int)addresses[i], strings[i]);
-#elif __WORDSIZE == 64
-                               ast_log(LOG_DEBUG, "#%d: [%016lX] %s\n", i, (unsigned long)addresses[i], strings[i]);
-#endif
+               stackcount = backtrace(addresses, MAX_BACKTRACE_FRAMES);
+#    if defined(HAVE_DLADDR) && defined(HAVE_BFD) && defined(BETTER_BACKTRACES)
+               ast_log(LOG_DEBUG, "Got %d backtrace record%c\n", stackcount, stackcount != 1 ? 's' : ' ');
+               for (stackfr = 0; stackfr < stackcount; stackfr++) {
+                       int found = 0, symbolcount;
+
+                       if (!dladdr(addresses[stackfr], &dli)) {
+                               continue;
+                       }
+
+                       if (strcmp(dli.dli_fname, "asterisk") == 0) {
+                               char asteriskpath[256];
+                               if (!(dli.dli_fname = ast_utils_which("asterisk", asteriskpath, sizeof(asteriskpath)))) {
+                                       /* This will fail to find symbols */
+                                       ast_log(LOG_DEBUG, "Failed to find asterisk binary for debug symbols.\n");
+                                       dli.dli_fname = "asterisk";
+                               }
+                       }
+
+                       lastslash = strrchr(dli.dli_fname, '/');
+                       if (    (bfdobj = bfd_openr(dli.dli_fname, NULL)) &&
+                                       bfd_check_format(bfdobj, bfd_object) &&
+                                       (allocsize = bfd_get_symtab_upper_bound(bfdobj)) > 0 &&
+                                       (syms = ast_malloc(allocsize)) &&
+                                       (symbolcount = bfd_canonicalize_symtab(bfdobj, syms))) {
+
+                               if (bfdobj->flags & DYNAMIC) {
+                                       offset = addresses[stackfr] - dli.dli_fbase;
+                               } else {
+                                       offset = addresses[stackfr] - (void *) 0;
+                               }
+
+                               for (section = bfdobj->sections; section; section = section->next) {
+                                       if (    !bfd_get_section_flags(bfdobj, section) & SEC_ALLOC ||
+                                                       section->vma > offset ||
+                                                       section->size + section->vma < offset) {
+                                               continue;
+                                       }
+
+                                       if (!bfd_find_nearest_line(bfdobj, section, syms, offset - section->vma, &file, &func, &line)) {
+                                               continue;
+                                       }
+
+                                       /* Stack trace output */
+                                       found++;
+                                       lastslash = strrchr(file, '/');
+#      if __WORDSIZE == 32
+                                       if (dli.dli_saddr == NULL) {
+                                               address_str[0] = '\0';
+                                       } else {
+                                               snprintf(address_str, sizeof(address_str), " (%08lX+%lX)",
+                                                       (unsigned long) dli.dli_saddr,
+                                                       (unsigned long) (addresses[stackfr] - dli.dli_saddr));
+                                       }
+                                       ast_log(LOG_DEBUG, "#%d: [%08lX] %s:%u %s()%s\n", stackfr,
+                                               (unsigned long) addresses[stackfr],
+                                               lastslash ? lastslash + 1 : file, line,
+                                               S_OR(func, "???"),
+                                               address_str);
+#      elif __WORDSIZE == 64
+                                       if (dli.dli_saddr == NULL) {
+                                               address_str[0] = '\0';
+                                       } else {
+                                               snprintf(address_str, sizeof(address_str), " (%016lX+%lX)",
+                                                       (unsigned long) dli.dli_saddr,
+                                                       (unsigned long) (addresses[stackfr] - dli.dli_saddr));
+                                       }
+                                       ast_log(LOG_DEBUG, "#%d: [%016lX] %s:%u %s()%s\n", stackfr,
+                                               (unsigned long) addresses[stackfr],
+                                               lastslash ? lastslash + 1 : file, line,
+                                               S_OR(func, "???"),
+                                               address_str);
+#      endif
+
+                                       break;
+                               }
+                       }
+                       if (bfdobj) {
+                               bfd_close(bfdobj);
+                               if (syms) {
+                                       ast_free(syms);
+                               }
+                       }
+
+                       /* Default output, if we cannot find the information within BFD */
+                       if (!found) {
+#      if __WORDSIZE == 32
+                               if (dli.dli_saddr == NULL) {
+                                       address_str[0] = '\0';
+                               } else {
+                                       snprintf(address_str, sizeof(address_str), " (%08lX+%lX)",
+                                               (unsigned long) dli.dli_saddr,
+                                               (unsigned long) (addresses[stackfr] - dli.dli_saddr));
+                               }
+                               ast_log(LOG_DEBUG, "#%d: [%08lX] %s %s()%s\n", stackfr,
+                                       (unsigned long) addresses[stackfr],
+                                       lastslash ? lastslash + 1 : dli.dli_fname,
+                                       S_OR(dli.dli_sname, "<unknown>"),
+                                       address_str);
+#      elif __WORDSIZE == 64
+                               if (dli.dli_saddr == NULL) {
+                                       address_str[0] = '\0';
+                               } else {
+                                       snprintf(address_str, sizeof(address_str), " (%016lX+%lX)",
+                                               (unsigned long) dli.dli_saddr,
+                                               (unsigned long) (addresses[stackfr] - dli.dli_saddr));
+                               }
+                               ast_log(LOG_DEBUG, "#%d: [%016lX] %s %s()%s\n", stackfr,
+                                       (unsigned long) addresses[stackfr],
+                                       lastslash ? lastslash + 1 : dli.dli_fname,
+                                       S_OR(dli.dli_sname, "<unknown>"),
+                                       address_str);
+#      endif
+                       }
+               }
+#    else /* !defined(HAVE_DLADDR) || !defined(HAVE_BFD) || !defined(BETTER_BACKTRACES) */
+               if ((strings = backtrace_symbols(addresses, stackcount))) {
+                       ast_log(LOG_DEBUG, "Got %d backtrace record%c\n", stackcount, stackcount != 1 ? 's' : ' ');
+                       for (stackfr = 0; stackfr < stackcount ; stackfr++) {
+#      if __WORDSIZE == 32
+                               ast_log(LOG_DEBUG, "#%d: [%08X] %s\n", stackfr, (unsigned int)addresses[stackfr], strings[stackfr]);
+#      elif __WORDSIZE == 64
+                               ast_log(LOG_DEBUG, "#%d: [%016lX] %s\n", stackfr, (unsigned long)addresses[stackfr], strings[stackfr]);
+#      endif
                        }
                        free(strings);
                } else {
                        ast_log(LOG_DEBUG, "Could not allocate memory for backtrace\n");
                }
+#    endif /* defined(HAVE_DLADDR) && defined(HAVE_BFD) && defined(BETTER_BACKTRACES) */
                free(addresses);
        }
-#else
+#  else /* !defined(AST_DEVMODE) */
        ast_log(LOG_WARNING, "Must run configure with '--enable-dev-mode' for stack backtraces.\n");
-#endif
+#  endif /* defined(AST_DEVMODE) */
 #else /* ndef linux */
        ast_log(LOG_WARNING, "Inline stack backtraces are only available on the Linux platform.\n");
 #endif
index a9b887205c2312c05767fb9e8f3b082e86e31dda..17e21390ef2e91dbe4c807921c2f7e4a3f3fbc60 100644 (file)
@@ -38,6 +38,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
+#include <sys/stat.h>
 
 #define AST_API_MODULE         /* ensure that inlinable API functions will be built in lock.h if required */
 #include "asterisk/lock.h"
@@ -1441,3 +1442,22 @@ int _ast_asprintf(char **ret, const char *file, int lineno, const char *func, co
        return res;
 }
 #endif
+
+char *ast_utils_which(const char *binary, char *fullpath, size_t fullpath_size)
+{
+       const char *envPATH = getenv("PATH");
+       char *tpath, *path;
+       struct stat unused;
+       if (!envPATH) {
+               return NULL;
+       }
+       tpath = ast_strdupa(envPATH);
+       while ((path = strsep(&tpath, ":"))) {
+               snprintf(fullpath, fullpath_size, "%s/%s", path, binary);
+               if (!stat(fullpath, &unused)) {
+                       return fullpath;
+               }
+       }
+       return NULL;
+}
+
index ca3fd3267ee3747bafc321fc42eaa4106d4bd558..e0f86410d316ce269f591bf6b0d5679c9484f2fb 100644 (file)
@@ -73,6 +73,9 @@ AST_FORTIFY_SOURCE=@AST_FORTIFY_SOURCE@
 ASOUND_INCLUDE=@ALSA_INCLUDE@
 ASOUND_LIB=@ALSA_LIB@
 
+BFD_INCLUDE=@BFD_INCLUDE@
+BFD_LIB=@BFD_LIB@
+
 CURL_INCLUDE=@CURL_INCLUDE@
 CURL_LIB=@CURL_LIB@