- cleanup

- reduced epicsStackTraceGetFeatures to epicsFindAddrGetFeatures
This commit is contained in:
Till Straumann
2014-09-10 12:00:51 -07:00
parent 438863ebd9
commit fad25a3b11

View File

@@ -27,9 +27,8 @@
#include <sys/mman.h>
#endif
#include "epicsThread.h"
#include "epicsMutex.h"
#include "epicsThread.h"
#include <errlog.h>
#define epicsExportSharedSymbols
@@ -38,10 +37,12 @@
#define FIND_ADDR_DEBUG 0
/* 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.
/*
* On some systems (linux, solaris) dladdr doesn't find local symbols
* or symbols in the main executable.
* Hence, we want to use dladdr() to find the file name
* where a symbol is defined and if not more information is available
* then proceed to lookup symbols in the ELF symbol tables.
*/
/* Macros to handle elf32 vs. elf64 access to unions etc. */
@@ -100,49 +101,31 @@ typedef struct ESyms_ {
/* 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:
* - elfsLockWrite() must block until all readers have left
* - elfsLockRead() must block until writer has left.
* - elfsLockConvertWriteRead() atomically converts writer holding the
* writer's lock into a reader.
* Right now we just use a single, global lock (for the stack trace) since we
* only need to guard against multiple threads dumping stacks simultaneously and
* we do not lock the symbol table(s) at all.
* should be implemented.
*/
/* Linked list where we keep all our ESyms */
static ESyms elfs = 0;
static epicsMutexId listMtx;
static epicsThreadOnceId listMtxInitId = EPICS_THREAD_ONCE_INIT;
static void listMtxInit(void *unused)
{
listMtx = epicsMutexMustCreate();
}
static void
elfsLockWrite()
{
/* Only a single writer can hold this while no readers are active */
epicsThreadOnce(&listMtxInitId, listMtxInit, 0);
epicsMutexMustLock(listMtx);
}
static void
elfsUnlockWrite()
{
/* Must wake up readers blocking in elfsLockRead() */
}
static void
elfsLockConvertWriteRead()
{
/* Must atomically convert a writer into a reader, i.e., unlock
* the writer's lock and atomically acquire the reader's lock
*/
}
static void
elfsLockRead()
{
/* Multiple readers can hold this while the writer is not active */
}
static void
elfsUnlockRead()
{
/* Must wake up a (single) writer blocking in elfsLockWrite */
epicsMutexUnlock(listMtx);
}
static void
@@ -218,6 +201,11 @@ bail:
freeMap(rval);
return 0;
}
#else
static MMap getscn_mmap(int fd, uint8_t c, Shrd *shdr_p)
{
return 0;
}
#endif
/* Destructor for data that is read into a malloc()ed buffer */
@@ -273,25 +261,15 @@ 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)
static MMap
getscn(int fd, uint8_t c, Shdr *shdr_p)
{
#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;
MMap rval = getscn_mmap(fd, c, shdr_p);
if ( ! rval )
rval = getscn_read(fd, c, shdr_p);
return rval;
}
/* Release resources but keep filename so that
@@ -486,22 +464,35 @@ elfSymsDestroy(ESyms es)
}
}
/* Destroy all cached ELF symbol tables */
/* Destroy all cached ELF symbol tables
*
* However - w/o proper locking for read access
* this must not be used. Otherwise, readers
* will hold stale pointers...
*
* We leave the commented code here to show
* how the tables can be torn down.
void
epicsSymTblFlush()
elfSymTblFlush()
{
ESyms es;
elfsLockWrite();
while ( (es = elfs) ) {
elfs = es->next;
es->next = 0; /* paranoia */
es->next = 0;
elfsUnlockWrite();
elfSymsDestroy(es);
elfsLockWrite();
}
elfsUnlockWrite();
elfsUnlockWrite();
}
*/
/* This routine must be called with the write-lock held */
static ESyms
elfSymsFind(const char *fname)
{
@@ -515,7 +506,7 @@ int
epicsFindAddr(void *addr, epicsSymbol *sym_p)
{
Dl_info inf;
ESyms es,nes;
ESyms es,nes = 0;
uintptr_t minoff,off;
int i;
Sym sym;
@@ -544,13 +535,14 @@ size_t idx;
/* No symbol info; try to access ELF file and ready symbol table from there */
elfsLockRead();
elfsLockWrite();
/* See if we have loaded this file already */
es = elfSymsFind(inf.dli_fname);
if ( !es ) {
elfsUnlockRead();
elfsUnlockWrite();
if ( ! (nes = elfRead(inf.dli_fname, (uintptr_t)inf.dli_fbase)) ) {
/* this path can only be taken if there is no memory for '*nes' */
@@ -563,15 +555,20 @@ size_t idx;
es = elfSymsFind(inf.dli_fname);
if ( es ) {
/* undo our work in the unlikely event... */
elfSymsDestroy( nes );
/* will undo our work in the unlikely event... */
} else {
nes->next = elfs;
es = elfs = nes;
es = elfs = nes;
nes = 0;
}
elfsLockConvertWriteRead();
}
elfsUnlockWrite();
/* Undo our work in the unlikely event that it was redundant */
if ( nes )
elfSymsDestroy( nes );
nearest.raw = 0;
minoff = (uintptr_t)-1LL;
@@ -632,25 +629,18 @@ size_t idx;
sym_p->s_val = (char*) ARR(c, nearest, 0, st_value) + es->addr;
}
elfsUnlockRead();
return 0;
}
int epicsStackTraceGetFeatures(void)
int epicsFindAddrGetFeatures(void)
{
/* We are a bit conservative here. The actual
* situation depends on how we are linked (something
* we don't have under control at compilation time)
* Linux' dladdr finds global symbols
* (not from dynamic libraries) when statically linked but
* not when dynamically linked.
* OTOH: for a stripped executable it is unlikely that
* even the ELF reader is able to help much...
*/
/* The static information given here may not be correct;
* it also depends on
* - compilation (frame pointer optimization)
* - linkage (static vs. dynamic)
* - stripping
*/
return EPICS_STACKTRACE_LCL_SYMBOLS
| EPICS_STACKTRACE_GBL_SYMBOLS
| EPICS_STACKTRACE_DYN_SYMBOLS
| EPICS_STACKTRACE_ADDRESSES;
| EPICS_STACKTRACE_DYN_SYMBOLS;
}