aboutsummaryrefslogtreecommitdiffstats
path: root/main/logger.c
diff options
context:
space:
mode:
authortilghman <tilghman@f38db490-d61c-443f-a65b-d21fe96a405b>2010-12-17 23:30:55 +0000
committertilghman <tilghman@f38db490-d61c-443f-a65b-d21fe96a405b>2010-12-17 23:30:55 +0000
commite81ed3fc262e65b8e5f2a3d207c1b435ca2e669d (patch)
tree74460e8cd1b5b2149afa0f07b856a96ad8bac972 /main/logger.c
parent1c923ad9517ce0ce50806f1348fc861089285b01 (diff)
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: http://svn.digium.com/svn/asterisk/branches/1.6.2@298957 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'main/logger.c')
-rw-r--r--main/logger.c156
1 files changed, 152 insertions, 4 deletions
diff --git a/main/logger.c b/main/logger.c
index 6425183b3..9849a595c 100644
--- a/main/logger.c
+++ b/main/logger.c
@@ -46,8 +46,12 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <sys/stat.h>
#include <fcntl.h>
#ifdef HAVE_BKTR
-#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,
@@ -1214,6 +1218,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)
@@ -1228,7 +1376,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 = 0; i < bt->num_frames; i++) {
ast_log(LOG_DEBUG, "#%d: [%p] %s\n", i, bt->addresses[i], strings[i]);
@@ -1240,7 +1388,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)