summaryrefslogtreecommitdiffstats
path: root/lib/libprocstat/libprocstat.c
diff options
context:
space:
mode:
authortrociny <trociny@FreeBSD.org>2013-04-20 08:17:20 +0000
committertrociny <trociny@FreeBSD.org>2013-04-20 08:17:20 +0000
commit457eff386468328043f16986ad34521af9ffafc7 (patch)
tree2152fd93e707be2148caddeed1984a93cbeaead0 /lib/libprocstat/libprocstat.c
parent814255607be8d0162a05c8b6c4291a57b7744e53 (diff)
downloadFreeBSD-src-457eff386468328043f16986ad34521af9ffafc7.zip
FreeBSD-src-457eff386468328043f16986ad34521af9ffafc7.tar.gz
Add procstat_getkstack function to dump kernel stacks of a process.
MFC after: 1 month
Diffstat (limited to 'lib/libprocstat/libprocstat.c')
-rw-r--r--lib/libprocstat/libprocstat.c70
1 files changed, 70 insertions, 0 deletions
diff --git a/lib/libprocstat/libprocstat.c b/lib/libprocstat/libprocstat.c
index b70586d..a54b90d 100644
--- a/lib/libprocstat/libprocstat.c
+++ b/lib/libprocstat/libprocstat.c
@@ -142,6 +142,8 @@ static int procstat_get_vnode_info_sysctl(struct filestat *fst,
static gid_t *procstat_getgroups_core(struct procstat_core *core,
unsigned int *count);
static gid_t *procstat_getgroups_sysctl(pid_t pid, unsigned int *count);
+static struct kinfo_kstack *procstat_getkstack_sysctl(pid_t pid,
+ int *cntp);
static int procstat_getpathname_core(struct procstat_core *core,
char *pathname, size_t maxlen);
static int procstat_getpathname_sysctl(pid_t pid, char *pathname,
@@ -1764,6 +1766,7 @@ 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");
@@ -2227,3 +2230,70 @@ procstat_freeauxv(struct procstat *procstat __unused, Elf_Auxinfo *auxv)
free(auxv);
}
+
+static struct kinfo_kstack *
+procstat_getkstack_sysctl(pid_t pid, int *cntp)
+{
+ struct kinfo_kstack *kkstp;
+ int error, name[4];
+ size_t len;
+
+ name[0] = CTL_KERN;
+ name[1] = KERN_PROC;
+ name[2] = KERN_PROC_KSTACK;
+ name[3] = pid;
+
+ len = 0;
+ error = sysctl(name, 4, NULL, &len, NULL, 0);
+ if (error < 0 && errno != ESRCH && errno != EPERM && errno != ENOENT) {
+ warn("sysctl: kern.proc.kstack: %d", pid);
+ return (NULL);
+ }
+ if (error == -1 && errno == ENOENT) {
+ warnx("sysctl: kern.proc.kstack unavailable"
+ " (options DDB or options STACK required in kernel)");
+ return (NULL);
+ }
+ if (error == -1)
+ return (NULL);
+ kkstp = malloc(len);
+ if (kkstp == NULL) {
+ warn("malloc(%zu)", len);
+ return (NULL);
+ }
+ if (sysctl(name, 4, kkstp, &len, NULL, 0) == -1) {
+ warn("sysctl: kern.proc.pid: %d", pid);
+ free(kkstp);
+ return (NULL);
+ }
+ *cntp = len / sizeof(*kkstp);
+
+ return (kkstp);
+}
+
+struct kinfo_kstack *
+procstat_getkstack(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 (procstat_getkstack_sysctl(kp->ki_pid, cntp));
+ case PROCSTAT_CORE:
+ warnx("core method is not supported");
+ return (NULL);
+ default:
+ warnx("unknown access method: %d", procstat->type);
+ return (NULL);
+ }
+}
+
+void
+procstat_freekstack(struct procstat *procstat __unused,
+ struct kinfo_kstack *kkstp)
+{
+
+ free(kkstp);
+}
OpenPOWER on IntegriCloud