This is Unofficial EPICS BASE Doxygen Site
osdElfFindAddr.c File Reference
#include <unistd.h>
#include <dlfcn.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <elf.h>
#include <errno.h>
#include <inttypes.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
#include "epicsMutex.h"
#include "epicsThread.h"
#include "epicsTime.h"
#include "errlog.h"
#include "epicsStackTrace.h"
#include "epicsStackTracePvt.h"
+ Include dependency graph for osdElfFindAddr.c:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

union  Ehdr_
 
union  Shdr_
 
union  Sym_
 
struct  MMap_
 
struct  ESyms_
 

Macros

#define FIND_ADDR_DEBUG   0
 
#define FLD(c, s, f)   (ELFCLASS32==c ? s.e32.f : s.e64.f )
 
#define ARR(c, s, i, f)   (ELFCLASS32==c ? s.e32[i].f : s.e64[i].f)
 

Typedefs

typedef union Ehdr_ Ehdr
 
typedef union Shdr_ Shdr
 
typedef union Sym_ Sym
 
typedef struct MMap_MMap
 
typedef struct ESyms_ESyms
 

Functions

LIBCOM_API void ClockTime_GetProgramStart (epicsTimeStamp *pDest)
 
int epicsFindAddr (void *addr, epicsSymbol *sym_p)
 
int epicsFindAddrGetFeatures (void)
 

Macro Definition Documentation

#define ARR (   c,
  s,
  i,
 
)    (ELFCLASS32==c ? s.e32[i].f : s.e64[i].f)

Definition at line 49 of file osdElfFindAddr.c.

#define FIND_ADDR_DEBUG   0

Definition at line 36 of file osdElfFindAddr.c.

#define FLD (   c,
  s,
 
)    (ELFCLASS32==c ? s.e32.f : s.e64.f )

Definition at line 48 of file osdElfFindAddr.c.

Typedef Documentation

typedef union Ehdr_ Ehdr
typedef struct ESyms_ * ESyms
typedef struct MMap_ * MMap
typedef union Shdr_ Shdr
typedef union Sym_ Sym

Function Documentation

LIBCOM_API void ClockTime_GetProgramStart ( epicsTimeStamp pDest)
int epicsFindAddr ( void *  addr,
epicsSymbol sym_p 
)

Definition at line 518 of file osdElfFindAddr.c.

519 {
520  Dl_info inf;
521  ESyms es,nes = 0;
522  uintptr_t minoff,off;
523  size_t i;
524  Sym sym;
525  Sym nearest;
526  const char *strtab;
527  uint8_t c;
528  size_t idx;
529 
530  if ( ! dladdr(addr, &inf) || (!inf.dli_fname && !inf.dli_sname) ) {
531  sym_p->f_nam = 0;
532  sym_p->s_nam = 0;
533  /* unable to lookup */
534  return 0;
535  }
536 
537  sym_p->f_nam = inf.dli_fname;
538 
539  /* If the symbol is in the main executable then solaris' dladdr returns bogus info */
540 #ifndef __sun
541  if ( (sym_p->s_nam = inf.dli_sname) ) {
542  sym_p->s_val = inf.dli_saddr;
543  /* Have a symbol name - just use it and be done */
544  return 0;
545  }
546 #endif
547 
548  /* No symbol info; try to access ELF file and ready symbol table from there */
549 
550  elfsLockWrite();
551 
552  /* See if we have loaded this file already */
553  es = elfSymsFind(inf.dli_fname);
554 
555  if ( !es ) {
556 
557  elfsUnlockWrite();
558 
559  if ( ! (nes = elfRead(inf.dli_fname, (uintptr_t)inf.dli_fbase)) ) {
560  /* this path can only be taken if there is no memory for '*nes' */
561  return 0;
562  }
563 
564  elfsLockWrite();
565 
566  /* Has someone else intervened and already added this file while we were reading ? */
567  es = elfSymsFind(inf.dli_fname);
568 
569  if ( es ) {
570  /* will undo our work in the unlikely event... */
571  } else {
572  nes->next = elfs;
573  es = elfs = nes;
574  nes = 0;
575  }
576  }
577 
578  elfsUnlockWrite();
579 
580  /* Undo our work in the unlikely event that it was redundant */
581  if ( nes )
582  elfSymsDestroy( nes );
583 
584  nearest.raw = 0;
585  minoff = (uintptr_t)-1LL;
586 
587  if ( es->nsyms ) {
588  c = es->eclss;
589  sym.raw = (char*)es->symMap->addr + es->symMap->off;
590  strtab = (char*)es->strMap->addr + es->strMap->off;
591 
592  /* Do a brute-force search through the symbol table; if this is executed
593  * very often then it would be worthwhile constructing a sorted list of
594  * symbol addresses but for the stack trace we don't care...
595  */
596 #if (FIND_ADDR_DEBUG & 1)
597  printf("Looking for %p\n", addr);
598 #endif
599 
600  if ( ELFCLASS32 == c ) {
601  for ( i=0; i<es->nsyms; i++ ) {
602  if ( STT_FUNC != ELF32_ST_TYPE(sym.e32[i].st_info) )
603  continue;
604  /* don't bother about undefined symbols */
605  if ( 0 == sym.e32[i].st_shndx )
606  continue;
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));
609 #endif
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 ) {
613  minoff = off;
614  nearest.e32 = &sym.e32[i];
615  }
616  }
617  }
618  } else {
619  for ( i=0; i<es->nsyms; i++ ) {
620  if ( STT_FUNC != ELF64_ST_TYPE(sym.e64[i].st_info) )
621  continue;
622  /* don't bother about undefined symbols */
623  if ( 0 == sym.e64[i].st_shndx )
624  continue;
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));
627 #endif
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 ) {
631  minoff = off;
632  nearest.e64 = &sym.e64[i];
633  }
634  }
635  }
636  }
637  }
638 
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;
642  }
643 
644  return 0;
645 }
MMap symMap
void * addr
int i
Definition: scan.c:967
MMap strMap
size_t max
#define printf
Definition: epicsStdio.h:41
Elf64_Sym * e64
const char * f_nam
uintptr_t addr
off_t off
uint8_t eclss
size_t nsyms
const char * s_nam
Elf32_Sym * e32
struct ESyms_ * next
void * raw
#define ARR(c, s, i, f)
int epicsFindAddrGetFeatures ( void  )

Definition at line 647 of file osdElfFindAddr.c.

648 {
649  /* The static information given here may not be correct;
650  * it also depends on
651  * - compilation (frame pointer optimization)
652  * - linkage (static vs. dynamic)
653  * - stripping
654  */
658 }
#define EPICS_STACKTRACE_LCL_SYMBOLS
#define EPICS_STACKTRACE_GBL_SYMBOLS
#define EPICS_STACKTRACE_DYN_SYMBOLS