]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Merged revisions 298957 via svnmerge from
authorTilghman Lesher <tilghman@meg.abyt.es>
Fri, 17 Dec 2010 23:52:04 +0000 (23:52 +0000)
committerTilghman Lesher <tilghman@meg.abyt.es>
Fri, 17 Dec 2010 23:52:04 +0000 (23:52 +0000)
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.
  ........
................

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

19 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/say.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 37f7a4d4f40be1cb352a6f8977793a7f6fd315d1..85d7bc8ce2d60c11da1705b9a45cacfc72c06030 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 2a5bcd74b2d727850057e18f1b7ddb1adf642e8d..35573c3bf17b5af945f22814ab0034212c741bfc 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 392e42362c5b92ecfa1ac05de0cb3bfead3824f1..af44296967a013d338bc525df44d9b8e68023f4c 100755 (executable)
--- a/configure
+++ b/configure
@@ -1,5 +1,5 @@
 #! /bin/sh
-# From configure.ac Revision: 298051 .
+# From configure.ac Revision: 298818 .
 # 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
@@ -8703,26 +8710,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
 
@@ -8895,29 +8937,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
 
@@ -16660,6 +16699,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 32d43e786032cee8e2730e0d1fd9faa998b3d538..219897632ea08ee19744eaa6933a549c9b46b59b 100644 (file)
@@ -361,16 +361,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])
@@ -1006,6 +1007,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)
 
@@ -1014,6 +1032,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 2ec7b7ed816a884893c3ad4f760b0fecdf0eb2cf..a48da38148fbc5d04086c02cda4a4ea79e89228b 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 886c43ce02bdc2c4a628cb18900c20a7ab5edd9b..91824d70440fe705007f17736b7cfc483fcbff9e 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 a0208e7f20182f003fa871418ae8e0c97cbfd1e5..7b75db808fc6b5f79561536b4f88d6d16f7abc93 100644 (file)
@@ -758,4 +758,13 @@ int ast_str_to_eid(struct ast_eid *eid, const char *s);
  */
 int ast_eid_cmp(const struct ast_eid *eid1, const struct ast_eid *eid2);
 
+/*!\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 af294dda678d0593a855d25ad71ad94f497cc131..64ad43fbb24ea5b53d65aa1b4af781a98a938997 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 d0b438940f728d87451d727069b25331977aaaad..50886de2ecbf09a0cd2ceee688268449c09ec1e2 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 25f252f31cc962d480572ef15312045c026ce879..23b9078b922839776c6f42046186b1cfdfdb3360 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
 
 #if defined(__linux__) && !defined(__NR_gettid)
@@ -1222,6 +1226,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)
@@ -1236,7 +1384,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]);
@@ -1251,7 +1399,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 b57989ef39098245f6d8f19b90cb3377602e9281..be4b899874847d8a4420f064d9e9f42c109d1952 100644 (file)
@@ -3680,6 +3680,8 @@ int ast_say_date_with_format_en(struct ast_channel *chan, time_t t, const char *
        int res=0, offset, sndoffset;
        char sndfile[256], nextmsg[256];
 
+       ast_backtrace();
+
        if (format == NULL)
                format = "ABdY 'digits/at' IMp";
 
index 6f2c884d0ffc766f0317e8ca7fa458f870c55fe1..268ab8eb5ca952e291d7e5142413c87f074c6cc5 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>
@@ -739,7 +740,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) {
@@ -2081,3 +2082,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 5e9ef8c7aa8c3cb72c552a01241be1ac9f757bff..3cde8141d43811c980b30b3bb72e9ff7b36ea393 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 8b28d31d3b1da7b8fac2d4f38c0d760026f13e92..e5a7346edb2977c4f55a1a68eebe8cb7a140aa19 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 a8d2e6525baaa06db3db973711490e6f751a1403..b904b482464672a896089f7e8f2ff6f0c91f7f0d 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 48a18392c363532ac3e101ac6f9c97c8b0ad1c34..538818b2509bb4e9dbafd23eeaf34f9529989e6a 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 16c5e1d9b18caa2d023b02525c8c56faa06ed9bb..9ec597f4e7ecf5388e9fb06b4e8fbca718e5df3a 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 a9fdf661b6b68f784d5da76fdef095e4a7a41a48..7953decf6613f047409a3a397331cb5e88583992 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 d71ebf1d8a32d5cdcbbeda5016195192bc05b412..1c679e8221460bd868eeace48d8f05e84b72da0b 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)
 {