Index: lib/libproc/_libproc.h =================================================================== --- lib/libproc/_libproc.h +++ lib/libproc/_libproc.h @@ -35,6 +35,16 @@ #include "libproc.h" +/* Symbol cache */ +#define SYMCACHE_ENTRIES 64 + +struct proc_symcache { + TAILQ_ENTRY(proc_symcache) link; + unsigned char name[64]; + GElf_Sym sym; + uintptr_t addr; +}; + struct proc_handle { pid_t pid; /* Process ID. */ int kq; /* Kernel event queue ID. */ @@ -48,6 +58,9 @@ struct lwpstatus lwps; rd_loadobj_t *rdexec; /* rdobj index of program executable. */ char execname[MAXPATHLEN]; /* Path to program executable. */ + + TAILQ_HEAD(proc_symhead, proc_symcache) symcache; + size_t nsyms; }; #ifdef DEBUG Index: lib/libproc/proc_create.c =================================================================== --- lib/libproc/proc_create.c +++ lib/libproc/proc_create.c @@ -65,6 +65,7 @@ } if (len == 0) phdl->execname[0] = '\0'; + TAILQ_INIT(&phdl->symcache); return (0); } @@ -185,5 +186,12 @@ void proc_free(struct proc_handle *phdl) { + struct proc_symcache *scp; + + while (!TAILQ_EMPTY(&phdl->symcache)) { + scp = TAILQ_FIRST(&phdl->symcache); + TAILQ_REMOVE(&phdl->symcache, scp, link); + free(scp); + } free(phdl); } Index: lib/libproc/proc_sym.c =================================================================== --- lib/libproc/proc_sym.c +++ lib/libproc/proc_sym.c @@ -257,12 +257,74 @@ return (NULL); } +static unsigned int symcache_hit; +static unsigned int symcache_access; + +/* + * Symbol cache functions. + */ +static int +symcache_lookup(struct proc_handle *p, uintptr_t addr, char *name, + size_t namesz, GElf_Sym *sym) +{ + struct proc_symcache *scp, *scp_tmp; + + symcache_access++; + TAILQ_FOREACH_SAFE(scp, &p->symcache, link, scp_tmp) { + if (addr == scp->addr) { + strlcpy(name, scp->name, namesz); + memcpy(sym, &scp->sym, sizeof(*sym)); + TAILQ_REMOVE(&p->symcache, scp, link); + TAILQ_INSERT_HEAD(&p->symcache, scp, link); + symcache_hit++; + return (0); + } + } + + return (1); +} + +static void +symcache_insert(struct proc_handle *p, const char *name, size_t namesz, + uintptr_t addr, GElf_Sym *sym) +{ + struct proc_symcache *scp; + + if (namesz > sizeof(scp->name)) + return; + scp = malloc(sizeof(*scp)); + if (scp == NULL) + return; + bzero(scp, sizeof(*scp)); + strlcpy(scp->name, name, sizeof(scp->name)); + scp->addr = addr; + memcpy(&scp->sym, sym, sizeof(scp->sym)); + TAILQ_INSERT_HEAD(&p->symcache, scp, link); + if (p->nsyms >= SYMCACHE_ENTRIES) + TAILQ_REMOVE(&p->symcache, + TAILQ_LAST(&p->symcache, proc_symhead), link); + else + p->nsyms++; + +} + +#ifdef DEBUG +__attribute__((destructor)) +static void +symcache_stats(void) +{ + printf("Number of accesses: %u\n", symcache_access); + if (symcache_access) + printf("Hit ratio: %f\n", (float)symcache_hit/symcache_access); +} +#endif + /* * Look up the symbol at addr, returning a copy of the symbol and its name. */ static int -lookup_addr(Elf *e, Elf_Scn *scn, u_long stridx, uintptr_t off, uintptr_t addr, - const char **name, GElf_Sym *symcopy) +lookup_addr(struct proc_handle *p, Elf *e, Elf_Scn *scn, u_long stridx, + uintptr_t off, uintptr_t addr, const char **name, GElf_Sym *symcopy) { GElf_Sym sym; Elf_Data *data; @@ -287,6 +349,7 @@ * the function. */ symcopy->st_value = rsym; + symcache_insert(p, s, strlen(s), addr, symcopy); return (0); } } @@ -308,6 +371,8 @@ u_long symtabstridx = 0, dynsymstridx = 0; int fd, error = -1; + if (symcache_lookup(p, addr, name, namesz, symcopy) == 0) + return (0); if ((map = proc_addr2map(p, addr)) == NULL) return (-1); if ((fd = find_dbg_obj(map->pr_mapname)) < 0) { @@ -348,11 +413,11 @@ * First look up the symbol in the dynsymtab, and fall back to the * symtab if the lookup fails. */ - error = lookup_addr(e, dynsymscn, dynsymstridx, off, addr, &s, symcopy); + error = lookup_addr(p, e, dynsymscn, dynsymstridx, off, addr, &s, symcopy); if (error == 0) goto out; - error = lookup_addr(e, symtabscn, symtabstridx, off, addr, &s, symcopy); + error = lookup_addr(p, e, symtabscn, symtabstridx, off, addr, &s, symcopy); if (error != 0) goto err2; @@ -364,6 +429,7 @@ close(fd); err0: free(map); + return (error); }