Merged revisions 298960 via svnmerge from
authorTilghman Lesher <tilghman@meg.abyt.es>
Sat, 18 Dec 2010 00:08:13 +0000 (00:08 +0000)
committerTilghman Lesher <tilghman@meg.abyt.es>
Sat, 18 Dec 2010 00:08:13 +0000 (00:08 +0000)
https://origsvn.digium.com/svn/asterisk/branches/1.8

................
  r298960 | tilghman | 2010-12-17 17:52:04 -0600 (Fri, 17 Dec 2010) | 20 lines

  Merged revisions 298957 via svnmerge from
  https://origsvn.digium.com/svn/asterisk/branches/1.6.2

  ................
    r298957 | tilghman | 2010-12-17 17:30:55 -0600 (Fri, 17 Dec 2010) | 13 lines

    Merged revisions 298905 via svnmerge from
    https://origsvn.digium.com/svn/asterisk/branches/1.4

    ........
      r298905 | tilghman | 2010-12-17 15:40:56 -0600 (Fri, 17 Dec 2010) | 6 lines

      Let Asterisk find better backtrace information with libbfd.

      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.

      Review: https://reviewboard.asterisk.org/r/1055/
    ........
  ................
................

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

18 files changed:
build_tools/cflags-devmode.xml
build_tools/menuselect-deps.in
configure
configure.ac
include/asterisk/autoconfig.h.in
include/asterisk/logger.h
include/asterisk/utils.h
main/Makefile
main/astobj2.c
main/logger.c
main/utils.c
makeopts.in
utils/ael_main.c
utils/check_expr.c
utils/conf2ael.c
utils/hashtest.c
utils/hashtest2.c
utils/refcounter.c

index 37f7a4d..85d7bc8 100644 (file)
@@ -22,5 +22,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 2a5bcd7..35573c3 100644 (file)
@@ -1,9 +1,11 @@
 ALSA=@PBX_ALSA@
 BLUETOOTH=@PBX_BLUETOOTH@
 CRYPTO=@PBX_CRYPTO@
+BFD=@PBX_BFD@
 BISON=@PBX_BISON@
 CURL=@PBX_CURL@
 DAHDI=@PBX_DAHDI@
+DLADDR=@PBX_DLADDR@
 FLEX=@PBX_FLEX@
 FREETDS=@PBX_FREETDS@
 GENERIC_ODBC=@PBX_GENERIC_ODBC@
index 82465db..76e68d7 100755 (executable)
--- a/configure
+++ b/configure
@@ -1,5 +1,5 @@
 #! /bin/sh
-# From configure.ac Revision: 298137 .
+# From configure.ac Revision: 298819 .
 # Guess values for system-dependent variables and create Makefiles.
 # Generated by GNU Autoconf 2.65 for asterisk trunk.
 #
@@ -650,6 +650,7 @@ CONFIG_LIBXML2
 GSM_INTERNAL
 PBX_DAHDI_HALF_FULL
 PKGCONFIG
+PBX_DLADDR
 PBX_IP_MTU_DISCOVER
 PBX_GLOB_BRACE
 PBX_GLOB_NOMAGIC
@@ -977,10 +978,10 @@ PBX_GSM
 GSM_DIR
 GSM_INCLUDE
 GSM_LIB
-PBX_BKTR
-BKTR_DIR
-BKTR_INCLUDE
-BKTR_LIB
+PBX_FFMPEG
+FFMPEG_DIR
+FFMPEG_INCLUDE
+FFMPEG_LIB
 PBX_DAHDI
 DAHDI_DIR
 DAHDI_INCLUDE
@@ -1001,10 +1002,14 @@ PBX_BLUETOOTH
 BLUETOOTH_DIR
 BLUETOOTH_INCLUDE
 BLUETOOTH_LIB
-PBX_FFMPEG
-FFMPEG_DIR
-FFMPEG_INCLUDE
-FFMPEG_LIB
+PBX_BKTR
+BKTR_DIR
+BKTR_INCLUDE
+BKTR_LIB
+PBX_BFD
+BFD_DIR
+BFD_INCLUDE
+BFD_LIB
 PBX_ALSA
 ALSA_DIR
 ALSA_INCLUDE
@@ -1149,13 +1154,14 @@ with_gnu_ld
 enable_dev_mode
 enable_coverage
 with_asound
-with_avcodec
+with_bfd
+with_execinfo
 with_bluetooth
 with_cap
 with_curses
 with_crypto
 with_dahdi
-with_execinfo
+with_avcodec
 with_gsm
 with_gtk2
 with_gmime
@@ -1860,13 +1866,14 @@ 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-avcodec=PATH     use Ffmpeg and avcodec files in PATH
+  --with-bfd=PATH         use Debug symbol decoding files in PATH
+  --with-execinfo=PATH    use Stack Backtrace files in PATH
   --with-bluetooth=PATH   use Bluetooth files in PATH
   --with-cap=PATH         use POSIX 1.e capabilities files in PATH
   --with-curses=PATH      use curses files in PATH
   --with-crypto=PATH      use OpenSSL Cryptography files in PATH
   --with-dahdi=PATH       use DAHDI files in PATH
-  --with-execinfo=PATH    use Stack Backtrace files in PATH
+  --with-avcodec=PATH     use Ffmpeg and avcodec files in PATH
   --with-gsm=PATH         use External GSM files in PATH, use 'internal' GSM
                           otherwise
   --with-gtk2=PATH        use gtk2 files in PATH
@@ -8706,26 +8713,61 @@ fi
 
 
 
-    FFMPEG_DESCRIP="Ffmpeg and avcodec"
-    FFMPEG_OPTION="avcodec"
-    PBX_FFMPEG=0
+    BFD_DESCRIP="Debug symbol decoding"
+    BFD_OPTION="bfd"
+    PBX_BFD=0
 
-# Check whether --with-avcodec was given.
-if test "${with_avcodec+set}" = set; then :
-  withval=$with_avcodec;
+# Check whether --with-bfd was given.
+if test "${with_bfd+set}" = set; then :
+  withval=$with_bfd;
        case ${withval} in
        n|no)
-       USE_FFMPEG=no
+       USE_BFD=no
        # -1 is a magic value used by menuselect to know that the package
        # was disabled, other than 'not found'
-       PBX_FFMPEG=-1
+       PBX_BFD=-1
        ;;
        y|ye|yes)
-       ac_mandatory_list="${ac_mandatory_list} FFMPEG"
+       ac_mandatory_list="${ac_mandatory_list} BFD"
        ;;
        *)
-       FFMPEG_DIR="${withval}"
-       ac_mandatory_list="${ac_mandatory_list} FFMPEG"
+       BFD_DIR="${withval}"
+       ac_mandatory_list="${ac_mandatory_list} BFD"
+       ;;
+       esac
+
+fi
+
+
+
+
+
+
+
+
+# BKTR is used for backtrace support on platforms that do not
+# have it natively.
+
+    BKTR_DESCRIP="Stack Backtrace"
+    BKTR_OPTION="execinfo"
+    PBX_BKTR=0
+
+# Check whether --with-execinfo was given.
+if test "${with_execinfo+set}" = set; then :
+  withval=$with_execinfo;
+       case ${withval} in
+       n|no)
+       USE_BKTR=no
+       # -1 is a magic value used by menuselect to know that the package
+       # was disabled, other than 'not found'
+       PBX_BKTR=-1
+       ;;
+       y|ye|yes)
+       ac_mandatory_list="${ac_mandatory_list} BKTR"
+       ;;
+       *)
+       BKTR_DIR="${withval}"
+       ac_mandatory_list="${ac_mandatory_list} BKTR"
        ;;
        esac
 
@@ -8898,29 +8940,26 @@ fi
 
 
 
-# BKTR is used for backtrace support on platforms that do not
-# have it natively.
-
-    BKTR_DESCRIP="Stack Backtrace"
-    BKTR_OPTION="execinfo"
-    PBX_BKTR=0
+    FFMPEG_DESCRIP="Ffmpeg and avcodec"
+    FFMPEG_OPTION="avcodec"
+    PBX_FFMPEG=0
 
-# Check whether --with-execinfo was given.
-if test "${with_execinfo+set}" = set; then :
-  withval=$with_execinfo;
+# Check whether --with-avcodec was given.
+if test "${with_avcodec+set}" = set; then :
+  withval=$with_avcodec;
        case ${withval} in
        n|no)
-       USE_BKTR=no
+       USE_FFMPEG=no
        # -1 is a magic value used by menuselect to know that the package
        # was disabled, other than 'not found'
-       PBX_BKTR=-1
+       PBX_FFMPEG=-1
        ;;
        y|ye|yes)
-       ac_mandatory_list="${ac_mandatory_list} BKTR"
+       ac_mandatory_list="${ac_mandatory_list} FFMPEG"
        ;;
        *)
-       BKTR_DIR="${withval}"
-       ac_mandatory_list="${ac_mandatory_list} BKTR"
+       FFMPEG_DIR="${withval}"
+       ac_mandatory_list="${ac_mandatory_list} FFMPEG"
        ;;
        esac
 
@@ -16677,6 +16716,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}
+
 # PKGCONFIG is used in later tests
 if test -n "$ac_tool_prefix"; then
   # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args.
 
 
 
+if test "x${PBX_BFD}" != "x1" -a "${USE_BFD}" != "no"; then
+   pbxlibdir=""
+   # if --with-BFD=DIR has been specified, use it.
+   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
+   pbxfuncname="bfd_openr"
+   if test "x${pbxfuncname}" = "x" ; then   # empty lib, assume only headers
+      AST_BFD_FOUND=yes
+   else
+      ast_ext_lib_check_save_CFLAGS="${CFLAGS}"
+      CFLAGS="${CFLAGS} "
+      as_ac_Lib=`$as_echo "ac_cv_lib_bfd_${pbxfuncname}" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lbfd" >&5
+$as_echo_n "checking for ${pbxfuncname} in -lbfd... " >&6; }
+if { as_var=$as_ac_Lib; eval "test \"\${$as_var+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 ${pbxfuncname} ();
+int
+main ()
+{
+return ${pbxfuncname} ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  eval "$as_ac_Lib=yes"
+else
+  eval "$as_ac_Lib=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+eval ac_res=\$$as_ac_Lib
+              { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+eval as_val=\$$as_ac_Lib
+   if test "x$as_val" = x""yes; then :
+  AST_BFD_FOUND=yes
+else
+  AST_BFD_FOUND=no
+fi
+
+      CFLAGS="${ast_ext_lib_check_save_CFLAGS}"
+   fi
+
+   # now check for the header.
+   if test "${AST_BFD_FOUND}" = "yes"; then
+      BFD_LIB="${pbxlibdir} -lbfd "
+      # if --with-BFD=DIR has been specified, use it.
+      if test "x${BFD_DIR}" != "x"; then
+         BFD_INCLUDE="-I${BFD_DIR}/include"
+      fi
+      BFD_INCLUDE="${BFD_INCLUDE} "
+      if test "xbfd.h" = "x" ; then    # no header, assume found
+         BFD_HEADER_FOUND="1"
+      else                             # check for the header
+         ast_ext_lib_check_saved_CPPFLAGS="${CPPFLAGS}"
+         CPPFLAGS="${CPPFLAGS} ${BFD_INCLUDE}"
+         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
+
+
+         CPPFLAGS="${ast_ext_lib_check_saved_CPPFLAGS}"
+      fi
+      if test "x${BFD_HEADER_FOUND}" = "x0" ; then
+         BFD_LIB=""
+         BFD_INCLUDE=""
+      else
+         if test "x${pbxfuncname}" = "x" ; then                # only checking headers -> no library
+            BFD_LIB=""
+         fi
+         PBX_BFD=1
+         cat >>confdefs.h <<_ACEOF
+#define HAVE_BFD 1
+_ACEOF
+
+      fi
+   fi
+fi
+
+
+
+
 if test "x${PBX_CURSES}" != "x1" -a "${USE_CURSES}" != "no"; then
    pbxlibdir=""
    # if --with-CURSES=DIR has been specified, use it.
index 8bc894d..593b5c7 100644 (file)
@@ -364,16 +364,17 @@ AC_SUBST(AST_CODE_COVERAGE)
 # to make things easier for the users.
 
 AST_EXT_LIB_SETUP([ALSA], [Advanced Linux Sound Architecture], [asound])
-AST_EXT_LIB_SETUP([FFMPEG], [Ffmpeg and avcodec], [avcodec])
+AST_EXT_LIB_SETUP([BFD], [Debug symbol decoding], [bfd])
+
+# BKTR is used for backtrace support on platforms that do not
+# have it natively.
+AST_EXT_LIB_SETUP([BKTR], [Stack Backtrace], [execinfo])
 AST_EXT_LIB_SETUP([BLUETOOTH], [Bluetooth], [bluetooth])
 AST_EXT_LIB_SETUP([CAP], [POSIX 1.e capabilities], [cap])
 AST_EXT_LIB_SETUP([CURSES], [curses], [curses])
 AST_EXT_LIB_SETUP([CRYPTO], [OpenSSL Cryptography], [crypto])
 AST_EXT_LIB_SETUP([DAHDI], [DAHDI], [dahdi])
-
-# BKTR is used for backtrace support on platforms that do not
-# have it natively.
-AST_EXT_LIB_SETUP([BKTR], [Stack Backtrace], [execinfo])
+AST_EXT_LIB_SETUP([FFMPEG], [Ffmpeg and avcodec], [avcodec])
 AST_EXT_LIB_SETUP([GSM], [External GSM], [gsm], [, use 'internal' GSM otherwise])
 AST_EXT_LIB_SETUP([GTK2], [gtk2], [gtk2])
 AST_EXT_LIB_SETUP([GMIME], [GMime], [gmime])
@@ -1012,6 +1013,23 @@ 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}
+
 # PKGCONFIG is used in later tests
 AC_CHECK_TOOL(PKGCONFIG, pkg-config, No)
 
@@ -1020,6 +1038,8 @@ AC_CHECK_TOOL(PKGCONFIG, pkg-config, No)
 
 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 5ef3dc1..d59eef2 100644 (file)
 /* Define to 1 if your GCC C compiler supports the 'weakref' attribute. */
 #undef HAVE_ATTRIBUTE_weakref
 
+/* Define to 1 if you have the Debug symbol decoding library. */
+#undef HAVE_BFD
+
 /* Define to 1 if you have the Stack Backtrace library. */
 #undef HAVE_BKTR
 
    */
 #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 886c43c..91824d7 100644 (file)
@@ -296,6 +296,16 @@ int ast_bt_get_addresses(struct ast_bt *bt);
  */
 void *ast_bt_destroy(struct ast_bt *bt);
 
+/* \brief Retrieve symbols for a set of backtrace addresses
+ *
+ * \param addresses A list of addresses, such as the ->addresses structure element of struct ast_bt.
+ * \param num_frames Number of addresses in the addresses list
+ * \retval NULL Unable to allocate memory
+ * \return List of strings
+ * \since 1.6.2.16
+ */
+char **ast_bt_get_symbols(void **addresses, size_t num_frames);
+
 #endif /* HAVE_BKTR */
 #endif /* _LOGGER_BACKTRACE_H */
 
index 97f32bf..3d3f18f 100644 (file)
@@ -765,4 +765,13 @@ int ast_eid_cmp(const struct ast_eid *eid1, const struct ast_eid *eid2);
  */
 int ast_get_tid(void);
 
+/*!\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 0bb7c97..ad4d39c 100644 (file)
@@ -46,6 +46,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
   ASTLINK=-Xlinker -macosx_version_min -Xlinker 10.4 -Xlinker -undefined -Xlinker dynamic_lookup -force_flat_namespace
index d0b4389..50886de 100644 (file)
@@ -88,7 +88,7 @@ void ao2_bt(void)
        char **strings;
 
        c = backtrace(addresses, N1);
-       strings = backtrace_symbols(addresses,c);
+       strings = ast_bt_get_symbols(addresses,c);
        ast_verbose("backtrace returned: %d\n", c);
        for(i = 0; i < c; i++) {
                ast_verbose("%d: %p %s\n", i, addresses[i], strings[i]);
index 430f01f..12f835f 100644 (file)
@@ -56,6 +56,10 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #ifdef HAVE_BKTR
 #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
 
 static char dateformat[256] = "%b %e %T";              /* Original Asterisk Format */
@@ -1213,6 +1217,150 @@ void *ast_bt_destroy(struct ast_bt *bt)
        return NULL;
 }
 
+char **ast_bt_get_symbols(void **addresses, size_t num_frames)
+{
+       char **strings = NULL;
+#if defined(BETTER_BACKTRACES)
+       int stackfr;
+       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];
+       char msg[1024];
+       size_t strings_size;
+       size_t *eachlen;
+#endif
+
+#if defined(BETTER_BACKTRACES)
+       strings_size = num_frames * sizeof(*strings);
+       eachlen = ast_calloc(num_frames, sizeof(*eachlen));
+
+       if (!(strings = ast_calloc(num_frames, sizeof(*strings)))) {
+               return NULL;
+       }
+
+       for (stackfr = 0; stackfr < num_frames; stackfr++) {
+               int found = 0, symbolcount;
+
+               msg[0] = '\0';
+
+               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++;
+                               if ((lastslash = strrchr(file, '/'))) {
+                                       const char *prevslash;
+                                       for (prevslash = lastslash - 1; *prevslash != '/' && prevslash >= file; prevslash--);
+                                       if (prevslash >= file) {
+                                               lastslash = prevslash;
+                                       }
+                               }
+                               if (dli.dli_saddr == NULL) {
+                                       address_str[0] = '\0';
+                               } else {
+                                       snprintf(address_str, sizeof(address_str), " (%p+%lX)",
+                                               dli.dli_saddr,
+                                               (unsigned long) (addresses[stackfr] - dli.dli_saddr));
+                               }
+                               snprintf(msg, sizeof(msg), "%s:%u %s()%s",
+                                       lastslash ? lastslash + 1 : file, line,
+                                       S_OR(func, "???"),
+                                       address_str);
+
+                               break; /* out of section iteration */
+                       }
+               }
+               if (bfdobj) {
+                       bfd_close(bfdobj);
+                       if (syms) {
+                               ast_free(syms);
+                       }
+               }
+
+               /* Default output, if we cannot find the information within BFD */
+               if (!found) {
+                       if (dli.dli_saddr == NULL) {
+                               address_str[0] = '\0';
+                       } else {
+                               snprintf(address_str, sizeof(address_str), " (%p+%lX)",
+                                       dli.dli_saddr,
+                                       (unsigned long) (addresses[stackfr] - dli.dli_saddr));
+                       }
+                       snprintf(msg, sizeof(msg), "%s %s()%s",
+                               lastslash ? lastslash + 1 : dli.dli_fname,
+                               S_OR(dli.dli_sname, "<unknown>"),
+                               address_str);
+               }
+
+               if (!ast_strlen_zero(msg)) {
+                       char **tmp;
+                       eachlen[stackfr] = strlen(msg);
+                       if (!(tmp = ast_realloc(strings, strings_size + eachlen[stackfr] + 1))) {
+                               ast_free(strings);
+                               strings = NULL;
+                               break; /* out of stack frame iteration */
+                       }
+                       strings = tmp;
+                       strings[stackfr] = (char *) strings + strings_size;
+                       ast_copy_string(strings[stackfr], msg, eachlen[stackfr] + 1);
+                       strings_size += eachlen[stackfr] + 1;
+               }
+       }
+
+       if (strings) {
+               /* Recalculate the offset pointers */
+               strings[0] = (char *) strings + num_frames * sizeof(*strings);
+               for (stackfr = 1; stackfr < num_frames; stackfr++) {
+                       strings[stackfr] = strings[stackfr - 1] + eachlen[stackfr - 1] + 1;
+               }
+       }
+#else /* !defined(BETTER_BACKTRACES) */
+       strings = backtrace_symbols(addresses, num_frames);
+#endif /* defined(BETTER_BACKTRACES) */
+       return strings;
+}
+
 #endif /* HAVE_BKTR */
 
 void ast_backtrace(void)
@@ -1227,7 +1375,7 @@ void ast_backtrace(void)
                return;
        }
 
-       if ((strings = backtrace_symbols(bt->addresses, bt->num_frames))) {
+       if ((strings = ast_bt_get_symbols(bt->addresses, bt->num_frames))) {
                ast_debug(1, "Got %d backtrace record%c\n", bt->num_frames, bt->num_frames != 1 ? 's' : ' ');
                for (i = 3; i < bt->num_frames - 2; i++) {
                        ast_log(LOG_DEBUG, "#%d: [%p] %s\n", i - 3, bt->addresses[i], strings[i]);
@@ -1242,7 +1390,7 @@ void ast_backtrace(void)
        ast_bt_destroy(bt);
 #else
        ast_log(LOG_WARNING, "Must run configure with '--with-execinfo' for stack backtraces.\n");
-#endif
+#endif /* defined(HAVE_BKTR) */
 }
 
 void __ast_verbose_ap(const char *file, int line, const char *func, const char *fmt, va_list ap)
index 7ac62bd..f8ec82f 100644 (file)
@@ -29,6 +29,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
 #include <ctype.h>
 #include <sys/stat.h>
+#include <sys/stat.h>
 
 #ifdef HAVE_DEV_URANDOM
 #include <fcntl.h>
@@ -746,7 +747,7 @@ static void append_backtrace_information(struct ast_str **str, struct ast_bt *bt
                return;
        }
 
-       if ((symbols = backtrace_symbols(bt->addresses, bt->num_frames))) {
+       if ((symbols = ast_bt_get_symbols(bt->addresses, bt->num_frames))) {
                int frame_iterator;
                
                for (frame_iterator = 0; frame_iterator < bt->num_frames; ++frame_iterator) {
@@ -2106,3 +2107,22 @@ int ast_get_tid(void)
 #endif
        return ret;
 }
+
+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 5e9ef8c..3cde814 100644 (file)
@@ -104,6 +104,9 @@ AST_FORTIFY_SOURCE=@AST_FORTIFY_SOURCE@
 ALSA_INCLUDE=@ALSA_INCLUDE@
 ALSA_LIB=@ALSA_LIB@
 
+BFD_INCLUDE=@BFD_INCLUDE@
+BFD_LIB=@BFD_LIB@
+
 BLUETOOTH_INCLUDE=@BLUETOOTH_INCLUDE@
 BLUETOOTH_LIB=@BLUETOOTH_LIB@
 
index 8b28d31..e5a7346 100644 (file)
@@ -591,6 +591,17 @@ int ast_bt_get_addresses(struct ast_bt *bt)
        return 0;
 }
 
+char **ast_bt_get_symbols(void **addresses, size_t num_frames)
+{
+       char **foo = calloc(num_frames, sizeof(char *) + 1);
+       if (foo) {
+               int i;
+               for (i = 0; i < num_frames; i++) {
+                       foo[i] = (char *) foo + sizeof(char *) * num_frames;
+               }
+       }
+       return foo;
+}
 #else
 void ast_remove_lock_info(void *lock_addr)
 {
index a8d2e65..b904b48 100644 (file)
@@ -73,6 +73,18 @@ int ast_bt_get_addresses(struct ast_bt *bt)
        /* Suck it, you stupid utils directory! */
        return 0;
 }
+char **ast_bt_get_symbols(void **addresses, size_t num_frames);
+char **ast_bt_get_symbols(void **addresses, size_t num_frames)
+{
+       char **foo = calloc(num_frames, sizeof(char *) + 1);
+       if (foo) {
+               int i;
+               for (i = 0; i < num_frames; i++) {
+                       foo[i] = (char *) foo + sizeof(char *) * num_frames;
+               }
+       }
+       return foo;
+}
 #else
 void ast_store_lock_info(enum ast_lock_type type, const char *filename,
                        int line_num, const char *func, const char *lock_name, void *lock_addr);
index 48a1839..538818b 100644 (file)
@@ -724,6 +724,18 @@ int ast_bt_get_addresses(struct ast_bt *bt)
        return 0;
 }
 
+char **ast_bt_get_symbols(void **addresses, size_t num_frames)
+{
+       char **foo = calloc(num_frames, sizeof(char *) + 1);
+       if (foo) {
+               int i;
+               for (i = 0; i < num_frames; i++) {
+                       foo[i] = (char *) foo + sizeof(char *) * num_frames;
+               }
+       }
+       return foo;
+}
+
 #else
 void ast_remove_lock_info(void *lock_addr)
 {
index 16c5e1d..9ec597f 100644 (file)
@@ -385,6 +385,19 @@ int ast_bt_get_addresses(struct ast_bt *bt)
        return 0;
 }
 
+char **ast_bt_get_symbols(void **addresses, size_t num_frames);
+char **ast_bt_get_symbols(void **addresses, size_t num_frames)
+{
+       char **foo = calloc(num_frames, sizeof(char *) + 1);
+       if (foo) {
+               int i;
+               for (i = 0; i < num_frames; i++) {
+                       foo[i] = (char *) foo + sizeof(char *) * num_frames;
+               }
+       }
+       return foo;
+}
+
 void *ast_bt_destroy(struct ast_bt *bt);
 void *ast_bt_destroy(struct ast_bt *bt)
 {
index a9fdf66..7953dec 100644 (file)
@@ -395,6 +395,18 @@ int ast_bt_get_addresses(struct ast_bt *bt)
        return -1;
 }
 
+char **ast_bt_get_symbols(void **addresses, size_t num_frames)
+{
+       char **foo = calloc(num_frames, sizeof(char *) + 1);
+       if (foo) {
+               int i;
+               for (i = 0; i < num_frames; i++) {
+                       foo[i] = (char *) foo + sizeof(char *) * num_frames;
+               }
+       }
+       return foo;
+}
+
 void *ast_bt_destroy(struct ast_bt *bt)
 {
        return NULL;
index d71ebf1..1c679e8 100644 (file)
@@ -287,6 +287,19 @@ int ast_bt_get_addresses(struct ast_bt *bt)
        return 0;
 }
 
+char **ast_bt_get_symbols(void **addresses, size_t num_frames);
+char **ast_bt_get_symbols(void **addresses, size_t num_frames)
+{
+       char **foo = calloc(num_frames, sizeof(char *) + 1);
+       if (foo) {
+               int i;
+               for (i = 0; i < num_frames; i++) {
+                       foo[i] = (char *) foo + sizeof(char *) * num_frames;
+               }
+       }
+       return foo;
+}
+
 void *ast_bt_destroy(struct ast_bt *bt);
 void *ast_bt_destroy(struct ast_bt *bt)
 {