summaryrefslogtreecommitdiff
path: root/usr/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib')
-rw-r--r--usr/src/lib/libproc/common/Pcontrol.h4
-rw-r--r--usr/src/lib/libproc/common/Pcore.c106
-rw-r--r--usr/src/lib/libproc/common/Pgcore.c23
-rw-r--r--usr/src/lib/libproc/common/Plwpregs.c37
-rw-r--r--usr/src/lib/libproc/common/Psyscall.c18
-rw-r--r--usr/src/lib/libproc/common/libproc.h2
-rw-r--r--usr/src/lib/libproc/common/mapfile-vers2
7 files changed, 176 insertions, 16 deletions
diff --git a/usr/src/lib/libproc/common/Pcontrol.h b/usr/src/lib/libproc/common/Pcontrol.h
index 4774093b6d..4bb7e0ca3c 100644
--- a/usr/src/lib/libproc/common/Pcontrol.h
+++ b/usr/src/lib/libproc/common/Pcontrol.h
@@ -24,6 +24,7 @@
*/
/*
* Copyright 2012 DEY Storage Systems, Inc. All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
*/
#ifndef _PCONTROL_H
@@ -233,6 +234,9 @@ struct ps_prochandle {
char *zoneroot; /* cached path to zone root */
plist_t fd_head; /* head of file desc info list */
int num_fd; /* number of file descs in list */
+ uintptr_t map_missing; /* first missing mapping in core due to sig */
+ siginfo_t killinfo; /* signal that interrupted core dump */
+ psinfo_t spymaster; /* agent LWP's spymaster, if any */
};
/* flags */
diff --git a/usr/src/lib/libproc/common/Pcore.c b/usr/src/lib/libproc/common/Pcore.c
index 3e0350eb04..e16e019ab9 100644
--- a/usr/src/lib/libproc/common/Pcore.c
+++ b/usr/src/lib/libproc/common/Pcore.c
@@ -24,11 +24,13 @@
*/
/*
* Copyright 2012 DEY Storage Systems, Inc. All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
*/
#include <sys/types.h>
#include <sys/utsname.h>
#include <sys/sysmacros.h>
+#include <sys/proc.h>
#include <alloca.h>
#include <rtld_db.h>
@@ -40,6 +42,7 @@
#include <errno.h>
#include <gelf.h>
#include <stddef.h>
+#include <signal.h>
#include "libproc.h"
#include "Pcontrol.h"
@@ -672,6 +675,35 @@ note_asrs(struct ps_prochandle *P, size_t nbytes)
#endif /* __sparcv9 */
#endif /* __sparc */
+static int
+note_spymaster(struct ps_prochandle *P, size_t nbytes)
+{
+#ifdef _LP64
+ if (P->core->core_dmodel == PR_MODEL_ILP32) {
+ psinfo32_t ps32;
+
+ if (nbytes < sizeof (psinfo32_t) ||
+ read(P->asfd, &ps32, sizeof (ps32)) != sizeof (ps32))
+ goto err;
+
+ psinfo_32_to_n(&ps32, &P->spymaster);
+ } else
+#endif
+ if (nbytes < sizeof (psinfo_t) || read(P->asfd,
+ &P->spymaster, sizeof (psinfo_t)) != sizeof (psinfo_t))
+ goto err;
+
+ dprintf("spymaster pr_fname = <%s>\n", P->psinfo.pr_fname);
+ dprintf("spymaster pr_psargs = <%s>\n", P->psinfo.pr_psargs);
+ dprintf("spymaster pr_wstat = 0x%x\n", P->psinfo.pr_wstat);
+
+ return (0);
+
+err:
+ dprintf("Pgrab_core: failed to read NT_SPYMASTER\n");
+ return (-1);
+}
+
/*ARGSUSED*/
static int
note_notsup(struct ps_prochandle *P, size_t nbytes)
@@ -725,8 +757,72 @@ static int (*nhdlrs[])(struct ps_prochandle *, size_t) = {
note_content, /* 20 NT_CONTENT */
note_zonename, /* 21 NT_ZONENAME */
note_fdinfo, /* 22 NT_FDINFO */
+ note_spymaster, /* 23 NT_SPYMASTER */
};
+static void
+core_report_mapping(struct ps_prochandle *P, GElf_Phdr *php)
+{
+ prkillinfo_t killinfo;
+ siginfo_t *si = &killinfo.prk_info;
+ char signame[SIG2STR_MAX], sig[64], info[64];
+ void *addr = (void *)(uintptr_t)php->p_vaddr;
+
+ const char *errfmt = "core file data for mapping at %p not saved: %s\n";
+ const char *incfmt = "core file incomplete due to %s%s\n";
+ const char *msgfmt = "mappings at and above %p are missing\n";
+
+ if (!(php->p_flags & PF_SUNW_KILLED)) {
+ int err = 0;
+
+ (void) pread64(P->asfd, &err,
+ sizeof (err), (off64_t)php->p_offset);
+
+ Perror_printf(P, errfmt, addr, strerror(err));
+ dprintf(errfmt, addr, strerror(err));
+ return;
+ }
+
+ if (!(php->p_flags & PF_SUNW_SIGINFO))
+ return;
+
+ (void) memset(&killinfo, 0, sizeof (killinfo));
+
+ (void) pread64(P->asfd, &killinfo,
+ sizeof (killinfo), (off64_t)php->p_offset);
+
+ /*
+ * While there is (or at least should be) only one segment that has
+ * PF_SUNW_SIGINFO set, the signal information there is globally
+ * useful (even if only to those debugging libproc consumers); we hang
+ * the signal information gleaned here off of the ps_prochandle.
+ */
+ P->map_missing = php->p_vaddr;
+ P->killinfo = killinfo.prk_info;
+
+ if (sig2str(si->si_signo, signame) == -1) {
+ (void) snprintf(sig, sizeof (sig),
+ "<Unknown signal: 0x%x>, ", si->si_signo);
+ } else {
+ (void) snprintf(sig, sizeof (sig), "SIG%s, ", signame);
+ }
+
+ if (si->si_code == SI_USER || si->si_code == SI_QUEUE) {
+ (void) snprintf(info, sizeof (info),
+ "pid=%d uid=%d zone=%d ctid=%d",
+ si->si_pid, si->si_uid, si->si_zoneid, si->si_ctid);
+ } else {
+ (void) snprintf(info, sizeof (info),
+ "code=%d", si->si_code);
+ }
+
+ Perror_printf(P, incfmt, sig, info);
+ Perror_printf(P, msgfmt, addr);
+
+ dprintf(incfmt, sig, info);
+ dprintf(msgfmt, addr);
+}
+
/*
* Add information on the address space mapping described by the given
* PT_LOAD program header. We fill in more information on the mapping later.
@@ -734,7 +830,6 @@ static int (*nhdlrs[])(struct ps_prochandle *, size_t) = {
static int
core_add_mapping(struct ps_prochandle *P, GElf_Phdr *php)
{
- int err = 0;
prmap_t pmap;
dprintf("mapping base %llx filesz %llu memsz %llu offset %llu\n",
@@ -749,14 +844,7 @@ core_add_mapping(struct ps_prochandle *P, GElf_Phdr *php)
* PF_SUNW_FAILURE in the Phdr and try to stash away the errno for us.
*/
if (php->p_flags & PF_SUNW_FAILURE) {
- (void) pread64(P->asfd, &err,
- sizeof (err), (off64_t)php->p_offset);
-
- Perror_printf(P, "core file data for mapping at %p not saved: "
- "%s\n", (void *)(uintptr_t)php->p_vaddr, strerror(err));
- dprintf("core file data for mapping at %p not saved: %s\n",
- (void *)(uintptr_t)php->p_vaddr, strerror(err));
-
+ core_report_mapping(P, php);
} else if (php->p_filesz != 0 && php->p_offset >= P->core->core_size) {
Perror_printf(P, "core file may be corrupt -- data for mapping "
"at %p is missing\n", (void *)(uintptr_t)php->p_vaddr);
diff --git a/usr/src/lib/libproc/common/Pgcore.c b/usr/src/lib/libproc/common/Pgcore.c
index f409e96259..2b5ec7c9bd 100644
--- a/usr/src/lib/libproc/common/Pgcore.c
+++ b/usr/src/lib/libproc/common/Pgcore.c
@@ -25,6 +25,7 @@
*/
/*
* Copyright 2012 DEY Storage Systems, Inc. All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
*/
#define _STRUCTURED_PROC 1
@@ -481,6 +482,7 @@ new_per_lwp(void *data, const lwpstatus_t *lsp, const lwpsinfo_t *lip)
{
pgcore_t *pgc = data;
struct ps_prochandle *P = pgc->P;
+ psinfo_t ps;
/*
* If lsp is NULL this indicates that this is a zombie LWP in
@@ -548,6 +550,27 @@ new_per_lwp(void *data, const lwpstatus_t *lsp, const lwpsinfo_t *lip)
#endif /* __sparcv9 */
#endif /* sparc */
+ if (!(lsp->pr_flags & PR_AGENT))
+ return (0);
+
+ if (Plwp_getspymaster(P, lsp->pr_lwpid, &ps) != 0)
+ return (0);
+
+ if (P->status.pr_dmodel == PR_MODEL_NATIVE) {
+ if (write_note(pgc->pgc_fd, NT_SPYMASTER, &ps,
+ sizeof (psinfo_t), pgc->pgc_doff) != 0)
+ return (1);
+#ifdef _LP64
+ } else {
+ psinfo32_t ps32;
+ psinfo_n_to_32(&ps, &ps32);
+ if (write_note(pgc->pgc_fd, NT_SPYMASTER, &ps32,
+ sizeof (psinfo32_t), pgc->pgc_doff) != 0)
+ return (1);
+#endif /* _LP64 */
+ }
+
+
return (0);
}
diff --git a/usr/src/lib/libproc/common/Plwpregs.c b/usr/src/lib/libproc/common/Plwpregs.c
index 76f658a458..7549bc142d 100644
--- a/usr/src/lib/libproc/common/Plwpregs.c
+++ b/usr/src/lib/libproc/common/Plwpregs.c
@@ -23,7 +23,9 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ */
#include <sys/types.h>
#include <sys/uio.h>
@@ -349,6 +351,39 @@ Plwp_getpsinfo(struct ps_prochandle *P, lwpid_t lwpid, lwpsinfo_t *lps)
}
int
+Plwp_getspymaster(struct ps_prochandle *P, lwpid_t lwpid, psinfo_t *ps)
+{
+ lwpstatus_t lps;
+
+ if (P->state == PS_IDLE) {
+ errno = ENODATA;
+ return (-1);
+ }
+
+ if (getlwpstatus(P, lwpid, &lps) != 0)
+ return (-1);
+
+ if (!(lps.pr_flags & PR_AGENT)) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (P->state != PS_DEAD) {
+ return (getlwpfile(P, lwpid, "spymaster",
+ ps, sizeof (psinfo_t)));
+ }
+
+ if (P->spymaster.pr_nlwp != 0) {
+ (void) memcpy(ps, &P->spymaster, sizeof (psinfo_t));
+ return (0);
+ }
+
+ errno = ENODATA;
+
+ return (-1);
+}
+
+int
Plwp_stack(struct ps_prochandle *P, lwpid_t lwpid, stack_t *stkp)
{
uintptr_t addr;
diff --git a/usr/src/lib/libproc/common/Psyscall.c b/usr/src/lib/libproc/common/Psyscall.c
index a6cc285251..af2f229641 100644
--- a/usr/src/lib/libproc/common/Psyscall.c
+++ b/usr/src/lib/libproc/common/Psyscall.c
@@ -22,8 +22,9 @@
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
+
/*
- * Copyright (c) 2013, Joyent Inc. All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
*/
#include <stdio.h>
@@ -61,7 +62,7 @@ Pabort_agent(struct ps_prochandle *P)
int sysnum = P->status.pr_lwp.pr_syscall;
int stop;
- dprintf("agent LWP is asleep in syscall %d\n", sysnum);
+ dprintf("agent LWP is stopped or asleep in syscall %d\n", sysnum);
(void) Pstop(P, 0);
stop = Psysexit(P, sysnum, TRUE);
@@ -147,11 +148,16 @@ Pcreate_agent(struct ps_prochandle *P)
P->agentctlfd = fd;
/*
- * If the agent is currently asleep in a system call, attempt
- * to abort the system call so it's ready to serve.
+ * If the agent is currently asleep in a system call or stopped on
+ * system call entry, attempt to abort the system call so it's ready to
+ * serve.
*/
- if (P->status.pr_lwp.pr_flags & PR_ASLEEP) {
- dprintf("Pcreate_agent: aborting agent syscall\n");
+ if ((P->status.pr_lwp.pr_flags & PR_ASLEEP) ||
+ ((P->status.pr_lwp.pr_flags & PR_STOPPED) &&
+ P->status.pr_lwp.pr_why == PR_SYSENTRY)) {
+ dprintf("Pcreate_agent: aborting agent syscall; lwp is %s\n",
+ (P->status.pr_lwp.pr_flags & PR_ASLEEP) ?
+ "asleep" : "stopped");
Pabort_agent(P);
}
diff --git a/usr/src/lib/libproc/common/libproc.h b/usr/src/lib/libproc/common/libproc.h
index 1e59b5089f..7cfc80cd7a 100644
--- a/usr/src/lib/libproc/common/libproc.h
+++ b/usr/src/lib/libproc/common/libproc.h
@@ -25,6 +25,7 @@
*
* Portions Copyright 2007 Chad Mynhier
* Copyright 2012 DEY Storage Systems, Inc. All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
*/
/*
@@ -389,6 +390,7 @@ extern int proc_get_ldt(pid_t, struct ssd *, int);
#endif /* __i386 || __amd64 */
extern int Plwp_getpsinfo(struct ps_prochandle *, lwpid_t, lwpsinfo_t *);
+extern int Plwp_getspymaster(struct ps_prochandle *, lwpid_t, psinfo_t *);
extern int Plwp_stack(struct ps_prochandle *, lwpid_t, stack_t *);
extern int Plwp_main_stack(struct ps_prochandle *, lwpid_t, stack_t *);
diff --git a/usr/src/lib/libproc/common/mapfile-vers b/usr/src/lib/libproc/common/mapfile-vers
index 9482a53145..eb91461d98 100644
--- a/usr/src/lib/libproc/common/mapfile-vers
+++ b/usr/src/lib/libproc/common/mapfile-vers
@@ -21,6 +21,7 @@
#
# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
# Copyright 2012 DEY Storage Systems, Inc. All rights reserved.
+# Copyright (c) 2013, Joyent, Inc. All rights reserved.
#
#
@@ -133,6 +134,7 @@ SYMBOL_VERSION SUNWprivate_1.1 {
Plwp_getfpregs;
Plwp_getpsinfo;
Plwp_getregs;
+ Plwp_getspymaster;
Plwp_iter;
Plwp_iter_all;
Plwp_main_stack;