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.
  ........
................


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.8@298960 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Tilghman Lesher
2010-12-17 23:52:04 +00:00
parent 072c12c04b
commit d70a3b0856
19 changed files with 529 additions and 48 deletions

View File

@@ -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

View File

@@ -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]);

View File

@@ -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)

View File

@@ -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";

View File

@@ -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;
}