diff options
author | trociny <trociny@FreeBSD.org> | 2013-04-20 07:49:35 +0000 |
---|---|---|
committer | trociny <trociny@FreeBSD.org> | 2013-04-20 07:49:35 +0000 |
commit | 08b1137c14b2ad1dd61b67f218f6438e0ca54780 (patch) | |
tree | 10d242826932cd7fe16d4b323cb7306ef42d628b /lib/libprocstat | |
parent | 16ea6280bfe1e44cbde69ee9e5bf59725bf0853c (diff) | |
download | FreeBSD-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.map | 2 | ||||
-rw-r--r-- | lib/libprocstat/libprocstat.3 | 29 | ||||
-rw-r--r-- | lib/libprocstat/libprocstat.c | 83 | ||||
-rw-r--r-- | lib/libprocstat/libprocstat.h | 5 |
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); |