[asterisk-commits] tilghman: branch 1.4 r298905 - in /branches/1.4: ./ build_tools/ doc/ include...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Fri Dec 17 21:41:00 UTC 2010


Author: tilghman
Date: Fri Dec 17 15:40:56 2010
New Revision: 298905

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=298905
Log:
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.

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

Modified: branches/1.4/build_tools/cflags-devmode.xml
URL: http://svnview.digium.com/svn/asterisk/branches/1.4/build_tools/cflags-devmode.xml?view=diff&rev=298905&r1=298904&r2=298905
==============================================================================
--- branches/1.4/build_tools/cflags-devmode.xml (original)
+++ branches/1.4/build_tools/cflags-devmode.xml Fri Dec 17 15:40:56 2010
@@ -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>

Modified: branches/1.4/build_tools/menuselect-deps.in
URL: http://svnview.digium.com/svn/asterisk/branches/1.4/build_tools/menuselect-deps.in?view=diff&rev=298905&r1=298904&r2=298905
==============================================================================
--- branches/1.4/build_tools/menuselect-deps.in (original)
+++ branches/1.4/build_tools/menuselect-deps.in Fri Dec 17 15:40:56 2010
@@ -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@

Modified: branches/1.4/configure.ac
URL: http://svnview.digium.com/svn/asterisk/branches/1.4/configure.ac?view=diff&rev=298905&r1=298904&r2=298905
==============================================================================
--- branches/1.4/configure.ac (original)
+++ branches/1.4/configure.ac Fri Dec 17 15:40:56 2010
@@ -232,6 +232,7 @@
 # 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,10 +674,29 @@
   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])
 

Modified: branches/1.4/doc/asterisk.8
URL: http://svnview.digium.com/svn/asterisk/branches/1.4/doc/asterisk.8?view=diff&rev=298905&r1=298904&r2=298905
==============================================================================
--- branches/1.4/doc/asterisk.8 (original)
+++ branches/1.4/doc/asterisk.8 Fri Dec 17 15:40:56 2010
@@ -58,10 +58,7 @@
 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

Modified: branches/1.4/include/asterisk/autoconfig.h.in
URL: http://svnview.digium.com/svn/asterisk/branches/1.4/include/asterisk/autoconfig.h.in?view=diff&rev=298905&r1=298904&r2=298905
==============================================================================
--- branches/1.4/include/asterisk/autoconfig.h.in (original)
+++ branches/1.4/include/asterisk/autoconfig.h.in Fri Dec 17 15:40:56 2010
@@ -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
 
@@ -98,6 +101,9 @@
 /* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
    */
 #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

Modified: branches/1.4/include/asterisk/utils.h
URL: http://svnview.digium.com/svn/asterisk/branches/1.4/include/asterisk/utils.h?view=diff&rev=298905&r1=298904&r2=298905
==============================================================================
--- branches/1.4/include/asterisk/utils.h (original)
+++ branches/1.4/include/asterisk/utils.h Fri Dec 17 15:40:56 2010
@@ -563,4 +563,13 @@
 #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 */

Modified: branches/1.4/main/Makefile
URL: http://svnview.digium.com/svn/asterisk/branches/1.4/main/Makefile?view=diff&rev=298905&r1=298904&r2=298905
==============================================================================
--- branches/1.4/main/Makefile (original)
+++ branches/1.4/main/Makefile Fri Dec 17 15:40:56 2010
@@ -48,6 +48,10 @@
   AST_LIBS+=-lpthread $(EDITLINE_LIB) -lm -lresolv
 else
   AST_LIBS+=$(EDITLINE_LIB) -lm
+endif
+
+ifneq ($(findstring BETTER_BACKTRACES,$(MENUSELECT_CFLAGS)),)
+  AST_LIBS+=$(BFD_LIB)
 endif
 
 ifneq ($(findstring darwin,$(OSARCH)),)

Modified: branches/1.4/main/logger.c
URL: http://svnview.digium.com/svn/asterisk/branches/1.4/main/logger.c?view=diff&rev=298905&r1=298904&r2=298905
==============================================================================
--- branches/1.4/main/logger.c (original)
+++ branches/1.4/main/logger.c Fri Dec 17 15:40:56 2010
@@ -39,8 +39,12 @@
 #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_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

Modified: branches/1.4/main/utils.c
URL: http://svnview.digium.com/svn/asterisk/branches/1.4/main/utils.c?view=diff&rev=298905&r1=298904&r2=298905
==============================================================================
--- branches/1.4/main/utils.c (original)
+++ branches/1.4/main/utils.c Fri Dec 17 15:40:56 2010
@@ -38,6 +38,7 @@
 #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 @@
 	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;
+}
+

Modified: branches/1.4/makeopts.in
URL: http://svnview.digium.com/svn/asterisk/branches/1.4/makeopts.in?view=diff&rev=298905&r1=298904&r2=298905
==============================================================================
--- branches/1.4/makeopts.in (original)
+++ branches/1.4/makeopts.in Fri Dec 17 15:40:56 2010
@@ -73,6 +73,9 @@
 ASOUND_INCLUDE=@ALSA_INCLUDE@
 ASOUND_LIB=@ALSA_LIB@
 
+BFD_INCLUDE=@BFD_INCLUDE@
+BFD_LIB=@BFD_LIB@
+
 CURL_INCLUDE=@CURL_INCLUDE@
 CURL_LIB=@CURL_LIB@
 




More information about the asterisk-commits mailing list