aboutsummaryrefslogtreecommitdiff
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)
Notes
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.c16
-rw-r--r--lib/libproc/proc_rtld.c90
-rw-r--r--lib/libproc/proc_sym.c318
5 files changed, 231 insertions, 219 deletions
diff --git a/lib/libproc/_libproc.h b/lib/libproc/_libproc.h
index 8026128544b6..b1ed8e3e88fd 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 a41606f3ac2c..5798a3b4b58d 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 ce8ecd2d932b..a4ac3cc8a15c 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 22aa8d1072b7..7774a3e48423 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 dccf397b2ede..cb950f2cb3dc 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];
+ 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, 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);
}