svn commit: r309594 - head/lib/libproc

Mark Johnston markj at FreeBSD.org
Tue Dec 6 04:19:10 UTC 2016


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 <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

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 <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;
-
-	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 <markj at FreeBSD.org>
  * Copyright (c) 2010 The FreeBSD Foundation
  * Copyright (c) 2008 John Birrell (jb at 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);
 }


More information about the svn-src-all mailing list