diff options
Diffstat (limited to 'usr/src/lib')
-rw-r--r-- | usr/src/lib/libproc/common/Pcontrol.h | 4 | ||||
-rw-r--r-- | usr/src/lib/libproc/common/Pcore.c | 106 | ||||
-rw-r--r-- | usr/src/lib/libproc/common/Pgcore.c | 23 | ||||
-rw-r--r-- | usr/src/lib/libproc/common/Plwpregs.c | 37 | ||||
-rw-r--r-- | usr/src/lib/libproc/common/Psyscall.c | 18 | ||||
-rw-r--r-- | usr/src/lib/libproc/common/libproc.h | 2 | ||||
-rw-r--r-- | usr/src/lib/libproc/common/mapfile-vers | 2 |
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; |