summaryrefslogtreecommitdiffstats
path: root/lib/libutil/kinfo_getvmmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libutil/kinfo_getvmmap.c')
-rw-r--r--lib/libutil/kinfo_getvmmap.c73
1 files changed, 73 insertions, 0 deletions
diff --git a/lib/libutil/kinfo_getvmmap.c b/lib/libutil/kinfo_getvmmap.c
new file mode 100644
index 0000000..129aa03
--- /dev/null
+++ b/lib/libutil/kinfo_getvmmap.c
@@ -0,0 +1,73 @@
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/user.h>
+#include <sys/sysctl.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "libutil.h"
+
+struct kinfo_vmentry *
+kinfo_getvmmap(pid_t pid, int *cntp)
+{
+ int mib[4];
+ int error;
+ int cnt;
+ size_t len;
+ char *buf, *bp, *eb;
+ struct kinfo_vmentry *kiv, *kp, *kv;
+
+ *cntp = 0;
+ len = 0;
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_VMMAP;
+ mib[3] = pid;
+
+ error = sysctl(mib, 4, NULL, &len, NULL, 0);
+ if (error)
+ return (NULL);
+ len = len * 4 / 3;
+ buf = malloc(len);
+ if (buf == NULL)
+ return (NULL);
+ error = sysctl(mib, 4, buf, &len, NULL, 0);
+ if (error) {
+ free(buf);
+ return (NULL);
+ }
+ /* 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 */
+}
OpenPOWER on IntegriCloud