- paranoia test; errlogFlush; fixed debug messages

1) Added a paranoia test to make sure an ill-formatted
      ELF string table is not overrun if there is no NULL
      char found.

   2) Added errlogFlush() before and after stack dump (suggestion
      by Michael Davidsaver, thanks).

   3) Fixed (out of sync) debug messages.
This commit is contained in:
Till Straumann
2014-08-28 11:43:46 -07:00
parent 47408ed14c
commit 768c2c02e7

View File

@@ -20,6 +20,8 @@
#define MAXDEPTH 100
#define STACKTRACE_DEBUG 0
/* Darwin and GNU have dladdr() but Darwin's backtrace_symbols()
* already prints local symbols, too, whereas linux' does not.
* Hence, on linux we want to use dladdr() and lookup static
@@ -93,9 +95,10 @@ typedef union Sym_ {
*/
typedef struct MMap_ {
void *addr;
off_t off; /* offset into the map where 'real' data start */
off_t off; /* offset into the map where 'real' data start */
size_t len;
void (*freeMap)(struct MMap_*); /* 'method' to destroy the mapping */
size_t max; /* max offset: legal data from addr+off .. addr+off+max-1 */
void (*freeMap)(struct MMap_*); /* 'method' to destroy the mapping */
} *MMap;
/* Structure describing symbol information
@@ -196,6 +199,7 @@ size_t pgsz = sysconf(_SC_PAGESIZE);
rval->off = FLD(c,(*shdr_p),sh_offset) & (pgsz-1);
rval->len = (n + rval->off + (pgsz - 1)) & ~(pgsz - 1);
rval->max = rval->len - rval->off;
if ( MAP_FAILED == (rval->addr = mmap(0, rval->len, PROT_READ, MAP_SHARED, fd, FLD(c,(*shdr_p),sh_offset) & ~(pgsz-1))) ) {
errlogPrintf("elfRead - getscn() -- mapping section contents: %s\n", strerror(errno));
@@ -244,6 +248,7 @@ MMap rval = 0;
rval->off = 0;
rval->len = n;
rval->max = rval->len - rval->off;
/* seek to symbol table contents */
if ( (off_t)-1 == lseek(fd, FLD(c,(*shdr_p),sh_offset), SEEK_SET) ) {
@@ -290,6 +295,8 @@ Ehdr ehdr;
Shdr shdr;
uint8_t c;
ESyms es;
ssize_t idx;
const char *cp;
if ( !(es = malloc(sizeof(*es))) ) {
/* no memory -- give up */
@@ -397,6 +404,14 @@ ESyms es;
goto bail;
}
/* Make sure there is a terminating NUL - unfortunately, memrchr is not portable */
cp = es->strMap->addr + es->strMap->off;
for ( idx = es->strMap->max - 1; i >= 0; i-- ) {
if ( !cp[i] )
break;
}
es->strMap->max = idx + 1;
switch ( FLD(c,ehdr,e_type) ) {
case ET_EXEC:
/* Symbols in an executable already has absolute addresses */
@@ -470,6 +485,7 @@ Sym sym;
Sym nearest;
const char *strtab;
uint8_t c;
size_t idx;
if ( ! dladdr(addr, &inf) || (!inf.dli_fname && !inf.dli_sname) ) {
/* unable to lookup */
@@ -515,7 +531,9 @@ uint8_t c;
* very often then it would be worthwhile constructing a sorted list of
* symbol addresses but for the stack trace we don't care...
*/
//printf("Looking for %p\n", addr);
#if (STACKTRACE_DEBUG & 1)
printf("Looking for %p\n", addr);
#endif
if ( ELFCLASS32 == c ) {
for ( i=0; i<es->nsyms; i++ ) {
@@ -524,7 +542,9 @@ uint8_t c;
/* don't bother about undefined symbols */
if ( 0 == sym.e32[i].st_shndx )
continue;
//printf("Trying: %s (0x%x)\n", elf_strptr(es->elf, es->idx, es->syms[i].st_name), es->syms[i].st_value + es->addr);
#if (STACKTRACE_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 ) {
off = (uintptr_t)addr - ((uintptr_t)sym.e32[i].st_value + es->addr);
if ( off < minoff ) {
@@ -540,7 +560,9 @@ uint8_t c;
/* don't bother about undefined symbols */
if ( 0 == sym.e64[i].st_shndx )
continue;
//printf("Trying: %s (0x%x)\n", elf_strptr(es->elf, es->idx, es->syms[i].st_name), es->syms[i].st_value + es->addr);
#if (STACKTRACE_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 ) {
off = (uintptr_t)addr - ((uintptr_t)sym.e64[i].st_value + es->addr);
if ( off < minoff ) {
@@ -552,8 +574,8 @@ uint8_t c;
}
}
if ( nearest.raw ) {
errlogPrintf("%s(%s+0x%"PRIxPTR"): [%p]\n", es->fname, strtab + ARR(c,nearest,0,st_name), minoff, addr);
if ( nearest.raw && ( (idx = ARR(c,nearest,0,st_name)) < es->strMap->max ) ) {
errlogPrintf("%s(%s+0x%"PRIxPTR"): [%p]\n", es->fname, strtab + idx, minoff, addr);
} else {
errlogPrintf("%s[%p]\n", es->fname, addr);
}
@@ -568,6 +590,8 @@ char **bts;
#endif
int i,n;
errlogFlush();
if ( ! (buf = malloc(sizeof(*buf) * MAXDEPTH)) ) {
errlogPrintf("epicsStackTrace(): not enough memory for backtrace\n");
return;
@@ -600,6 +624,8 @@ int i,n;
}
#endif
errlogFlush();
free(buf);
}