From owner-svn-src-all@freebsd.org Tue Dec 6 04:19:09 2016 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id EBBE4C6958B; Tue, 6 Dec 2016 04:19:09 +0000 (UTC) (envelope-from markj@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id B41C31D0E; Tue, 6 Dec 2016 04:19:09 +0000 (UTC) (envelope-from markj@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id uB64J9Wi063776; Tue, 6 Dec 2016 04:19:09 GMT (envelope-from markj@FreeBSD.org) Received: (from markj@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id uB64J8oA063771; Tue, 6 Dec 2016 04:19:08 GMT (envelope-from markj@FreeBSD.org) Message-Id: <201612060419.uB64J8oA063771@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: markj set sender to markj@FreeBSD.org using -f From: Mark Johnston Date: Tue, 6 Dec 2016 04:19:08 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r309594 - head/lib/libproc X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 06 Dec 2016 04:19:10 -0000 Author: markj Date: Tue Dec 6 04:19:08 2016 New Revision: 309594 URL: https://svnweb.freebsd.org/changeset/base/309594 Log: libproc: Cache ELF handles for loaded objects. libproc previously created a new handle for each symbol lookup, which gives rather egregious performance for DTrace's ustack() action. With this change libproc will cache the libelf descriptor upon access, making lookups much faster in the common case. Modified: head/lib/libproc/_libproc.h head/lib/libproc/libproc.h head/lib/libproc/proc_create.c head/lib/libproc/proc_rtld.c head/lib/libproc/proc_sym.c Modified: head/lib/libproc/_libproc.h ============================================================================== --- head/lib/libproc/_libproc.h Tue Dec 6 04:18:09 2016 (r309593) +++ head/lib/libproc/_libproc.h Tue Dec 6 04:19:08 2016 (r309594) @@ -32,12 +32,24 @@ #include #include +#include #include #include "libproc.h" struct procstat; +struct file_info { + Elf *elf; + int fd; + u_int refs; +}; + +struct map_info { + prmap_t map; + struct file_info *file; +}; + struct proc_handle { struct proc_handle_public public; /* Public fields. */ int flags; /* Process flags. */ @@ -45,13 +57,13 @@ struct proc_handle { int wstat; /* Process wait status. */ int model; /* Process data model. */ rd_agent_t *rdap; /* librtld_db agent */ - rd_loadobj_t *rdobjs; /* Array of loaded objects. */ - size_t rdobjsz; /* Array size. */ - size_t nobjs; /* Num. objects currently loaded. */ - rd_loadobj_t *rdexec; /* rdobj for program executable. */ - struct lwpstatus lwps; /* Process status. */ + struct map_info *mappings; /* File mappings for proc. */ + size_t maparrsz; /* Map array size. */ + size_t nmappings; /* Number of mappings. */ + prmap_t *exec_map; /* Executable text mapping. */ + lwpstatus_t lwps; /* Process status. */ struct procstat *procstat; /* libprocstat handle. */ - char execpath[MAXPATHLEN]; /* Path to program executable. */ + char execpath[PATH_MAX]; /* Path to program executable. */ }; #ifdef DEBUG Modified: head/lib/libproc/libproc.h ============================================================================== --- head/lib/libproc/libproc.h Tue Dec 6 04:18:09 2016 (r309593) +++ head/lib/libproc/libproc.h Tue Dec 6 04:19:08 2016 (r309594) @@ -131,7 +131,7 @@ char *proc_objname(struct proc_handle *, prmap_t *proc_obj2map(struct proc_handle *, const char *); int proc_iter_objs(struct proc_handle *, proc_map_f *, void *); int proc_iter_symbyaddr(struct proc_handle *, const char *, int, - int, proc_sym_f *, void *); + int, proc_sym_f *, void *); int proc_addr2sym(struct proc_handle *, uintptr_t, char *, size_t, GElf_Sym *); int proc_attach(pid_t pid, int flags, struct proc_handle **pphdl); int proc_continue(struct proc_handle *); Modified: head/lib/libproc/proc_create.c ============================================================================== --- head/lib/libproc/proc_create.c Tue Dec 6 04:18:09 2016 (r309593) +++ head/lib/libproc/proc_create.c Tue Dec 6 04:19:08 2016 (r309594) @@ -230,8 +230,24 @@ bad: void proc_free(struct proc_handle *phdl) { + struct file_info *file; + size_t i; + for (i = 0; i < phdl->nmappings; i++) { + file = phdl->mappings[i].file; + if (file != NULL && --file->refs == 0) { + if (file->elf != NULL) { + (void)elf_end(file->elf); + (void)close(file->fd); + } + free(file); + } + } + if (phdl->maparrsz > 0) + free(phdl->mappings); if (phdl->procstat != NULL) procstat_close(phdl->procstat); + if (phdl->rdap != NULL) + rd_delete(phdl->rdap); free(phdl); } Modified: head/lib/libproc/proc_rtld.c ============================================================================== --- head/lib/libproc/proc_rtld.c Tue Dec 6 04:18:09 2016 (r309593) +++ head/lib/libproc/proc_rtld.c Tue Dec 6 04:19:08 2016 (r309594) @@ -31,46 +31,99 @@ __FBSDID("$FreeBSD$"); #include -#include #include +#include + #include #include "_libproc.h" +static void rdl2prmap(const rd_loadobj_t *, prmap_t *); + static int map_iter(const rd_loadobj_t *lop, void *arg) { - struct proc_handle *phdl = arg; - - if (phdl->nobjs >= phdl->rdobjsz) { - phdl->rdobjsz *= 2; - phdl->rdobjs = reallocf(phdl->rdobjs, sizeof(*phdl->rdobjs) * - phdl->rdobjsz); - if (phdl->rdobjs == NULL) + struct file_info *file; + struct map_info *mapping, *tmp; + struct proc_handle *phdl; + size_t i; + + phdl = arg; + if (phdl->nmappings >= phdl->maparrsz) { + phdl->maparrsz *= 2; + tmp = reallocarray(phdl->mappings, phdl->maparrsz, + sizeof(*phdl->mappings)); + if (tmp == NULL) return (-1); + phdl->mappings = tmp; } + + mapping = &phdl->mappings[phdl->nmappings]; + rdl2prmap(lop, &mapping->map); if (strcmp(lop->rdl_path, phdl->execpath) == 0 && (lop->rdl_prot & RD_RDL_X) != 0) - phdl->rdexec = &phdl->rdobjs[phdl->nobjs]; - memcpy(&phdl->rdobjs[phdl->nobjs++], lop, sizeof(*lop)); + phdl->exec_map = &mapping->map; + file = NULL; + if (lop->rdl_path[0] != '\0') { + /* Look for an existing mapping of the same file. */ + for (i = 0; i < phdl->nmappings; i++) + if (strcmp(mapping->map.pr_mapname, + phdl->mappings[i].map.pr_mapname) == 0) { + file = phdl->mappings[i].file; + break; + } + + if (file == NULL) { + file = malloc(sizeof(*file)); + if (file == NULL) + return (-1); + file->elf = NULL; + file->fd = -1; + file->refs = 1; + } else + file->refs++; + } + mapping->file = file; + phdl->nmappings++; return (0); } +static void +rdl2prmap(const rd_loadobj_t *rdl, prmap_t *map) +{ + + map->pr_vaddr = rdl->rdl_saddr; + map->pr_size = rdl->rdl_eaddr - rdl->rdl_saddr; + map->pr_offset = rdl->rdl_offset; + map->pr_mflags = 0; + if (rdl->rdl_prot & RD_RDL_R) + map->pr_mflags |= MA_READ; + if (rdl->rdl_prot & RD_RDL_W) + map->pr_mflags |= MA_WRITE; + if (rdl->rdl_prot & RD_RDL_X) + map->pr_mflags |= MA_EXEC; + (void)strlcpy(map->pr_mapname, rdl->rdl_path, + sizeof(map->pr_mapname)); +} + rd_agent_t * proc_rdagent(struct proc_handle *phdl) { + if (phdl->rdap == NULL && phdl->status != PS_UNDEAD && phdl->status != PS_IDLE) { - if ((phdl->rdap = rd_new(phdl)) != NULL) { - phdl->rdobjs = malloc(sizeof(*phdl->rdobjs) * 64); - phdl->rdobjsz = 64; - if (phdl->rdobjs == NULL) - return (phdl->rdap); - rd_loadobj_iter(phdl->rdap, map_iter, phdl); - } - } + if ((phdl->rdap = rd_new(phdl)) == NULL) + return (NULL); + phdl->maparrsz = 64; + phdl->mappings = calloc(phdl->maparrsz, + sizeof(*phdl->mappings)); + if (phdl->mappings == NULL) + return (phdl->rdap); + if (rd_loadobj_iter(phdl->rdap, map_iter, phdl) != RD_OK) + return (NULL); + } return (phdl->rdap); } @@ -78,7 +131,6 @@ void proc_updatesyms(struct proc_handle *phdl) { - memset(phdl->rdobjs, 0, sizeof(*phdl->rdobjs) * phdl->rdobjsz); - phdl->nobjs = 0; + memset(phdl->mappings, 0, sizeof(*phdl->mappings) * phdl->maparrsz); rd_loadobj_iter(phdl->rdap, map_iter, phdl); } Modified: head/lib/libproc/proc_sym.c ============================================================================== --- head/lib/libproc/proc_sym.c Tue Dec 6 04:18:09 2016 (r309593) +++ head/lib/libproc/proc_sym.c Tue Dec 6 04:19:08 2016 (r309594) @@ -1,4 +1,5 @@ /*- + * Copyright (c) 2016 Mark Johnston * Copyright (c) 2010 The FreeBSD Foundation * Copyright (c) 2008 John Birrell (jb@freebsd.org) * All rights reserved. @@ -64,8 +65,6 @@ typedef struct ctf_file ctf_file_t; extern char *__cxa_demangle(const char *, char *, size_t *, int *); #endif /* NO_CXA_DEMANGLE */ -static void proc_rdl2prmap(rd_loadobj_t *, prmap_t *); - static int crc32_file(int fd, uint32_t *crc) { @@ -131,18 +130,27 @@ out: * returned. */ static int -open_object(prmap_t *map, Elf **elfp, int *fdp) +open_object(struct map_info *mapping) { char path[PATH_MAX]; GElf_Shdr shdr; Elf *e, *e2; Elf_Data *data; Elf_Scn *scn; + struct file_info *file; + prmap_t *map; const char *debugfile, *scnname; size_t ndx; uint32_t crc; int fd, fd2; + if (mapping->map.pr_mapname[0] == '\0') + return (-1); /* anonymous object */ + if (mapping->file->elf != NULL) + return (0); /* already loaded */ + + file = mapping->file; + map = &mapping->map; if ((fd = open(map->pr_mapname, O_RDONLY | O_CLOEXEC)) < 0) { DPRINTF("ERROR: open %s failed", map->pr_mapname); return (-1); @@ -225,8 +233,8 @@ open_object(prmap_t *map, Elf **elfp, in internal: /* We didn't find a debug file, just return the object's descriptor. */ - *elfp = e; - *fdp = fd; + file->elf = e; + file->fd = fd; return (0); external: @@ -237,8 +245,8 @@ external: } (void)elf_end(e); (void)close(fd); - *elfp = e2; - *fdp = fd2; + file->elf = e2; + file->fd = fd2; return (0); err: @@ -248,166 +256,107 @@ err: return (-1); } -static void -proc_rdl2prmap(rd_loadobj_t *rdl, prmap_t *map) -{ - map->pr_vaddr = rdl->rdl_saddr; - map->pr_size = rdl->rdl_eaddr - rdl->rdl_saddr; - map->pr_offset = rdl->rdl_offset; - map->pr_mflags = 0; - if (rdl->rdl_prot & RD_RDL_R) - map->pr_mflags |= MA_READ; - if (rdl->rdl_prot & RD_RDL_W) - map->pr_mflags |= MA_WRITE; - if (rdl->rdl_prot & RD_RDL_X) - map->pr_mflags |= MA_EXEC; - strlcpy(map->pr_mapname, rdl->rdl_path, - sizeof(map->pr_mapname)); -} - char * proc_objname(struct proc_handle *p, uintptr_t addr, char *objname, size_t objnamesz) { + prmap_t *map; size_t i; - rd_loadobj_t *rdl; - for (i = 0; i < p->nobjs; i++) { - rdl = &p->rdobjs[i]; - if (addr >= rdl->rdl_saddr && addr < rdl->rdl_eaddr) { - strlcpy(objname, rdl->rdl_path, objnamesz); + for (i = 0; i < p->nmappings; i++) { + map = &p->mappings[i].map; + if (addr >= map->pr_vaddr && + addr < map->pr_vaddr + map->pr_size) { + strlcpy(objname, map->pr_mapname, objnamesz); return (objname); } } return (NULL); } +/* + * Currently just returns the first mapping of the named object, effectively + * what Plmid_to_map(p, PR_LMID_EVERY, objname) does in illumos libproc. + */ prmap_t * proc_obj2map(struct proc_handle *p, const char *objname) { - size_t i; + char path[PATH_MAX], *base; prmap_t *map; - rd_loadobj_t *rdl; - char path[MAXPATHLEN]; + size_t i; - rdl = NULL; - for (i = 0; i < p->nobjs; i++) { - basename_r(p->rdobjs[i].rdl_path, path); - if (strcmp(path, objname) == 0) { - rdl = &p->rdobjs[i]; + map = NULL; + for (i = 0; i < p->nmappings; i++) { + strlcpy(path, p->mappings[i].map.pr_mapname, sizeof(path)); + base = basename(path); + if (strcmp(base, objname) == 0) { + map = &p->mappings[i].map; break; } } - if (rdl == NULL) { - if (strcmp(objname, "a.out") == 0 && p->rdexec != NULL) - rdl = p->rdexec; - else - return (NULL); - } - - if ((map = malloc(sizeof(*map))) == NULL) - return (NULL); - proc_rdl2prmap(rdl, map); + if (map == NULL && strcmp(objname, "a.out") == 0 && p->exec_map != NULL) + map = p->exec_map; return (map); } int proc_iter_objs(struct proc_handle *p, proc_map_f *func, void *cd) { + char last[MAXPATHLEN], path[MAXPATHLEN], *base; + prmap_t *map; size_t i; - rd_loadobj_t *rdl; - prmap_t map; - char path[MAXPATHLEN]; - char last[MAXPATHLEN]; int error; - if (p->nobjs == 0) - return (-1); + if (p->nmappings == 0) + if (proc_rdagent(p) == NULL) + return (-1); error = 0; memset(last, 0, sizeof(last)); - for (i = 0; i < p->nobjs; i++) { - rdl = &p->rdobjs[i]; - proc_rdl2prmap(rdl, &map); - basename_r(rdl->rdl_path, path); + for (i = 0; i < p->nmappings; i++) { + map = &p->mappings[i].map; + strlcpy(path, map->pr_mapname, sizeof(path)); + base = basename(path); /* * We shouldn't call the callback twice with the same object. * To do that we are assuming the fact that if there are * repeated object names (i.e. different mappings for the * same object) they occur next to each other. */ - if (strcmp(path, last) == 0) + if (strcmp(base, last) == 0) continue; - if ((error = (*func)(cd, &map, path)) != 0) + if ((error = (*func)(cd, map, base)) != 0) break; strlcpy(last, path, sizeof(last)); } return (error); } -prmap_t * -proc_addr2map(struct proc_handle *p, uintptr_t addr) +static struct map_info * +_proc_addr2map(struct proc_handle *p, uintptr_t addr) { + struct map_info *mapping; size_t i; - int cnt, lastvn = 0; - prmap_t *map; - rd_loadobj_t *rdl; - struct kinfo_vmentry *kves, *kve; - /* - * If we don't have a cache of listed objects, we need to query - * it ourselves. - */ - if (p->nobjs == 0) { - if ((kves = kinfo_getvmmap(proc_getpid(p), &cnt)) == NULL) + if (p->nmappings == 0) + if (proc_rdagent(p) == NULL) return (NULL); - for (i = 0; i < (size_t)cnt; i++) { - kve = kves + i; - if (kve->kve_type == KVME_TYPE_VNODE) - lastvn = i; - if (addr >= kve->kve_start && addr < kve->kve_end) { - if ((map = malloc(sizeof(*map))) == NULL) { - free(kves); - return (NULL); - } - map->pr_vaddr = kve->kve_start; - map->pr_size = kve->kve_end - kve->kve_start; - map->pr_offset = kve->kve_offset; - map->pr_mflags = 0; - if (kve->kve_protection & KVME_PROT_READ) - map->pr_mflags |= MA_READ; - if (kve->kve_protection & KVME_PROT_WRITE) - map->pr_mflags |= MA_WRITE; - if (kve->kve_protection & KVME_PROT_EXEC) - map->pr_mflags |= MA_EXEC; - if (kve->kve_flags & KVME_FLAG_COW) - map->pr_mflags |= MA_COW; - if (kve->kve_flags & KVME_FLAG_NEEDS_COPY) - map->pr_mflags |= MA_NEEDS_COPY; - if (kve->kve_flags & KVME_FLAG_NOCOREDUMP) - map->pr_mflags |= MA_NOCOREDUMP; - strlcpy(map->pr_mapname, kves[lastvn].kve_path, - sizeof(map->pr_mapname)); - free(kves); - return (map); - } - } - free(kves); - return (NULL); - } - - for (i = 0; i < p->nobjs; i++) { - rdl = &p->rdobjs[i]; - if (addr >= rdl->rdl_saddr && addr < rdl->rdl_eaddr) { - if ((map = malloc(sizeof(*map))) == NULL) - return (NULL); - proc_rdl2prmap(rdl, map); - return (map); - } + for (i = 0; i < p->nmappings; i++) { + mapping = &p->mappings[i]; + if (addr >= mapping->map.pr_vaddr && + addr < mapping->map.pr_vaddr + mapping->map.pr_size) + return (mapping); } return (NULL); } +prmap_t * +proc_addr2map(struct proc_handle *p, uintptr_t addr) +{ + + return (&_proc_addr2map(p, addr)->map); +} + /* * Look up the symbol at addr, returning a copy of the symbol and its name. */ @@ -452,21 +401,23 @@ proc_addr2sym(struct proc_handle *p, uin GElf_Ehdr ehdr; GElf_Shdr shdr; Elf *e; - Elf_Scn *scn, *dynsymscn = NULL, *symtabscn = NULL; - prmap_t *map; + Elf_Scn *scn, *dynsymscn, *symtabscn; + struct map_info *mapping; const char *s; uintptr_t off; - u_long symtabstridx = 0, dynsymstridx = 0; - int fd, error = -1; + u_long symtabstridx, dynsymstridx; + int error = -1; - if ((map = proc_addr2map(p, addr)) == NULL) { + if ((mapping = _proc_addr2map(p, addr)) == NULL) { DPRINTFX("ERROR: proc_addr2map failed to resolve 0x%jx", addr); return (-1); } - if (open_object(map, &e, &fd) != 0) { - DPRINTFX("ERROR: failed to open object %s", map->pr_mapname); + if (open_object(mapping) != 0) { + DPRINTFX("ERROR: failed to open object %s", + mapping->map.pr_mapname); return (-1); } + e = mapping->file->elf; if (gelf_getehdr(e, &ehdr) == NULL) { DPRINTFX("ERROR: gelf_getehdr() failed: %s", elf_errmsg(-1)); goto err; @@ -476,7 +427,8 @@ proc_addr2sym(struct proc_handle *p, uin * Find the index of the STRTAB and SYMTAB sections to locate * symbol names. */ - scn = NULL; + symtabstridx = dynsymstridx = 0; + scn = dynsymscn = symtabscn = NULL; while ((scn = elf_nextscn(e, scn)) != NULL) { gelf_getshdr(scn, &shdr); switch (shdr.sh_type) { @@ -491,7 +443,7 @@ proc_addr2sym(struct proc_handle *p, uin } } - off = ehdr.e_type == ET_EXEC ? 0 : map->pr_vaddr; + off = ehdr.e_type == ET_EXEC ? 0 : mapping->map.pr_vaddr; /* * First look up the symbol in the dynsymtab, and fall back to the @@ -508,56 +460,39 @@ proc_addr2sym(struct proc_handle *p, uin out: demangle(s, name, namesz); err: - (void)elf_end(e); - (void)close(fd); - free(map); return (error); } -prmap_t * -proc_name2map(struct proc_handle *p, const char *name) +static struct map_info * +_proc_name2map(struct proc_handle *p, const char *name) { + char path[MAXPATHLEN], *base; + struct map_info *mapping; size_t i; - int cnt; - prmap_t *map = NULL; - char tmppath[MAXPATHLEN]; - struct kinfo_vmentry *kves, *kve; - rd_loadobj_t *rdl; - /* - * If we haven't iterated over the list of loaded objects, - * librtld_db isn't yet initialized and it's very likely - * that librtld_db called us. We need to do the heavy - * lifting here to find the symbol librtld_db is looking for. - */ - if (p->nobjs == 0) { - if ((kves = kinfo_getvmmap(proc_getpid(p), &cnt)) == NULL) + mapping = NULL; + if (p->nmappings == 0) + if (proc_rdagent(p) == NULL) return (NULL); - for (i = 0; i < (size_t)cnt; i++) { - kve = kves + i; - basename_r(kve->kve_path, tmppath); - if (strcmp(tmppath, name) == 0) { - map = proc_addr2map(p, kve->kve_start); - break; - } - } - free(kves); - } else - for (i = 0; i < p->nobjs; i++) { - rdl = &p->rdobjs[i]; - basename_r(rdl->rdl_path, tmppath); - if (strcmp(tmppath, name) == 0) { - if ((map = malloc(sizeof(*map))) == NULL) - return (NULL); - proc_rdl2prmap(rdl, map); - break; - } - } + for (i = 0; i < p->nmappings; i++) { + mapping = &p->mappings[i]; + (void)strlcpy(path, mapping->map.pr_mapname, sizeof(path)); + base = basename(path); + if (strcmp(base, name) == 0) + break; + } + if (i == p->nmappings) + mapping = NULL; + if (mapping == NULL && strcmp(name, "a.out") == 0) + mapping = _proc_addr2map(p, p->exec_map->pr_vaddr); + return (mapping); +} - if (map == NULL && strcmp(name, "a.out") == 0 && p->rdexec != NULL) - map = proc_addr2map(p, p->rdexec->rdl_saddr); +prmap_t * +proc_name2map(struct proc_handle *p, const char *name) +{ - return (map); + return (&_proc_name2map(p, name)->map); } /* @@ -592,23 +527,25 @@ int proc_name2sym(struct proc_handle *p, const char *object, const char *symbol, GElf_Sym *symcopy, prsyminfo_t *si) { - Elf *e; - Elf_Scn *scn, *dynsymscn = NULL, *symtabscn = NULL; - GElf_Shdr shdr; GElf_Ehdr ehdr; - prmap_t *map; + GElf_Shdr shdr; + Elf *e; + Elf_Scn *scn, *dynsymscn, *symtabscn; + struct map_info *mapping; uintptr_t off; - u_long symtabstridx = 0, dynsymstridx = 0; - int fd, error = -1; + u_long symtabstridx, dynsymstridx; + int error = -1; - if ((map = proc_name2map(p, object)) == NULL) { + if ((mapping = _proc_name2map(p, object)) == NULL) { DPRINTFX("ERROR: proc_name2map failed to resolve %s", object); return (-1); } - if (open_object(map, &e, &fd) != 0) { - DPRINTFX("ERROR: failed to open object %s", map->pr_mapname); + if (open_object(mapping) != 0) { + DPRINTFX("ERROR: failed to open object %s", + mapping->map.pr_mapname); return (-1); } + e = mapping->file->elf; if (gelf_getehdr(e, &ehdr) == NULL) { DPRINTFX("ERROR: gelf_getehdr() failed: %s", elf_errmsg(-1)); goto err; @@ -618,7 +555,8 @@ proc_name2sym(struct proc_handle *p, con * Find the index of the STRTAB and SYMTAB sections to locate * symbol names. */ - scn = NULL; + symtabstridx = dynsymstridx = 0; + scn = dynsymscn = symtabscn = NULL; while ((scn = elf_nextscn(e, scn)) != NULL) { gelf_getshdr(scn, &shdr); switch (shdr.sh_type) { @@ -646,13 +584,10 @@ proc_name2sym(struct proc_handle *p, con goto out; out: - off = ehdr.e_type == ET_EXEC ? 0 : map->pr_vaddr; + off = ehdr.e_type == ET_EXEC ? 0 : mapping->map.pr_vaddr; symcopy->st_value += off; err: - (void)elf_end(e); - (void)close(fd); - free(map); return (error); } @@ -668,7 +603,6 @@ proc_name2ctf(struct proc_handle *p, con return (NULL); ctf = ctf_open(map->pr_mapname, &error); - free(map); return (ctf); #else (void)p; @@ -681,26 +615,27 @@ int proc_iter_symbyaddr(struct proc_handle *p, const char *object, int which, int mask, proc_sym_f *func, void *cd) { - Elf *e; - int i, fd; - prmap_t *map; - Elf_Scn *scn, *foundscn; - Elf_Data *data; GElf_Ehdr ehdr; GElf_Shdr shdr; GElf_Sym sym; - unsigned long stridx = -1; + Elf *e; + Elf_Scn *scn, *foundscn; + Elf_Data *data; + struct map_info *mapping; char *s; - int error = -1; + unsigned long stridx = -1; + int error = -1, i; - if ((map = proc_name2map(p, object)) == NULL) { + if ((mapping = _proc_name2map(p, object)) == NULL) { DPRINTFX("ERROR: proc_name2map failed to resolve %s", object); return (-1); } - if (open_object(map, &e, &fd) != 0) { - DPRINTFX("ERROR: failed to open object %s", map->pr_mapname); + if (open_object(mapping) != 0) { + DPRINTFX("ERROR: failed to open object %s", + mapping->map.pr_mapname); return (-1); } + e = mapping->file->elf; if (gelf_getehdr(e, &ehdr) == NULL) { DPRINTFX("ERROR: gelf_getehdr() failed: %s", elf_errmsg(-1)); goto err; @@ -755,14 +690,11 @@ proc_iter_symbyaddr(struct proc_handle * continue; s = elf_strptr(e, stridx, sym.st_name); if (ehdr.e_type != ET_EXEC) - sym.st_value += map->pr_vaddr; + sym.st_value += mapping->map.pr_vaddr; if ((error = (*func)(cd, &sym, s)) != 0) goto err; } error = 0; err: - elf_end(e); - close(fd); - free(map); return (error); }