mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-14 20:37:06 +00:00
Add procstat_getkstack function to dump kernel stacks of a process.
MFC after: 1 month
This commit is contained in:
parent
61e1b7c67b
commit
89358231fa
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=249684
|
@ -20,12 +20,14 @@ FBSD_1.3 {
|
||||||
procstat_freeauxv;
|
procstat_freeauxv;
|
||||||
procstat_freeenvv;
|
procstat_freeenvv;
|
||||||
procstat_freegroups;
|
procstat_freegroups;
|
||||||
|
procstat_freekstack;
|
||||||
procstat_freevmmap;
|
procstat_freevmmap;
|
||||||
procstat_get_shm_info;
|
procstat_get_shm_info;
|
||||||
procstat_getargv;
|
procstat_getargv;
|
||||||
procstat_getauxv;
|
procstat_getauxv;
|
||||||
procstat_getenvv;
|
procstat_getenvv;
|
||||||
procstat_getgroups;
|
procstat_getgroups;
|
||||||
|
procstat_getkstack;
|
||||||
procstat_getosrel;
|
procstat_getosrel;
|
||||||
procstat_getpathname;
|
procstat_getpathname;
|
||||||
procstat_getrlimit;
|
procstat_getrlimit;
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
.Nm procstat_getenvv ,
|
.Nm procstat_getenvv ,
|
||||||
.Nm procstat_getfiles ,
|
.Nm procstat_getfiles ,
|
||||||
.Nm procstat_getgroups ,
|
.Nm procstat_getgroups ,
|
||||||
|
.Nm procstat_getkstack ,
|
||||||
.Nm procstat_getosrel ,
|
.Nm procstat_getosrel ,
|
||||||
.Nm procstat_getpathname ,
|
.Nm procstat_getpathname ,
|
||||||
.Nm procstat_getprocs ,
|
.Nm procstat_getprocs ,
|
||||||
|
@ -47,6 +48,7 @@
|
||||||
.Nm procstat_freeenvv ,
|
.Nm procstat_freeenvv ,
|
||||||
.Nm procstat_freefiles ,
|
.Nm procstat_freefiles ,
|
||||||
.Nm procstat_freegroups ,
|
.Nm procstat_freegroups ,
|
||||||
|
.Nm procstat_freekstack ,
|
||||||
.Nm procstat_freeprocs ,
|
.Nm procstat_freeprocs ,
|
||||||
.Nm procstat_freevmmap ,
|
.Nm procstat_freevmmap ,
|
||||||
.Nm procstat_get_pipe_info ,
|
.Nm procstat_get_pipe_info ,
|
||||||
|
@ -88,6 +90,11 @@
|
||||||
.Fa "gid_t *groups"
|
.Fa "gid_t *groups"
|
||||||
.Fc
|
.Fc
|
||||||
.Ft void
|
.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"
|
.Fn procstat_freeprocs "struct procstat *procstat" "struct kinfo_proc *p"
|
||||||
.Ft void
|
.Ft void
|
||||||
.Fo procstat_freevmmap
|
.Fo procstat_freevmmap
|
||||||
|
@ -166,6 +173,12 @@
|
||||||
.Fa "struct kinfo_proc *kp"
|
.Fa "struct kinfo_proc *kp"
|
||||||
.Fa "int *osrelp"
|
.Fa "int *osrelp"
|
||||||
.Fc
|
.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 *"
|
.Ft "struct kinfo_proc *"
|
||||||
.Fo procstat_getprocs
|
.Fo procstat_getprocs
|
||||||
.Fa "struct procstat *procstat"
|
.Fa "struct procstat *procstat"
|
||||||
|
@ -378,6 +391,22 @@ The caller is responsible to free the allocated memory with a subsequent
|
||||||
function call.
|
function call.
|
||||||
.Pp
|
.Pp
|
||||||
The
|
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
|
.Fn procstat_getosrel
|
||||||
function gets a pointer to the
|
function gets a pointer to the
|
||||||
.Vt procstat
|
.Vt procstat
|
||||||
|
|
|
@ -142,6 +142,8 @@ static int procstat_get_vnode_info_sysctl(struct filestat *fst,
|
||||||
static gid_t *procstat_getgroups_core(struct procstat_core *core,
|
static gid_t *procstat_getgroups_core(struct procstat_core *core,
|
||||||
unsigned int *count);
|
unsigned int *count);
|
||||||
static gid_t *procstat_getgroups_sysctl(pid_t pid, 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,
|
static int procstat_getpathname_core(struct procstat_core *core,
|
||||||
char *pathname, size_t maxlen);
|
char *pathname, size_t maxlen);
|
||||||
static int procstat_getpathname_sysctl(pid_t pid, char *pathname,
|
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,
|
procstat_getvmmap(struct procstat *procstat, struct kinfo_proc *kp,
|
||||||
unsigned int *cntp)
|
unsigned int *cntp)
|
||||||
{
|
{
|
||||||
|
|
||||||
switch(procstat->type) {
|
switch(procstat->type) {
|
||||||
case PROCSTAT_KVM:
|
case PROCSTAT_KVM:
|
||||||
warnx("kvm method is not supported");
|
warnx("kvm method is not supported");
|
||||||
|
@ -2227,3 +2230,70 @@ procstat_freeauxv(struct procstat *procstat __unused, Elf_Auxinfo *auxv)
|
||||||
|
|
||||||
free(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);
|
||||||
|
}
|
||||||
|
|
|
@ -97,6 +97,7 @@
|
||||||
#define PS_FST_FFLAG_EXEC 0x2000
|
#define PS_FST_FFLAG_EXEC 0x2000
|
||||||
#define PS_FST_FFLAG_HASLOCK 0x4000
|
#define PS_FST_FFLAG_HASLOCK 0x4000
|
||||||
|
|
||||||
|
struct kinfo_kstack;
|
||||||
struct kinfo_vmentry;
|
struct kinfo_vmentry;
|
||||||
struct procstat;
|
struct procstat;
|
||||||
struct rlimit;
|
struct rlimit;
|
||||||
|
@ -161,6 +162,8 @@ void procstat_freeauxv(struct procstat *procstat, Elf_Auxinfo *auxv);
|
||||||
#endif
|
#endif
|
||||||
void procstat_freeenvv(struct procstat *procstat);
|
void procstat_freeenvv(struct procstat *procstat);
|
||||||
void procstat_freegroups(struct procstat *procstat, gid_t *groups);
|
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_freeprocs(struct procstat *procstat, struct kinfo_proc *p);
|
||||||
void procstat_freefiles(struct procstat *procstat,
|
void procstat_freefiles(struct procstat *procstat,
|
||||||
struct filestat_list *head);
|
struct filestat_list *head);
|
||||||
|
@ -190,6 +193,8 @@ char **procstat_getenvv(struct procstat *procstat, struct kinfo_proc *p,
|
||||||
size_t nchr);
|
size_t nchr);
|
||||||
gid_t *procstat_getgroups(struct procstat *procstat, struct kinfo_proc *kp,
|
gid_t *procstat_getgroups(struct procstat *procstat, struct kinfo_proc *kp,
|
||||||
unsigned int *count);
|
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 procstat_getosrel(struct procstat *procstat, struct kinfo_proc *kp,
|
||||||
int *osrelp);
|
int *osrelp);
|
||||||
int procstat_getpathname(struct procstat *procstat, struct kinfo_proc *kp,
|
int procstat_getpathname(struct procstat *procstat, struct kinfo_proc *kp,
|
||||||
|
|
Loading…
Reference in a new issue