summaryrefslogtreecommitdiff
path: root/usr/src/lib/libproc/common
diff options
context:
space:
mode:
authorJeremy Jones <jeremy@delphix.com>2013-08-21 15:45:46 -0800
committerChristopher Siden <chris.siden@delphix.com>2013-08-21 16:45:46 -0700
commit2a12f85ad140e332791b4bad1208a734c3f26bf3 (patch)
treef4360a28249f0409ce5037f493a18f60e6219ea2 /usr/src/lib/libproc/common
parent840b2722e5294ae44aa3af6189002f521d7c50e0 (diff)
downloadillumos-joyent-2a12f85ad140e332791b4bad1208a734c3f26bf3.tar.gz
3946 ::gcore
Reviewed by: Adam Leventhal <ahl@delphix.com> Reviewed by: Matthew Ahrens <mahrens@delphix.com> Approved by: Robert Mustacchi <rm@joyent.com>
Diffstat (limited to 'usr/src/lib/libproc/common')
-rw-r--r--usr/src/lib/libproc/common/Pcontrol.c459
-rw-r--r--usr/src/lib/libproc/common/Pcontrol.h14
-rw-r--r--usr/src/lib/libproc/common/Pcore.c311
-rw-r--r--usr/src/lib/libproc/common/Pexecname.c66
-rw-r--r--usr/src/lib/libproc/common/Pgcore.c5
-rw-r--r--usr/src/lib/libproc/common/Pidle.c57
-rw-r--r--usr/src/lib/libproc/common/Plwpregs.c8
-rw-r--r--usr/src/lib/libproc/common/Pservice.c9
-rw-r--r--usr/src/lib/libproc/common/Psymtab.c105
-rw-r--r--usr/src/lib/libproc/common/Putil.c98
-rw-r--r--usr/src/lib/libproc/common/Putil.h7
-rw-r--r--usr/src/lib/libproc/common/Pzone.c19
-rw-r--r--usr/src/lib/libproc/common/libproc.h54
-rw-r--r--usr/src/lib/libproc/common/llib-lproc5
-rw-r--r--usr/src/lib/libproc/common/mapfile-vers2
15 files changed, 834 insertions, 385 deletions
diff --git a/usr/src/lib/libproc/common/Pcontrol.c b/usr/src/lib/libproc/common/Pcontrol.c
index 1e7ce1556e..751c0c3f8a 100644
--- a/usr/src/lib/libproc/common/Pcontrol.c
+++ b/usr/src/lib/libproc/common/Pcontrol.c
@@ -25,6 +25,7 @@
*
* Portions Copyright 2007 Chad Mynhier
* Copyright 2012 DEY Storage Systems, Inc. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
*/
#include <assert.h>
@@ -41,6 +42,7 @@
#include <limits.h>
#include <signal.h>
#include <atomic.h>
+#include <zone.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <sys/stat.h>
@@ -50,6 +52,7 @@
#include <sys/fault.h>
#include <sys/syscall.h>
#include <sys/sysmacros.h>
+#include <sys/systeminfo.h>
#include "libproc.h"
#include "Pcontrol.h"
@@ -71,25 +74,261 @@ char procfs_path[PATH_MAX] = "/proc";
static void deadcheck(struct ps_prochandle *);
static void restore_tracing_flags(struct ps_prochandle *);
static void Lfree_internal(struct ps_prochandle *, struct ps_lwphandle *);
+static prheader_t *read_lfile(struct ps_prochandle *, const char *);
/*
- * Read/write interface for live processes: just pread/pwrite the
- * /proc/<pid>/as file:
+ * Ops vector functions for live processes.
*/
+/*ARGSUSED*/
static ssize_t
-Pread_live(struct ps_prochandle *P, void *buf, size_t n, uintptr_t addr)
+Pread_live(struct ps_prochandle *P, void *buf, size_t n, uintptr_t addr,
+ void *data)
{
return (pread(P->asfd, buf, n, (off_t)addr));
}
+/*ARGSUSED*/
static ssize_t
-Pwrite_live(struct ps_prochandle *P, const void *buf, size_t n, uintptr_t addr)
+Pwrite_live(struct ps_prochandle *P, const void *buf, size_t n, uintptr_t addr,
+ void *data)
{
return (pwrite(P->asfd, buf, n, (off_t)addr));
}
-static const ps_rwops_t P_live_ops = { Pread_live, Pwrite_live };
+/*ARGSUSED*/
+static int
+Pread_maps_live(struct ps_prochandle *P, prmap_t **Pmapp, ssize_t *nmapp,
+ void *data)
+{
+ char mapfile[PATH_MAX];
+ int mapfd;
+ struct stat statb;
+ ssize_t nmap;
+ prmap_t *Pmap = NULL;
+
+ (void) snprintf(mapfile, sizeof (mapfile), "%s/%d/map",
+ procfs_path, (int)P->pid);
+ if ((mapfd = open(mapfile, O_RDONLY)) < 0 ||
+ fstat(mapfd, &statb) != 0 ||
+ statb.st_size < sizeof (prmap_t) ||
+ (Pmap = malloc(statb.st_size)) == NULL ||
+ (nmap = pread(mapfd, Pmap, statb.st_size, 0L)) <= 0 ||
+ (nmap /= sizeof (prmap_t)) == 0) {
+ if (Pmap != NULL)
+ free(Pmap);
+ if (mapfd >= 0)
+ (void) close(mapfd);
+ Preset_maps(P); /* utter failure; destroy tables */
+ return (-1);
+ }
+ (void) close(mapfd);
+
+ *Pmapp = Pmap;
+ *nmapp = nmap;
+
+ return (0);
+}
+
+/*ARGSUSED*/
+static void
+Pread_aux_live(struct ps_prochandle *P, auxv_t **auxvp, int *nauxp, void *data)
+{
+ char auxfile[64];
+ int fd;
+ struct stat statb;
+ auxv_t *auxv;
+ ssize_t naux;
+
+ (void) snprintf(auxfile, sizeof (auxfile), "%s/%d/auxv",
+ procfs_path, (int)P->pid);
+ if ((fd = open(auxfile, O_RDONLY)) < 0) {
+ dprintf("%s: failed to open %s: %s\n",
+ __func__, auxfile, strerror(errno));
+ return;
+ }
+
+ if (fstat(fd, &statb) == 0 &&
+ statb.st_size >= sizeof (auxv_t) &&
+ (auxv = malloc(statb.st_size + sizeof (auxv_t))) != NULL) {
+ if ((naux = read(fd, auxv, statb.st_size)) < 0 ||
+ (naux /= sizeof (auxv_t)) < 1) {
+ dprintf("%s: read failed: %s\n",
+ __func__, strerror(errno));
+ free(auxv);
+ } else {
+ auxv[naux].a_type = AT_NULL;
+ auxv[naux].a_un.a_val = 0L;
+
+ *auxvp = auxv;
+ *nauxp = (int)naux;
+ }
+ }
+
+ (void) close(fd);
+}
+
+/*ARGSUSED*/
+static int
+Pcred_live(struct ps_prochandle *P, prcred_t *pcrp, int ngroups, void *data)
+{
+ return (proc_get_cred(P->pid, pcrp, ngroups));
+}
+
+/*ARGSUSED*/
+static int
+Ppriv_live(struct ps_prochandle *P, prpriv_t **pprv, void *data)
+{
+ prpriv_t *pp;
+
+ pp = proc_get_priv(P->pid);
+ if (pp == NULL) {
+ return (-1);
+ }
+
+ *pprv = pp;
+ return (0);
+}
+
+/*ARGSUSED*/
+static const psinfo_t *
+Ppsinfo_live(struct ps_prochandle *P, psinfo_t *psinfo, void *data)
+{
+ if (proc_get_psinfo(P->pid, psinfo) == -1)
+ return (NULL);
+
+ return (psinfo);
+}
+
+/*ARGSUSED*/
+static prheader_t *
+Plstatus_live(struct ps_prochandle *P, void *data)
+{
+ return (read_lfile(P, "lstatus"));
+}
+
+/*ARGSUSED*/
+static prheader_t *
+Plpsinfo_live(struct ps_prochandle *P, void *data)
+{
+ return (read_lfile(P, "lpsinfo"));
+}
+
+/*ARGSUSED*/
+static char *
+Pplatform_live(struct ps_prochandle *P, char *s, size_t n, void *data)
+{
+ if (sysinfo(SI_PLATFORM, s, n) == -1)
+ return (NULL);
+ return (s);
+}
+
+/*ARGSUSED*/
+static int
+Puname_live(struct ps_prochandle *P, struct utsname *u, void *data)
+{
+ return (uname(u));
+}
+
+/*ARGSUSED*/
+static char *
+Pzonename_live(struct ps_prochandle *P, char *s, size_t n, void *data)
+{
+ if (getzonenamebyid(P->status.pr_zoneid, s, n) < 0)
+ return (NULL);
+ s[n - 1] = '\0';
+ return (s);
+}
+
+/*
+ * Callback function for Pfindexec(). We return a match if we can stat the
+ * suggested pathname and confirm its device and inode number match our
+ * previous information about the /proc/<pid>/object/a.out file.
+ */
+static int
+stat_exec(const char *path, void *arg)
+{
+ struct stat64 *stp = arg;
+ struct stat64 st;
+
+ return (stat64(path, &st) == 0 && S_ISREG(st.st_mode) &&
+ stp->st_dev == st.st_dev && stp->st_ino == st.st_ino);
+}
+
+/*ARGSUSED*/
+static char *
+Pexecname_live(struct ps_prochandle *P, char *buf, size_t buflen, void *data)
+{
+ char exec_name[PATH_MAX];
+ char cwd[PATH_MAX];
+ char proc_cwd[64];
+ struct stat64 st;
+ int ret;
+
+ /*
+ * Try to get the path information first.
+ */
+ (void) snprintf(exec_name, sizeof (exec_name),
+ "%s/%d/path/a.out", procfs_path, (int)P->pid);
+ if ((ret = readlink(exec_name, buf, buflen - 1)) > 0) {
+ buf[ret] = '\0';
+ (void) Pfindobj(P, buf, buf, buflen);
+ return (buf);
+ }
+
+ /*
+ * Stat the executable file so we can compare Pfindexec's
+ * suggestions to the actual device and inode number.
+ */
+ (void) snprintf(exec_name, sizeof (exec_name),
+ "%s/%d/object/a.out", procfs_path, (int)P->pid);
+
+ if (stat64(exec_name, &st) != 0 || !S_ISREG(st.st_mode))
+ return (NULL);
+
+ /*
+ * Attempt to figure out the current working directory of the
+ * target process. This only works if the target process has
+ * not changed its current directory since it was exec'd.
+ */
+ (void) snprintf(proc_cwd, sizeof (proc_cwd),
+ "%s/%d/path/cwd", procfs_path, (int)P->pid);
+
+ if ((ret = readlink(proc_cwd, cwd, PATH_MAX - 1)) > 0)
+ cwd[ret] = '\0';
+
+ (void) Pfindexec(P, ret > 0 ? cwd : NULL, stat_exec, &st);
+
+ return (NULL);
+}
+
+#if defined(__i386) || defined(__amd64)
+/*ARGSUSED*/
+static int
+Pldt_live(struct ps_prochandle *P, struct ssd *pldt, int nldt, void *data)
+{
+ return (proc_get_ldt(P->pid, pldt, nldt));
+}
+#endif
+
+static const ps_ops_t P_live_ops = {
+ .pop_pread = Pread_live,
+ .pop_pwrite = Pwrite_live,
+ .pop_read_maps = Pread_maps_live,
+ .pop_read_aux = Pread_aux_live,
+ .pop_cred = Pcred_live,
+ .pop_priv = Ppriv_live,
+ .pop_psinfo = Ppsinfo_live,
+ .pop_lstatus = Plstatus_live,
+ .pop_lpsinfo = Plpsinfo_live,
+ .pop_platform = Pplatform_live,
+ .pop_uname = Puname_live,
+ .pop_zonename = Pzonename_live,
+ .pop_execname = Pexecname_live,
+#if defined(__i386) || defined(__amd64)
+ .pop_ldt = Pldt_live
+#endif
+};
/*
* This is the library's .init handler.
@@ -249,7 +488,7 @@ Pxcreate(const char *file, /* executable file name */
P->statfd = -1;
P->agentctlfd = -1;
P->agentstatfd = -1;
- P->ops = &P_live_ops;
+ Pinit_ops(&P->ops, &P_live_ops);
Pinitsym(P);
/*
@@ -552,7 +791,7 @@ again: /* Come back here if we lose it in the Window of Vulnerability */
P->statfd = -1;
P->agentctlfd = -1;
P->agentstatfd = -1;
- P->ops = &P_live_ops;
+ Pinit_ops(&P->ops, &P_live_ops);
Pinitsym(P);
/*
@@ -933,45 +1172,6 @@ Pfree(struct ps_prochandle *P)
{
uint_t i;
- if (P->core != NULL) {
- extern void __priv_free_info(void *);
- lwp_info_t *nlwp, *lwp = list_next(&P->core->core_lwp_head);
-
- for (i = 0; i < P->core->core_nlwp; i++, lwp = nlwp) {
- nlwp = list_next(lwp);
-#ifdef __sparc
- if (lwp->lwp_gwins != NULL)
- free(lwp->lwp_gwins);
- if (lwp->lwp_xregs != NULL)
- free(lwp->lwp_xregs);
- if (lwp->lwp_asrs != NULL)
- free(lwp->lwp_asrs);
-#endif
- free(lwp);
- }
-
- if (P->core->core_platform != NULL)
- free(P->core->core_platform);
- if (P->core->core_uts != NULL)
- free(P->core->core_uts);
- if (P->core->core_cred != NULL)
- free(P->core->core_cred);
- if (P->core->core_priv != NULL)
- free(P->core->core_priv);
- if (P->core->core_privinfo != NULL)
- __priv_free_info(P->core->core_privinfo);
- if (P->core->core_ppii != NULL)
- free(P->core->core_ppii);
- if (P->core->core_zonename != NULL)
- free(P->core->core_zonename);
-#if defined(__i386) || defined(__amd64)
- if (P->core->core_ldt != NULL)
- free(P->core->core_ldt);
-#endif
-
- free(P->core);
- }
-
if (P->ucaddrs != NULL) {
free(P->ucaddrs);
P->ucaddrs = NULL;
@@ -1008,6 +1208,7 @@ Pfree(struct ps_prochandle *P)
if (P->statfd >= 0)
(void) close(P->statfd);
Preset_maps(P);
+ P->ops.pop_fini(P, P->data);
/* clear out the structure as a precaution against reuse */
(void) memset(P, 0, sizeof (*P));
@@ -1059,15 +1260,7 @@ Pctlfd(struct ps_prochandle *P)
const psinfo_t *
Ppsinfo(struct ps_prochandle *P)
{
- if (P->state == PS_IDLE) {
- errno = ENODATA;
- return (NULL);
- }
-
- if (P->state != PS_DEAD && proc_get_psinfo(P->pid, &P->psinfo) == -1)
- return (NULL);
-
- return (&P->psinfo);
+ return (P->ops.pop_psinfo(P, &P->psinfo, P->data));
}
/*
@@ -1081,6 +1274,12 @@ Pstatus(struct ps_prochandle *P)
return (&P->status);
}
+static void
+Pread_status(struct ps_prochandle *P)
+{
+ P->ops.pop_status(P, &P->status, P->data);
+}
+
/*
* Fill in a pointer to a process credentials structure. The ngroups parameter
* is the number of supplementary group entries allocated in the caller's cred
@@ -1090,32 +1289,22 @@ Pstatus(struct ps_prochandle *P)
int
Pcred(struct ps_prochandle *P, prcred_t *pcrp, int ngroups)
{
- if (P->state == PS_IDLE) {
- errno = ENODATA;
- return (-1);
- }
-
- if (P->state != PS_DEAD)
- return (proc_get_cred(P->pid, pcrp, ngroups));
-
- if (P->core->core_cred != NULL) {
- /*
- * Avoid returning more supplementary group data than the
- * caller has allocated in their buffer. We expect them to
- * check pr_ngroups afterward and potentially call us again.
- */
- ngroups = MIN(ngroups, P->core->core_cred->pr_ngroups);
-
- (void) memcpy(pcrp, P->core->core_cred,
- sizeof (prcred_t) + (ngroups - 1) * sizeof (gid_t));
+ return (P->ops.pop_cred(P, pcrp, ngroups, P->data));
+}
- return (0);
- }
+static prheader_t *
+Plstatus(struct ps_prochandle *P)
+{
+ return (P->ops.pop_lstatus(P, P->data));
+}
- errno = ENODATA;
- return (-1);
+static prheader_t *
+Plpsinfo(struct ps_prochandle *P)
+{
+ return (P->ops.pop_lpsinfo(P, P->data));
}
+
#if defined(__i386) || defined(__amd64)
/*
* Fill in a pointer to a process LDT structure.
@@ -1126,55 +1315,18 @@ Pcred(struct ps_prochandle *P, prcred_t *pcrp, int ngroups)
int
Pldt(struct ps_prochandle *P, struct ssd *pldt, int nldt)
{
- if (P->state == PS_IDLE) {
- errno = ENODATA;
- return (-1);
- }
-
- if (P->state != PS_DEAD)
- return (proc_get_ldt(P->pid, pldt, nldt));
-
- if (pldt == NULL || nldt == 0)
- return (P->core->core_nldt);
-
- if (P->core->core_ldt != NULL) {
- nldt = MIN(nldt, P->core->core_nldt);
+ return (P->ops.pop_ldt(P, pldt, nldt, P->data));
- (void) memcpy(pldt, P->core->core_ldt,
- nldt * sizeof (struct ssd));
-
- return (nldt);
- }
-
- errno = ENODATA;
- return (-1);
}
#endif /* __i386 */
/*
- * Fill in a pointer to a process privilege structure.
+ * Return a malloced process privilege structure in *pprv.
*/
-ssize_t
-Ppriv(struct ps_prochandle *P, prpriv_t *pprv, size_t size)
-{
- if (P->state != PS_DEAD) {
- prpriv_t *pp = proc_get_priv(P->pid);
- if (pp != NULL) {
- size = MIN(size, PRIV_PRPRIV_SIZE(pp));
- (void) memcpy(pprv, pp, size);
- free(pp);
- return (size);
- }
- return (-1);
- }
-
- if (P->core->core_priv != NULL) {
- size = MIN(P->core->core_priv_size, size);
- (void) memcpy(pprv, P->core->core_priv, size);
- return (size);
- }
- errno = ENODATA;
- return (-1);
+int
+Ppriv(struct ps_prochandle *P, prpriv_t **pprv)
+{
+ return (P->ops.pop_priv(P, pprv, P->data));
}
int
@@ -1214,11 +1366,13 @@ Psetpriv(struct ps_prochandle *P, prpriv_t *pprv)
void *
Pprivinfo(struct ps_prochandle *P)
{
+ core_info_t *core = P->data;
+
/* Use default from libc */
if (P->state != PS_DEAD)
return (NULL);
- return (P->core->core_privinfo);
+ return (core->core_privinfo);
}
/*
@@ -1978,12 +2132,12 @@ Pread(struct ps_prochandle *P,
size_t nbyte, /* number of bytes to read */
uintptr_t address) /* address in process */
{
- return (P->ops->p_pread(P, buf, nbyte, address));
+ return (P->ops.pop_pread(P, buf, nbyte, address, P->data));
}
ssize_t
Pread_string(struct ps_prochandle *P,
- char *buf, /* caller's buffer */
+ char *buf, /* caller's buffer */
size_t size, /* upper limit on bytes to read */
uintptr_t addr) /* address in process */
{
@@ -2003,7 +2157,8 @@ Pread_string(struct ps_prochandle *P,
string[STRSZ] = '\0';
for (nbyte = STRSZ; nbyte == STRSZ && leng < size; addr += STRSZ) {
- if ((nbyte = P->ops->p_pread(P, string, STRSZ, addr)) <= 0) {
+ if ((nbyte = P->ops.pop_pread(P, string, STRSZ, addr,
+ P->data)) <= 0) {
buf[leng] = '\0';
return (leng ? leng : -1);
}
@@ -2024,7 +2179,7 @@ Pwrite(struct ps_prochandle *P,
size_t nbyte, /* number of bytes to write */
uintptr_t address) /* address in process */
{
- return (P->ops->p_pwrite(P, buf, nbyte, address));
+ return (P->ops.pop_pwrite(P, buf, nbyte, address, P->data));
}
int
@@ -2765,10 +2920,11 @@ Plwp_iter(struct ps_prochandle *P, proc_lwp_f *func, void *cd)
* list of LWP structs we read in from the core file.
*/
if (P->state == PS_DEAD) {
- lwp_info_t *lwp = list_prev(&P->core->core_lwp_head);
+ core_info_t *core = P->data;
+ lwp_info_t *lwp = list_prev(&core->core_lwp_head);
uint_t i;
- for (i = 0; i < P->core->core_nlwp; i++, lwp = list_prev(lwp)) {
+ for (i = 0; i < core->core_nlwp; i++, lwp = list_prev(lwp)) {
if (lwp->lwp_psinfo.pr_sname != 'Z' &&
(rv = func(cd, &lwp->lwp_status)) != 0)
break;
@@ -2781,7 +2937,7 @@ Plwp_iter(struct ps_prochandle *P, proc_lwp_f *func, void *cd)
* For the live process multi-LWP case, we have to work a little
* harder: the /proc/pid/lstatus file has the array of LWP structs.
*/
- if ((Lhp = read_lfile(P, "lstatus")) == NULL)
+ if ((Lhp = Plstatus(P)) == NULL)
return (-1);
for (nlwp = Lhp->pr_nent, Lsp = (lwpstatus_t *)(uintptr_t)(Lhp + 1);
@@ -2836,10 +2992,11 @@ retry:
* list of LWP structs we read in from the core file.
*/
if (P->state == PS_DEAD) {
- lwp_info_t *lwp = list_prev(&P->core->core_lwp_head);
+ core_info_t *core = P->data;
+ lwp_info_t *lwp = list_prev(&core->core_lwp_head);
uint_t i;
- for (i = 0; i < P->core->core_nlwp; i++, lwp = list_prev(lwp)) {
+ for (i = 0; i < core->core_nlwp; i++, lwp = list_prev(lwp)) {
sp = (lwp->lwp_psinfo.pr_sname == 'Z')? NULL :
&lwp->lwp_status;
if ((rv = func(cd, sp, &lwp->lwp_psinfo)) != 0)
@@ -2850,13 +3007,12 @@ retry:
}
/*
- * For the live process multi-LWP case, we have to work a little
- * harder: the /proc/pid/lstatus file has the array of lwpstatus_t's
- * and the /proc/pid/lpsinfo file has the array of lwpsinfo_t's.
+ * For all other cases retrieve the array of lwpstatus_t's and
+ * lwpsinfo_t's.
*/
- if ((Lhp = read_lfile(P, "lstatus")) == NULL)
+ if ((Lhp = Plstatus(P)) == NULL)
return (-1);
- if ((Lphp = read_lfile(P, "lpsinfo")) == NULL) {
+ if ((Lphp = Plpsinfo(P)) == NULL) {
free(Lhp);
return (-1);
}
@@ -2920,8 +3076,10 @@ retry:
core_content_t
Pcontent(struct ps_prochandle *P)
{
+ core_info_t *core = P->data;
+
if (P->state == PS_DEAD)
- return (P->core->core_content);
+ return (core->core_content);
if (P->state == PS_IDLE)
return (CC_CONTENT_TEXT | CC_CONTENT_DATA | CC_CONTENT_CTF);
@@ -3728,3 +3886,32 @@ Psort_mappings(struct ps_prochandle *P)
mp->map_relocate = 0;
}
}
+
+struct ps_prochandle *
+Pgrab_ops(pid_t pid, void *data, const ps_ops_t *ops, int flags)
+{
+ struct ps_prochandle *P;
+
+ if ((P = calloc(1, sizeof (*P))) == NULL) {
+ return (NULL);
+ }
+
+ Pinit_ops(&P->ops, ops);
+ (void) mutex_init(&P->proc_lock, USYNC_THREAD, NULL);
+ P->pid = pid;
+ P->state = PS_STOP;
+ P->asfd = -1;
+ P->ctlfd = -1;
+ P->statfd = -1;
+ P->agentctlfd = -1;
+ P->agentstatfd = -1;
+ Pinitsym(P);
+ P->data = data;
+ Pread_status(P);
+
+ if (flags & PGRAB_INCORE) {
+ P->flags |= INCORE;
+ }
+
+ return (P);
+}
diff --git a/usr/src/lib/libproc/common/Pcontrol.h b/usr/src/lib/libproc/common/Pcontrol.h
index 4bb7e0ca3c..3e72a32804 100644
--- a/usr/src/lib/libproc/common/Pcontrol.h
+++ b/usr/src/lib/libproc/common/Pcontrol.h
@@ -25,6 +25,7 @@
/*
* Copyright 2012 DEY Storage Systems, Inc. All rights reserved.
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
*/
#ifndef _PCONTROL_H
@@ -43,6 +44,7 @@
#include <libproc.h>
#include <libctf.h>
#include <limits.h>
+#include <libproc.h>
#ifdef __cplusplus
extern "C" {
@@ -190,13 +192,6 @@ typedef struct elf_file { /* convenience for managing ELF files */
int e_fd; /* file descriptor */
} elf_file_t;
-typedef struct ps_rwops { /* ops vector for Pread() and Pwrite() */
- ssize_t (*p_pread)(struct ps_prochandle *,
- void *, size_t, uintptr_t);
- ssize_t (*p_pwrite)(struct ps_prochandle *,
- const void *, size_t, uintptr_t);
-} ps_rwops_t;
-
#define HASHSIZE 1024 /* hash table size, power of 2 */
struct ps_prochandle {
@@ -227,8 +222,7 @@ struct ps_prochandle {
rd_agent_t *rap; /* cookie for rtld_db */
map_info_t *map_exec; /* the mapping for the executable file */
map_info_t *map_ldso; /* the mapping for ld.so.1 */
- const ps_rwops_t *ops; /* pointer to ops-vector for read and write */
- core_info_t *core; /* information specific to core (if PS_DEAD) */
+ ps_ops_t ops; /* ops-vector */
uintptr_t *ucaddrs; /* ucontext-list addresses */
uint_t ucnelems; /* number of elements in the ucaddrs list */
char *zoneroot; /* cached path to zone root */
@@ -237,6 +231,7 @@ struct ps_prochandle {
uintptr_t map_missing; /* first missing mapping in core due to sig */
siginfo_t killinfo; /* signal that interrupted core dump */
psinfo_t spymaster; /* agent LWP's spymaster, if any */
+ void *data; /* private data */
};
/* flags */
@@ -247,6 +242,7 @@ struct ps_prochandle {
#define SETEXIT 0x10 /* set sysexit trace mask before continuing */
#define SETHOLD 0x20 /* set signal hold mask before continuing */
#define SETREGS 0x40 /* set registers before continuing */
+#define INCORE 0x80 /* use in-core data to build symbol tables */
struct ps_lwphandle {
struct ps_prochandle *lwp_proc; /* process to which this lwp belongs */
diff --git a/usr/src/lib/libproc/common/Pcore.c b/usr/src/lib/libproc/common/Pcore.c
index e16e019ab9..596c45861a 100644
--- a/usr/src/lib/libproc/common/Pcore.c
+++ b/usr/src/lib/libproc/common/Pcore.c
@@ -25,6 +25,7 @@
/*
* Copyright 2012 DEY Storage Systems, Inc. All rights reserved.
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
*/
#include <sys/types.h>
@@ -111,20 +112,202 @@ core_rw(struct ps_prochandle *P, void *buf, size_t n, uintptr_t addr,
return (n - resid);
}
+/*ARGSUSED*/
static ssize_t
-Pread_core(struct ps_prochandle *P, void *buf, size_t n, uintptr_t addr)
+Pread_core(struct ps_prochandle *P, void *buf, size_t n, uintptr_t addr,
+ void *data)
{
return (core_rw(P, buf, n, addr, pread64));
}
+/*ARGSUSED*/
static ssize_t
-Pwrite_core(struct ps_prochandle *P, const void *buf, size_t n, uintptr_t addr)
+Pwrite_core(struct ps_prochandle *P, const void *buf, size_t n, uintptr_t addr,
+ void *data)
{
return (core_rw(P, (void *)buf, n, addr,
(ssize_t (*)(int, void *, size_t, off64_t)) pwrite64));
}
-static const ps_rwops_t P_core_ops = { Pread_core, Pwrite_core };
+/*ARGSUSED*/
+static int
+Pcred_core(struct ps_prochandle *P, prcred_t *pcrp, int ngroups, void *data)
+{
+ core_info_t *core = data;
+
+ if (core->core_cred != NULL) {
+ /*
+ * Avoid returning more supplementary group data than the
+ * caller has allocated in their buffer. We expect them to
+ * check pr_ngroups afterward and potentially call us again.
+ */
+ ngroups = MIN(ngroups, core->core_cred->pr_ngroups);
+
+ (void) memcpy(pcrp, core->core_cred,
+ sizeof (prcred_t) + (ngroups - 1) * sizeof (gid_t));
+
+ return (0);
+ }
+
+ errno = ENODATA;
+ return (-1);
+}
+
+/*ARGSUSED*/
+static int
+Ppriv_core(struct ps_prochandle *P, prpriv_t **pprv, void *data)
+{
+ core_info_t *core = data;
+
+ if (core->core_priv == NULL) {
+ errno = ENODATA;
+ return (-1);
+ }
+
+ *pprv = malloc(core->core_priv_size);
+ if (*pprv == NULL) {
+ return (-1);
+ }
+
+ (void) memcpy(*pprv, core->core_priv, core->core_priv_size);
+ return (0);
+}
+
+/*ARGSUSED*/
+static const psinfo_t *
+Ppsinfo_core(struct ps_prochandle *P, psinfo_t *psinfo, void *data)
+{
+ return (&P->psinfo);
+}
+
+/*ARGSUSED*/
+static void
+Pfini_core(struct ps_prochandle *P, void *data)
+{
+ core_info_t *core = data;
+
+ if (core != NULL) {
+ extern void __priv_free_info(void *);
+ lwp_info_t *nlwp, *lwp = list_next(&core->core_lwp_head);
+ int i;
+
+ for (i = 0; i < core->core_nlwp; i++, lwp = nlwp) {
+ nlwp = list_next(lwp);
+#ifdef __sparc
+ if (lwp->lwp_gwins != NULL)
+ free(lwp->lwp_gwins);
+ if (lwp->lwp_xregs != NULL)
+ free(lwp->lwp_xregs);
+ if (lwp->lwp_asrs != NULL)
+ free(lwp->lwp_asrs);
+#endif
+ free(lwp);
+ }
+
+ if (core->core_platform != NULL)
+ free(core->core_platform);
+ if (core->core_uts != NULL)
+ free(core->core_uts);
+ if (core->core_cred != NULL)
+ free(core->core_cred);
+ if (core->core_priv != NULL)
+ free(core->core_priv);
+ if (core->core_privinfo != NULL)
+ __priv_free_info(core->core_privinfo);
+ if (core->core_ppii != NULL)
+ free(core->core_ppii);
+ if (core->core_zonename != NULL)
+ free(core->core_zonename);
+#if defined(__i386) || defined(__amd64)
+ if (core->core_ldt != NULL)
+ free(core->core_ldt);
+#endif
+
+ free(core);
+ }
+}
+
+/*ARGSUSED*/
+static char *
+Pplatform_core(struct ps_prochandle *P, char *s, size_t n, void *data)
+{
+ core_info_t *core = data;
+
+ if (core->core_platform == NULL) {
+ errno = ENODATA;
+ return (NULL);
+ }
+ (void) strncpy(s, core->core_platform, n - 1);
+ s[n - 1] = '\0';
+ return (s);
+}
+
+/*ARGSUSED*/
+static int
+Puname_core(struct ps_prochandle *P, struct utsname *u, void *data)
+{
+ core_info_t *core = data;
+
+ if (core->core_uts == NULL) {
+ errno = ENODATA;
+ return (-1);
+ }
+ (void) memcpy(u, core->core_uts, sizeof (struct utsname));
+ return (0);
+}
+
+/*ARGSUSED*/
+static char *
+Pzonename_core(struct ps_prochandle *P, char *s, size_t n, void *data)
+{
+ core_info_t *core = data;
+
+ if (core->core_zonename == NULL) {
+ errno = ENODATA;
+ return (NULL);
+ }
+ (void) strlcpy(s, core->core_zonename, n);
+ return (s);
+}
+
+#if defined(__i386) || defined(__amd64)
+/*ARGSUSED*/
+static int
+Pldt_core(struct ps_prochandle *P, struct ssd *pldt, int nldt, void *data)
+{
+ core_info_t *core = data;
+
+ if (pldt == NULL || nldt == 0)
+ return (core->core_nldt);
+
+ if (core->core_ldt != NULL) {
+ nldt = MIN(nldt, core->core_nldt);
+
+ (void) memcpy(pldt, core->core_ldt,
+ nldt * sizeof (struct ssd));
+
+ return (nldt);
+ }
+
+ errno = ENODATA;
+ return (-1);
+}
+#endif
+
+static const ps_ops_t P_core_ops = {
+ .pop_pread = Pread_core,
+ .pop_pwrite = Pwrite_core,
+ .pop_cred = Pcred_core,
+ .pop_priv = Ppriv_core,
+ .pop_psinfo = Ppsinfo_core,
+ .pop_fini = Pfini_core,
+ .pop_platform = Pplatform_core,
+ .pop_uname = Puname_core,
+ .pop_zonename = Pzonename_core,
+#if defined(__i386) || defined(__amd64)
+ .pop_ldt = Pldt_core
+#endif
+};
/*
* Return the lwp_info_t for the given lwpid. If no such lwpid has been
@@ -134,13 +317,14 @@ static const ps_rwops_t P_core_ops = { Pread_core, Pwrite_core };
static lwp_info_t *
lwpid2info(struct ps_prochandle *P, lwpid_t id)
{
- lwp_info_t *lwp = list_next(&P->core->core_lwp_head);
+ core_info_t *core = P->data;
+ lwp_info_t *lwp = list_next(&core->core_lwp_head);
lwp_info_t *next;
uint_t i;
- for (i = 0; i < P->core->core_nlwp; i++, lwp = list_next(lwp)) {
+ for (i = 0; i < core->core_nlwp; i++, lwp = list_next(lwp)) {
if (lwp->lwp_id == id) {
- P->core->core_lwp = lwp;
+ core->core_lwp = lwp;
return (lwp);
}
if (lwp->lwp_id < id) {
@@ -155,8 +339,8 @@ lwpid2info(struct ps_prochandle *P, lwpid_t id)
list_link(lwp, next);
lwp->lwp_id = id;
- P->core->core_lwp = lwp;
- P->core->core_nlwp++;
+ core->core_lwp = lwp;
+ core->core_nlwp++;
return (lwp);
}
@@ -175,7 +359,9 @@ static int
note_pstatus(struct ps_prochandle *P, size_t nbytes)
{
#ifdef _LP64
- if (P->core->core_dmodel == PR_MODEL_ILP32) {
+ core_info_t *core = P->data;
+
+ if (core->core_dmodel == PR_MODEL_ILP32) {
pstatus32_t ps32;
if (nbytes < sizeof (pstatus32_t) ||
@@ -207,7 +393,9 @@ note_lwpstatus(struct ps_prochandle *P, size_t nbytes)
lwpstatus_t lps;
#ifdef _LP64
- if (P->core->core_dmodel == PR_MODEL_ILP32) {
+ core_info_t *core = P->data;
+
+ if (core->core_dmodel == PR_MODEL_ILP32) {
lwpstatus32_t l32;
if (nbytes < sizeof (lwpstatus32_t) ||
@@ -246,7 +434,9 @@ static int
note_psinfo(struct ps_prochandle *P, size_t nbytes)
{
#ifdef _LP64
- if (P->core->core_dmodel == PR_MODEL_ILP32) {
+ core_info_t *core = P->data;
+
+ if (core->core_dmodel == PR_MODEL_ILP32) {
psinfo32_t ps32;
if (nbytes < sizeof (psinfo32_t) ||
@@ -278,7 +468,9 @@ note_lwpsinfo(struct ps_prochandle *P, size_t nbytes)
lwpsinfo_t lps;
#ifdef _LP64
- if (P->core->core_dmodel == PR_MODEL_ILP32) {
+ core_info_t *core = P->data;
+
+ if (core->core_dmodel == PR_MODEL_ILP32) {
lwpsinfo32_t l32;
if (nbytes < sizeof (lwpsinfo32_t) ||
@@ -328,9 +520,10 @@ note_fdinfo(struct ps_prochandle *P, size_t nbytes)
static int
note_platform(struct ps_prochandle *P, size_t nbytes)
{
+ core_info_t *core = P->data;
char *plat;
- if (P->core->core_platform != NULL)
+ if (core->core_platform != NULL)
return (0); /* Already seen */
if (nbytes != 0 && ((plat = malloc(nbytes + 1)) != NULL)) {
@@ -340,7 +533,7 @@ note_platform(struct ps_prochandle *P, size_t nbytes)
return (-1);
}
plat[nbytes - 1] = '\0';
- P->core->core_platform = plat;
+ core->core_platform = plat;
}
return (0);
@@ -349,10 +542,11 @@ note_platform(struct ps_prochandle *P, size_t nbytes)
static int
note_utsname(struct ps_prochandle *P, size_t nbytes)
{
+ core_info_t *core = P->data;
size_t ubytes = sizeof (struct utsname);
struct utsname *utsp;
- if (P->core->core_uts != NULL || nbytes < ubytes)
+ if (core->core_uts != NULL || nbytes < ubytes)
return (0); /* Already seen or bad size */
if ((utsp = malloc(ubytes)) == NULL)
@@ -372,22 +566,23 @@ note_utsname(struct ps_prochandle *P, size_t nbytes)
dprintf("uts.machine = \"%s\"\n", utsp->machine);
}
- P->core->core_uts = utsp;
+ core->core_uts = utsp;
return (0);
}
static int
note_content(struct ps_prochandle *P, size_t nbytes)
{
+ core_info_t *core = P->data;
core_content_t content;
- if (sizeof (P->core->core_content) != nbytes)
+ if (sizeof (core->core_content) != nbytes)
return (-1);
if (read(P->asfd, &content, sizeof (content)) != sizeof (content))
return (-1);
- P->core->core_content = content;
+ core->core_content = content;
dprintf("core content = %llx\n", content);
@@ -397,6 +592,7 @@ note_content(struct ps_prochandle *P, size_t nbytes)
static int
note_cred(struct ps_prochandle *P, size_t nbytes)
{
+ core_info_t *core = P->data;
prcred_t *pcrp;
int ngroups;
const size_t min_size = sizeof (prcred_t) - sizeof (gid_t);
@@ -407,7 +603,7 @@ note_cred(struct ps_prochandle *P, size_t nbytes)
* no group memberships. This allows for more flexibility when it
* comes to slightly malformed -- but still valid -- notes.
*/
- if (P->core->core_cred != NULL || nbytes < min_size)
+ if (core->core_cred != NULL || nbytes < min_size)
return (0); /* Already seen or bad size */
ngroups = (nbytes - min_size) / sizeof (gid_t);
@@ -428,7 +624,7 @@ note_cred(struct ps_prochandle *P, size_t nbytes)
pcrp->pr_ngroups = ngroups;
}
- P->core->core_cred = pcrp;
+ core->core_cred = pcrp;
return (0);
}
@@ -436,10 +632,11 @@ note_cred(struct ps_prochandle *P, size_t nbytes)
static int
note_ldt(struct ps_prochandle *P, size_t nbytes)
{
+ core_info_t *core = P->data;
struct ssd *pldt;
uint_t nldt;
- if (P->core->core_ldt != NULL || nbytes < sizeof (struct ssd))
+ if (core->core_ldt != NULL || nbytes < sizeof (struct ssd))
return (0); /* Already seen or bad size */
nldt = nbytes / sizeof (struct ssd);
@@ -454,8 +651,8 @@ note_ldt(struct ps_prochandle *P, size_t nbytes)
return (-1);
}
- P->core->core_ldt = pldt;
- P->core->core_nldt = nldt;
+ core->core_ldt = pldt;
+ core->core_nldt = nldt;
return (0);
}
#endif /* __i386 */
@@ -463,9 +660,10 @@ note_ldt(struct ps_prochandle *P, size_t nbytes)
static int
note_priv(struct ps_prochandle *P, size_t nbytes)
{
+ core_info_t *core = P->data;
prpriv_t *pprvp;
- if (P->core->core_priv != NULL || nbytes < sizeof (prpriv_t))
+ if (core->core_priv != NULL || nbytes < sizeof (prpriv_t))
return (0); /* Already seen or bad size */
if ((pprvp = malloc(nbytes)) == NULL)
@@ -477,18 +675,19 @@ note_priv(struct ps_prochandle *P, size_t nbytes)
return (-1);
}
- P->core->core_priv = pprvp;
- P->core->core_priv_size = nbytes;
+ core->core_priv = pprvp;
+ core->core_priv_size = nbytes;
return (0);
}
static int
note_priv_info(struct ps_prochandle *P, size_t nbytes)
{
+ core_info_t *core = P->data;
extern void *__priv_parse_info();
priv_impl_info_t *ppii;
- if (P->core->core_privinfo != NULL ||
+ if (core->core_privinfo != NULL ||
nbytes < sizeof (priv_impl_info_t))
return (0); /* Already seen or bad size */
@@ -502,17 +701,18 @@ note_priv_info(struct ps_prochandle *P, size_t nbytes)
return (-1);
}
- P->core->core_privinfo = __priv_parse_info(ppii);
- P->core->core_ppii = ppii;
+ core->core_privinfo = __priv_parse_info(ppii);
+ core->core_ppii = ppii;
return (0);
}
static int
note_zonename(struct ps_prochandle *P, size_t nbytes)
{
+ core_info_t *core = P->data;
char *zonename;
- if (P->core->core_zonename != NULL)
+ if (core->core_zonename != NULL)
return (0); /* Already seen */
if (nbytes != 0) {
@@ -524,7 +724,7 @@ note_zonename(struct ps_prochandle *P, size_t nbytes)
return (-1);
}
zonename[nbytes - 1] = '\0';
- P->core->core_zonename = zonename;
+ core->core_zonename = zonename;
}
return (0);
@@ -536,7 +736,9 @@ note_auxv(struct ps_prochandle *P, size_t nbytes)
size_t n, i;
#ifdef _LP64
- if (P->core->core_dmodel == PR_MODEL_ILP32) {
+ core_info_t *core = P->data;
+
+ if (core->core_dmodel == PR_MODEL_ILP32) {
auxv32_t *a32;
n = nbytes / sizeof (auxv32_t);
@@ -594,7 +796,8 @@ note_auxv(struct ps_prochandle *P, size_t nbytes)
static int
note_xreg(struct ps_prochandle *P, size_t nbytes)
{
- lwp_info_t *lwp = P->core->core_lwp;
+ core_info_t *core = P->data;
+ lwp_info_t *lwp = core->core_lwp;
size_t xbytes = sizeof (prxregset_t);
prxregset_t *xregs;
@@ -617,7 +820,8 @@ note_xreg(struct ps_prochandle *P, size_t nbytes)
static int
note_gwindows(struct ps_prochandle *P, size_t nbytes)
{
- lwp_info_t *lwp = P->core->core_lwp;
+ core_info_t *core = P->data;
+ lwp_info_t *lwp = core->core_lwp;
if (lwp == NULL || lwp->lwp_gwins != NULL || nbytes == 0)
return (0); /* No lwp yet or already seen or no data */
@@ -632,7 +836,7 @@ note_gwindows(struct ps_prochandle *P, size_t nbytes)
* fails since we have to zero out gwindows first anyway.
*/
#ifdef _LP64
- if (P->core->core_dmodel == PR_MODEL_ILP32) {
+ if (core->core_dmodel == PR_MODEL_ILP32) {
gwindows32_t g32;
(void) memset(&g32, 0, sizeof (g32));
@@ -654,7 +858,8 @@ note_gwindows(struct ps_prochandle *P, size_t nbytes)
static int
note_asrs(struct ps_prochandle *P, size_t nbytes)
{
- lwp_info_t *lwp = P->core->core_lwp;
+ core_info_t *core = P->data;
+ lwp_info_t *lwp = core->core_lwp;
int64_t *asrs;
if (lwp == NULL || lwp->lwp_asrs != NULL || nbytes < sizeof (asrset_t))
@@ -679,7 +884,9 @@ static int
note_spymaster(struct ps_prochandle *P, size_t nbytes)
{
#ifdef _LP64
- if (P->core->core_dmodel == PR_MODEL_ILP32) {
+ core_info_t *core = P->data;
+
+ if (core->core_dmodel == PR_MODEL_ILP32) {
psinfo32_t ps32;
if (nbytes < sizeof (psinfo32_t) ||
@@ -830,6 +1037,7 @@ core_report_mapping(struct ps_prochandle *P, GElf_Phdr *php)
static int
core_add_mapping(struct ps_prochandle *P, GElf_Phdr *php)
{
+ core_info_t *core = P->data;
prmap_t pmap;
dprintf("mapping base %llx filesz %llu memsz %llu offset %llu\n",
@@ -845,7 +1053,7 @@ core_add_mapping(struct ps_prochandle *P, GElf_Phdr *php)
*/
if (php->p_flags & PF_SUNW_FAILURE) {
core_report_mapping(P, php);
- } else if (php->p_filesz != 0 && php->p_offset >= P->core->core_size) {
+ } else if (php->p_filesz != 0 && php->p_offset >= core->core_size) {
Perror_printf(P, "core file may be corrupt -- data for mapping "
"at %p is missing\n", (void *)(uintptr_t)php->p_vaddr);
dprintf("core file may be corrupt -- data for mapping "
@@ -1481,6 +1689,7 @@ core_find_data(struct ps_prochandle *P, Elf *elf, rd_loadobj_t *rlp)
static int
core_iter_mapping(const rd_loadobj_t *rlp, struct ps_prochandle *P)
{
+ core_info_t *core = P->data;
char lname[PATH_MAX], buf[PATH_MAX];
file_info_t *fp;
map_info_t *mp;
@@ -1508,7 +1717,7 @@ core_iter_mapping(const rd_loadobj_t *rlp, struct ps_prochandle *P)
*/
if ((fp = mp->map_file) == NULL &&
(fp = file_info_new(P, mp)) == NULL) {
- P->core->core_errno = errno;
+ core->core_errno = errno;
dprintf("failed to malloc mapping data\n");
return (0); /* Abort */
}
@@ -1516,7 +1725,7 @@ core_iter_mapping(const rd_loadobj_t *rlp, struct ps_prochandle *P)
/* Create a local copy of the load object representation */
if ((fp->file_lo = calloc(1, sizeof (rd_loadobj_t))) == NULL) {
- P->core->core_errno = errno;
+ core->core_errno = errno;
dprintf("failed to malloc mapping data\n");
return (0); /* Abort */
}
@@ -1783,6 +1992,7 @@ struct ps_prochandle *
Pfgrab_core(int core_fd, const char *aout_path, int *perr)
{
struct ps_prochandle *P;
+ core_info_t *core_info;
map_info_t *stk_mp, *brk_mp;
const char *execname;
char *interp;
@@ -1848,7 +2058,7 @@ Pfgrab_core(int core_fd, const char *aout_path, int *perr)
P->agentstatfd = -1;
P->zoneroot = NULL;
P->info_valid = 1;
- P->ops = &P_core_ops;
+ Pinit_ops(&P->ops, &P_core_ops);
Pinitsym(P);
@@ -1867,28 +2077,29 @@ Pfgrab_core(int core_fd, const char *aout_path, int *perr)
* Allocate and initialize a core_info_t to hang off the ps_prochandle
* structure. We keep all core-specific information in this structure.
*/
- if ((P->core = calloc(1, sizeof (core_info_t))) == NULL) {
+ if ((core_info = calloc(1, sizeof (core_info_t))) == NULL) {
*perr = G_STRANGE;
goto err;
}
- list_link(&P->core->core_lwp_head, NULL);
- P->core->core_size = stbuf.st_size;
+ P->data = core_info;
+ list_link(&core_info->core_lwp_head, NULL);
+ core_info->core_size = stbuf.st_size;
/*
* In the days before adjustable core file content, this was the
* default core file content. For new core files, this value will
* be overwritten by the NT_CONTENT note section.
*/
- P->core->core_content = CC_CONTENT_STACK | CC_CONTENT_HEAP |
+ core_info->core_content = CC_CONTENT_STACK | CC_CONTENT_HEAP |
CC_CONTENT_DATA | CC_CONTENT_RODATA | CC_CONTENT_ANON |
CC_CONTENT_SHANON;
switch (core.e_hdr.e_ident[EI_CLASS]) {
case ELFCLASS32:
- P->core->core_dmodel = PR_MODEL_ILP32;
+ core_info->core_dmodel = PR_MODEL_ILP32;
break;
case ELFCLASS64:
- P->core->core_dmodel = PR_MODEL_LP64;
+ core_info->core_dmodel = PR_MODEL_LP64;
break;
default:
*perr = G_FORMAT;
@@ -2114,7 +2325,7 @@ Pfgrab_core(int core_fd, const char *aout_path, int *perr)
interp = dp->d_buf;
} else if (base_addr != (uintptr_t)-1L) {
- if (P->core->core_dmodel == PR_MODEL_LP64)
+ if (core_info->core_dmodel == PR_MODEL_LP64)
interp = "/usr/lib/64/ld.so.1";
else
interp = "/usr/lib/ld.so.1";
@@ -2229,8 +2440,8 @@ Pfgrab_core(int core_fd, const char *aout_path, int *perr)
(void) rd_loadobj_iter(P->rap, (rl_iter_f *)
core_iter_mapping, P);
- if (P->core->core_errno != 0) {
- errno = P->core->core_errno;
+ if (core_info->core_errno != 0) {
+ errno = core_info->core_errno;
*perr = G_STRANGE;
goto err;
}
diff --git a/usr/src/lib/libproc/common/Pexecname.c b/usr/src/lib/libproc/common/Pexecname.c
index 82b4219560..8af0416e10 100644
--- a/usr/src/lib/libproc/common/Pexecname.c
+++ b/usr/src/lib/libproc/common/Pexecname.c
@@ -22,6 +22,9 @@
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright (c) 2013 by Delphix. All rights reserved.
+ */
#define __EXTENSIONS__
#include <string.h>
@@ -236,23 +239,7 @@ found:
}
/*
- * Callback function for Pfindexec(). We return a match if we can stat the
- * suggested pathname and confirm its device and inode number match our
- * previous information about the /proc/<pid>/object/a.out file.
- */
-static int
-stat_exec(const char *path, struct stat64 *stp)
-{
- struct stat64 st;
-
- return (stat64(path, &st) == 0 && S_ISREG(st.st_mode) &&
- stp->st_dev == st.st_dev && stp->st_ino == st.st_ino);
-}
-
-/*
- * Return the full pathname for the executable file. If the process handle is
- * a core file, we've already tried our best to get the executable name.
- * Otherwise, we make an attempt using Pfindexec().
+ * Return the full pathname for the executable file.
*/
char *
Pexecname(struct ps_prochandle *P, char *buf, size_t buflen)
@@ -262,48 +249,5 @@ Pexecname(struct ps_prochandle *P, char *buf, size_t buflen)
return (buf);
}
- if (P->state != PS_DEAD && P->state != PS_IDLE) {
- char exec_name[PATH_MAX];
- char cwd[PATH_MAX];
- char proc_cwd[64];
- struct stat64 st;
- int ret;
-
- /*
- * Try to get the path information first.
- */
- (void) snprintf(exec_name, sizeof (exec_name),
- "%s/%d/path/a.out", procfs_path, (int)P->pid);
- if ((ret = readlink(exec_name, buf, buflen - 1)) > 0) {
- buf[ret] = '\0';
- (void) Pfindobj(P, buf, buf, buflen);
- return (buf);
- }
-
- /*
- * Stat the executable file so we can compare Pfindexec's
- * suggestions to the actual device and inode number.
- */
- (void) snprintf(exec_name, sizeof (exec_name),
- "%s/%d/object/a.out", procfs_path, (int)P->pid);
-
- if (stat64(exec_name, &st) != 0 || !S_ISREG(st.st_mode))
- return (NULL);
-
- /*
- * Attempt to figure out the current working directory of the
- * target process. This only works if the target process has
- * not changed its current directory since it was exec'd.
- */
- (void) snprintf(proc_cwd, sizeof (proc_cwd),
- "%s/%d/path/cwd", procfs_path, (int)P->pid);
-
- if ((ret = readlink(proc_cwd, cwd, PATH_MAX - 1)) > 0)
- cwd[ret] = '\0';
-
- (void) Pfindexec(P, ret > 0 ? cwd : NULL,
- (int (*)(const char *, void *))stat_exec, &st);
- }
-
- return (NULL);
+ return (P->ops.pop_execname(P, buf, buflen, P->data));
}
diff --git a/usr/src/lib/libproc/common/Pgcore.c b/usr/src/lib/libproc/common/Pgcore.c
index 2b5ec7c9bd..bf530be90c 100644
--- a/usr/src/lib/libproc/common/Pgcore.c
+++ b/usr/src/lib/libproc/common/Pgcore.c
@@ -26,6 +26,7 @@
/*
* Copyright 2012 DEY Storage Systems, Inc. All rights reserved.
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
*/
#define _STRUCTURED_PROC 1
@@ -1357,11 +1358,11 @@ Pfgcore(struct ps_prochandle *P, int fd, core_content_t content)
}
{
- prpriv_t *ppriv;
+ prpriv_t *ppriv = NULL;
const priv_impl_info_t *pinfo;
size_t pprivsz, pinfosz;
- if ((ppriv = proc_get_priv(P->pid)) == NULL)
+ if (Ppriv(P, &ppriv) == -1)
goto err;
pprivsz = PRIV_PRPRIV_SIZE(ppriv);
diff --git a/usr/src/lib/libproc/common/Pidle.c b/usr/src/lib/libproc/common/Pidle.c
index 938510abeb..3191f4fa7e 100644
--- a/usr/src/lib/libproc/common/Pidle.c
+++ b/usr/src/lib/libproc/common/Pidle.c
@@ -22,6 +22,9 @@
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright (c) 2013 by Delphix. All rights reserved.
+ */
#include <stdlib.h>
#include <libelf.h>
@@ -34,8 +37,10 @@
#include "libproc.h"
#include "Pcontrol.h"
+/*ARGSUSED*/
static ssize_t
-Pread_idle(struct ps_prochandle *P, void *buf, size_t n, uintptr_t addr)
+Pread_idle(struct ps_prochandle *P, void *buf, size_t n, uintptr_t addr,
+ void *data)
{
size_t resid = n;
@@ -65,15 +70,55 @@ Pread_idle(struct ps_prochandle *P, void *buf, size_t n, uintptr_t addr)
/*ARGSUSED*/
static ssize_t
-Pwrite_idle(struct ps_prochandle *P, const void *buf, size_t n, uintptr_t addr)
+Pwrite_idle(struct ps_prochandle *P, const void *buf, size_t n, uintptr_t addr,
+ void *data)
{
errno = EIO;
return (-1);
}
-static const ps_rwops_t P_idle_ops = {
- Pread_idle,
- Pwrite_idle
+/*ARGSUSED*/
+static int
+Ppriv_idle(struct ps_prochandle *P, prpriv_t **pprv, void *data)
+{
+ prpriv_t *pp;
+
+ pp = proc_get_priv(P->pid);
+ if (pp == NULL) {
+ return (-1);
+ }
+
+ *pprv = pp;
+ return (0);
+}
+
+/* Default operations for the idl ops vector. */
+static void *
+Pidle_voidp()
+{
+ errno = ENODATA;
+ return (NULL);
+}
+
+static int
+Pidle_int()
+{
+ errno = ENODATA;
+ return (-1);
+}
+
+static const ps_ops_t P_idle_ops = {
+ .pop_pread = Pread_idle,
+ .pop_pwrite = Pwrite_idle,
+ .pop_cred = (pop_cred_t)Pidle_int,
+ .pop_priv = Ppriv_idle,
+ .pop_psinfo = (pop_psinfo_t)Pidle_voidp,
+ .pop_platform = (pop_platform_t)Pidle_voidp,
+ .pop_uname = (pop_uname_t)Pidle_int,
+ .pop_zonename = (pop_zonename_t)Pidle_voidp,
+#if defined(__i386) || defined(__amd64)
+ .pop_ldt = (pop_ldt_t)Pidle_int
+#endif
};
static int
@@ -143,7 +188,7 @@ Pgrab_file(const char *fname, int *perr)
P->agentctlfd = -1;
P->agentstatfd = -1;
P->info_valid = -1;
- P->ops = &P_idle_ops;
+ Pinit_ops(&P->ops, &P_idle_ops);
Pinitsym(P);
if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
diff --git a/usr/src/lib/libproc/common/Plwpregs.c b/usr/src/lib/libproc/common/Plwpregs.c
index 7549bc142d..c2b150000f 100644
--- a/usr/src/lib/libproc/common/Plwpregs.c
+++ b/usr/src/lib/libproc/common/Plwpregs.c
@@ -25,6 +25,7 @@
/*
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
*/
#include <sys/types.h>
@@ -50,10 +51,11 @@
static lwp_info_t *
getlwpcore(struct ps_prochandle *P, lwpid_t lwpid)
{
- lwp_info_t *lwp = list_next(&P->core->core_lwp_head);
+ core_info_t *core = P->data;
+ lwp_info_t *lwp = list_next(&core->core_lwp_head);
uint_t i;
- for (i = 0; i < P->core->core_nlwp; i++, lwp = list_next(lwp)) {
+ for (i = 0; i < core->core_nlwp; i++, lwp = list_next(lwp)) {
if (lwp->lwp_id == lwpid)
return (lwp);
}
@@ -118,7 +120,7 @@ getlwpstatus(struct ps_prochandle *P, lwpid_t lwpid, lwpstatus_t *lps)
* If this is a core file, we need to iterate through our list of
* cached lwp information and then copy out the status.
*/
- if (P->core != NULL && (lwp = getlwpcore(P, lwpid)) != NULL) {
+ if (P->data != NULL && (lwp = getlwpcore(P, lwpid)) != NULL) {
(void) memcpy(lps, &lwp->lwp_status, sizeof (lwpstatus_t));
return (0);
}
diff --git a/usr/src/lib/libproc/common/Pservice.c b/usr/src/lib/libproc/common/Pservice.c
index cd43947171..62c88d3ec8 100644
--- a/usr/src/lib/libproc/common/Pservice.c
+++ b/usr/src/lib/libproc/common/Pservice.c
@@ -22,8 +22,9 @@
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright (c) 2013 by Delphix. All rights reserved.
+ */
#include <stdarg.h>
#include <string.h>
@@ -56,7 +57,7 @@ ps_pdmodel(struct ps_prochandle *P, int *modelp)
ps_err_e
ps_pread(struct ps_prochandle *P, psaddr_t addr, void *buf, size_t size)
{
- if (P->ops->p_pread(P, buf, size, addr) != size)
+ if (P->ops.pop_pread(P, buf, size, addr, P->data) != size)
return (PS_BADADDR);
return (PS_OK);
}
@@ -64,7 +65,7 @@ ps_pread(struct ps_prochandle *P, psaddr_t addr, void *buf, size_t size)
ps_err_e
ps_pwrite(struct ps_prochandle *P, psaddr_t addr, const void *buf, size_t size)
{
- if (P->ops->p_pwrite(P, buf, size, addr) != size)
+ if (P->ops.pop_pwrite(P, buf, size, addr, P->data) != size)
return (PS_BADADDR);
return (PS_OK);
}
diff --git a/usr/src/lib/libproc/common/Psymtab.c b/usr/src/lib/libproc/common/Psymtab.c
index 7c8166d5c3..62354f9a7b 100644
--- a/usr/src/lib/libproc/common/Psymtab.c
+++ b/usr/src/lib/libproc/common/Psymtab.c
@@ -22,6 +22,7 @@
/*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
*/
#include <assert.h>
@@ -41,7 +42,6 @@
#include <libgen.h>
#include <sys/types.h>
#include <sys/stat.h>
-#include <sys/systeminfo.h>
#include <sys/sysmacros.h>
#include "libproc.h"
@@ -434,6 +434,12 @@ load_static_maps(struct ps_prochandle *P)
map_set(P, mptr, "ld.so.1");
}
+int
+Preadmaps(struct ps_prochandle *P, prmap_t **Pmapp, ssize_t *nmapp)
+{
+ return (P->ops.pop_read_maps(P, Pmapp, nmapp, P->data));
+}
+
/*
* Go through all the address space mappings, validating or updating
* the information already gathered, or gathering new information.
@@ -444,9 +450,6 @@ load_static_maps(struct ps_prochandle *P)
void
Pupdate_maps(struct ps_prochandle *P)
{
- char mapfile[PATH_MAX];
- int mapfd;
- struct stat statb;
prmap_t *Pmap = NULL;
prmap_t *pmap;
ssize_t nmap;
@@ -460,22 +463,8 @@ Pupdate_maps(struct ps_prochandle *P)
Preadauxvec(P);
- (void) snprintf(mapfile, sizeof (mapfile), "%s/%d/map",
- procfs_path, (int)P->pid);
- if ((mapfd = open(mapfile, O_RDONLY)) < 0 ||
- fstat(mapfd, &statb) != 0 ||
- statb.st_size < sizeof (prmap_t) ||
- (Pmap = malloc(statb.st_size)) == NULL ||
- (nmap = pread(mapfd, Pmap, statb.st_size, 0L)) <= 0 ||
- (nmap /= sizeof (prmap_t)) == 0) {
- if (Pmap != NULL)
- free(Pmap);
- if (mapfd >= 0)
- (void) close(mapfd);
- Preset_maps(P); /* utter failure; destroy tables */
+ if (Preadmaps(P, &Pmap, &nmap) != 0)
return;
- }
- (void) close(mapfd);
if ((newmap = calloc(1, nmap * sizeof (map_info_t))) == NULL)
return;
@@ -848,51 +837,16 @@ Pname_to_ctf(struct ps_prochandle *P, const char *name)
return (Plmid_to_ctf(P, PR_LMID_EVERY, name));
}
-/*
- * If we're not a core file, re-read the /proc/<pid>/auxv file and store
- * its contents in P->auxv. In the case of a core file, we either
- * initialized P->auxv in Pcore() from the NT_AUXV, or we don't have an
- * auxv because the note was missing.
- */
void
Preadauxvec(struct ps_prochandle *P)
{
- char auxfile[64];
- struct stat statb;
- ssize_t naux;
- int fd;
-
- if (P->state == PS_DEAD)
- return; /* Already read during Pgrab_core() */
- if (P->state == PS_IDLE)
- return; /* No aux vec for Pgrab_file() */
-
if (P->auxv != NULL) {
free(P->auxv);
P->auxv = NULL;
P->nauxv = 0;
}
- (void) snprintf(auxfile, sizeof (auxfile), "%s/%d/auxv",
- procfs_path, (int)P->pid);
- if ((fd = open(auxfile, O_RDONLY)) < 0)
- return;
-
- if (fstat(fd, &statb) == 0 &&
- statb.st_size >= sizeof (auxv_t) &&
- (P->auxv = malloc(statb.st_size + sizeof (auxv_t))) != NULL) {
- if ((naux = read(fd, P->auxv, statb.st_size)) < 0 ||
- (naux /= sizeof (auxv_t)) < 1) {
- free(P->auxv);
- P->auxv = NULL;
- } else {
- P->auxv[naux].a_type = AT_NULL;
- P->auxv[naux].a_un.a_val = 0L;
- P->nauxv = (int)naux;
- }
- }
-
- (void) close(fd);
+ P->ops.pop_read_aux(P, &P->auxv, &P->nauxv, P->data);
}
/*
@@ -1683,7 +1637,7 @@ Pbuild_file_symtab(struct ps_prochandle *P, file_info_t *fptr)
* the in-core elf image.
*/
- if (_libproc_incore_elf) {
+ if (_libproc_incore_elf || (P->flags & INCORE)) {
dprintf("Pbuild_file_symtab: using in-core data for: %s\n",
fptr->file_pname);
@@ -2969,52 +2923,21 @@ Psymbol_iter_by_name(struct ps_prochandle *P,
}
/*
- * Get the platform string from the core file if we have it;
- * just perform the system call for the caller if this is a live process.
+ * Get the platform string.
*/
char *
Pplatform(struct ps_prochandle *P, char *s, size_t n)
{
- if (P->state == PS_IDLE) {
- errno = ENODATA;
- return (NULL);
- }
-
- if (P->state == PS_DEAD) {
- if (P->core->core_platform == NULL) {
- errno = ENODATA;
- return (NULL);
- }
- (void) strncpy(s, P->core->core_platform, n - 1);
- s[n - 1] = '\0';
-
- } else if (sysinfo(SI_PLATFORM, s, n) == -1)
- return (NULL);
-
- return (s);
+ return (P->ops.pop_platform(P, s, n, P->data));
}
/*
- * Get the uname(2) information from the core file if we have it;
- * just perform the system call for the caller if this is a live process.
+ * Get the uname(2) information.
*/
int
Puname(struct ps_prochandle *P, struct utsname *u)
{
- if (P->state == PS_IDLE) {
- errno = ENODATA;
- return (-1);
- }
-
- if (P->state == PS_DEAD) {
- if (P->core->core_uts == NULL) {
- errno = ENODATA;
- return (-1);
- }
- (void) memcpy(u, P->core->core_uts, sizeof (struct utsname));
- return (0);
- }
- return (uname(u));
+ return (P->ops.pop_uname(P, u, P->data));
}
/*
diff --git a/usr/src/lib/libproc/common/Putil.c b/usr/src/lib/libproc/common/Putil.c
index 791ec668cb..f6f2aa862e 100644
--- a/usr/src/lib/libproc/common/Putil.c
+++ b/usr/src/lib/libproc/common/Putil.c
@@ -23,8 +23,9 @@
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright (c) 2013 by Delphix. All rights reserved.
+ */
#include <limits.h>
#include <string.h>
@@ -150,3 +151,96 @@ Perror_printf(struct ps_prochandle *P, const char *format, ...)
{
/* nothing to do here */
}
+
+/*
+ * Default operations.
+ */
+static ssize_t
+Pdefault_ssizet()
+{
+ return (-1);
+}
+
+static int
+Pdefault_int()
+{
+ return (-1);
+}
+
+static void
+Pdefault_void()
+{
+}
+
+static void *
+Pdefault_voidp()
+{
+ return (NULL);
+}
+
+static const ps_ops_t P_default_ops = {
+ .pop_pread = (pop_pread_t)Pdefault_ssizet,
+ .pop_pwrite = (pop_pwrite_t)Pdefault_ssizet,
+ .pop_read_maps = (pop_read_maps_t)Pdefault_int,
+ .pop_read_aux = (pop_read_aux_t)Pdefault_void,
+ .pop_cred = (pop_cred_t)Pdefault_int,
+ .pop_priv = (pop_priv_t)Pdefault_int,
+ .pop_psinfo = (pop_psinfo_t)Pdefault_voidp,
+ .pop_status = (pop_status_t)Pdefault_void,
+ .pop_lstatus = (pop_lstatus_t)Pdefault_voidp,
+ .pop_lpsinfo = (pop_lpsinfo_t)Pdefault_voidp,
+ .pop_fini = (pop_fini_t)Pdefault_void,
+ .pop_platform = (pop_platform_t)Pdefault_voidp,
+ .pop_uname = (pop_uname_t)Pdefault_int,
+ .pop_zonename = (pop_zonename_t)Pdefault_voidp,
+ .pop_execname = (pop_execname_t)Pdefault_voidp,
+#if defined(__i386) || defined(__amd64)
+ .pop_ldt = (pop_ldt_t)Pdefault_int
+#endif
+};
+
+/*
+ * Initialize the destination ops vector with functions from the source.
+ * Functions which are NULL in the source ops vector are set to corresponding
+ * default function in the destination vector.
+ */
+void
+Pinit_ops(ps_ops_t *dst, const ps_ops_t *src)
+{
+ *dst = P_default_ops;
+
+ if (src->pop_pread != NULL)
+ dst->pop_pread = src->pop_pread;
+ if (src->pop_pwrite != NULL)
+ dst->pop_pwrite = src->pop_pwrite;
+ if (src->pop_read_maps != NULL)
+ dst->pop_read_maps = src->pop_read_maps;
+ if (src->pop_read_aux != NULL)
+ dst->pop_read_aux = src->pop_read_aux;
+ if (src->pop_cred != NULL)
+ dst->pop_cred = src->pop_cred;
+ if (src->pop_priv != NULL)
+ dst->pop_priv = src->pop_priv;
+ if (src->pop_psinfo != NULL)
+ dst->pop_psinfo = src->pop_psinfo;
+ if (src->pop_status != NULL)
+ dst->pop_status = src->pop_status;
+ if (src->pop_lstatus != NULL)
+ dst->pop_lstatus = src->pop_lstatus;
+ if (src->pop_lpsinfo != NULL)
+ dst->pop_lpsinfo = src->pop_lpsinfo;
+ if (src->pop_fini != NULL)
+ dst->pop_fini = src->pop_fini;
+ if (src->pop_platform != NULL)
+ dst->pop_platform = src->pop_platform;
+ if (src->pop_uname != NULL)
+ dst->pop_uname = src->pop_uname;
+ if (src->pop_zonename != NULL)
+ dst->pop_zonename = src->pop_zonename;
+ if (src->pop_execname != NULL)
+ dst->pop_execname = src->pop_execname;
+#if defined(__i386) || defined(__amd64)
+ if (src->pop_ldt != NULL)
+ dst->pop_ldt = src->pop_ldt;
+#endif
+}
diff --git a/usr/src/lib/libproc/common/Putil.h b/usr/src/lib/libproc/common/Putil.h
index 55ea45dba2..57814a9a7f 100644
--- a/usr/src/lib/libproc/common/Putil.h
+++ b/usr/src/lib/libproc/common/Putil.h
@@ -23,12 +23,13 @@
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright (c) 2013 by Delphix. All rights reserved.
+ */
#ifndef _PUTIL_H
#define _PUTIL_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#ifdef __cplusplus
extern "C" {
#endif
@@ -64,6 +65,8 @@ extern int prset_ismember(void *, size_t, uint_t);
*/
extern void dprintf(const char *, ...);
+extern void Pinit_ops(ps_ops_t *, const ps_ops_t *);
+
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/lib/libproc/common/Pzone.c b/usr/src/lib/libproc/common/Pzone.c
index 68efea7a72..67a8c0b3c9 100644
--- a/usr/src/lib/libproc/common/Pzone.c
+++ b/usr/src/lib/libproc/common/Pzone.c
@@ -25,6 +25,7 @@
*/
/*
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
*/
#include <assert.h>
@@ -231,23 +232,7 @@ Pbrandname(struct ps_prochandle *P, char *buf, size_t buflen)
char *
Pzonename(struct ps_prochandle *P, char *s, size_t n)
{
- if (P->state == PS_IDLE) {
- errno = ENODATA;
- return (NULL);
- }
-
- if (P->state == PS_DEAD) {
- if (P->core->core_zonename == NULL) {
- errno = ENODATA;
- return (NULL);
- }
- (void) strlcpy(s, P->core->core_zonename, n);
- } else {
- if (getzonenamebyid(P->status.pr_zoneid, s, n) < 0)
- return (NULL);
- s[n - 1] = '\0';
- }
- return (s);
+ return (P->ops.pop_zonename(P, s, n, P->data));
}
char *
diff --git a/usr/src/lib/libproc/common/libproc.h b/usr/src/lib/libproc/common/libproc.h
index 7cfc80cd7a..01970f439e 100644
--- a/usr/src/lib/libproc/common/libproc.h
+++ b/usr/src/lib/libproc/common/libproc.h
@@ -26,6 +26,7 @@
* Portions Copyright 2007 Chad Mynhier
* Copyright 2012 DEY Storage Systems, Inc. All rights reserved.
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
*/
/*
@@ -127,6 +128,7 @@ extern int _libproc_incore_elf; /* only use in-core elf data */
#define PGRAB_FORCE 0x02 /* Open the process w/o O_EXCL */
#define PGRAB_RDONLY 0x04 /* Open the process or core w/ O_RDONLY */
#define PGRAB_NOSTOP 0x08 /* Open the process but do not stop it */
+#define PGRAB_INCORE 0x10 /* Use in-core data to build symbol tables */
/* Error codes from Pcreate() */
#define C_STRANGE -1 /* Unanticipated error, errno is meaningful */
@@ -188,6 +190,55 @@ typedef struct { /* argument descriptor for system call (Psyscall) */
#define MAXARGL (4*1024)
/*
+ * Ops vector definition for the Pgrab_ops().
+ */
+typedef ssize_t (*pop_pread_t)(struct ps_prochandle *, void *, size_t,
+ uintptr_t, void *);
+typedef ssize_t (*pop_pwrite_t)(struct ps_prochandle *, const void *, size_t,
+ uintptr_t, void *);
+typedef int (*pop_read_maps_t)(struct ps_prochandle *, prmap_t **, ssize_t *,
+ void *);
+typedef void (*pop_read_aux_t)(struct ps_prochandle *, auxv_t **, int *,
+ void *);
+typedef int (*pop_cred_t)(struct ps_prochandle *, prcred_t *, int,
+ void *);
+typedef int (*pop_priv_t)(struct ps_prochandle *, prpriv_t **, void *);
+typedef const psinfo_t *(*pop_psinfo_t)(struct ps_prochandle *, psinfo_t *,
+ void *);
+typedef void (*pop_status_t)(struct ps_prochandle *, pstatus_t *, void *);
+typedef prheader_t *(*pop_lstatus_t)(struct ps_prochandle *, void *);
+typedef prheader_t *(*pop_lpsinfo_t)(struct ps_prochandle *, void *);
+typedef void (*pop_fini_t)(struct ps_prochandle *, void *);
+typedef char *(*pop_platform_t)(struct ps_prochandle *, char *, size_t, void *);
+typedef int (*pop_uname_t)(struct ps_prochandle *, struct utsname *, void *);
+typedef char *(*pop_zonename_t)(struct ps_prochandle *, char *, size_t, void *);
+typedef char *(*pop_execname_t)(struct ps_prochandle *, char *, size_t, void *);
+#if defined(__i386) || defined(__amd64)
+typedef int (*pop_ldt_t)(struct ps_prochandle *, struct ssd *, int, void *);
+#endif
+
+typedef struct ps_ops {
+ pop_pread_t pop_pread;
+ pop_pwrite_t pop_pwrite;
+ pop_read_maps_t pop_read_maps;
+ pop_read_aux_t pop_read_aux;
+ pop_cred_t pop_cred;
+ pop_priv_t pop_priv;
+ pop_psinfo_t pop_psinfo;
+ pop_status_t pop_status;
+ pop_lstatus_t pop_lstatus;
+ pop_lpsinfo_t pop_lpsinfo;
+ pop_fini_t pop_fini;
+ pop_platform_t pop_platform;
+ pop_uname_t pop_uname;
+ pop_zonename_t pop_zonename;
+ pop_execname_t pop_execname;
+#if defined(__i386) || defined(__amd64)
+ pop_ldt_t pop_ldt;
+#endif
+} ps_ops_t;
+
+/*
* Function prototypes for routines in the process control package.
*/
extern struct ps_prochandle *Pcreate(const char *, char *const *,
@@ -201,6 +252,7 @@ extern struct ps_prochandle *Pgrab(pid_t, int, int *);
extern struct ps_prochandle *Pgrab_core(const char *, const char *, int, int *);
extern struct ps_prochandle *Pfgrab_core(int, const char *, int *);
extern struct ps_prochandle *Pgrab_file(const char *, int *);
+extern struct ps_prochandle *Pgrab_ops(pid_t, void *, const ps_ops_t *, int);
extern const char *Pgrab_error(int);
extern int Preopen(struct ps_prochandle *);
@@ -221,7 +273,7 @@ extern const psinfo_t *Ppsinfo(struct ps_prochandle *);
extern const pstatus_t *Pstatus(struct ps_prochandle *);
extern int Pcred(struct ps_prochandle *, prcred_t *, int);
extern int Psetcred(struct ps_prochandle *, const prcred_t *);
-extern ssize_t Ppriv(struct ps_prochandle *, prpriv_t *, size_t);
+extern int Ppriv(struct ps_prochandle *, prpriv_t **);
extern int Psetpriv(struct ps_prochandle *, prpriv_t *);
extern void *Pprivinfo(struct ps_prochandle *);
extern int Psetzoneid(struct ps_prochandle *, zoneid_t);
diff --git a/usr/src/lib/libproc/common/llib-lproc b/usr/src/lib/libproc/common/llib-lproc
index 9626e80024..35907f04d0 100644
--- a/usr/src/lib/libproc/common/llib-lproc
+++ b/usr/src/lib/libproc/common/llib-lproc
@@ -25,6 +25,9 @@
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+/*
+ * Copyright (c) 2013 by Delphix. All rights reserved.
+ */
#include "libproc.h"
/*
@@ -46,7 +49,7 @@ int Pctlfd(struct ps_prochandle *Pr);
const psinfo_t *Ppsinfo(struct ps_prochandle *Pr);
const pstatus_t *Pstatus(struct ps_prochandle *Pr);
int Pcred(struct ps_prochandle *Pr, prcred_t *pcrp, int ngroups);
-ssize_t Ppriv(struct ps_prochandle *Pr, prpriv_t *pprivp, size_t);
+int Ppriv(struct ps_prochandle *Pr, prpriv_t **pprivp);
void Psync(struct ps_prochandle *Pr);
int Pcreate_agent(struct ps_prochandle *Pr);
void Pdestroy_agent(struct ps_prochandle *Pr);
diff --git a/usr/src/lib/libproc/common/mapfile-vers b/usr/src/lib/libproc/common/mapfile-vers
index eb91461d98..666d63fbf0 100644
--- a/usr/src/lib/libproc/common/mapfile-vers
+++ b/usr/src/lib/libproc/common/mapfile-vers
@@ -22,6 +22,7 @@
# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
# Copyright 2012 DEY Storage Systems, Inc. All rights reserved.
# Copyright (c) 2013, Joyent, Inc. All rights reserved.
+# Copyright (c) 2013 by Delphix. All rights reserved.
#
#
@@ -123,6 +124,7 @@ SYMBOL_VERSION SUNWprivate_1.1 {
Pgrab_core;
Pgrab_error;
Pgrab_file;
+ Pgrab_ops;
Pisprocdir;
Pissyscall_prev;
Plmid;