diff options
| author | Bryan Cantrill <bryan@joyent.com> | 2013-04-01 20:37:48 +0000 |
|---|---|---|
| committer | Bryan Cantrill <bryan@joyent.com> | 2013-04-01 21:51:10 +0000 |
| commit | 68ed78e133f47cac73505baee6a6fe41e3931d39 (patch) | |
| tree | 615e78bf3bacfd45189486cb73590d270f78227c /usr/src | |
| parent | 69f1a29c0a273d0df7d94ffad4e08ce6b4b1fc3f (diff) | |
| download | illumos-joyent-68ed78e133f47cac73505baee6a6fe41e3931d39.tar.gz | |
OS-2085 add visibility into agent LWP's spymaster
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Keith Wesolowski <keith.wesolowski@joyent.com>
Diffstat (limited to 'usr/src')
23 files changed, 421 insertions, 19 deletions
diff --git a/usr/src/cmd/ptools/pflags/pflags.c b/usr/src/cmd/ptools/pflags/pflags.c index 9a3c723ed4..4ae6f3c679 100644 --- a/usr/src/cmd/ptools/pflags/pflags.c +++ b/usr/src/cmd/ptools/pflags/pflags.c @@ -24,6 +24,10 @@ * Use is subject to license terms. */ +/* + * Copyright (c) 2013, Joyent, Inc. All rights reserved. + */ + #include <stdio.h> #include <stdio_ext.h> #include <stdlib.h> @@ -258,6 +262,7 @@ lwplook(look_arg_t *arg, const lwpstatus_t *psp, const lwpsinfo_t *pip) int flags; uint32_t sighold, sighold1, sighold2; uint32_t sigpend, sigpend1, sigpend2; + psinfo_t ps; int cursig; char buf[32]; @@ -331,6 +336,17 @@ lwplook(look_arg_t *arg, const lwpstatus_t *psp, const lwpsinfo_t *pip) (void) printf("\tcursig = %s\n", proc_signame(cursig, buf, sizeof (buf))); + if ((flags & PR_AGENT) && + Plwp_getspymaster(Pr, pip->pr_lwpid, &ps) == 0) { + time_t time = ps.pr_time.tv_sec; + char t[64]; + + (void) strftime(t, sizeof (t), "%F:%H.%M.%S", localtime(&time)); + + (void) printf("\tspymaster = pid %d, \"%s\" at %s\n", + ps.pr_pid, ps.pr_psargs, t); + } + if (rflag) { if (Pstate(Pr) == PS_DEAD || (arg->pflags & PR_STOPPED)) { #if defined(__sparc) && defined(_ILP32) diff --git a/usr/src/cmd/sgs/elfdump/common/corenote.c b/usr/src/cmd/sgs/elfdump/common/corenote.c index 243fd12f22..f75056991a 100644 --- a/usr/src/cmd/sgs/elfdump/common/corenote.c +++ b/usr/src/cmd/sgs/elfdump/common/corenote.c @@ -25,6 +25,7 @@ */ /* * Copyright 2012 DEY Storage Systems, Inc. All rights reserved. + * Copyright (c) 2013, Joyent, Inc. All rights reserved. */ #include <stdlib.h> @@ -1437,7 +1438,6 @@ dump_psinfo(note_state_t *state, const char *title) indent_exit(state); } - /* * Output information from prpsinfo_t structure. */ @@ -1849,6 +1849,13 @@ corenote(Half mach, int do_swap, Word type, state.ns_v2col = 54; dump_prfdinfo(&state, MSG_ORIG(MSG_CNOTE_DESC_PRFDINFO_T)); return (CORENOTE_R_OK); + + case NT_SPYMASTER: + state.ns_vcol = 25; + state.ns_t2col = 45; + state.ns_v2col = 58; + dump_psinfo(&state, MSG_ORIG(MSG_CNOTE_DESC_PSINFO_T)); + return (CORENOTE_R_OK); } return (CORENOTE_R_BADTYPE); diff --git a/usr/src/cmd/sgs/libconv/common/corenote.c b/usr/src/cmd/sgs/libconv/common/corenote.c index 352dd3ee70..eb998bae45 100644 --- a/usr/src/cmd/sgs/libconv/common/corenote.c +++ b/usr/src/cmd/sgs/libconv/common/corenote.c @@ -25,6 +25,7 @@ */ /* * Copyright 2012 DEY Storage Systems, Inc. All rights reserved. + * Copyright (c) 2013, Joyent, Inc. All rights reserved. */ /* @@ -55,9 +56,10 @@ conv_cnote_type(Word type, Conv_fmt_flags_t fmt_flags, MSG_NT_UTSNAME, MSG_NT_LWPSTATUS, MSG_NT_LWPSINFO, MSG_NT_PRPRIV, MSG_NT_PRPRIVINFO, MSG_NT_CONTENT, - MSG_NT_ZONENAME, MSG_NT_FDINFO + MSG_NT_ZONENAME, MSG_NT_FDINFO, + MSG_NT_SPYMASTER }; -#if NT_NUM != NT_FDINFO +#if NT_NUM != NT_SPYMASTER #error "NT_NUM has grown. Update core note types[]" #endif static const conv_ds_msg_t ds_types = { diff --git a/usr/src/cmd/sgs/libconv/common/corenote.msg b/usr/src/cmd/sgs/libconv/common/corenote.msg index 36925e1039..f1cc32dfde 100644 --- a/usr/src/cmd/sgs/libconv/common/corenote.msg +++ b/usr/src/cmd/sgs/libconv/common/corenote.msg @@ -24,6 +24,7 @@ # Use is subject to license terms. # # Copyright 2012 DEY Storage Systems, Inc. All rights reserved. +# Copyright (c) 2013, Joyent, Inc. All rights reserved. # @ MSG_NT_PRSTATUS "[ NT_PRSTATUS ]" @@ -46,6 +47,7 @@ @ MSG_NT_CONTENT "[ NT_CONTENT ]" @ MSG_NT_ZONENAME "[ NT_ZONENAME ]" @ MSG_NT_FDINFO "[ NT_FDINFO ]" +@ MSG_NT_SPYMASTER "[ NT_SPYMASTER ]" @ MSG_AUXV_AF_SUN_SETUGID "AF_SUN_SETUGID" diff --git a/usr/src/lib/libproc/common/Pcontrol.h b/usr/src/lib/libproc/common/Pcontrol.h index b3e3dbb930..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 @@ -235,6 +236,7 @@ struct ps_prochandle { 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 4eff92a8d6..e16e019ab9 100644 --- a/usr/src/lib/libproc/common/Pcore.c +++ b/usr/src/lib/libproc/common/Pcore.c @@ -24,6 +24,7 @@ */ /* * Copyright 2012 DEY Storage Systems, Inc. All rights reserved. + * Copyright (c) 2013, Joyent, Inc. All rights reserved. */ #include <sys/types.h> @@ -674,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) @@ -727,6 +757,7 @@ 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 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/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; diff --git a/usr/src/man/man4/core.4 b/usr/src/man/man4/core.4 index 3c773a3a6c..1bec81b38b 100644 --- a/usr/src/man/man4/core.4 +++ b/usr/src/man/man4/core.4 @@ -1,11 +1,12 @@ '\" te .\" Copyright (C) 2008, Sun Microsystems, Inc. All Rights Reserved. .\" Copyright 2012 DEY Storage Systems, Inc. All rights reserved. +.\" Copyright (c) 2013, Joyent, Inc. All rights reserved. .\" Copyright 1989 AT&T .\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License. .\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License. .\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner] -.TH CORE 4 "Oct 23, 2012" +.TH CORE 4 "Mar 31, 2013" .SH NAME core \- process core file .SH DESCRIPTION @@ -438,6 +439,18 @@ registers for the \fBLWP.\fR The \fBasrset_t\fR structure is defined in .RE .sp +.ne 2 +.na +\fB\fBpsinfo_t\fR\fR +.ad +.RS 15n +\fBn_type\fR: \fBNT_SPYMASTER\fR. This entry is present only for an agent +LWP and contains the \fBpsinfo_t\fR of the process that created the agent +LWP. See the \fBproc\fR(4) description of the \fBspymaster\fR entry for +more details. +.RE + +.sp .LP Depending on the \fBcoreadm\fR(1M) settings, the section header of an ELF core file can contain entries for CTF, symbol table, and string table sections. The diff --git a/usr/src/man/man4/proc.4 b/usr/src/man/man4/proc.4 index fa06141ae7..20f2089f5e 100644 --- a/usr/src/man/man4/proc.4 +++ b/usr/src/man/man4/proc.4 @@ -1,10 +1,11 @@ '\" te .\" Copyright 1989 AT&T .\" Copyright (c) 2006, Sun Microsystems, Inc. All Rights Reserved. +.\" Copyright (c) 2013, Joyent, Inc. All rights reserved. .\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License. .\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License. .\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner] -.TH PROC 4 "Nov 29, 2006" +.TH PROC 4 "Mar 31, 2013" .SH NAME proc \- /proc, the process file system .SH DESCRIPTION @@ -1481,7 +1482,7 @@ A directory containing entries each of which names an active or zombie lwp within the process. These entries are themselves directories containing additional files as described below. Only the \fBlwpsinfo\fR file exists in the directory of a zombie lwp. -.SH STRUCTURE OF \fB/proc/\fR\fIpid\fR\fB/lwp/\fR \fIlwpid\fR +.SH STRUCTURE OF \fB/proc/\fR\fIpid\fR\fB/lwp/\fR\fIlwpid\fR .sp .LP A given directory \fB/proc/\fR\fIpid\fR\fB/lwp/\fR\fIlwpid\fR contains the @@ -1538,6 +1539,15 @@ This file exists only for 64-bit SPARC V9 processes. It contains an values of the lwp's platform-dependent ancillary state registers. If the lwp is not stopped, all register values are undefined. See also the \fBPCSASRS\fR control operation, below. +.SS "spymaster" +.sp +.LP +For an agent lwp (see \fBPCAGENT\fR), this file contains a \fBpsinfo_t\fR +structure that corresponds to the process that created the agent lwp at the +time the agent was created. This structure is identical to that retrieved via +the \fBpsinfo\fR file, with one modification: the \fBpr_time\fR field does not +correspond to the CPU time for the process, but rather to the creation time of +the agent lwp. .SS "templates" .sp .LP @@ -2263,6 +2273,16 @@ register values given to the agent lwp on creation are typically the registers of the representative lwp, so that the agent lwp can use its stack. .sp .LP +If the controlling process neglects to force the agent lwp to execute the +\fBSYS_lwp_exit\fR system call (due to either logic error or fatal failure on +the part of the controlling process), the agent lwp will remain in the target +process. For purposes of being able to debug these otherwise rogue agents, +information as to the creator of the agent lwp is reflected in that lwp's +\fBspymaster\fR file in \fB/proc\fR. Should the target process generate a core +dump with the agent lwp in place, this information will be available via the +\fBNT_SPYMASTER\fR note in the core file (see \fBcore\fR(4)). +.sp +.LP The agent lwp is not allowed to execute any variation of the \fBSYS_fork\fR or \fBSYS_exec\fR system call traps. Attempts to do so yield \fBENOTSUP\fR to the agent lwp. @@ -2789,6 +2809,16 @@ extra state registers ancillary state registers (SPARC V9 only) .RE +.sp +.ne 2 +.na +\fB\fB/proc/\fIpid\fR/lwp/\fIlwpid\fR/spymaster\fR\fR +.ad +.sp .6 +.RS 4n +For an agent LWP, the controlling process +.RE + .SH SEE ALSO .sp .LP @@ -2803,8 +2833,8 @@ ancillary state registers (SPARC V9 only) \fBreaddir\fR(3C), \fBpthread_create\fR(3C), \fBpthread_join\fR(3C), \fBsiginfo.h\fR(3HEAD), \fBsignal.h\fR(3HEAD), \fBthr_create\fR(3C), \fBthr_join\fR(3C), \fBtypes32.h\fR(3HEAD), \fBucontext.h\fR(3HEAD), -\fBwait\fR(3C), \fBcontract\fR(4), \fBprocess\fR(4), \fBlfcompile\fR(5), -\fBprivileges\fR(5) +\fBwait\fR(3C), \fBcontract\fR(4), \fBcore\fR(4), \fBprocess\fR(4), +\fBlfcompile\fR(5), \fBprivileges\fR(5) .SH DIAGNOSTICS .sp .LP diff --git a/usr/src/uts/common/exec/elf/elf_notes.c b/usr/src/uts/common/exec/elf/elf_notes.c index 719d215dd5..51db603177 100644 --- a/usr/src/uts/common/exec/elf/elf_notes.c +++ b/usr/src/uts/common/exec/elf/elf_notes.c @@ -26,6 +26,7 @@ /* * Copyright 2012 DEY Storage Systems, Inc. All rights reserved. + * Copyright (c) 2013, Joyent, Inc. All rights reserved. */ #include <sys/types.h> @@ -107,6 +108,11 @@ setup_note_header(Phdr *v, proc_t *p) + nlwp * roundup(sizeof (lwpstatus_t), sizeof (Word)) + nfd * roundup(sizeof (prfdinfo_t), sizeof (Word)); + if (curproc->p_agenttp != NULL) { + v[0].p_filesz += sizeof (Note) + + roundup(sizeof (psinfo_t), sizeof (Word)); + } + size = sizeof (prcred_t) + sizeof (gid_t) * (ngroups_max - 1); pcrp = kmem_alloc(size, KM_SLEEP); prgetcred(p, pcrp); @@ -519,6 +525,31 @@ write_elfnotes(proc_t *p, int sig, vnode_t *vp, offset_t offset, if (error) goto done; } + + if (t->t_lwp->lwp_spymaster != NULL) { + void *psaddr = t->t_lwp->lwp_spymaster; +#ifdef _ELF32_COMPAT + /* + * On a 64-bit kernel with 32-bit ELF compatibility, + * this file is compiled into two different objects: + * one is compiled normally, and the other is compiled + * with _ELF32_COMPAT set -- and therefore with a + * psinfo_t defined to be a psinfo32_t. However, the + * psinfo_t denoting our spymaster is always of the + * native type; if we are in the _ELF32_COMPAT case, + * we need to explicitly convert it. + */ + if (p->p_model == DATAMODEL_ILP32) { + psinfo_kto32(psaddr, &bigwad->psinfo); + psaddr = &bigwad->psinfo; + } +#endif + + error = elfnote(vp, &offset, NT_SPYMASTER, + sizeof (psinfo_t), psaddr, rlimit, credp); + if (error) + goto done; + } } ASSERT(nlwp == 0); diff --git a/usr/src/uts/common/fs/proc/prcontrol.c b/usr/src/uts/common/fs/proc/prcontrol.c index dc95278c0b..d0733b9044 100644 --- a/usr/src/uts/common/fs/proc/prcontrol.c +++ b/usr/src/uts/common/fs/proc/prcontrol.c @@ -25,7 +25,7 @@ */ /* - * Copyright (c) 2012, Joyent, Inc. All rights reserved. + * Copyright (c) 2013, Joyent, Inc. All rights reserved. */ #include <sys/types.h> @@ -2012,6 +2012,23 @@ pr_agent(prnode_t *pnp, prgregset_t prgregset, int *unlocked) return (ENOMEM); } prsetprregs(clwp, prgregset, 1); + + /* + * Because abandoning the agent inside the target process leads to + * a state that is essentially undebuggable, we record the psinfo of + * the process creating the agent and hang that off of the lwp. + */ + clwp->lwp_spymaster = kmem_zalloc(sizeof (psinfo_t), KM_SLEEP); + mutex_enter(&curproc->p_lock); + prgetpsinfo(curproc, clwp->lwp_spymaster); + mutex_exit(&curproc->p_lock); + + /* + * We overload pr_time in the spymaster to denote the time at which the + * agent was created. + */ + gethrestime(&clwp->lwp_spymaster->pr_time); + retry: cid = t->t_cid; (void) CL_ALLOC(&bufp, cid, KM_SLEEP); diff --git a/usr/src/uts/common/fs/proc/prdata.h b/usr/src/uts/common/fs/proc/prdata.h index ce925778f2..6f86282cbd 100644 --- a/usr/src/uts/common/fs/proc/prdata.h +++ b/usr/src/uts/common/fs/proc/prdata.h @@ -24,7 +24,7 @@ */ /* - * Copyright (c) 2012, Joyent, Inc. All rights reserved. + * Copyright (c) 2013, Joyent, Inc. All rights reserved. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ @@ -34,8 +34,6 @@ #ifndef _SYS_PROC_PRDATA_H #define _SYS_PROC_PRDATA_H -#pragma ident "%Z%%M% %I% %E% SMI" - #include <sys/isa_defs.h> #include <sys/proc.h> #include <sys/vnode.h> @@ -145,6 +143,7 @@ typedef enum prnodetype { PR_XREGS, /* /proc/<pid>/lwp/<lwpid>/xregs */ PR_TMPLDIR, /* /proc/<pid>/lwp/<lwpid>/templates */ PR_TMPL, /* /proc/<pid>/lwp/<lwpid>/templates/<id> */ + PR_SPYMASTER, /* /proc/<pid>/lwp/<lwpid>/spymaster */ #if defined(__sparc) PR_GWINDOWS, /* /proc/<pid>/lwp/<lwpid>/gwindows */ PR_ASRS, /* /proc/<pid>/lwp/<lwpid>/asrs */ diff --git a/usr/src/uts/common/fs/proc/prsubr.c b/usr/src/uts/common/fs/proc/prsubr.c index b4daac42b1..7801fd0ac8 100644 --- a/usr/src/uts/common/fs/proc/prsubr.c +++ b/usr/src/uts/common/fs/proc/prsubr.c @@ -21,6 +21,7 @@ /* * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, Joyent, Inc. All rights reserved. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ @@ -2490,6 +2491,7 @@ prgetpsinfo32(proc_t *p, psinfo32_t *psp) psp->pr_envp = 0; } } + #endif /* _SYSCALL32_IMPL */ void @@ -2628,6 +2630,100 @@ prgetlwpsinfo32(kthread_t *t, lwpsinfo32_t *psp) } #endif /* _SYSCALL32_IMPL */ +#ifdef _SYSCALL32_IMPL + +#define PR_COPY_FIELD(s, d, field) d->field = s->field + +#define PR_COPY_FIELD_ILP32(s, d, field) \ + if (s->pr_dmodel == PR_MODEL_ILP32) { \ + d->field = s->field; \ + } + +#define PR_COPY_TIMESPEC(s, d, field) \ + TIMESPEC_TO_TIMESPEC32(&d->field, &s->field); + +#define PR_COPY_BUF(s, d, field) \ + bcopy(s->field, d->field, sizeof (d->field)); + +#define PR_IGNORE_FIELD(s, d, field) + +void +lwpsinfo_kto32(const struct lwpsinfo *src, struct lwpsinfo32 *dest) +{ + bzero(dest, sizeof (*dest)); + + PR_COPY_FIELD(src, dest, pr_flag); + PR_COPY_FIELD(src, dest, pr_lwpid); + PR_IGNORE_FIELD(src, dest, pr_addr); + PR_IGNORE_FIELD(src, dest, pr_wchan); + PR_COPY_FIELD(src, dest, pr_stype); + PR_COPY_FIELD(src, dest, pr_state); + PR_COPY_FIELD(src, dest, pr_sname); + PR_COPY_FIELD(src, dest, pr_nice); + PR_COPY_FIELD(src, dest, pr_syscall); + PR_COPY_FIELD(src, dest, pr_oldpri); + PR_COPY_FIELD(src, dest, pr_cpu); + PR_COPY_FIELD(src, dest, pr_pri); + PR_COPY_FIELD(src, dest, pr_pctcpu); + PR_COPY_TIMESPEC(src, dest, pr_start); + PR_COPY_BUF(src, dest, pr_clname); + PR_COPY_BUF(src, dest, pr_name); + PR_COPY_FIELD(src, dest, pr_onpro); + PR_COPY_FIELD(src, dest, pr_bindpro); + PR_COPY_FIELD(src, dest, pr_bindpset); + PR_COPY_FIELD(src, dest, pr_lgrp); +} + +void +psinfo_kto32(const struct psinfo *src, struct psinfo32 *dest) +{ + bzero(dest, sizeof (*dest)); + + PR_COPY_FIELD(src, dest, pr_flag); + PR_COPY_FIELD(src, dest, pr_nlwp); + PR_COPY_FIELD(src, dest, pr_pid); + PR_COPY_FIELD(src, dest, pr_ppid); + PR_COPY_FIELD(src, dest, pr_pgid); + PR_COPY_FIELD(src, dest, pr_sid); + PR_COPY_FIELD(src, dest, pr_uid); + PR_COPY_FIELD(src, dest, pr_euid); + PR_COPY_FIELD(src, dest, pr_gid); + PR_COPY_FIELD(src, dest, pr_egid); + PR_IGNORE_FIELD(src, dest, pr_addr); + PR_COPY_FIELD_ILP32(src, dest, pr_size); + PR_COPY_FIELD_ILP32(src, dest, pr_rssize); + PR_COPY_FIELD(src, dest, pr_ttydev); + PR_COPY_FIELD(src, dest, pr_pctcpu); + PR_COPY_FIELD(src, dest, pr_pctmem); + PR_COPY_TIMESPEC(src, dest, pr_start); + PR_COPY_TIMESPEC(src, dest, pr_time); + PR_COPY_TIMESPEC(src, dest, pr_ctime); + PR_COPY_BUF(src, dest, pr_fname); + PR_COPY_BUF(src, dest, pr_psargs); + PR_COPY_FIELD(src, dest, pr_wstat); + PR_COPY_FIELD(src, dest, pr_argc); + PR_COPY_FIELD_ILP32(src, dest, pr_argv); + PR_COPY_FIELD_ILP32(src, dest, pr_envp); + PR_COPY_FIELD(src, dest, pr_dmodel); + PR_COPY_FIELD(src, dest, pr_taskid); + PR_COPY_FIELD(src, dest, pr_projid); + PR_COPY_FIELD(src, dest, pr_nzomb); + PR_COPY_FIELD(src, dest, pr_poolid); + PR_COPY_FIELD(src, dest, pr_contract); + PR_COPY_FIELD(src, dest, pr_poolid); + PR_COPY_FIELD(src, dest, pr_poolid); + + lwpsinfo_kto32(&src->pr_lwp, &dest->pr_lwp); +} + +#undef PR_COPY_FIELD +#undef PR_COPY_FIELD_ILP32 +#undef PR_COPY_TIMESPEC +#undef PR_COPY_BUF +#undef PR_IGNORE_FIELD + +#endif /* _SYSCALL32_IMPL */ + /* * This used to get called when microstate accounting was disabled but * microstate information was requested. Since Microstate accounting is on diff --git a/usr/src/uts/common/fs/proc/prvnops.c b/usr/src/uts/common/fs/proc/prvnops.c index 7831c1f9ea..432bda2c66 100644 --- a/usr/src/uts/common/fs/proc/prvnops.c +++ b/usr/src/uts/common/fs/proc/prvnops.c @@ -21,6 +21,7 @@ /* * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, Joyent, Inc. All rights reserved. */ /* @@ -193,10 +194,12 @@ static prdirent_t lwpiddir[] = { "xregs" }, { PR_TMPLDIR, 8 * sizeof (prdirent_t), sizeof (prdirent_t), "templates" }, + { PR_SPYMASTER, 9 * sizeof (prdirent_t), sizeof (prdirent_t), + "spymaster" }, #if defined(__sparc) - { PR_GWINDOWS, 9 * sizeof (prdirent_t), sizeof (prdirent_t), + { PR_GWINDOWS, 10 * sizeof (prdirent_t), sizeof (prdirent_t), "gwindows" }, - { PR_ASRS, 10 * sizeof (prdirent_t), sizeof (prdirent_t), + { PR_ASRS, 11 * sizeof (prdirent_t), sizeof (prdirent_t), "asrs" }, #endif }; @@ -586,6 +589,7 @@ static int pr_read_inval(), pr_read_as(), pr_read_status(), pr_read_usage(), pr_read_lusage(), pr_read_pagedata(), pr_read_watch(), pr_read_lwpstatus(), pr_read_lwpsinfo(), pr_read_lwpusage(), pr_read_xregs(), pr_read_priv(), + pr_read_spymaster(), #if defined(__sparc) pr_read_gwindows(), pr_read_asrs(), #endif @@ -629,6 +633,7 @@ static int (*pr_read_function[PR_NFILES])() = { pr_read_xregs, /* /proc/<pid>/lwp/<lwpid>/xregs */ pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/templates */ pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/templates/<id> */ + pr_read_spymaster, /* /proc/<pid>/lwp/<lwpid>/spymaster */ #if defined(__sparc) pr_read_gwindows, /* /proc/<pid>/lwp/<lwpid>/gwindows */ pr_read_asrs, /* /proc/<pid>/lwp/<lwpid>/asrs */ @@ -1575,6 +1580,31 @@ out: #endif } +static int +pr_read_spymaster(prnode_t *pnp, uio_t *uiop) +{ + psinfo_t psinfo; + int error; + klwp_t *lwp; + + ASSERT(pnp->pr_type == PR_SPYMASTER); + + if ((error = prlock(pnp, ZNO)) != 0) + return (error); + + lwp = pnp->pr_common->prc_thread->t_lwp; + + if (lwp->lwp_spymaster == NULL) { + prunlock(pnp); + return (0); + } + + bcopy(lwp->lwp_spymaster, &psinfo, sizeof (psinfo_t)); + prunlock(pnp); + + return (pr_uioread(&psinfo, sizeof (psinfo), uiop)); +} + #if defined(__sparc) static int @@ -1716,7 +1746,7 @@ static int pr_read_status_32(), pr_read_sigact_32(), pr_read_auxv_32(), pr_read_usage_32(), pr_read_lusage_32(), pr_read_pagedata_32(), pr_read_watch_32(), pr_read_lwpstatus_32(), pr_read_lwpsinfo_32(), - pr_read_lwpusage_32(), + pr_read_lwpusage_32(), pr_read_spymaster_32(), #if defined(__sparc) pr_read_gwindows_32(), #endif @@ -1760,6 +1790,7 @@ static int (*pr_read_function_32[PR_NFILES])() = { pr_read_xregs, /* /proc/<pid>/lwp/<lwpid>/xregs */ pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/templates */ pr_read_inval, /* /proc/<pid>/lwp/<lwpid>/templates/<id> */ + pr_read_spymaster_32, /* /proc/<pid>/lwp/<lwpid>/spymaster */ #if defined(__sparc) pr_read_gwindows_32, /* /proc/<pid>/lwp/<lwpid>/gwindows */ pr_read_asrs, /* /proc/<pid>/lwp/<lwpid>/asrs */ @@ -2558,6 +2589,31 @@ out: return (error); } +static int +pr_read_spymaster_32(prnode_t *pnp, uio_t *uiop) +{ + psinfo32_t psinfo; + int error; + klwp_t *lwp; + + ASSERT(pnp->pr_type == PR_SPYMASTER); + + if ((error = prlock(pnp, ZNO)) != 0) + return (error); + + lwp = pnp->pr_common->prc_thread->t_lwp; + + if (lwp->lwp_spymaster == NULL) { + prunlock(pnp); + return (0); + } + + psinfo_kto32(lwp->lwp_spymaster, &psinfo); + prunlock(pnp); + + return (pr_uioread(&psinfo, sizeof (psinfo), uiop)); +} + #if defined(__sparc) static int pr_read_gwindows_32(prnode_t *pnp, uio_t *uiop) @@ -3067,6 +3123,13 @@ prgetattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr, else vap->va_size = 0; break; + case PR_SPYMASTER: + if (pnp->pr_common->prc_thread->t_lwp->lwp_spymaster != NULL) { + vap->va_size = PR_OBJSIZE(psinfo32_t, psinfo_t); + } else { + vap->va_size = 0; + } + break; #if defined(__sparc) case PR_GWINDOWS: { @@ -3267,6 +3330,7 @@ static vnode_t *(*pr_lookup_function[PR_NFILES])() = { pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/xregs */ pr_lookup_tmpldir, /* /proc/<pid>/lwp/<lwpid>/templates */ pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/templates/<id> */ + pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/spymaster */ #if defined(__sparc) pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/gwindows */ pr_lookup_notdir, /* /proc/<pid>/lwp/<lwpid>/asrs */ @@ -4615,6 +4679,7 @@ static int (*pr_readdir_function[PR_NFILES])() = { pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/xregs */ pr_readdir_tmpldir, /* /proc/<pid>/lwp/<lwpid>/templates */ pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/templates/<id> */ + pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/spymaster */ #if defined(__sparc) pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/gwindows */ pr_readdir_notdir, /* /proc/<pid>/lwp/<lwpid>/asrs */ diff --git a/usr/src/uts/common/os/lwp.c b/usr/src/uts/common/os/lwp.c index 64c541187d..6d518e1aae 100644 --- a/usr/src/uts/common/os/lwp.c +++ b/usr/src/uts/common/os/lwp.c @@ -24,6 +24,10 @@ * Use is subject to license terms. */ +/* + * Copyright (c) 2013, Joyent, Inc. All rights reserved. + */ + #include <sys/param.h> #include <sys/types.h> #include <sys/sysmacros.h> @@ -995,6 +999,15 @@ lwp_exit(void) lwp->lwp_curinfo = NULL; } + /* + * If we have spymaster information (that is, if we're an agent LWP), + * free that now. + */ + if (lwp->lwp_spymaster != NULL) { + kmem_free(lwp->lwp_spymaster, sizeof (psinfo_t)); + lwp->lwp_spymaster = NULL; + } + thread_rele(t); /* diff --git a/usr/src/uts/common/sys/elf.h b/usr/src/uts/common/sys/elf.h index 9bda8486e4..dd1eecc70d 100644 --- a/usr/src/uts/common/sys/elf.h +++ b/usr/src/uts/common/sys/elf.h @@ -20,6 +20,7 @@ */ /* * Copyright 2012 DEY Storage Systems, Inc. All rights reserved. + * Copyright (c) 2013, Joyent, Inc. All rights reserved. */ /* * Copyright 2010 Sun Microsystems, Inc. All rights reserved. @@ -818,7 +819,8 @@ typedef Elf64_Word Elf64_Capchain; #define NT_CONTENT 20 /* core_content_t <sys/corectl.h> */ #define NT_ZONENAME 21 /* string from getzonenamebyid(3C) */ #define NT_FDINFO 22 /* open fd info */ -#define NT_NUM 22 +#define NT_SPYMASTER 23 /* psinfo_t for agent LWP spymaster */ +#define NT_NUM 23 #ifdef _KERNEL diff --git a/usr/src/uts/common/sys/klwp.h b/usr/src/uts/common/sys/klwp.h index 93d1e9816f..41b70f6a6e 100644 --- a/usr/src/uts/common/sys/klwp.h +++ b/usr/src/uts/common/sys/klwp.h @@ -23,11 +23,13 @@ * Use is subject to license terms. */ +/* + * Copyright (c) 2013, Joyent, Inc. All rights reserved. + */ + #ifndef _SYS_KLWP_H #define _SYS_KLWP_H -#pragma ident "%Z%%M% %I% %E% SMI" - #include <sys/types.h> #include <sys/condvar.h> #include <sys/thread.h> @@ -190,6 +192,7 @@ typedef struct _klwp { struct contract *lwp_ct_latest[CTT_MAXTYPE]; /* last created contract */ void *lwp_brand; /* per-lwp brand data */ + struct psinfo *lwp_spymaster; /* if an agent LWP, our spymaster */ } klwp_t; /* lwp states */ diff --git a/usr/src/uts/common/sys/prsystm.h b/usr/src/uts/common/sys/prsystm.h index c6f474743a..ebded76dce 100644 --- a/usr/src/uts/common/sys/prsystm.h +++ b/usr/src/uts/common/sys/prsystm.h @@ -27,6 +27,9 @@ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ +/* + * Copyright (c) 2013, Joyent, Inc. All rights reserved. + */ #ifndef _SYS_PRSYSTM_H #define _SYS_PRSYSTM_H @@ -129,6 +132,8 @@ extern void prgetstatus32(proc_t *, struct pstatus32 *, zone_t *); extern void prgetlwpstatus32(kthread_t *, struct lwpstatus32 *, zone_t *); extern void prgetpsinfo32(proc_t *, struct psinfo32 *); extern void prgetlwpsinfo32(kthread_t *, struct lwpsinfo32 *); +extern void lwpsinfo_kto32(const struct lwpsinfo *src, struct lwpsinfo32 *dest); +extern void psinfo_kto32(const struct psinfo *src, struct psinfo32 *dest); extern void prgetprfpregs32(klwp_t *, struct prfpregset32 *); #if defined(__sparc) struct gwindows32; diff --git a/usr/src/uts/intel/ia32/ml/modstubs.s b/usr/src/uts/intel/ia32/ml/modstubs.s index 6953d15bb5..9b58102e2a 100644 --- a/usr/src/uts/intel/ia32/ml/modstubs.s +++ b/usr/src/uts/intel/ia32/ml/modstubs.s @@ -21,6 +21,7 @@ /* * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, Joyent, Inc. All rights reserved. */ #include <sys/asm_linkage.h> @@ -695,6 +696,8 @@ fcnname/**/_info: \ NO_UNLOAD_STUB(procfs, prgetlwpsinfo32, nomod_zero); NO_UNLOAD_STUB(procfs, oprgetstatus32, nomod_zero); NO_UNLOAD_STUB(procfs, oprgetpsinfo32, nomod_zero); + NO_UNLOAD_STUB(procfs, psinfo_kto32, nomod_zero); + NO_UNLOAD_STUB(procfs, lwpsinfo_kto32, nomod_zero); #endif /* _SYSCALL32_IMPL */ NO_UNLOAD_STUB(procfs, prnotify, nomod_zero); NO_UNLOAD_STUB(procfs, prexecstart, nomod_zero); diff --git a/usr/src/uts/sparc/ml/modstubs.s b/usr/src/uts/sparc/ml/modstubs.s index 7a09e76bda..29bf48f260 100644 --- a/usr/src/uts/sparc/ml/modstubs.s +++ b/usr/src/uts/sparc/ml/modstubs.s @@ -20,6 +20,7 @@ */ /* * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, Joyent, Inc. All rights reserved. */ #if !defined(lint) @@ -582,6 +583,8 @@ stubs_base: NO_UNLOAD_STUB(procfs, prgetlwpsinfo32, nomod_zero); NO_UNLOAD_STUB(procfs, oprgetstatus32, nomod_zero); NO_UNLOAD_STUB(procfs, oprgetpsinfo32, nomod_zero); + NO_UNLOAD_STUB(procfs, psinfo_kto32, nomod_zero); + NO_UNLOAD_STUB(procfs, lwpsinfo_kto32, nomod_zero); #endif /* _SYSCALL32_IMPL */ NO_UNLOAD_STUB(procfs, prnotify, nomod_zero); NO_UNLOAD_STUB(procfs, prexecstart, nomod_zero); |
