19 #include <sys/types.h> 22 #ifdef _POSIX_MAPPED_FILES 36 #define FIND_ADDR_DEBUG 0 48 #define FLD(c,s,f) (ELFCLASS32==c ? s.e32.f : s.e64.f ) 49 #define ARR(c,s,i,f) (ELFCLASS32==c ? s.e32[i].f : s.e64[i].f) 106 static ESyms elfs = 0;
111 static void listMtxInit(
void *unused)
142 do_read(
int fd,
void *buf, ssize_t sz)
145 char *ptr=(
char*)buf;
148 if ( (got=
read(
fd,ptr,sz)) <= 0 ) {
154 return ptr-(
char*)buf;
159 #ifdef _POSIX_MAPPED_FILES 164 if ( MAP_FAILED != m->
addr )
170 getscn_mmap(
int fd, uint8_t c,
Shdr *shdr_p)
174 size_t pgsz = sysconf(_SC_PAGESIZE);
176 if ( 0 == (n = (off_t)
FLD(c,(*shdr_p),sh_size)) ) {
177 errlogPrintf(
"elfRead - getscn() -- no section data\n");
181 if ( ! (rval = (
MMap) malloc(
sizeof(*rval))) ) {
182 errlogPrintf(
"elfRead - getscn() -- no memory for section map\n");
188 rval->
off = (off_t) (
FLD(c,(*shdr_p),sh_offset) & (pgsz-1));
189 rval->
len = (n + rval->
off + (pgsz - 1)) & ~(pgsz - 1);
192 if ( MAP_FAILED == (rval->
addr = mmap(0, rval->
len, PROT_READ, MAP_SHARED,
fd, (off_t) (
FLD(c,(*shdr_p),sh_offset) & ~(pgsz-1)))) ) {
193 errlogPrintf(
"elfRead - getscn() -- mapping section contents: %s\n", strerror(errno));
204 static MMap getscn_mmap(
int fd, uint8_t c, Shrd *shdr_p)
212 freeMapMalloc(
MMap m)
219 getscn_read(
int fd, uint8_t c,
Shdr *shdr_p)
224 if ( 0 == (n = (ssize_t)
FLD(c,(*shdr_p),sh_size)) ) {
225 errlogPrintf(
"elfRead - getscn() -- no section data\n");
229 if ( ! (rval = (
MMap) malloc(
sizeof(*rval))) ) {
230 errlogPrintf(
"elfRead - getscn() -- no memory for section map\n");
236 if ( ! (rval->
addr = malloc(n)) ) {
237 errlogPrintf(
"elfRead - getscn() -- no memory for section data\n");
246 if ( (off_t)-1 == lseek(
fd, (off_t)
FLD(c,(*shdr_p),sh_offset), SEEK_SET) ) {
247 errlogPrintf(
"elfRead - getscn() -- seeking to sh_offset: %s\n", strerror(errno));
251 if ( n != do_read(
fd, rval->
addr, n) ) {
252 errlogPrintf(
"elfRead - getscn() -- reading section contents: %s\n", strerror(errno));
264 getscn(
int fd, uint8_t c,
Shdr *shdr_p)
266 MMap rval = getscn_mmap(
fd, c, shdr_p);
269 rval = getscn_read(
fd, c, shdr_p);
278 elfSymsRelease(
ESyms es)
293 elfRead(
const char *
fname, uintptr_t fbase)
304 if ( !(es = (
ESyms) malloc(
sizeof(*es))) ) {
309 memset(es, 0,
sizeof(*es));
313 if ( (es->
fd = open(fname, O_RDONLY)) < 0 ) {
314 errlogPrintf(
"elfRead() -- unable to open file: %s\n", strerror(errno));
318 if ( EI_NIDENT != do_read(es->
fd, &ehdr, EI_NIDENT) ) {
319 errlogPrintf(
"elfRead() -- unable to read ELF e_ident: %s\n", strerror(errno));
323 if ( ELFMAG0 != ehdr.
e32.e_ident[EI_MAG0]
324 || ELFMAG1 != ehdr.
e32.e_ident[EI_MAG1]
325 || ELFMAG2 != ehdr.
e32.e_ident[EI_MAG2]
326 || ELFMAG3 != ehdr.
e32.e_ident[EI_MAG3] ) {
331 if ( EV_CURRENT != ehdr.
e32.e_ident[EI_VERSION] ) {
336 switch ( (es->
eclss = c = ehdr.
e32.e_ident[EI_CLASS]) ) {
342 n =
sizeof(Elf32_Ehdr);
345 n =
sizeof(Elf64_Ehdr);
350 if ( 0 == fstat(es->
fd, &stat_b) ) {
352 time_t progStartTime;
356 if ( stat_b.st_mtime >= progStartTime ) {
357 errlogPrintf(
"elfRead() -- WARNING: '%s' was modified after program start -- symbol information may be inaccurate or invalid\n", fname);
362 if ( n != do_read(es->
fd, ehdr.
e32.e_ident + EI_NIDENT, n) ) {
363 errlogPrintf(
"elfRead() -- unable to read ELF ehdr: %s\n", strerror(errno));
368 if ( (off_t)-1 == lseek(es->
fd, (off_t)
FLD(c,ehdr,e_shoff), SEEK_SET) ) {
369 errlogPrintf(
"elfRead() -- unable to seek to shoff: %s\n", strerror(errno));
373 n = ELFCLASS32 == c ?
sizeof(shdr.
e32) :
sizeof(shdr.
e64);
375 for ( i = 0; i<
FLD(c,ehdr,e_shnum); i++ ) {
376 if ( n != do_read(es->
fd, &shdr, n) ) {
377 errlogPrintf(
"elfRead() -- unable to read section header: %s\n", strerror(errno));
380 if ( SHT_SYMTAB ==
FLD(c,shdr,sh_type) )
384 if ( i>=
FLD(c,ehdr,e_shnum) ) {
387 if ( (off_t)-1 == lseek(es->
fd, (off_t) FLD(c,ehdr,e_shoff), SEEK_SET) ) {
388 errlogPrintf(
"elfRead() -- unable to seek to shoff: %s\n", strerror(errno));
392 for ( i = 0; i<
FLD(c,ehdr,e_shnum); i++ ) {
393 if ( n != do_read(es->
fd, &shdr, n) ) {
394 errlogPrintf(
"elfRead() -- unable to read section header: %s\n", strerror(errno));
397 if ( SHT_DYNSYM ==
FLD(c,shdr,sh_type) )
402 if ( i>=
FLD(c,ehdr,e_shnum) ) {
407 if ( 0 == (n = (ssize_t)
FLD(c,shdr,sh_size)) ) {
412 if ( !(es->
symMap = getscn(es->
fd, c, &shdr)) ) {
413 errlogPrintf(
"elfRead() -- unable to read ELF symtab\n");
417 es->
nsyms = n / (ELFCLASS32==c ?
sizeof(Elf32_Sym) :
sizeof(Elf64_Sym));
421 n = ELFCLASS32 == c ?
sizeof(shdr.
e32) :
sizeof(shdr.
e64);
424 if ( (off_t)-1 == lseek(es->
fd, (off_t) (FLD(c,ehdr,e_shoff) + n *
FLD(c,shdr,sh_link)), SEEK_SET) ) {
425 errlogPrintf(
"elfRead() -- unable to lseek to ELF e_shoff: %s\n", strerror(errno));
429 if ( n != do_read(es->
fd, &shdr, n) ) {
430 errlogPrintf(
"elfRead() -- unable to read ELF strtab section header: %s\n", strerror(errno));
434 if ( !(es->
strMap = getscn(es->
fd,c,&shdr)) ) {
435 errlogPrintf(
"elfRead() -- unable to read ELF strtab\n");
441 for ( idx = es->
strMap->
max - 1; i >= 0; i-- ) {
447 switch (
FLD(c,ehdr,e_type) ) {
457 errlogPrintf(
"dlLookupAddr(): Unexpected ELF object file type %u\n",
FLD(c,ehdr,e_type));
470 elfSymsDestroy(
ESyms es)
508 elfSymsFind(
const char *fname)
512 for ( es=elfs; es && strcmp(fname, es->
fname); es = es->
next )
522 uintptr_t minoff,off;
530 if ( ! dladdr(addr, &inf) || (!inf.dli_fname && !inf.dli_sname) ) {
537 sym_p->
f_nam = inf.dli_fname;
541 if ( (sym_p->
s_nam = inf.dli_sname) ) {
542 sym_p->
s_val = inf.dli_saddr;
553 es = elfSymsFind(inf.dli_fname);
559 if ( ! (nes = elfRead(inf.dli_fname, (uintptr_t)inf.dli_fbase)) ) {
567 es = elfSymsFind(inf.dli_fname);
582 elfSymsDestroy( nes );
585 minoff = (uintptr_t)-1LL;
596 #if (FIND_ADDR_DEBUG & 1) 597 printf(
"Looking for %p\n", addr);
600 if ( ELFCLASS32 == c ) {
601 for ( i=0; i<es->
nsyms; i++ ) {
602 if ( STT_FUNC != ELF32_ST_TYPE(sym.
e32[i].st_info) )
605 if ( 0 == sym.
e32[i].st_shndx )
607 #if (FIND_ADDR_DEBUG & 1) 608 printf(
"Trying: %s (0x%lx)\n", strtab + sym.
e32[i].st_name, (
unsigned long)(sym.
e32[i].st_value + es->
addr));
610 if ( (uintptr_t)addr >= (uintptr_t)sym.
e32[i].st_value + es->
addr ) {
611 off = (uintptr_t)addr - ((uintptr_t)sym.
e32[
i].st_value + es->
addr);
612 if ( off < minoff ) {
619 for ( i=0; i<es->
nsyms; i++ ) {
620 if ( STT_FUNC != ELF64_ST_TYPE(sym.
e64[i].st_info) )
623 if ( 0 == sym.
e64[i].st_shndx )
625 #if (FIND_ADDR_DEBUG & 1) 626 printf(
"Trying: %s (0x%llx)\n", strtab + sym.
e64[i].st_name, (
unsigned long long)(sym.
e64[i].st_value + es->
addr));
628 if ( (uintptr_t)addr >= (uintptr_t)sym.
e64[i].st_value + es->
addr ) {
629 off = (uintptr_t)addr - ((uintptr_t)sym.
e64[
i].st_value + es->
addr);
630 if ( off < minoff ) {
639 if ( nearest.
raw && ( (idx =
ARR(c,nearest,0,st_name)) < es->
strMap->
max ) ) {
640 sym_p->
s_nam = strtab + idx;
641 sym_p->
s_val = (
char*)
ARR(c, nearest, 0, st_value) + es->
addr;
#define EPICS_STACKTRACE_LCL_SYMBOLS
#define EPICS_STACKTRACE_GBL_SYMBOLS
LIBCOM_API void ClockTime_GetProgramStart(epicsTimeStamp *pDest)
#define epicsMutexMustCreate()
Create an epicsMutex semaphore for use from C code.
void epicsStdCall epicsMutexUnlock(epicsMutexId pmutexNode)
Release the semaphore.
void(* freeMap)(struct MMap_ *)
int epicsFindAddr(void *addr, epicsSymbol *sym_p)
int epicsFindAddrGetFeatures(void)
LIBCOM_API int epicsStdCall epicsTimeToTime_t(time_t *pDest, const epicsTimeStamp *pSrc)
Convert epicsTimeStamp to ANSI C time_t.
#define EPICS_THREAD_ONCE_INIT
#define EPICS_STACKTRACE_DYN_SYMBOLS
APIs for the epicsMutex mutual exclusion semaphore.
LIBCOM_API void epicsStdCall epicsThreadOnce(epicsThreadOnceId *id, EPICSTHREADFUNC, void *arg)
int errlogPrintf(const char *pFormat,...)
EPICS time stamp, for use from C code.
EPICS time-stamps (epicsTimeStamp), epicsTime C++ class and C functions for handling wall-clock times...
C++ and C descriptions for a thread.
#define epicsMutexMustLock(ID)
Claim a semaphore (see epicsMutexLock()).