summaryrefslogtreecommitdiff
path: root/lib/libproc
diff options
context:
space:
mode:
authorMark Johnston <markj@FreeBSD.org>2016-12-06 04:19:08 +0000
committerMark Johnston <markj@FreeBSD.org>2016-12-06 04:19:08 +0000
commit07a9c2e65d5f2f21cc9783e33dd94a5ce8cc592d (patch)
tree8c4d207e88011c6e05f5c8ad8690038eabfeb3b1 /lib/libproc
parent76c6531c6549d171f3e4de9eed29aec18ac08b4b (diff)
downloadsrc-test-07a9c2e65d5f2f21cc9783e33dd94a5ce8cc592d.tar.gz
src-test-07a9c2e65d5f2f21cc9783e33dd94a5ce8cc592d.zip
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.
Notes
Notes: svn path=/head/; revision=309594
Diffstat (limited to 'lib/libproc')
-rw-r--r--lib/libproc/_libproc.h24
-rw-r--r--lib/libproc/libproc.h2
-rw-r--r--lib/libproc/proc_create.c18
-rw-r--r--lib/libproc/proc_rtld.c90
-rw-r--r--lib/libproc/proc_sym.c320
5 files changed, 233 insertions, 221 deletions
diff --git a/lib/libproc/_libproc.h b/lib/libproc/_libproc.h
index 8026128544b6f..b1ed8e3e88fd7 100644
--- a/lib/libproc/_libproc.h
+++ b/lib/libproc/_libproc.h
@@ -32,12 +32,24 @@
#include <sys/types.h>
#include <sys/ptrace.h>
+#include <libelf.h>
#include <rtld_db.h>
#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
diff --git a/lib/libproc/libproc.h b/lib/libproc/libproc.h
index a41606f3ac2c3..5798a3b4b58d8 100644
--- a/lib/libproc/libproc.h
+++ b/lib/libproc/libproc.h
@@ -131,7 +131,7 @@ char *proc_objname(struct proc_handle *, uintptr_t, char *, size_t);
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 *);
diff --git a/lib/libproc/proc_create.c b/lib/libproc/proc_create.c
index ce8ecd2d932b4..a4ac3cc8a15c8 100644
--- a/lib/libproc/proc_create.c
+++ b/lib/libproc/proc_create.c
@@ -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);
}
diff --git a/lib/libproc/proc_rtld.c b/lib/libproc/proc_rtld.c
index 22aa8d1072b7d..7774a3e484231 100644
--- a/lib/libproc/proc_rtld.c
+++ b/lib/libproc/proc_rtld.c
@@ -31,46 +31,99 @@
__FBSDID("$FreeBSD$");
#include <stdio.h>
-#include <string.h>
#include <stdlib.h>
+#include <string.h>
+
#include <rtld_db.h>
#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;
+ struct file_info *file;
+ struct map_info *mapping, *tmp;
+ struct proc_handle *phdl;
+ size_t i;
- if (phdl->nobjs >= phdl->rdobjsz) {
- phdl->rdobjsz *= 2;
- phdl->rdobjs = reallocf(phdl->rdobjs, sizeof(*phdl->rdobjs) *
- phdl->rdobjsz);
- if (phdl->rdobjs == NULL)
+ 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);
}
diff --git a/lib/libproc/proc_sym.c b/lib/libproc/proc_sym.c
index dccf397b2ede9..cb950f2cb3dcd 100644
--- a/lib/libproc/proc_sym.c
+++ b/lib/libproc/proc_sym.c
@@ -1,4 +1,5 @@
/*-
+ * Copyright (c) 2016 Mark Johnston <markj@FreeBSD.org>
* 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, int *fdp)
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];
-
- 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];
+ size_t 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, uintptr_t addr, char *name,
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, uintptr_t addr, char *name,
* 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, uintptr_t addr, char *name,
}
}
- 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, uintptr_t addr, char *name,
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, const char *object, const char *symbol,
* 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, const char *object, const char *symbol,
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, const char *name)
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 *p, const char *object, int which,
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);
}