summaryrefslogtreecommitdiffstats
path: root/lib/libprocstat
diff options
context:
space:
mode:
authortrociny <trociny@FreeBSD.org>2013-04-20 07:49:35 +0000
committertrociny <trociny@FreeBSD.org>2013-04-20 07:49:35 +0000
commit08b1137c14b2ad1dd61b67f218f6438e0ca54780 (patch)
tree10d242826932cd7fe16d4b323cb7306ef42d628b /lib/libprocstat
parent16ea6280bfe1e44cbde69ee9e5bf59725bf0853c (diff)
downloadFreeBSD-src-08b1137c14b2ad1dd61b67f218f6438e0ca54780.zip
FreeBSD-src-08b1137c14b2ad1dd61b67f218f6438e0ca54780.tar.gz
Add procstat_getvmmap function to get VM layout of a process.
MFC after: 1 month
Diffstat (limited to 'lib/libprocstat')
-rw-r--r--lib/libprocstat/Symbol.map2
-rw-r--r--lib/libprocstat/libprocstat.329
-rw-r--r--lib/libprocstat/libprocstat.c83
-rw-r--r--lib/libprocstat/libprocstat.h5
4 files changed, 118 insertions, 1 deletions
diff --git a/lib/libprocstat/Symbol.map b/lib/libprocstat/Symbol.map
index a078090..aa74659 100644
--- a/lib/libprocstat/Symbol.map
+++ b/lib/libprocstat/Symbol.map
@@ -16,6 +16,8 @@ FBSD_1.2 {
};
FBSD_1.3 {
+ procstat_freevmmap;
procstat_get_shm_info;
+ procstat_getvmmap;
procstat_open_core;
};
diff --git a/lib/libprocstat/libprocstat.3 b/lib/libprocstat/libprocstat.3
index a64376c..18dc1e9 100644
--- a/lib/libprocstat/libprocstat.3
+++ b/lib/libprocstat/libprocstat.3
@@ -34,8 +34,10 @@
.Nm procstat_close ,
.Nm procstat_getfiles ,
.Nm procstat_getprocs ,
+.Nm procstat_getvmmap ,
.Nm procstat_freefiles ,
.Nm procstat_freeprocs ,
+.Nm procstat_freevmmap ,
.Nm procstat_get_pipe_info ,
.Nm procstat_get_pts_info ,
.Nm procstat_get_shm_info ,
@@ -57,6 +59,11 @@
.Fc
.Ft void
.Fn procstat_freeprocs "struct procstat *procstat" "struct kinfo_proc *p"
+.Ft void
+.Fo procstat_freevmmap
+.Fa "struct procstat *procstat"
+.Fa "struct kinfo_vmentry *vmmap"
+.Fc
.Ft int
.Fo procstat_get_pipe_info
.Fa "struct procstat *procstat"
@@ -105,6 +112,12 @@
.Fa "int arg"
.Fa "unsigned int *count"
.Fc
+.Ft "struct kinfo_vmentry *"
+.Fo procstat_getvmmap
+.Fa "struct procstat *procstat"
+.Fa "struct kinfo_proc *kp"
+.Fa "unsigned int *count"
+.Fc
.Ft "struct procstat *"
.Fn procstat_open_core "const char *filename"
.Ft "struct procstat *"
@@ -214,6 +227,22 @@ The caller is responsible to free the allocated memory with a subsequent
function call.
.Pp
The
+.Fn procstat_getvmmap
+function gets a pointer to the
+.Vt procstat
+structure initialized with one of the
+.Fn procstat_open_*
+functions, a pointer to
+.Vt kinfo_proc
+structure, and returns VM layout of the process as a dynamically allocated
+array of
+.Vt kinfo_vmentry
+structures.
+The caller is responsible to free the allocated memory with a subsequent
+.Fn procstat_freevmmap
+function call.
+.Pp
+The
.Fn procstat_get_pipe_info ,
.Fn procstat_get_pts_info ,
.Fn procstat_get_shm_info ,
diff --git a/lib/libprocstat/libprocstat.c b/lib/libprocstat/libprocstat.c
index 574d654..283f802 100644
--- a/lib/libprocstat/libprocstat.c
+++ b/lib/libprocstat/libprocstat.c
@@ -105,6 +105,8 @@ int statfs(const char *, struct statfs *); /* XXX */
#define PROCSTAT_CORE 3
static char *getmnton(kvm_t *kd, struct mount *m);
+static struct kinfo_vmentry * kinfo_getvmmap_core(struct procstat_core *core,
+ int *cntp);
static struct filestat_list *procstat_getfiles_kvm(
struct procstat *procstat, struct kinfo_proc *kp, int mmapped);
static struct filestat_list *procstat_getfiles_sysctl(
@@ -802,7 +804,7 @@ procstat_getfiles_sysctl(struct procstat *procstat, struct kinfo_proc *kp,
STAILQ_INSERT_TAIL(head, entry, next);
}
if (mmapped != 0) {
- vmentries = kinfo_getvmmap(kp->ki_pid, &cnt);
+ vmentries = procstat_getvmmap(procstat, kp, &cnt);
procstat->vmentries = vmentries;
if (vmentries == NULL || cnt == 0)
goto fail;
@@ -1507,3 +1509,82 @@ getmnton(kvm_t *kd, struct mount *m)
return (mt->mntonname);
}
+static struct kinfo_vmentry *
+kinfo_getvmmap_core(struct procstat_core *core, int *cntp)
+{
+ int cnt;
+ size_t len;
+ char *buf, *bp, *eb;
+ struct kinfo_vmentry *kiv, *kp, *kv;
+
+ buf = procstat_core_get(core, PSC_TYPE_VMMAP, NULL, &len);
+ if (buf == NULL)
+ return (NULL);
+
+ /*
+ * XXXMG: The code below is just copy&past from libutil.
+ * The code duplication can be avoided if libutil
+ * is extended to provide something like:
+ * struct kinfo_vmentry *kinfo_getvmmap_from_buf(const char *buf,
+ * size_t len, int *cntp);
+ */
+
+ /* Pass 1: count items */
+ cnt = 0;
+ bp = buf;
+ eb = buf + len;
+ while (bp < eb) {
+ kv = (struct kinfo_vmentry *)(uintptr_t)bp;
+ bp += kv->kve_structsize;
+ cnt++;
+ }
+
+ kiv = calloc(cnt, sizeof(*kiv));
+ if (kiv == NULL) {
+ free(buf);
+ return (NULL);
+ }
+ bp = buf;
+ eb = buf + len;
+ kp = kiv;
+ /* Pass 2: unpack */
+ while (bp < eb) {
+ kv = (struct kinfo_vmentry *)(uintptr_t)bp;
+ /* Copy/expand into pre-zeroed buffer */
+ memcpy(kp, kv, kv->kve_structsize);
+ /* Advance to next packed record */
+ bp += kv->kve_structsize;
+ /* Set field size to fixed length, advance */
+ kp->kve_structsize = sizeof(*kp);
+ kp++;
+ }
+ free(buf);
+ *cntp = cnt;
+ return (kiv); /* Caller must free() return value */
+}
+
+struct kinfo_vmentry *
+procstat_getvmmap(struct procstat *procstat, struct kinfo_proc *kp,
+ unsigned int *cntp)
+{
+ switch(procstat->type) {
+ case PROCSTAT_KVM:
+ warnx("kvm method is not supported");
+ return (NULL);
+ case PROCSTAT_SYSCTL:
+ return (kinfo_getvmmap(kp->ki_pid, cntp));
+ case PROCSTAT_CORE:
+ return (kinfo_getvmmap_core(procstat->core, cntp));
+ default:
+ warnx("unknown access method: %d", procstat->type);
+ return (NULL);
+ }
+}
+
+void
+procstat_freevmmap(struct procstat *procstat __unused,
+ struct kinfo_vmentry *vmmap)
+{
+
+ free(vmmap);
+}
diff --git a/lib/libprocstat/libprocstat.h b/lib/libprocstat/libprocstat.h
index 4ad9cee..71d85a1 100644
--- a/lib/libprocstat/libprocstat.h
+++ b/lib/libprocstat/libprocstat.h
@@ -89,6 +89,7 @@
#define PS_FST_FFLAG_EXEC 0x2000
#define PS_FST_FFLAG_HASLOCK 0x4000
+struct kinfo_vmentry;
struct procstat;
struct filestat {
int fs_type; /* Descriptor type. */
@@ -148,6 +149,8 @@ void procstat_close(struct procstat *procstat);
void procstat_freeprocs(struct procstat *procstat, struct kinfo_proc *p);
void procstat_freefiles(struct procstat *procstat,
struct filestat_list *head);
+void procstat_freevmmap(struct procstat *procstat,
+ struct kinfo_vmentry *vmmap);
struct filestat_list *procstat_getfiles(struct procstat *procstat,
struct kinfo_proc *kp, int mmapped);
struct kinfo_proc *procstat_getprocs(struct procstat *procstat,
@@ -162,6 +165,8 @@ int procstat_get_socket_info(struct procstat *procstat, struct filestat *fst,
struct sockstat *sock, char *errbuf);
int procstat_get_vnode_info(struct procstat *procstat, struct filestat *fst,
struct vnstat *vn, char *errbuf);
+struct kinfo_vmentry *procstat_getvmmap(struct procstat *procstat,
+ struct kinfo_proc *kp, unsigned int *count);
struct procstat *procstat_open_core(const char *filename);
struct procstat *procstat_open_sysctl(void);
struct procstat *procstat_open_kvm(const char *nlistf, const char *memf);
OpenPOWER on IntegriCloud