mirror of
https://github.com/asterisk/asterisk.git
synced 2025-11-19 16:20:37 +00:00
Merged revisions 298960 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.8 ................ r298960 | tilghman | 2010-12-17 17:52:04 -0600 (Fri, 17 Dec 2010) | 20 lines Merged revisions 298957 via svnmerge from 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. Review: https://reviewboard.asterisk.org/r/1055/ ........ ................ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@298961 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
152
main/logger.c
152
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)
|
||||
|
||||
Reference in New Issue
Block a user