summaryrefslogtreecommitdiffstats
path: root/lib/libprocstat
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
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')
-rw-r--r--lib/libprocstat/Symbol.map2
-rw-r--r--lib/libprocstat/libprocstat.329
-rw-r--r--lib/libprocstat/libprocstat.c70
-rw-r--r--lib/libprocstat/libprocstat.h5
4 files changed, 106 insertions, 0 deletions
diff --git a/lib/libprocstat/Symbol.map b/lib/libprocstat/Symbol.map
index 322d46f..085720c 100644
--- a/lib/libprocstat/Symbol.map
+++ b/lib/libprocstat/Symbol.map
@@ -20,12 +20,14 @@ FBSD_1.3 {
procstat_freeauxv;
procstat_freeenvv;
procstat_freegroups;
+ procstat_freekstack;
procstat_freevmmap;
procstat_get_shm_info;
procstat_getargv;
procstat_getauxv;
procstat_getenvv;
procstat_getgroups;
+ procstat_getkstack;
procstat_getosrel;
procstat_getpathname;
procstat_getrlimit;
diff --git a/lib/libprocstat/libprocstat.3 b/lib/libprocstat/libprocstat.3
index 5a425e7..1367741 100644
--- a/lib/libprocstat/libprocstat.3
+++ b/lib/libprocstat/libprocstat.3
@@ -37,6 +37,7 @@
.Nm procstat_getenvv ,
.Nm procstat_getfiles ,
.Nm procstat_getgroups ,
+.Nm procstat_getkstack ,
.Nm procstat_getosrel ,
.Nm procstat_getpathname ,
.Nm procstat_getprocs ,
@@ -47,6 +48,7 @@
.Nm procstat_freeenvv ,
.Nm procstat_freefiles ,
.Nm procstat_freegroups ,
+.Nm procstat_freekstack ,
.Nm procstat_freeprocs ,
.Nm procstat_freevmmap ,
.Nm procstat_get_pipe_info ,
@@ -88,6 +90,11 @@
.Fa "gid_t *groups"
.Fc
.Ft void
+.Fo procstat_freekstack
+.Fa "struct procstat *procstat"
+.Fa "struct kinfo_kstack *kkstp"
+.Fc
+.Ft void
.Fn procstat_freeprocs "struct procstat *procstat" "struct kinfo_proc *p"
.Ft void
.Fo procstat_freevmmap
@@ -166,6 +173,12 @@
.Fa "struct kinfo_proc *kp"
.Fa "int *osrelp"
.Fc
+.Ft "struct kinfo_kstack *"
+.Fo procstat_getkstack
+.Fa "struct procstat *procstat"
+.Fa "struct kinfo_proc *kp"
+.Fa "unsigned int *count"
+.Fc
.Ft "struct kinfo_proc *"
.Fo procstat_getprocs
.Fa "struct procstat *procstat"
@@ -378,6 +391,22 @@ The caller is responsible to free the allocated memory with a subsequent
function call.
.Pp
The
+.Fn procstat_getkstack
+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 kernel stacks of the process as a dynamically allocated
+array of
+.Vt kinfo_kstack
+structures.
+The caller is responsible to free the allocated memory with a subsequent
+.Fn procstat_freekstack
+function call.
+.Pp
+The
.Fn procstat_getosrel
function gets a pointer to the
.Vt procstat
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);
+}
diff --git a/lib/libprocstat/libprocstat.h b/lib/libprocstat/libprocstat.h
index 3ac51e1..2c2662d 100644
--- a/lib/libprocstat/libprocstat.h
+++ b/lib/libprocstat/libprocstat.h
@@ -97,6 +97,7 @@
#define PS_FST_FFLAG_EXEC 0x2000
#define PS_FST_FFLAG_HASLOCK 0x4000
+struct kinfo_kstack;
struct kinfo_vmentry;
struct procstat;
struct rlimit;
@@ -161,6 +162,8 @@ void procstat_freeauxv(struct procstat *procstat, Elf_Auxinfo *auxv);
#endif
void procstat_freeenvv(struct procstat *procstat);
void procstat_freegroups(struct procstat *procstat, gid_t *groups);
+void procstat_freekstack(struct procstat *procstat,
+ struct kinfo_kstack *kkstp);
void procstat_freeprocs(struct procstat *procstat, struct kinfo_proc *p);
void procstat_freefiles(struct procstat *procstat,
struct filestat_list *head);
@@ -190,6 +193,8 @@ char **procstat_getenvv(struct procstat *procstat, struct kinfo_proc *p,
size_t nchr);
gid_t *procstat_getgroups(struct procstat *procstat, struct kinfo_proc *kp,
unsigned int *count);
+struct kinfo_kstack *procstat_getkstack(struct procstat *procstat,
+ struct kinfo_proc *kp, unsigned int *count);
int procstat_getosrel(struct procstat *procstat, struct kinfo_proc *kp,
int *osrelp);
int procstat_getpathname(struct procstat *procstat, struct kinfo_proc *kp,
OpenPOWER on IntegriCloud