diff options
author | trociny <trociny@FreeBSD.org> | 2013-04-20 08:17:20 +0000 |
---|---|---|
committer | trociny <trociny@FreeBSD.org> | 2013-04-20 08:17:20 +0000 |
commit | 457eff386468328043f16986ad34521af9ffafc7 (patch) | |
tree | 2152fd93e707be2148caddeed1984a93cbeaead0 /lib/libprocstat/libprocstat.c | |
parent | 814255607be8d0162a05c8b6c4291a57b7744e53 (diff) | |
download | FreeBSD-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.c | 70 |
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); +} |