summaryrefslogtreecommitdiff
path: root/main
diff options
context:
space:
mode:
Diffstat (limited to 'main')
-rw-r--r--main/Makefile4
-rw-r--r--main/astobj2.c2
-rw-r--r--main/logger.c152
-rw-r--r--main/utils.c22
4 files changed, 176 insertions, 4 deletions
diff --git a/main/Makefile b/main/Makefile
index 0bb7c97c0..ad4d39c03 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 430f01f58..12f835f99 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
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)
diff --git a/main/utils.c b/main/utils.c
index 7ac62bd39..f8ec82f25 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>
@@ -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;
+}
+