aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/libprocstat/Symbol.map5
-rw-r--r--lib/libprocstat/core.c136
-rw-r--r--lib/libprocstat/core.h4
-rw-r--r--lib/libprocstat/libprocstat.c44
-rw-r--r--lib/libprocstat/libprocstat.h6
-rw-r--r--sys/kern/imgact_elf.c36
-rw-r--r--sys/kern/kern_sig.c28
-rw-r--r--sys/kern/sys_process.c4
-rw-r--r--sys/sys/elf_common.h2
-rw-r--r--sys/sys/proc.h2
-rw-r--r--usr.bin/gcore/elfcore.c21
-rw-r--r--usr.bin/procstat/Makefile1
-rw-r--r--usr.bin/procstat/procstat.14
-rw-r--r--usr.bin/procstat/procstat.c14
-rw-r--r--usr.bin/procstat/procstat.h2
-rw-r--r--usr.bin/procstat/procstat_ptlwpinfo.c91
16 files changed, 342 insertions, 58 deletions
diff --git a/lib/libprocstat/Symbol.map b/lib/libprocstat/Symbol.map
index 1495bfc28c66..75a8916aca67 100644
--- a/lib/libprocstat/Symbol.map
+++ b/lib/libprocstat/Symbol.map
@@ -36,3 +36,8 @@ FBSD_1.3 {
procstat_getvmmap;
procstat_open_core;
};
+
+FBSD_1.5 {
+ procstat_freeptlwpinfo;
+ procstat_getptlwpinfo;
+};
diff --git a/lib/libprocstat/core.c b/lib/libprocstat/core.c
index 70ab86df5b0b..9baa0cde10ca 100644
--- a/lib/libprocstat/core.c
+++ b/lib/libprocstat/core.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2013 Mikolaj Golub <trociny@FreeBSD.org>
+ * Copyright (c) 2017 Dell EMC
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -30,6 +31,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/elf.h>
#include <sys/exec.h>
+#include <sys/ptrace.h>
#include <sys/user.h>
#include <assert.h>
@@ -56,6 +58,24 @@ struct procstat_core
GElf_Phdr pc_phdr;
};
+static struct psc_type_info {
+ unsigned int n_type;
+ int structsize;
+} psc_type_info[PSC_TYPE_MAX] = {
+ { .n_type = NT_PROCSTAT_PROC, .structsize = sizeof(struct kinfo_proc) },
+ { .n_type = NT_PROCSTAT_FILES, .structsize = sizeof(struct kinfo_file) },
+ { .n_type = NT_PROCSTAT_VMMAP, .structsize = sizeof(struct kinfo_vmentry) },
+ { .n_type = NT_PROCSTAT_GROUPS, .structsize = sizeof(gid_t) },
+ { .n_type = NT_PROCSTAT_UMASK, .structsize = sizeof(u_short) },
+ { .n_type = NT_PROCSTAT_RLIMIT, .structsize = sizeof(struct rlimit) * RLIM_NLIMITS },
+ { .n_type = NT_PROCSTAT_OSREL, .structsize = sizeof(int) },
+ { .n_type = NT_PROCSTAT_PSSTRINGS, .structsize = sizeof(vm_offset_t) },
+ { .n_type = NT_PROCSTAT_PSSTRINGS, .structsize = sizeof(vm_offset_t) },
+ { .n_type = NT_PROCSTAT_PSSTRINGS, .structsize = sizeof(vm_offset_t) },
+ { .n_type = NT_PROCSTAT_AUXV, .structsize = sizeof(Elf_Auxinfo) },
+ { .n_type = NT_PTLWPINFO, .structsize = sizeof(struct ptrace_lwpinfo) },
+};
+
static bool core_offset(struct procstat_core *core, off_t offset);
static bool core_read(struct procstat_core *core, void *buf, size_t len);
static ssize_t core_read_mem(struct procstat_core *core, void *buf,
@@ -154,59 +174,20 @@ procstat_core_get(struct procstat_core *core, enum psc_type type, void *buf,
off_t offset, eoffset;
vm_offset_t psstrings;
void *freebuf;
- size_t len;
- u_int32_t n_type;
- int cstructsize, structsize;
+ size_t len, curlen;
+ int cstructsize;
char nbuf[8];
assert(core->pc_magic == PROCSTAT_CORE_MAGIC);
- switch(type) {
- case PSC_TYPE_PROC:
- n_type = NT_PROCSTAT_PROC;
- structsize = sizeof(struct kinfo_proc);
- break;
- case PSC_TYPE_FILES:
- n_type = NT_PROCSTAT_FILES;
- structsize = sizeof(struct kinfo_file);
- break;
- case PSC_TYPE_VMMAP:
- n_type = NT_PROCSTAT_VMMAP;
- structsize = sizeof(struct kinfo_vmentry);
- break;
- case PSC_TYPE_GROUPS:
- n_type = NT_PROCSTAT_GROUPS;
- structsize = sizeof(gid_t);
- break;
- case PSC_TYPE_UMASK:
- n_type = NT_PROCSTAT_UMASK;
- structsize = sizeof(u_short);
- break;
- case PSC_TYPE_RLIMIT:
- n_type = NT_PROCSTAT_RLIMIT;
- structsize = sizeof(struct rlimit) * RLIM_NLIMITS;
- break;
- case PSC_TYPE_OSREL:
- n_type = NT_PROCSTAT_OSREL;
- structsize = sizeof(int);
- break;
- case PSC_TYPE_PSSTRINGS:
- case PSC_TYPE_ARGV:
- case PSC_TYPE_ENVV:
- n_type = NT_PROCSTAT_PSSTRINGS;
- structsize = sizeof(vm_offset_t);
- break;
- case PSC_TYPE_AUXV:
- n_type = NT_PROCSTAT_AUXV;
- structsize = sizeof(Elf_Auxinfo);
- break;
- default:
+ if (type >= PSC_TYPE_MAX) {
warnx("unknown core stat type: %d", type);
return (NULL);
}
offset = core->pc_phdr.p_offset;
eoffset = offset + core->pc_phdr.p_filesz;
+ curlen = 0;
while (offset < eoffset) {
if (!core_offset(core, offset))
@@ -220,7 +201,7 @@ procstat_core_get(struct procstat_core *core, enum psc_type type, void *buf,
if (nhdr.n_namesz == 0 && nhdr.n_descsz == 0)
break;
- if (nhdr.n_type != n_type)
+ if (nhdr.n_type != psc_type_info[type].n_type)
continue;
if (nhdr.n_namesz != 8)
continue;
@@ -234,7 +215,7 @@ procstat_core_get(struct procstat_core *core, enum psc_type type, void *buf,
}
if (!core_read(core, &cstructsize, sizeof(cstructsize)))
return (NULL);
- if (cstructsize != structsize) {
+ if (cstructsize != psc_type_info[type].structsize) {
warnx("version mismatch");
return (NULL);
}
@@ -251,7 +232,7 @@ procstat_core_get(struct procstat_core *core, enum psc_type type, void *buf,
return (NULL);
}
}
- if (!core_read(core, buf, len)) {
+ if (!core_read(core, (char *)buf + curlen, len)) {
free(freebuf);
return (NULL);
}
@@ -267,11 +248,20 @@ procstat_core_get(struct procstat_core *core, enum psc_type type, void *buf,
buf = NULL;
free(freebuf);
buf = get_args(core, psstrings, type, buf, &len);
+ } else if (type == PSC_TYPE_PTLWPINFO) {
+ *lenp -= len;
+ curlen += len;
+ continue;
}
*lenp = len;
return (buf);
}
+ if (curlen != 0) {
+ *lenp = curlen;
+ return (buf);
+ }
+
return (NULL);
}
@@ -431,3 +421,57 @@ done:
free(argv);
return (args);
}
+
+int
+procstat_core_note_count(struct procstat_core *core, enum psc_type type)
+{
+ Elf_Note nhdr;
+ off_t offset, eoffset;
+ int cstructsize;
+ char nbuf[8];
+ int n;
+
+ if (type >= PSC_TYPE_MAX) {
+ warnx("unknown core stat type: %d", type);
+ return (0);
+ }
+
+ offset = core->pc_phdr.p_offset;
+ eoffset = offset + core->pc_phdr.p_filesz;
+
+ for (n = 0; offset < eoffset; n++) {
+ if (!core_offset(core, offset))
+ return (0);
+ if (!core_read(core, &nhdr, sizeof(nhdr)))
+ return (0);
+
+ offset += sizeof(nhdr) +
+ roundup2(nhdr.n_namesz, sizeof(Elf32_Size)) +
+ roundup2(nhdr.n_descsz, sizeof(Elf32_Size));
+
+ if (nhdr.n_namesz == 0 && nhdr.n_descsz == 0)
+ break;
+ if (nhdr.n_type != psc_type_info[type].n_type)
+ continue;
+ if (nhdr.n_namesz != 8)
+ continue;
+ if (!core_read(core, nbuf, sizeof(nbuf)))
+ return (0);
+ if (strcmp(nbuf, "FreeBSD") != 0)
+ continue;
+ if (nhdr.n_descsz < sizeof(cstructsize)) {
+ warnx("corrupted core file");
+ return (0);
+ }
+ if (!core_read(core, &cstructsize, sizeof(cstructsize)))
+ return (0);
+ if (cstructsize != psc_type_info[type].structsize) {
+ warnx("version mismatch");
+ return (0);
+ }
+ if (nhdr.n_descsz - sizeof(cstructsize) == 0)
+ return (0);
+ }
+
+ return (n);
+}
diff --git a/lib/libprocstat/core.h b/lib/libprocstat/core.h
index 6639abce174d..701697be0541 100644
--- a/lib/libprocstat/core.h
+++ b/lib/libprocstat/core.h
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2013 Mikolaj Golub <trociny@FreeBSD.org>
+ * Copyright (c) 2017 Dell EMC
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -41,6 +42,8 @@ enum psc_type {
PSC_TYPE_ARGV,
PSC_TYPE_ENVV,
PSC_TYPE_AUXV,
+ PSC_TYPE_PTLWPINFO,
+ PSC_TYPE_MAX
};
struct procstat_core;
@@ -48,6 +51,7 @@ struct procstat_core;
void procstat_core_close(struct procstat_core *core);
void *procstat_core_get(struct procstat_core *core, enum psc_type type,
void * buf, size_t *lenp);
+int procstat_core_note_count(struct procstat_core *core, enum psc_type type);
struct procstat_core *procstat_core_open(const char *filename);
#endif /* !_CORE_H_ */
diff --git a/lib/libprocstat/libprocstat.c b/lib/libprocstat/libprocstat.c
index 85dcec07015d..b81811408799 100644
--- a/lib/libprocstat/libprocstat.c
+++ b/lib/libprocstat/libprocstat.c
@@ -1,4 +1,5 @@
/*-
+ * Copyright (c) 2017 Dell EMC
* Copyright (c) 2009 Stanislav Sedov <stas@FreeBSD.org>
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
@@ -65,6 +66,7 @@ __FBSDID("$FreeBSD$");
#define _KERNEL
#include <sys/mount.h>
#include <sys/pipe.h>
+#include <sys/ptrace.h>
#include <ufs/ufs/quota.h>
#include <ufs/ufs/inode.h>
#include <fs/devfs/devfs.h>
@@ -2470,6 +2472,48 @@ procstat_freeauxv(struct procstat *procstat __unused, Elf_Auxinfo *auxv)
free(auxv);
}
+static struct ptrace_lwpinfo *
+procstat_getptlwpinfo_core(struct procstat_core *core, unsigned int *cntp)
+{
+ void *buf;
+ struct ptrace_lwpinfo *pl;
+ unsigned int cnt;
+ size_t len;
+
+ cnt = procstat_core_note_count(core, PSC_TYPE_PTLWPINFO);
+ if (cnt == 0)
+ return (NULL);
+
+ len = cnt * sizeof(*pl);
+ buf = calloc(1, len);
+ pl = procstat_core_get(core, PSC_TYPE_PTLWPINFO, buf, &len);
+ if (pl == NULL) {
+ free(buf);
+ return (NULL);
+ }
+ *cntp = len / sizeof(*pl);
+ return (pl);
+}
+
+struct ptrace_lwpinfo *
+procstat_getptlwpinfo(struct procstat *procstat, unsigned int *cntp)
+{
+ switch (procstat->type) {
+ case PROCSTAT_CORE:
+ return (procstat_getptlwpinfo_core(procstat->core, cntp));
+ default:
+ warnx("unknown access method: %d", procstat->type);
+ return (NULL);
+ }
+}
+
+void
+procstat_freeptlwpinfo(struct procstat *procstat __unused,
+ struct ptrace_lwpinfo *pl)
+{
+ free(pl);
+}
+
static struct kinfo_kstack *
procstat_getkstack_sysctl(pid_t pid, int *cntp)
{
diff --git a/lib/libprocstat/libprocstat.h b/lib/libprocstat/libprocstat.h
index 7af6ccba14a2..00b6f1c1c110 100644
--- a/lib/libprocstat/libprocstat.h
+++ b/lib/libprocstat/libprocstat.h
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2009 Stanislav Sedov <stas@FreeBSD.org>
+ * Copyright (c) 2017 Dell EMC
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -101,6 +102,7 @@
struct kinfo_kstack;
struct kinfo_vmentry;
struct procstat;
+struct ptrace_lwpinfo;
struct rlimit;
struct filestat {
int fs_type; /* Descriptor type. */
@@ -172,6 +174,8 @@ void procstat_freekstack(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_freeptlwpinfo(struct procstat *procstat,
+ struct ptrace_lwpinfo *pl);
void procstat_freevmmap(struct procstat *procstat,
struct kinfo_vmentry *vmmap);
struct filestat_list *procstat_getfiles(struct procstat *procstat,
@@ -196,6 +200,8 @@ char **procstat_getargv(struct procstat *procstat, struct kinfo_proc *p,
Elf_Auxinfo *procstat_getauxv(struct procstat *procstat,
struct kinfo_proc *kp, unsigned int *cntp);
#endif
+struct ptrace_lwpinfo *procstat_getptlwpinfo(struct procstat *procstat,
+ unsigned int *cntp);
char **procstat_getenvv(struct procstat *procstat, struct kinfo_proc *p,
size_t nchr);
gid_t *procstat_getgroups(struct procstat *procstat, struct kinfo_proc *kp,
diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c
index ad5c3acf4dd9..dedc3660e172 100644
--- a/sys/kern/imgact_elf.c
+++ b/sys/kern/imgact_elf.c
@@ -1,4 +1,5 @@
/*-
+ * Copyright (c) 2017 Dell EMC
* Copyright (c) 2000 David O'Brien
* Copyright (c) 1995-1996 Søren Schmidt
* Copyright (c) 1996 Peter Wemm
@@ -52,6 +53,7 @@ __FBSDID("$FreeBSD$");
#include <sys/pioctl.h>
#include <sys/proc.h>
#include <sys/procfs.h>
+#include <sys/ptrace.h>
#include <sys/racct.h>
#include <sys/resourcevar.h>
#include <sys/rwlock.h>
@@ -1202,6 +1204,7 @@ static void __elfN(note_prpsinfo)(void *, struct sbuf *, size_t *);
static void __elfN(note_prstatus)(void *, struct sbuf *, size_t *);
static void __elfN(note_threadmd)(void *, struct sbuf *, size_t *);
static void __elfN(note_thrmisc)(void *, struct sbuf *, size_t *);
+static void __elfN(note_ptlwpinfo)(void *, struct sbuf *, size_t *);
static void __elfN(note_procstat_auxv)(void *, struct sbuf *, size_t *);
static void __elfN(note_procstat_proc)(void *, struct sbuf *, size_t *);
static void __elfN(note_procstat_psstrings)(void *, struct sbuf *, size_t *);
@@ -1628,6 +1631,8 @@ __elfN(prepare_notes)(struct thread *td, struct note_info_list *list,
__elfN(note_fpregset), thr);
size += register_note(list, NT_THRMISC,
__elfN(note_thrmisc), thr);
+ size += register_note(list, NT_PTLWPINFO,
+ __elfN(note_ptlwpinfo), thr);
size += register_note(list, -1,
__elfN(note_threadmd), thr);
@@ -2018,6 +2023,37 @@ __elfN(note_thrmisc)(void *arg, struct sbuf *sb, size_t *sizep)
*sizep = sizeof(thrmisc);
}
+static void
+__elfN(note_ptlwpinfo)(void *arg, struct sbuf *sb, size_t *sizep)
+{
+ struct thread *td;
+ size_t size;
+ int structsize;
+ struct ptrace_lwpinfo pl;
+
+ td = (struct thread *)arg;
+ size = sizeof(structsize) + sizeof(struct ptrace_lwpinfo);
+ if (sb != NULL) {
+ KASSERT(*sizep == size, ("invalid size"));
+ structsize = sizeof(struct ptrace_lwpinfo);
+ sbuf_bcat(sb, &structsize, sizeof(structsize));
+ bzero(&pl, sizeof(pl));
+ pl.pl_lwpid = td->td_tid;
+ pl.pl_event = PL_EVENT_NONE;
+ pl.pl_sigmask = td->td_sigmask;
+ pl.pl_siglist = td->td_siglist;
+ if (td->td_si.si_signo != 0) {
+ pl.pl_event = PL_EVENT_SIGNAL;
+ pl.pl_flags |= PL_FLAG_SI;
+ pl.pl_siginfo = td->td_si;
+ }
+ strcpy(pl.pl_tdname, td->td_name);
+ /* XXX TODO: supply more information in struct ptrace_lwpinfo*/
+ sbuf_bcat(sb, &pl, sizeof(struct ptrace_lwpinfo));
+ }
+ *sizep = size;
+}
+
/*
* Allow for MD specific notes, as well as any MD
* specific preparations for writing MI notes.
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index 6f102ceb6c68..e43cd6b8482f 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -1226,6 +1226,19 @@ sys_sigwaitinfo(struct thread *td, struct sigwaitinfo_args *uap)
return (error);
}
+static void
+proc_td_siginfo_capture(struct thread *td, siginfo_t *si)
+{
+ struct thread *thr;
+
+ FOREACH_THREAD_IN_PROC(td->td_proc, thr) {
+ if (thr == td)
+ thr->td_si = *si;
+ else
+ thr->td_si.si_signo = 0;
+ }
+}
+
int
kern_sigtimedwait(struct thread *td, sigset_t waitset, ksiginfo_t *ksi,
struct timespec *timeout)
@@ -1334,8 +1347,10 @@ kern_sigtimedwait(struct thread *td, sigset_t waitset, ksiginfo_t *ksi,
ktrpsig(sig, action, &td->td_sigmask, ksi->ksi_code);
}
#endif
- if (sig == SIGKILL)
+ if (sig == SIGKILL) {
+ proc_td_siginfo_capture(td, &ksi->ksi_info);
sigexit(td, sig);
+ }
}
PROC_UNLOCK(p);
return (error);
@@ -2756,6 +2771,7 @@ issignal(struct thread *td)
struct sigqueue *queue;
sigset_t sigpending;
int sig, prop;
+ ksiginfo_t ksi;
p = td->td_proc;
ps = p->p_sigacts;
@@ -2811,14 +2827,15 @@ issignal(struct thread *td)
* be thrown away.
*/
queue = &td->td_sigqueue;
- td->td_dbgksi.ksi_signo = 0;
- if (sigqueue_get(queue, sig, &td->td_dbgksi) == 0) {
+ ksiginfo_init(&ksi);
+ if (sigqueue_get(queue, sig, &ksi) == 0) {
queue = &p->p_sigqueue;
- sigqueue_get(queue, sig, &td->td_dbgksi);
+ sigqueue_get(queue, sig, &ksi);
}
+ td->td_si = ksi.ksi_info;
mtx_unlock(&ps->ps_mtx);
- sig = ptracestop(td, sig, &td->td_dbgksi);
+ sig = ptracestop(td, sig, &ksi);
mtx_lock(&ps->ps_mtx);
/*
@@ -2989,6 +3006,7 @@ postsig(sig)
* the process. (Other cases were ignored above.)
*/
mtx_unlock(&ps->ps_mtx);
+ proc_td_siginfo_capture(td, &ksi.ksi_info);
sigexit(td, sig);
/* NOTREACHED */
} else {
diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c
index ded874ac9819..7bb167a14ef2 100644
--- a/sys/kern/sys_process.c
+++ b/sys/kern/sys_process.c
@@ -1306,7 +1306,7 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
pl->pl_flags = 0;
if (td2->td_dbgflags & TDB_XSIG) {
pl->pl_event = PL_EVENT_SIGNAL;
- if (td2->td_dbgksi.ksi_signo != 0 &&
+ if (td2->td_si.si_signo != 0 &&
#ifdef COMPAT_FREEBSD32
((!wrap32 && data >= offsetof(struct ptrace_lwpinfo,
pl_siginfo) + sizeof(pl->pl_siginfo)) ||
@@ -1318,7 +1318,7 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
#endif
){
pl->pl_flags |= PL_FLAG_SI;
- pl->pl_siginfo = td2->td_dbgksi.ksi_info;
+ pl->pl_siginfo = td2->td_si;
}
}
if ((pl->pl_flags & PL_FLAG_SI) == 0)
diff --git a/sys/sys/elf_common.h b/sys/sys/elf_common.h
index e8a8709f37ef..90e9de640802 100644
--- a/sys/sys/elf_common.h
+++ b/sys/sys/elf_common.h
@@ -1,4 +1,5 @@
/*-
+ * Copyright (c) 2017 Dell EMC
* Copyright (c) 2000, 2001, 2008, 2011, David E. O'Brien
* Copyright (c) 1998 John D. Polstra.
* All rights reserved.
@@ -753,6 +754,7 @@ typedef struct {
#define NT_PROCSTAT_OSREL 14 /* Procstat osreldate data. */
#define NT_PROCSTAT_PSSTRINGS 15 /* Procstat ps_strings data. */
#define NT_PROCSTAT_AUXV 16 /* Procstat auxv data. */
+#define NT_PTLWPINFO 17 /* Thread ptrace miscellaneous info. */
#define NT_PPC_VMX 0x100 /* PowerPC Altivec/VMX registers */
#define NT_X86_XSTATE 0x202 /* x86 XSAVE extended state. */
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index ba308862aa53..0362552cf923 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -274,7 +274,7 @@ struct thread {
char td_name[MAXCOMLEN + 1]; /* (*) Thread name. */
struct file *td_fpop; /* (k) file referencing cdev under op */
int td_dbgflags; /* (c) Userland debugger flags */
- struct ksiginfo td_dbgksi; /* (c) ksi reflected to debugger. */
+ siginfo_t td_si; /* (c) For debugger or core file */
int td_ng_outbound; /* (k) Thread entered ng from above. */
struct osd td_osd; /* (k) Object specific data. */
struct vm_map_entry *td_map_def_user; /* (k) Deferred entries. */
diff --git a/usr.bin/gcore/elfcore.c b/usr.bin/gcore/elfcore.c
index 2a5a328d41ce..f32ff4270406 100644
--- a/usr.bin/gcore/elfcore.c
+++ b/usr.bin/gcore/elfcore.c
@@ -1,4 +1,5 @@
/*-
+ * Copyright (c) 2017 Dell EMC
* Copyright (c) 2007 Sandvine Incorporated
* Copyright (c) 1998 John D. Polstra
* All rights reserved.
@@ -102,6 +103,7 @@ static void *elf_note_fpregset(void *, size_t *);
static void *elf_note_prpsinfo(void *, size_t *);
static void *elf_note_prstatus(void *, size_t *);
static void *elf_note_thrmisc(void *, size_t *);
+static void *elf_note_ptlwpinfo(void *, size_t *);
#if defined(__i386__) || defined(__amd64__)
static void *elf_note_x86_xstate(void *, size_t *);
#endif
@@ -360,6 +362,7 @@ elf_putnotes(pid_t pid, struct sbuf *sb, size_t *sizep)
elf_putnote(NT_PRSTATUS, elf_note_prstatus, tids + i, sb);
elf_putnote(NT_FPREGSET, elf_note_fpregset, tids + i, sb);
elf_putnote(NT_THRMISC, elf_note_thrmisc, tids + i, sb);
+ elf_putnote(NT_PTLWPINFO, elf_note_ptlwpinfo, tids + i, sb);
#if defined(__i386__) || defined(__amd64__)
elf_putnote(NT_X86_XSTATE, elf_note_x86_xstate, tids + i, sb);
#endif
@@ -689,6 +692,24 @@ elf_note_thrmisc(void *arg, size_t *sizep)
return (thrmisc);
}
+static void *
+elf_note_ptlwpinfo(void *arg, size_t *sizep)
+{
+ lwpid_t tid;
+ void *p;
+
+ tid = *(lwpid_t *)arg;
+ p = calloc(1, sizeof(int) + sizeof(struct ptrace_lwpinfo));
+ if (p == NULL)
+ errx(1, "out of memory");
+ *(int *)p = sizeof(struct ptrace_lwpinfo);
+ ptrace(PT_LWPINFO, tid,
+ (char *)p + sizeof (int), sizeof(struct ptrace_lwpinfo));
+
+ *sizep = sizeof(int) + sizeof(struct ptrace_lwpinfo);
+ return (p);
+}
+
#if defined(__i386__) || defined(__amd64__)
static void *
elf_note_x86_xstate(void *arg, size_t *sizep)
diff --git a/usr.bin/procstat/Makefile b/usr.bin/procstat/Makefile
index 21f325f05b2a..7c951966e414 100644
--- a/usr.bin/procstat/Makefile
+++ b/usr.bin/procstat/Makefile
@@ -11,6 +11,7 @@ SRCS= procstat.c \
procstat_cs.c \
procstat_files.c \
procstat_kstack.c \
+ procstat_ptlwpinfo.c \
procstat_rlimit.c \
procstat_rusage.c \
procstat_sigs.c \
diff --git a/usr.bin/procstat/procstat.1 b/usr.bin/procstat/procstat.1
index 68aaaee72f48..5d9c6087e386 100644
--- a/usr.bin/procstat/procstat.1
+++ b/usr.bin/procstat/procstat.1
@@ -36,7 +36,7 @@
.Op Fl -libxo
.Op Fl CHhn
.Op Fl w Ar interval
-.Op Fl b | c | e | f | i | j | k | l | r | s | S | t | v | x
+.Op Fl b | c | e | f | i | j | k | l | L | r | s | S | t | v | x
.Op Fl a | Ar pid | Ar core ...
.Sh DESCRIPTION
The
@@ -79,6 +79,8 @@ If the flag is repeated, function offsets as well as function names are
printed.
.It Fl l
Display resource limits for the process.
+.It Fl L
+Display LWP info for the process pertaining to it's signal driven exit.
.It Fl r
Display resource usage information for the process.
.It Fl s
diff --git a/usr.bin/procstat/procstat.c b/usr.bin/procstat/procstat.c
index 0388ba01e6af..7a27af0f1556 100644
--- a/usr.bin/procstat/procstat.c
+++ b/usr.bin/procstat/procstat.c
@@ -1,6 +1,7 @@
/*-
* Copyright (c) 2007, 2011 Robert N. M. Watson
* Copyright (c) 2015 Allan Jude <allanjude@freebsd.org>
+ * Copyright (c) 2017 Dell EMC
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -41,8 +42,8 @@
#include "procstat.h"
-static int aflag, bflag, cflag, eflag, fflag, iflag, jflag, kflag, lflag, rflag;
-static int sflag, tflag, vflag, xflag, Sflag;
+static int aflag, bflag, cflag, eflag, fflag, iflag, jflag, kflag;
+static int lflag, Lflag, rflag, sflag, tflag, vflag, xflag, Sflag;
int hflag, nflag, Cflag, Hflag;
static void
@@ -84,6 +85,8 @@ procstat(struct procstat *prstat, struct kinfo_proc *kipp)
procstat_kstack(prstat, kipp, kflag);
else if (lflag)
procstat_rlimit(prstat, kipp);
+ else if (Lflag)
+ procstat_ptlwpinfo(prstat);
else if (rflag)
procstat_rusage(prstat, kipp);
else if (sflag)
@@ -161,7 +164,7 @@ main(int argc, char *argv[])
argc = xo_parse_args(argc, argv);
xocontainer = "basic";
- while ((ch = getopt(argc, argv, "CHN:M:abcefijklhrsStvw:x")) != -1) {
+ while ((ch = getopt(argc, argv, "CHN:M:abcefijklLhrsStvw:x")) != -1) {
switch (ch) {
case 'C':
Cflag++;
@@ -225,6 +228,11 @@ main(int argc, char *argv[])
xocontainer = "rlimit";
break;
+ case 'L':
+ Lflag++;
+ xocontainer = "ptlwpinfo";
+ break;
+
case 'n':
nflag++;
break;
diff --git a/usr.bin/procstat/procstat.h b/usr.bin/procstat/procstat.h
index 43bd8416d96f..dd35c9c796c7 100644
--- a/usr.bin/procstat/procstat.h
+++ b/usr.bin/procstat/procstat.h
@@ -1,6 +1,7 @@
/*-
* Copyright (c) 2007 Robert N. M. Watson
* Copyright (c) 2015 Allan Jude <allanjude@freebsd.org>
+ * Copyright (c) 2017 Dell EMC
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -50,6 +51,7 @@ void procstat_env(struct procstat *prstat, struct kinfo_proc *kipp);
void procstat_files(struct procstat *prstat, struct kinfo_proc *kipp);
void procstat_kstack(struct procstat *prstat, struct kinfo_proc *kipp,
int kflag);
+void procstat_ptlwpinfo(struct procstat *prstat);
void procstat_rlimit(struct procstat *prstat, struct kinfo_proc *kipp);
void procstat_rusage(struct procstat *prstat, struct kinfo_proc *kipp);
void procstat_sigs(struct procstat *prstat, struct kinfo_proc *kipp);
diff --git a/usr.bin/procstat/procstat_ptlwpinfo.c b/usr.bin/procstat/procstat_ptlwpinfo.c
new file mode 100644
index 000000000000..96068df8f8a7
--- /dev/null
+++ b/usr.bin/procstat/procstat_ptlwpinfo.c
@@ -0,0 +1,91 @@
+/*-
+ * Copyright (c) 2017 Dell EMC
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+ #include <sys/cdefs.h>
+ __FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/ptrace.h>
+#include <sys/user.h>
+
+#include <libprocstat.h>
+
+#include "procstat.h"
+
+void
+procstat_ptlwpinfo(struct procstat *prstat)
+{
+ struct ptrace_lwpinfo *pl;
+ unsigned int count, i;
+
+ pl = procstat_getptlwpinfo(prstat, &count);
+ if (pl == NULL)
+ return;
+
+ if (!hflag)
+ xo_emit("{:/%6s %7s %5s %5s %5s %6s %5s} {[:/%d}{:/%s}{]:}"
+ " {:/%s}\n",
+ "LWPID", "EVENT", "SIGNO", "CODE", "ERRNO", "PID", "UID",
+ 2 * sizeof(void *) + 2, "ADDR", "TDNAME");
+
+ for (i = 0; i < count; i++) {
+ xo_emit("{:lpwid/%6d} ", pl[i].pl_lwpid);
+ switch (pl[i].pl_event) {
+ case PL_EVENT_NONE:
+ xo_emit("{eq:event/none}{d:event/%7s} ", "none");
+ break;
+ case PL_EVENT_SIGNAL:
+ xo_emit("{eq:event/signal}{d:event/%7s} ", "signal");
+ break;
+ default:
+ xo_emit("{eq:event/unknown}{d:event/%7s} ", "?");
+ break;
+ }
+ if ((pl[i].pl_flags & PL_FLAG_SI) != 0) {
+ siginfo_t *si;
+
+ si = &pl[i].pl_siginfo;
+ xo_emit("{:signal_number/%5d} ", si->si_signo);
+ xo_emit("{:code/%5d} ", si->si_code);
+ xo_emit("{:signal_errno/%5d} ", si->si_errno);
+ xo_emit("{:process_id/%6d} ", si->si_pid);
+ xo_emit("{:user_id/%5d} ", si->si_uid);
+ xo_emit("{[:/%d}{:address/%p}{]:} ",
+ 2 * sizeof(void *) + 2, si->si_addr);
+ } else {
+ xo_emit("{:signal_number/%5s} ", "-");
+ xo_emit("{:code/%5s} ", "-");
+ xo_emit("{:signal_errno/%5s} ", "-");
+ xo_emit("{:process_id/%6s} ", "-");
+ xo_emit("{:user_id/%5s} ", "-");
+ xo_emit("{[:/%d}{:address/%s}{]:} ",
+ 2 * sizeof(void *) + 2, "-");
+ }
+ xo_emit("{:tdname/%s}\n", pl[i].pl_tdname);
+ }
+
+ procstat_freeptlwpinfo(prstat, pl);
+}