aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--build_tools/cflags-devmode.xml6
-rw-r--r--build_tools/menuselect-deps.in2
-rwxr-xr-xconfigure256
-rw-r--r--configure.ac30
-rw-r--r--include/asterisk/autoconfig.h.in6
-rw-r--r--include/asterisk/logger.h10
-rw-r--r--include/asterisk/utils.h9
-rw-r--r--main/Makefile4
-rw-r--r--main/astobj2.c2
-rw-r--r--main/logger.c152
-rw-r--r--main/say.c2
-rw-r--r--main/utils.c22
-rw-r--r--makeopts.in3
-rw-r--r--utils/ael_main.c11
-rw-r--r--utils/check_expr.c12
-rw-r--r--utils/conf2ael.c12
-rw-r--r--utils/hashtest.c13
-rw-r--r--utils/hashtest2.c12
-rw-r--r--utils/refcounter.c13
19 files changed, 529 insertions, 48 deletions
diff --git a/build_tools/cflags-devmode.xml b/build_tools/cflags-devmode.xml
index 37f7a4d4f..85d7bc8ce 100644
--- a/build_tools/cflags-devmode.xml
+++ b/build_tools/cflags-devmode.xml
@@ -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>
diff --git a/build_tools/menuselect-deps.in b/build_tools/menuselect-deps.in
index 2a5bcd74b..35573c3bf 100644
--- a/build_tools/menuselect-deps.in
+++ b/build_tools/menuselect-deps.in
@@ -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@
diff --git a/configure b/configure
index 392e42362..af4429696 100755
--- 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.
@@ -16864,6 +16938,112 @@ fi
+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.
diff --git a/configure.ac b/configure.ac
index 32d43e786..219897632 100644
--- a/configure.ac
+++ b/configure.ac
@@ -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
diff --git a/include/asterisk/autoconfig.h.in b/include/asterisk/autoconfig.h.in
index 2ec7b7ed8..a48da3814 100644
--- a/include/asterisk/autoconfig.h.in
+++ b/include/asterisk/autoconfig.h.in
@@ -107,6 +107,9 @@
/* 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
@@ -168,6 +171,9 @@
*/
#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
diff --git a/include/asterisk/logger.h b/include/asterisk/logger.h
index 886c43ce0..91824d704 100644
--- a/include/asterisk/logger.h
+++ b/include/asterisk/logger.h
@@ -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 */
diff --git a/include/asterisk/utils.h b/include/asterisk/utils.h
index a0208e7f2..7b75db808 100644
--- a/include/asterisk/utils.h
+++ b/include/asterisk/utils.h
@@ -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 */
diff --git a/main/Makefile b/main/Makefile
index af294dda6..64ad43fbb 100644
--- a/main/Makefile
+++ b/main/Makefile
@@ -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
diff --git a/main/astobj2.c b/main/astobj2.c
index d0b438940..50886de2e 100644
--- a/main/astobj2.c
+++ b/main/astobj2.c
@@ -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]);
diff --git a/main/logger.c b/main/logger.c
index 25f252f31..23b9078b9 100644
--- a/main/logger.c
+++ b/main/logger.c
@@ -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)
diff --git a/main/say.c b/main/say.c
index b57989ef3..be4b89987 100644
--- a/main/say.c
+++ b/main/say.c
@@ -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";
diff --git a/main/utils.c b/main/utils.c
index 6f2c884d0..268ab8eb5 100644
--- a/main/utils.c
+++ b/main/utils.c
@@ -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;
+}
+
diff --git a/makeopts.in b/makeopts.in
index 5e9ef8c7a..3cde8141d 100644
--- a/makeopts.in
+++ b/makeopts.in
@@ -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@
diff --git a/utils/ael_main.c b/utils/ael_main.c
index 8b28d31d3..e5a7346ed 100644
--- a/utils/ael_main.c
+++ b/utils/ael_main.c
@@ -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)
{
diff --git a/utils/check_expr.c b/utils/check_expr.c
index a8d2e6525..b904b4824 100644
--- a/utils/check_expr.c
+++ b/utils/check_expr.c
@@ -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);
diff --git a/utils/conf2ael.c b/utils/conf2ael.c
index 48a18392c..538818b25 100644
--- a/utils/conf2ael.c
+++ b/utils/conf2ael.c
@@ -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)
{
diff --git a/utils/hashtest.c b/utils/hashtest.c
index 16c5e1d9b..9ec597f4e 100644
--- a/utils/hashtest.c
+++ b/utils/hashtest.c
@@ -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)
{
diff --git a/utils/hashtest2.c b/utils/hashtest2.c
index a9fdf661b..7953decf6 100644
--- a/utils/hashtest2.c
+++ b/utils/hashtest2.c
@@ -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;
diff --git a/utils/refcounter.c b/utils/refcounter.c
index d71ebf1d8..1c679e822 100644
--- a/utils/refcounter.c
+++ b/utils/refcounter.c
@@ -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)
{