From e349b3ab94067160792fa08ff5ad0a1e04cf9c75 Mon Sep 17 00:00:00 2001 From: strauman Date: Mon, 8 Sep 2014 19:41:06 -0700 Subject: [PATCH] - first stab at breaking stack trace facility into separate files --- src/libCom/osi/Makefile | 9 +- src/libCom/osi/epicsStackTrace.c | 137 ++++++++ src/libCom/osi/epicsStackTracePvt.h | 61 ++++ src/libCom/osi/os/Darwin/osdFindAddr.c | 45 +++ src/libCom/osi/os/Darwin/osdStackTrace.c | 20 -- src/libCom/osi/os/Linux/osdStackTrace.c | 20 -- src/libCom/osi/os/default/osdBackTrace.c | 15 + .../{osdStackTrace.c => osdFindAddr.c} | 6 +- src/libCom/osi/os/posix/osdBackTrace.c | 17 + .../posix/osdFindAddr.c} | 317 +++++------------- 10 files changed, 361 insertions(+), 286 deletions(-) create mode 100644 src/libCom/osi/epicsStackTrace.c create mode 100644 src/libCom/osi/epicsStackTracePvt.h create mode 100644 src/libCom/osi/os/Darwin/osdFindAddr.c delete mode 100644 src/libCom/osi/os/Darwin/osdStackTrace.c delete mode 100644 src/libCom/osi/os/Linux/osdStackTrace.c create mode 100644 src/libCom/osi/os/default/osdBackTrace.c rename src/libCom/osi/os/default/{osdStackTrace.c => osdFindAddr.c} (77%) create mode 100644 src/libCom/osi/os/posix/osdBackTrace.c rename src/libCom/osi/{execinfoStackTrace.c => os/posix/osdFindAddr.c} (76%) diff --git a/src/libCom/osi/Makefile b/src/libCom/osi/Makefile index 38fdf71c0..781497a1a 100644 --- a/src/libCom/osi/Makefile +++ b/src/libCom/osi/Makefile @@ -143,9 +143,6 @@ Com_SRCS_WIN32 += setThreadName.cpp Com_SRCS_WIN32 += forceBadAllocException.cpp #Stack trace support -Com_SRCS += osdStackTrace.c -Com_SRCS_Linux += execinfoStackTrace.c -Com_SRCS_Darwin += execinfoStackTrace.c -#we could use execinfoStackTrace.c on freebsd, too, but AFAIK -#you need libexecinfo.a and execinfo.h. I don't know if that -#is routinely available so we don't use it for now. +Com_SRCS += epicsStackTrace.c +Com_SRCS += osdBackTrace.c +Com_SRCS += osdFindAddr.c diff --git a/src/libCom/osi/epicsStackTrace.c b/src/libCom/osi/epicsStackTrace.c new file mode 100644 index 000000000..b0e02fa8a --- /dev/null +++ b/src/libCom/osi/epicsStackTrace.c @@ -0,0 +1,137 @@ +/* + * Copyright: Stanford University / SLAC National Laboratory. + * + * EPICS BASE is distributed subject to a Software License Agreement found + * in file LICENSE that is included with this distribution. + * + * Author: Till Straumann , 2011, 2014 + */ + +#include +#include + +#include "epicsStackTrace.h" +#include "epicsStackTracePvt.h" +#include "epicsThread.h" +#include "epicsMutex.h" +#include "errlog.h" + +/* How many stack frames to capture */ +#define MAXDEPTH 100 + +/* Max. formatted line length */ +#define MAXLINEL 300 + +#define NO_OFF ((unsigned long)-1L) + +static ssize_t +symDump(char *buf, size_t buf_sz, void *addr, epicsSymbol *sym_p); + +static epicsThreadOnceId stackTraceInitId = EPICS_THREAD_ONCE_INIT; +static epicsMutexId stackTraceMtx; + +static void stackTraceInit(void *unused) +{ + stackTraceMtx = epicsMutexMustCreate(); +} + +static void stackTraceLock(void) +{ + epicsThreadOnce( &stackTraceInitId, stackTraceInit, 0 ); + epicsMutexLock( stackTraceMtx ); +} + +static void stackTraceUnlock(void) +{ + epicsMutexUnlock( stackTraceMtx ); +} + +static ssize_t +dump(char **buf, size_t *buf_sz, size_t *good, const char *fmt, ...) +{ +va_list ap; +ssize_t rval, put; + va_start(ap, fmt); + if ( *buf ) { + put = rval = vsnprintf(*buf, *buf_sz, fmt, ap); + if ( put > *buf_sz ) + put = *buf_sz; + *buf += put; + *buf_sz -= put; + } else { + rval = errlogVprintf(fmt, ap); + } + va_end(ap); + if ( rval > 0 ) + *good += rval; + return rval; +} + +static ssize_t +symDump(char *buf, size_t buf_sz, void *addr, epicsSymbol *sym_p) +{ +size_t rval = 0; + + dump( &buf, &buf_sz, &rval, "[%*p]", sizeof(addr)*2 + 2, addr); + if ( sym_p ) { + if ( sym_p->f_nam ) { + dump( &buf, &buf_sz, &rval, ": %s", sym_p->f_nam ); + } + if ( sym_p->s_nam ) { + dump( &buf, &buf_sz, &rval, "(%s+0x%lx)", sym_p->s_nam, (unsigned long)(addr - sym_p->s_val)); + } + } + dump( &buf, &buf_sz, &rval, "\n"); + if ( ! buf ) + errlogFlush(); + + return rval; +} + +epicsShareFunc void epicsStackTrace(void) +{ +void **buf; +char *btsl = 0; +size_t btsl_sz = sizeof(*btsl)*MAXLINEL; +int i,n; +epicsSymbol sym; + + if ( 0 == epicsStackTraceGetFeatures() ) { + /* unsupported on this platform */ + return; + } + + if ( ! (buf = malloc(sizeof(*buf) * MAXDEPTH)) + || ! (btsl = malloc(btsl_sz)) + ) { + free(buf); + errlogPrintf("epicsStackTrace(): not enough memory for backtrace\n"); + return; + } + + n = epicsBackTrace(buf, MAXDEPTH); + + if ( n > 0 ) { + + stackTraceLock(); + + errlogPrintf("Dumping a stack trace of thread '%s':\n", epicsThreadGetNameSelf()); + + errlogFlush(); + + for ( i=0; i, 2011, 2014 + */ + +#ifndef INC_epicsStackTracePvt_H +#define INC_epicsStackTracePvt_H + +#include "shareLib.h" + +typedef struct epicsSymbol { + const char *f_nam; /* file where the symbol is defined */ + const char *s_nam; /* symbol name */ + void *s_val; /* symbol value */ +} epicsSymbol; + +#ifdef __cplusplus +extern "C" { +#endif + +/* Take a snapshot of the stack into 'buf' (limited to buf_sz entries) + * RETURNS: actual number of entries in 'buf' + */ +epicsShareFunc int epicsBackTrace(void **buf, int buf_sz); + +/* Find symbol closest to 'addr'. + * + * If successful the routine fills in the members of *sym_p but + * note that 'f_nam' and/or 's_nam' may be NULL if the address + * cannot be resolved. + * + * RETURNS: 0 on success, nonzero on failure (not finding an address + * is not considered an error). + * + * NOTE: epicsSymbolTableLock() must be held while the string + * pointers returned by epicsFindAddr are in use. + * + * I.e., + * + * epicsSymTblLock(); + * + * epicsFindAddr( addr, &sym ); + * + * do_something( &sym ); + * + * epicsSymTblUnlock(); + * + * epicsSymTblLock() may be implemented by the OSD code such that + * multiple readers may hold the lock. + */ +epicsShareFunc int epicsFindAddr(void *addr, epicsSymbol *sym_p); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/libCom/osi/os/Darwin/osdFindAddr.c b/src/libCom/osi/os/Darwin/osdFindAddr.c new file mode 100644 index 000000000..306279d2e --- /dev/null +++ b/src/libCom/osi/os/Darwin/osdFindAddr.c @@ -0,0 +1,45 @@ +/* + * Copyright: Stanford University / SLAC National Laboratory. + * + * EPICS BASE is distributed subject to a Software License Agreement found + * in file LICENSE that is included with this distribution. + * + * Author: Till Straumann , 2011, 2014 + */ + +/* Make sure dladdr() is visible */ +#define _DARWIN_C_SOURCE + +#include + +#include "epicsStackTrace.h" +#include "epicsStackTracePvt.h" + + +/* Darwin's finds local symbols, too :-) */ + +epicsShareFunc int epicsFindAddr(void *addr, epicsSymbol *sym_p) +{ +Dl_info inf; + + if ( ! dladdr(addr, &inf) || (!inf.dli_fname && !inf.dli_sname) ) { + sym_p->f_nam = 0; + sym_p->s_nam = 0; + /* unable to lookup */ + return 0; + } + + sym_p->f_nam = inf.dli_fname; + sym_p->s_nam = inf.dli_sname; + sym_p->s_val = inf.dli_saddr; + + return 0; +} + +epicsShareFunc int epicsStackTraceGetFeatures(void) +{ + return EPICS_STACKTRACE_LCL_SYMBOLS + | EPICS_STACKTRACE_GBL_SYMBOLS + | EPICS_STACKTRACE_DYN_SYMBOLS + | EPICS_STACKTRACE_ADDRESSES; +} diff --git a/src/libCom/osi/os/Darwin/osdStackTrace.c b/src/libCom/osi/os/Darwin/osdStackTrace.c deleted file mode 100644 index 3f25a0591..000000000 --- a/src/libCom/osi/os/Darwin/osdStackTrace.c +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright: Stanford University / SLAC National Laboratory. - * - * EPICS BASE is distributed subject to a Software License Agreement found - * in file LICENSE that is included with this distribution. - * - * Author: Till Straumann , 2011 - */ - -/* THIS FILE IS INTENTIONALLY EMPTY - * - * The presence of this file prevents the build - * system from using the no-op implementation of - * epicsStackTrace() in default/osdStackTrace.c. - * - * This OS uses a generic implementation which - * may be used by various OSes. The source file - * of this implementation is listed in the - * Makefile. - */ diff --git a/src/libCom/osi/os/Linux/osdStackTrace.c b/src/libCom/osi/os/Linux/osdStackTrace.c deleted file mode 100644 index 3f25a0591..000000000 --- a/src/libCom/osi/os/Linux/osdStackTrace.c +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright: Stanford University / SLAC National Laboratory. - * - * EPICS BASE is distributed subject to a Software License Agreement found - * in file LICENSE that is included with this distribution. - * - * Author: Till Straumann , 2011 - */ - -/* THIS FILE IS INTENTIONALLY EMPTY - * - * The presence of this file prevents the build - * system from using the no-op implementation of - * epicsStackTrace() in default/osdStackTrace.c. - * - * This OS uses a generic implementation which - * may be used by various OSes. The source file - * of this implementation is listed in the - * Makefile. - */ diff --git a/src/libCom/osi/os/default/osdBackTrace.c b/src/libCom/osi/os/default/osdBackTrace.c new file mode 100644 index 000000000..c8bccd61f --- /dev/null +++ b/src/libCom/osi/os/default/osdBackTrace.c @@ -0,0 +1,15 @@ +/* + * Copyright: Stanford University / SLAC National Laboratory. + * + * EPICS BASE is distributed subject to a Software License Agreement found + * in file LICENSE that is included with this distribution. + * + * Author: Till Straumann , 2011 + */ + +#include "epicsStackTracePvt.h" + +epicsShareFunc int epicsBackTrace(void **buf, int buf_sz) +{ + return -1; +} diff --git a/src/libCom/osi/os/default/osdStackTrace.c b/src/libCom/osi/os/default/osdFindAddr.c similarity index 77% rename from src/libCom/osi/os/default/osdStackTrace.c rename to src/libCom/osi/os/default/osdFindAddr.c index d56711267..d3d69cdec 100644 --- a/src/libCom/osi/os/default/osdStackTrace.c +++ b/src/libCom/osi/os/default/osdFindAddr.c @@ -7,15 +7,15 @@ * Author: Till Straumann , 2011 */ +#include "epicsStackTracePvt.h" #include "epicsStackTrace.h" -#include "errlog.h" -epicsShareFunc void epicsStackTrace(void) +epicsShareFunc int epicsFindAddr(void *addr, epicsSymbol *sym_p) { + return -1; } epicsShareFunc int epicsStackTraceGetFeatures(void) { return 0; } - diff --git a/src/libCom/osi/os/posix/osdBackTrace.c b/src/libCom/osi/os/posix/osdBackTrace.c new file mode 100644 index 000000000..806082a73 --- /dev/null +++ b/src/libCom/osi/os/posix/osdBackTrace.c @@ -0,0 +1,17 @@ +/* + * Copyright: Stanford University / SLAC National Laboratory. + * + * EPICS BASE is distributed subject to a Software License Agreement found + * in file LICENSE that is included with this distribution. + * + * Author: Till Straumann , 2011 + */ + +#include + +#include "epicsStackTracePvt.h" + +epicsShareFunc int epicsBackTrace(void **buf, int buf_sz) +{ + return backtrace(buf, buf_sz); +} diff --git a/src/libCom/osi/execinfoStackTrace.c b/src/libCom/osi/os/posix/osdFindAddr.c similarity index 76% rename from src/libCom/osi/execinfoStackTrace.c rename to src/libCom/osi/os/posix/osdFindAddr.c index 129bf553a..7395b5c37 100644 --- a/src/libCom/osi/execinfoStackTrace.c +++ b/src/libCom/osi/os/posix/osdFindAddr.c @@ -7,45 +7,16 @@ * Author: Till Straumann , 2011, 2014 */ -/* Make sure dladdr() is visible on linux/freebsd/darwin */ +/* Make sure dladdr() is visible on linux/solaris */ #define _GNU_SOURCE -/* Some freebsd versions seem to export dladdr() only if __BSD_VISIBLE */ -#define _BSD_VISIBLE -#define _DARWIN_C_SOURCE +/* For dladdr under solaris */ +#define __EXTENSIONS__ -#include "epicsStackTrace.h" -#include "epicsThread.h" -#include "epicsMutex.h" -#include -#include +#include +#include #include #include #include -#include - -/* How many stack frames to capture */ -#define MAXDEPTH 100 -/* How many chars to reserve for a line of output */ -#define MAXSYMLEN 500 - - -#define STACKTRACE_DEBUG 2 - -/* Darwin and GNU have dladdr() and Darwin's already finds local - * symbols, too, whereas linux' does not. - * Hence, on linux we want to use dladdr() and lookup static - * symbols in the ELF symbol table. - */ - -#include - -#if defined(__linux__) || defined(linux) -#define USE_ELF -#elif defined(freebsd) -#define USE_ELF -#endif - -#ifdef USE_ELF #include #include #include @@ -54,15 +25,20 @@ #include #endif -#endif /* USE_ELF */ +#include "epicsStackTrace.h" +#include "epicsStackTracePvt.h" -/* Forward Declaration */ -#define NO_OFF ((unsigned long)-1L) +#include "epicsThread.h" +#include "epicsMutex.h" +#include -static ssize_t -symDump(char *buf, size_t buf_sz, void *addr, const char *fnam, const char *snam, unsigned long off); +#define FIND_ADDR_DEBUG 0 -#ifdef USE_ELF +/* Darwin and GNU have dladdr() and Darwin's already finds local + * symbols, too, whereas linux' does not. + * Hence, on linux we want to use dladdr() and lookup static + * symbols in the ELF symbol table. + */ /* Macros to handle elf32 vs. elf64 access to unions etc. */ @@ -118,37 +94,6 @@ typedef struct ESyms_ { uint8_t class; } *ESyms; -/* Elf file access -- can either be with mmap or by sequential read */ - -#ifdef _POSIX_MAPPED_FILES -static MMap -getscn_mmap(int fd, uint8_t c, Shdr *shdr_p); -#endif - -static MMap -getscn_read(int fd, uint8_t c, Shdr *shdr_p); - -static MMap (*getscn)(int fd, uint8_t c, Shdr *shdr_p) = -#ifdef _POSIX_MAPPED_FILES - getscn_mmap -#else - getscn_read -#endif - ; - -int -epicsElfConfigAccess(int use_mmap) -{ -#ifndef _POSIX_MAPPED_FILES - if ( use_mmap ) - return -1; /* not supported on this system */ - /* else no need to change default */ -#else - getscn = use_mmap ? getscn_mmap : getscn_read; -#endif - return 0; -} - /* LOCKING NOTE: if the ELF symbol facility is ever expanded to be truly used * in a multithreaded way then proper multiple-readers, single-writer locking * should be implemented: @@ -214,7 +159,7 @@ do_read(int fd, void *buf, size_t sz) size_t got; void *ptr=buf; while ( sz > 0 ) { - if ( (got=read(fd,ptr,sz)) < 0 ) { + if ( (got=read(fd,ptr,sz)) <= 0 ) { return got; } ptr+=got; @@ -223,6 +168,8 @@ void *ptr=buf; return ptr-buf; } +/* Elf file access -- can either be with mmap or by sequential read */ + #ifdef _POSIX_MAPPED_FILES /* Destructor for data that is mmap()ed */ static void @@ -322,6 +269,27 @@ bail: return 0; } +static MMap (*getscn)(int fd, uint8_t c, Shdr *shdr_p) = +#ifdef _POSIX_MAPPED_FILES + getscn_mmap +#else + getscn_read +#endif + ; + +int +epicsElfConfigAccess(int use_mmap) +{ +#ifndef _POSIX_MAPPED_FILES + if ( use_mmap ) + return -1; /* not supported on this system */ + /* else no need to change default */ +#else + getscn = use_mmap ? getscn_mmap : getscn_read; +#endif + return 0; +} + /* Release resources but keep filename so that * a file w/o symbol table is not read over and over again. */ @@ -420,6 +388,24 @@ const char *cp; break; } + if ( i>=FLD(c,ehdr,e_shnum) ) { + /* no SYMTAB -- try dynamic symbols */ + + if ( (off_t)-1 == lseek(es->fd, FLD(c,ehdr,e_shoff), SEEK_SET) ) { + errlogPrintf("elfRead() -- unable to seek to shoff: %s\n", strerror(errno)); + goto bail; + } + + for ( i = 0; ifd, &shdr, n) ) { + errlogPrintf("elfRead() -- unable to read section header: %s\n", strerror(errno)); + goto bail; + } + if ( SHT_DYNSYM == FLD(c,shdr,sh_type) ) + break; + } + } + if ( i>=FLD(c,ehdr,e_shnum) ) { errlogPrintf("elfRead() -- no symbol table found\n"); goto bail; @@ -475,7 +461,7 @@ const char *cp; es->addr = fbase; break; default: - errlogPrintf("elfLookupAddr(): Unexpected ELF object file type %u\n", FLD(c,ehdr,e_type)); + errlogPrintf("dlLookupAddr(): Unexpected ELF object file type %u\n", FLD(c,ehdr,e_type)); goto bail; } @@ -497,8 +483,8 @@ elfSymsDestroy(ESyms es) } /* Destroy all cached ELF symbol tables */ -static void -elfSymsFlush() +void +epicsSymTblFlush() { ESyms es; @@ -520,15 +506,11 @@ ESyms es; /* nothing else to do */; return es; } -#endif /* USE_ELF */ -static ssize_t -elfLookupAddr(void *addr, char *buf, size_t buf_sz) +int +epicsFindAddr(void *addr, epicsSymbol *sym_p) { Dl_info inf; -ssize_t rval; - -#ifdef USE_ELF ESyms es,nes; uintptr_t minoff,off; int i; @@ -537,23 +519,24 @@ Sym nearest; const char *strtab; uint8_t c; size_t idx; -#endif if ( ! dladdr(addr, &inf) || (!inf.dli_fname && !inf.dli_sname) ) { + sym_p->f_nam = 0; + sym_p->s_nam = 0; /* unable to lookup */ - return symDump(buf, buf_sz, addr, 0, 0, NO_OFF); + return 0; } - if ( inf.dli_sname ) { + sym_p->f_nam = inf.dli_fname; + + /* If the symbol is in the main executable then solaris' dladdr returns bogus info */ +#ifndef __sun + if ( (sym_p->s_nam = inf.dli_sname) ) { + sym_p->s_val = inf.dli_saddr; /* Have a symbol name - just use it and be done */ - return symDump(buf, buf_sz, addr, inf.dli_fname, inf.dli_sname, (unsigned long)(addr - inf.dli_saddr)); + return 0; } - -#ifndef USE_ELF - - rval = symDump(buf, buf_sz, addr, inf.dli_fname, 0, NO_OFF); - -#else +#endif /* No symbol info; try to access ELF file and ready symbol table from there */ @@ -567,8 +550,6 @@ size_t idx; if ( ! (nes = elfRead(inf.dli_fname, (uintptr_t)inf.dli_fbase)) ) { /* this path can only be taken if there is no memory for '*nes' */ - if ( buf && buf_sz > 0 ) - *buf = 0; return 0; } @@ -599,7 +580,7 @@ size_t idx; * very often then it would be worthwhile constructing a sorted list of * symbol addresses but for the stack trace we don't care... */ -#if (STACKTRACE_DEBUG & 1) +#if (FIND_ADDR_DEBUG & 1) printf("Looking for %p\n", addr); #endif @@ -610,7 +591,7 @@ size_t idx; /* don't bother about undefined symbols */ if ( 0 == sym.e32[i].st_shndx ) continue; -#if (STACKTRACE_DEBUG & 1) +#if (FIND_ADDR_DEBUG & 1) printf("Trying: %s (0x%lx)\n", strtab + sym.e32[i].st_name, (unsigned long)(sym.e32[i].st_value + es->addr)); #endif if ( (uintptr_t)addr >= (uintptr_t)sym.e32[i].st_value + es->addr ) { @@ -628,7 +609,7 @@ size_t idx; /* don't bother about undefined symbols */ if ( 0 == sym.e64[i].st_shndx ) continue; -#if (STACKTRACE_DEBUG & 1) +#if (FIND_ADDR_DEBUG & 1) printf("Trying: %s (0x%llx)\n", strtab + sym.e64[i].st_name, (unsigned long long)(sym.e64[i].st_value + es->addr)); #endif if ( (uintptr_t)addr >= (uintptr_t)sym.e64[i].st_value + es->addr ) { @@ -643,145 +624,17 @@ size_t idx; } if ( nearest.raw && ( (idx = ARR(c,nearest,0,st_name)) < es->strMap->max ) ) { - rval = symDump(buf, buf_sz, addr, es->fname, strtab + idx, (unsigned long)minoff); - } else { - rval = symDump(buf, buf_sz, addr, es->fname, 0, NO_OFF); + sym_p->s_nam = strtab + idx; + sym_p->s_val = (void*) ARR(c, nearest, 0, st_value) + es->addr; } elfsUnlockRead(); -#endif /* USE_ELF */ - - return rval; + return 0; } -static epicsThreadOnceId stackTraceInitId = EPICS_THREAD_ONCE_INIT; -static epicsMutexId stackTraceMtx; - -static void stackTraceInit(void *unused) -{ - stackTraceMtx = epicsMutexMustCreate(); -} - -static void stackTraceLock(void) -{ - epicsThreadOnce( &stackTraceInitId, stackTraceInit, 0 ); - epicsMutexLock( stackTraceMtx ); -} - -static void stackTraceUnlock(void) -{ - epicsMutexUnlock( stackTraceMtx ); -} - -static ssize_t -dump(char **buf, size_t *buf_sz, size_t *good, const char *fmt, ...) -{ -va_list ap; -ssize_t rval, put; - va_start(ap, fmt); - if ( *buf ) { - put = rval = vsnprintf(*buf, *buf_sz, fmt, ap); - if ( put > *buf_sz ) - put = *buf_sz; - *buf += put; - *buf_sz -= put; - } else { - rval = errlogVprintf(fmt, ap); - } - va_end(ap); - if ( rval > 0 ) - *good += rval; - return rval; -} - - -static ssize_t -symDump(char *buf, size_t buf_sz, void *addr, const char *fnam, const char *snam, unsigned long off) -{ -size_t rval = 0; - - dump( &buf, &buf_sz, &rval, "[%*p]", sizeof(addr)*2 + 2, addr); - if ( fnam ) { - dump( &buf, &buf_sz, &rval, ": %s", fnam ); - } - if ( snam ) { - dump( &buf, &buf_sz, &rval, "(%s", snam ); - if ( NO_OFF != off ) { - dump( &buf, &buf_sz, &rval, "+0x%lx", off); - } - dump( &buf, &buf_sz, &rval, ")" ); - } - dump( &buf, &buf_sz, &rval, "\n"); - - return rval; -} - -epicsShareFunc void epicsStackTrace(void) -{ -void **buf; -char *btsl = 0; -size_t btsl_sz = sizeof(*btsl)*MAXSYMLEN; -int i,n; - - if ( ! (buf = malloc(sizeof(*buf) * MAXDEPTH)) - || ! (btsl = malloc(btsl_sz)) - ) { - free(buf); - errlogPrintf("epicsStackTrace(): not enough memory for backtrace\n"); - return; - } - - n = backtrace(buf, MAXDEPTH); - - stackTraceLock(); - - errlogPrintf("Dumping a stack trace of thread '%s':\n", epicsThreadGetNameSelf()); - - errlogFlush(); - - for ( i=0; i